From 0c35e38134fe24734d048d02d937b5a9e6b6b686 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Fri, 14 Jul 2023 13:37:51 -0700 Subject: [PATCH 001/300] first attempt to reconcile patch initialization logic with land-use + nocomp --- main/EDInitMod.F90 | 230 ++++++++++++++++-------------- main/EDTypesMod.F90 | 4 +- main/FatesConstantsMod.F90 | 5 +- main/FatesHistoryInterfaceMod.F90 | 2 +- main/FatesInterfaceMod.F90 | 25 +++- main/FatesInterfaceTypesMod.F90 | 10 +- 6 files changed, 158 insertions(+), 118 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 5f27e1f04f..0c6098a605 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -178,11 +178,8 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%dz_soil(site_in%nlevsoil)) allocate(site_in%z_soil(site_in%nlevsoil)) - if (hlm_use_nocomp .eq. itrue .and. hlm_use_fixed_biogeog .eq. itrue) then - allocate(site_in%area_pft(0:numpft)) - else ! SP and nocomp require a bare-ground patch. - allocate(site_in%area_pft(1:numpft)) - endif + allocate(site_in%area_pft(1:numpft,1:n_landuse_cats)) + allocate(site_in%use_this_pft(1:numpft)) allocate(site_in%area_by_age(1:nlevage)) @@ -321,7 +318,8 @@ subroutine zero_site( site_in ) ! canopy spread site_in%spread = 0._r8 - site_in%area_pft(:) = 0._r8 + site_in%area_pft(:,:) = 0._r8 + site_in%area_bareground = 0._r8 site_in%use_this_pft(:) = fates_unset_int site_in%area_by_age(:) = 0._r8 @@ -355,6 +353,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) real(r8) :: sumarea ! area of PFTs in nocomp mode. integer :: hlm_pft ! used in fixed biogeog mode integer :: fates_pft ! used in fixed biogeog mode + integer :: i_landusetype !---------------------------------------------------------------------- @@ -397,7 +396,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%acc_NI = acc_NI sites(s)%NF = 0.0_r8 sites(s)%NF_successful = 0.0_r8 - sites(s)%area_pft(:) = 0.0_r8 + sites(s)%area_pft(:,:) = 0.0_r8 do ft = 1,numpft sites(s)%rec_l2fr(ft,:) = prt_params%allom_l2fr(ft) @@ -408,66 +407,71 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%ema_npp = -9999._r8 if(hlm_use_fixed_biogeog.eq.itrue)then - ! MAPPING OF FATES PFTs on to HLM_PFTs - ! add up the area associated with each FATES PFT - ! where pft_areafrac is the area of land in each HLM PFT and (from surface dataset) - ! hlm_pft_map is the area of that land in each FATES PFT (from param file) - - do hlm_pft = 1,size( EDPftvarcon_inst%hlm_pft_map,2) - do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts - sites(s)%area_pft(fates_pft) = sites(s)%area_pft(fates_pft) + & - EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac(hlm_pft) + + use_fates_luh_if: if (use_fates_luh .eq. itrue.) then + ! MAPPING OF FATES PFTs on to HLM_PFTs with land use + ! add up the area associated with each FATES PFT + ! where pft_areafrac_lu is the area of land in each HLM PFT and land use type (from surface dataset) + ! hlm_pft_map is the area of that land in each FATES PFT (from param file) + do i_landusetype = 1, n_landuse_cats + do hlm_pft = 1,fates_hlm_num_natpfts + do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts + sites(s)%area_pft(fates_pft,i_landusetype) = sites(s)%area_pft_luh(fates_pft,i_landusetype) + & + EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac(hlm_pft) + end do + end do !hlm_pft end do - end do !hlm_pft - do ft = 1,numpft - if(sites(s)%area_pft(ft).lt.0.01_r8.and.sites(s)%area_pft(ft).gt.0.0_r8)then - if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,sites(s)%area_pft(ft) - sites(s)%area_pft(ft)=0.0_r8 - ! remove tiny patches to prevent numerical errors in terminate patches - endif - if(sites(s)%area_pft(ft).lt.0._r8)then - 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. - end do + sites(s)%area_bareground = bc_in(s)%baregroundfrac * area + + else use_fates_luh_if + ! MAPPING OF FATES PFTs on to HLM_PFTs + ! add up the area associated with each FATES PFT + ! where pft_areafrac is the area of land in each HLM PFT and (from surface dataset) + ! hlm_pft_map is the area of that land in each FATES PFT (from param file) + + do hlm_pft = 1,size( EDPftvarcon_inst%hlm_pft_map,2) + do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts + sites(s)%area_pft(fates_pft,primarylands) = sites(s)%area_pft(fates_pft,primarylands) + & + EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac(hlm_pft) + end do + sites(s)%area_bareground = bc_in(s)%pft_areafrac(0) + end do !hlm_pft - ! re-normalize PFT area to ensure it sums to one. - ! note that in areas of 'bare ground' (PFT 0 in CLM/ELM) - ! the bare ground will no longer be proscribed and should emerge from FATES - ! this may or may not be the right way to deal with this? + endif use_fates_luh_if - if(hlm_use_nocomp.eq.ifalse)then ! when not in nocomp (i.e. or SP) mode, - ! subsume bare ground evenly into the existing patches. + do i_landusetype = 1, n_landuse_cats + do ft = 1,numpft + if(sites(s)%area_pft(ft).lt.0.01_r8.and.sites(s)%area_pft(ft).gt.0.0_r8)then + if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,sites(s)%area_pft(ft) + sites(s)%area_pft(ft)=0.0_r8 + ! remove tiny patches to prevent numerical errors in terminate patches + endif + if(sites(s)%area_pft(ft).lt.0._r8)then + 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. + end do + end do - sumarea = sum(sites(s)%area_pft(1:numpft)) + ! re-normalize PFT area to ensure it sums to one for each (active) land use type + ! for nocomp cases, track bare ground area as a separate quantity + + do i_landusetype = 1, n_landuse_cats + sumarea = sum(sites(s)%area_pft(1:numpft,i_landusetype)) do ft = 1,numpft if(sumarea.gt.0._r8)then - sites(s)%area_pft(ft) = area * sites(s)%area_pft(ft)/sumarea + sites(s)%area_pft(ft, i_landusetype) = sites(s)%area_pft(ft, i_landusetype)/sumarea else - sites(s)%area_pft(ft) = area/numpft - ! in nocomp mode where there is only bare ground, we assign equal area to - ! all pfts and let the model figure out whether land should be bare or not. + ! if no PFT area in primary lands, set bare ground fraction to one. + if ( i_landusetype .eq. primarylands) then + sites(s)%area_bareground = 1._r8 + endif end if end do !ft - else ! for sp and nocomp mode, assert a bare ground patch if needed - sumarea = sum(sites(s)%area_pft(1:numpft)) - - ! In all the other FATES modes, bareground is the area in which plants - ! do not grow of their own accord. In SP mode we assert that the canopy is full for - ! each PFT patch. Thus, we also need to assert a bare ground area in - ! order to not have all of the ground filled by leaves. - - ! Further to that, one could calculate bare ground as the remaining area when - ! all fhe canopies are accounted for, but this means we don't pass balance checks - ! on canopy are inside FATES, and so in SP mode, we define the bare groud - ! patch as having a PFT identifier as zero. - - if(sumarea.lt.area)then !make some bare ground - sites(s)%area_pft(0) = area - sumarea - end if - end if !sp mode + end do + end if !fixed biogeog do ft = 1,numpft @@ -475,7 +479,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! are used for nocomp with no biogeog sites(s)%use_this_pft(ft) = itrue if(hlm_use_fixed_biogeog.eq.itrue)then - if(sites(s)%area_pft(ft).gt.0.0_r8)then + if(any(sites(s)%area_pft(ft,:).gt.0.0_r8))then sites(s)%use_this_pft(ft) = itrue else sites(s)%use_this_pft(ft) = ifalse @@ -580,13 +584,8 @@ subroutine init_patches( nsites, sites, bc_in) ! have smaller spread factors than bare ground (they are crowded) sites(s)%spread = init_spread_near_bare_ground - start_patch = 1 ! start at the first vegetated patch if(hlm_use_nocomp.eq.itrue)then num_new_patches = numpft - if( hlm_use_fixed_biogeog .eq.itrue )then - start_patch = 0 ! start at the bare ground patch - endif - ! allocate(newppft(numpft)) else !default num_new_patches = 1 end if !nocomp @@ -599,17 +598,7 @@ subroutine init_patches( nsites, sites, bc_in) ! categories based on which states are zero n_active_landuse_cats = n_landuse_cats call get_luh_statedata(bc_in(s), state_vector) - ! n_luh_states = 0 - ! do i_lu = 1, hlm_num_luh2_transitions - ! if ( state_vector(i_lu) .gt. nearzero ) then - ! n_luh_states = n_luh_states +1 - ! end if - ! end do - - ! if (n_luh_states .eq. 0) then - ! write(fates_log(),*) 'error. n_luh_states .eq. 0.' - ! call endrun(msg=errMsg(sourcefile, __LINE__)) - ! endif + else ! If LUH2 data is not being used, we initialize with primarylands, ! i.e. array index equals '1' @@ -619,42 +608,74 @@ subroutine init_patches( nsites, sites, bc_in) endif is_first_patch = itrue - ! luh_state_counter = 0 - new_patch_nocomp_loop: do n = start_patch, num_new_patches - ! set the PFT index for patches if in nocomp mode. - if(hlm_use_nocomp.eq.itrue)then - nocomp_pft = n - else - nocomp_pft = fates_unset_int - end if + ! first make a bare-ground patch if one is needed. + make_bareground_patch_if: if (hlm_use_nocomp.eq.itrue .and. hlm_use_fixed_biogeog .eq.itrue .and. sites(s)%area_bareground .gt. 0._r8) then + newparea = area * sites(s)%area_bareground - if(hlm_use_nocomp.eq.itrue)then - ! In no competition mode, if we are using the fixed_biogeog filter - ! then each PFT has the area dictated by the surface dataset. + allocate(newp) + + call create_patch(sites(s), newp, age, newparea, nocomp_bareground_land, nocomp_bareground) + + ! set poointers for first patch (or only patch, if nocomp is false) + newp%patchno = 1 + newp%younger => null() + newp%older => null() + sites(s)%youngest_patch => newp + sites(s)%oldest_patch => newp + is_first_patch = ifalse + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call newp%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + endif make_bareground_patch_if - ! If we are not using fixed biogeog model, each PFT gets the same area. - ! i.e. each grid cell is divided exactly into the number of FATES PFTs. + if (use_fates_luh2 .eq. itrue) then + end_landuse_idx = n_landuse_cats + else + end_landuse_idx = 1 + endif - if(hlm_use_fixed_biogeog.eq.itrue)then - newparea = sites(s)%area_pft(nocomp_pft) - else - newparea = area / numpft - end if - else ! The default case is initialized w/ one patch with the area of the whole site. - newparea = area - end if !nocomp mode + ! now make one or more vegetated patches based on nocomp and land use logic + new_patch_nocomp_loop: do n = 1, num_new_patches + luh_state_loop: do i_lu_state = 1, end_landuse_idx + lu_state_present_if: if (state_vector(i_lu_state) .gt. nearzero) then + ! set the PFT index for patches if in nocomp mode. + if(hlm_use_nocomp.eq.itrue)then + nocomp_pft = n + else + nocomp_pft = fates_unset_int + end if - luh_state_loop: do i_lu_state = 1, n_active_landuse_cats - lu_state_present_if: if ( state_vector(i_lu_state) .gt. nearzero ) then + if(hlm_use_nocomp.eq.itrue)then + ! In no competition mode, if we are using the fixed_biogeog filter + ! then each PFT has the area dictated by the surface dataset. - newparea_withlanduse = newparea * state_vector(i_lu_state) + ! If we are not using fixed biogeog model, each PFT gets the same area. + ! i.e. each grid cell is divided exactly into the number of FATES PFTs. + + if(hlm_use_fixed_biogeog.eq.itrue)then + newparea = sites(s)%area_pft(nocomp_pft) * area / state_vector(i_lu_state) + else + newparea = area / ( numpft * vector(i_lu_state)) + end if + else ! The default case is initialized w/ one patch with the area of the whole site. + newparea = area / state_vector(i_lu_state) + end if !nocomp mode ! for now, spread nocomp PFTs evenly across land use types - new_patch_area_gt_zero: if(newparea_withlanduse.gt.0._r8)then ! Stop patches being initilialized when PFT not present in nocomop mode + new_patch_area_gt_zero: if(newparea.gt.0._r8)then ! Stop patches being initilialized when PFT not present in nocomop mode allocate(newp) - call create_patch(sites(s), newp, age, newparea_withlanduse, i_lu_state, nocomp_pft) + call create_patch(sites(s), newp, age, newparea, i_lu_state, nocomp_pft) if(is_first_patch.eq.itrue)then !is this the first patch? ! set poointers for first patch (or only patch, if nocomp is false) @@ -687,13 +708,8 @@ subroutine init_patches( nsites, sites, bc_in) end do sitep => sites(s) - if(hlm_use_sp.eq.itrue)then - if(nocomp_pft.ne.0)then !don't initialize cohorts for SP bare ground patch - call init_cohorts(sitep, newp, bc_in(s)) - end if - else ! normal non SP case always call init cohorts - call init_cohorts(sitep, newp, bc_in(s)) - end if + call init_cohorts(sitep, newp, bc_in(s)) + end if new_patch_area_gt_zero end if lu_state_present_if end do luh_state_loop diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 84c1fb7a4b..79c230316b 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -736,7 +736,9 @@ module EDTypesMod real(r8) :: lon ! longitude: degrees ! Fixed Biogeography mode inputs - real(r8), allocatable :: area_PFT(:) ! Area allocated to individual PFTs + real(r8), allocatable :: area_PFT(:,:) ! Area allocated to individual PFTs, indexed by land use class [ha/ha of non-bareground area] + real(r8) :: area_bareground ! Area allocated to bare ground in nocomp configurations (corresponds to HLM PFT 0) [ha/ha] + integer, allocatable :: use_this_pft(:) ! Is area_PFT > 0 ? (1=yes, 0=no) ! Total area of patches in each age bin [m2] diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 03142b99bf..35b2ee42b2 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -38,7 +38,10 @@ module FatesConstantsMod integer, parameter, public :: pastureland = 4 integer, parameter, public :: cropland = 5 - ! Bareground label for no competition mode + ! Bareground nocomp land use label + integer, parameter, public :: nocomp_bareground_land = 0 ! not a real land use type, only for labeling any bare-ground nocomp patches + + ! Bareground nocomp PFT label for no competition mode integer, parameter, public :: nocomp_bareground = 0 ! Flags specifying how phosphorous uptake and turnover interacts diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 6964ee259b..4cbbda5b5d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -4537,7 +4537,7 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) ! Calculate the site-level total vegetated area (i.e. non-bareground) site_area_veg = area if (hlm_use_nocomp .eq. itrue .and. hlm_use_fixed_biogeog .eq. itrue) then - site_area_veg = area - sites(s)%area_pft(0) + site_area_veg = area - sites(s)%area_bareground * area end if cpatch => sites(s)%oldest_patch diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 3a86beff4f..431dda71ab 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -386,7 +386,7 @@ end subroutine zero_bcs ! =========================================================================== subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, num_luh2_states, & - num_luh2_transitions, natpft_lb,natpft_ub) + num_luh2_transitions, surfpft_lb,surfpft_ub) ! --------------------------------------------------------------------------------- ! Allocate and Initialze the FATES boundary condition vectors @@ -399,7 +399,7 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, integer,intent(in) :: num_lu_harvest_cats integer,intent(in) :: num_luh2_states integer,intent(in) :: num_luh2_transitions - integer,intent(in) :: natpft_lb,natpft_ub ! dimension bounds of the array holding surface file pft data + integer,intent(in) :: surfpft_lb,surfpft_ub ! dimension bounds of the array holding surface file pft data ! Allocate input boundaries @@ -533,7 +533,13 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, allocate(bc_in%hlm_harvest_catnames(0)) end if - allocate(bc_in%pft_areafrac(natpft_lb:natpft_ub)) + if ( hlm_use_fixed_biogeog .eq. itrue) then + if (hlm_use_luh .gt. 0 ) then + allocate(bc_in%pft_areafrac_lu(fates_hlm_num_natpfts,num_luh2_states)) + else + allocate(bc_in%pft_areafrac(surfpft_lb:surfpft_ub)) + endif + endif ! LUH2 state and transition data if (hlm_use_luh .gt. 0) then @@ -545,10 +551,11 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, ! Variables for SP mode. if(hlm_use_sp.eq.itrue) then - allocate(bc_in%hlm_sp_tlai(natpft_lb:natpft_ub)) - allocate(bc_in%hlm_sp_tsai(natpft_lb:natpft_ub)) - allocate(bc_in%hlm_sp_htop(natpft_lb:natpft_ub)) - end if + allocate(bc_in%hlm_sp_tlai(surfpft_lb:surfpft_ub)) + allocate(bc_in%hlm_sp_tsai(surfpft_lb:surfpft_ub)) + allocate(bc_in%hlm_sp_htop(surfpft_lb:surfpft_ub)) + end if + return end subroutine allocate_bcin @@ -768,6 +775,10 @@ subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) fates_maxPatchesPerSite = max(surf_numpft+surf_numcft,maxpatch_total+1) + ! if this is nocomp with land use, track things differently. + ! we want the number of natpfts minus the bare ground PFT. + fates_hlm_num_natpfts = surf_numpft -1 + else ! If we are using fixed biogeography or no-comp then we diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 4c6ba46043..47a382a22f 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -225,6 +225,9 @@ module FatesInterfaceTypesMod ! dataset than the number of PFTs in FATES, we have to allocate with ! the prior so that we can hold the LAI data integer, public :: fates_maxPatchesPerSite + + ! the number of natural PFTs tracked by the host model; NOT INCLUDING EITHER CROPS OR BARE GROUND + integer, public :: fates_hlm_num_natpfts integer, public :: max_comp_per_site ! This is the maximum number of nutrient aquisition ! competitors that will be generated on each site @@ -545,7 +548,12 @@ module FatesInterfaceTypesMod real(r8) :: site_area ! Actual area of current site [m2], only used in carbon-based harvest ! Fixed biogeography mode - real(r8), allocatable :: pft_areafrac(:) ! Fractional area of the FATES column occupied by each PFT + real(r8), allocatable :: pft_areafrac(:) ! Fractional area of the FATES column occupied by each PFT + + ! Fixed biogeography mode with land use active + real(r8), allocatable :: pft_areafrac_lu(:,:) ! Fractional area occupied by each PFT on each land use type + real(r8) :: baregroundfrac ! fractional area held as bare-ground + ! Satellite Phenology (SP) input variables. (where each patch only has one PFT) ! --------------------------------------------------------------------------------- From 2d9dd68b73b117387590395c71230d10949ceab9 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Fri, 14 Jul 2023 15:09:17 -0700 Subject: [PATCH 002/300] starting to put in logic to handle nocomp PFT transitions during LU change --- biogeochem/EDPatchDynamicsMod.F90 | 89 ++++++++++++++++++++++++++++++- main/EDTypesMod.F90 | 1 + 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 6dfa501d83..a969e1a4bb 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -473,6 +473,7 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: disturbance_rate ! rate of disturbance being resolved [fraction of patch area / day] real(r8) :: oldarea ! old patch area prior to disturbance logical :: clearing_matrix(n_landuse_cats,n_landuse_cats) ! do we clear vegetation when transferring from one LU type to another? + type (ed_patch_type) , pointer :: buffer_patch !--------------------------------------------------------------------- @@ -644,8 +645,6 @@ subroutine spawn_patches( currentSite, bc_in) ! Transfer in litter fluxes from plants in various contexts of death and destruction - ! CDK what do we do here for land use transitions? - select case(i_disturbance_type) case (dtype_ilog) call logging_litter_fluxes(currentSite, currentPatch, & @@ -660,6 +659,8 @@ subroutine spawn_patches( currentSite, bc_in) call landusechange_litter_fluxes(currentSite, currentPatch, & new_patch, patch_site_areadis,bc_in, & clearing_matrix(i_donorpatch_landuse_type,i_landusechange_receiverpatchlabel)) + + new_patch%changed_landuse_this_ts = .true. case default write(fates_log(),*) 'unknown disturbance mode?' write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type @@ -1256,6 +1257,89 @@ subroutine spawn_patches( currentSite, bc_in) end do nocomp_pft_loop + nocomp_and_luh_if: if ( use_fates_nocomp .eq. itrue .and. use_fates_luh .eq. itrue ) then + + ! disturbance has just hapopened, and now the nocomp PFT identities of the newly-disturbed patches + ! need to be remapped to those associated with the new land use type. + + ! logic: loop over land use types. figure out the nocomp PFT fractions for all newly-disturbed patches that have ebcome that land use type. + ! if the + + lu_loop: do i_land_use_label = 1, n_landuse_cats + + nocomp_pft_area_vector(:) = 0._r8 + nocomp_pft_area_vector_allocated(:) = 0._r8 + + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + if (currentPatch%changed_landuse_this_ts) then + nocomp_pft_area_vector(currentPatch%nocomp_pft_label) = nocomp_pft_area_vector(currentPatch%nocomp_pft_label) + currentPatch%area + end if + currentPatch => currentPatch%younger + end do + + ! create buffer patch to put all of the pieces carved off of other patches + call create_patch(currentSite, buffer_patch, 0._r8, & + 0._r8, i_land_use_label, 0) + + ! Initialize the litter pools to zero + do el=1,num_elements + call buffer_patch%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + buffer_patch%tallest => null() + buffer_patch%shortest => null() + + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + if (currentPatch%changed_landuse_this_ts) then + fraction_to_keep = currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * area / nocomp_pft_area_vector(currentPatch%nocomp_pft_label) + if (fraction_to_keep .lt. nearzero) then + ! we don't want any patch area with this PFT idendity at all anymore. Fuse it into the buffer patch. + currentPatch%nocomp_pft_label = 0 + call fuse_2_patches(currentSite, currentPatch, buffer_patch) + elseif (fraction_to_keep .lt. (1._r8 - nearzero)) then + ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. + !cdkcdk TODO + else + ! we want to keep all of this patch (and possibly more) + nocomp_pft_area_vector_allocated(currentPatch%nocomp_pft_label) = & + nocomp_pft_area_vector_allocated(currentPatch%nocomp_pft_label) + currentPatch%area + currentPatch%changed_landuse_this_ts = .false. + endif + end if + currentPatch => currentPatch%younger + end do + + ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list + nocomp_pft_loop: do i_pft = 1, numpft + + if (nocomp_pft_area_vector_allocated(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * area) then + + newp_area = currentSite%area_pft(i_pft,i_land_use_label) * area - nocomp_pft_area_vector_allocated(i_pft) + + if (newp_area .lt. buffer_patch%area) then + + ! split patch in two, and put one of them into the linked list cdkcdk TODO + + else + + ! put the buffer patch directly into the linked list cdkcdk TODO + + end if + + end if + + end do nocomp_pft_loop + + + end do lu_loop + endif nocomp_and_luh_if + !zero disturbance rate trackers on all patches currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) @@ -2476,6 +2560,7 @@ subroutine create_patch(currentSite, new_patch, age, areap, label,nocomp_pft) new_patch%burnt_frac_litter(:) = 0._r8 new_patch%total_tree_area = 0.0_r8 new_patch%NCL_p = 1 + new_patch%changed_landuse_this_ts = .false. return diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 79c230316b..037c46fe58 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -435,6 +435,7 @@ module EDTypesMod integer :: ncl_p ! Number of occupied canopy layers integer :: land_use_label ! patch label for land use classification (primaryland, secondaryland, etc) real(r8) :: age_since_anthro_disturbance ! average age for secondary forest since last anthropogenic disturbance + logical :: changed_landuse_this_ts ! logical flag to track patches that have just undergone land use change ! Running means From 9a0843001759daaf9d84a139698e920ac5975d67 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Fri, 28 Jul 2023 16:05:40 -0700 Subject: [PATCH 003/300] fixing some bugs I see while reading through code --- main/EDInitMod.F90 | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 0c6098a605..5e0d1c5939 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -416,8 +416,8 @@ subroutine set_site_properties( nsites, sites,bc_in ) do i_landusetype = 1, n_landuse_cats do hlm_pft = 1,fates_hlm_num_natpfts do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts - sites(s)%area_pft(fates_pft,i_landusetype) = sites(s)%area_pft_luh(fates_pft,i_landusetype) + & - EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac(hlm_pft) + sites(s)%area_pft(fates_pft,i_landusetype) = sites(s)%area_pft(fates_pft,i_landusetype) + & + EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac_luh(hlm_pft,i_landusetype) end do end do !hlm_pft end do @@ -442,16 +442,15 @@ subroutine set_site_properties( nsites, sites,bc_in ) do i_landusetype = 1, n_landuse_cats do ft = 1,numpft - if(sites(s)%area_pft(ft).lt.0.01_r8.and.sites(s)%area_pft(ft).gt.0.0_r8)then - if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,sites(s)%area_pft(ft) - sites(s)%area_pft(ft)=0.0_r8 + if(sites(s)%area_pft(ft, i_landusetype).lt.0.01_r8.and.sites(s)%area_pft(ft, i_landusetype).gt.0.0_r8)then + if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,i_landusetype,sites(s)%area_pft(ft, i_landusetype) + sites(s)%area_pft(ft, i_landusetype)=0.0_r8 ! remove tiny patches to prevent numerical errors in terminate patches endif - if(sites(s)%area_pft(ft).lt.0._r8)then - write(fates_log(),*) 'negative area',s,ft,sites(s)%area_pft(ft) + if(sites(s)%area_pft(ft, i_landusetype).lt.0._r8)then + write(fates_log(),*) 'negative area',s,ft,i_landusetype,sites(s)%area_pft(ft, i_landusetype) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - sites(s)%area_pft(ft)= sites(s)%area_pft(ft) * AREA ! rescale units to m2. end do end do @@ -477,7 +476,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) do ft = 1,numpft ! Setting this to true ensures that all pfts ! are used for nocomp with no biogeog - sites(s)%use_this_pft(ft) = itrue + sites(s)%use_this_pft(ft) = itrues if(hlm_use_fixed_biogeog.eq.itrue)then if(any(sites(s)%area_pft(ft,:).gt.0.0_r8))then sites(s)%use_this_pft(ft) = itrue @@ -663,7 +662,7 @@ subroutine init_patches( nsites, sites, bc_in) ! i.e. each grid cell is divided exactly into the number of FATES PFTs. if(hlm_use_fixed_biogeog.eq.itrue)then - newparea = sites(s)%area_pft(nocomp_pft) * area / state_vector(i_lu_state) + newparea = sites(s)%area_pft(nocomp_pft,i_lu_state) * area / state_vector(i_lu_state) else newparea = area / ( numpft * vector(i_lu_state)) end if From a93efe4938cc4d33a884602c3d38e2b08ee01e76 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Mon, 31 Jul 2023 09:45:28 -0700 Subject: [PATCH 004/300] added new generalized split_patch function --- biogeochem/EDPatchDynamicsMod.F90 | 125 +++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index a969e1a4bb..ab7cc37d76 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -473,7 +473,7 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: disturbance_rate ! rate of disturbance being resolved [fraction of patch area / day] real(r8) :: oldarea ! old patch area prior to disturbance logical :: clearing_matrix(n_landuse_cats,n_landuse_cats) ! do we clear vegetation when transferring from one LU type to another? - type (ed_patch_type) , pointer :: buffer_patch + type (ed_patch_type) , pointer :: buffer_patch, temp_patch !--------------------------------------------------------------------- @@ -1262,7 +1262,7 @@ subroutine spawn_patches( currentSite, bc_in) ! disturbance has just hapopened, and now the nocomp PFT identities of the newly-disturbed patches ! need to be remapped to those associated with the new land use type. - ! logic: loop over land use types. figure out the nocomp PFT fractions for all newly-disturbed patches that have ebcome that land use type. + ! logic: loop over land use types. figure out the nocomp PFT fractions for all newly-disturbed patches that have become that land use type. ! if the lu_loop: do i_land_use_label = 1, n_landuse_cats @@ -1303,8 +1303,12 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch%nocomp_pft_label = 0 call fuse_2_patches(currentSite, currentPatch, buffer_patch) elseif (fraction_to_keep .lt. (1._r8 - nearzero)) then + ! we have more patch are of this PFT than we want, but we do want to keep some of it. ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. - !cdkcdk TODO + call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep) + ! + temp_patch%nocomp_pft_label = 0 + call fuse_2_patches(currentSite, temp_patch, buffer_patch) else ! we want to keep all of this patch (and possibly more) nocomp_pft_area_vector_allocated(currentPatch%nocomp_pft_label) = & @@ -1324,7 +1328,10 @@ subroutine spawn_patches( currentSite, bc_in) if (newp_area .lt. buffer_patch%area) then - ! split patch in two, and put one of them into the linked list cdkcdk TODO + ! split buffer patch in two, keeping the smaller buffer patch to put into new patches + call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) + + ! put the new patch into the linked list cdkcdk TODO else @@ -1353,6 +1360,116 @@ end subroutine spawn_patches ! ============================================================================ + subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) + ! + ! !DESCRIPTION: + ! Split a patch into two patches that are identical except in their areas + ! + ! !USES: + ! + ! !ARGUMENTS: + type(ed_site_type),intent(in) :: currentSite + type(ed_patch_type) , intent(inout), target :: currentPatch ! Donor Patch + type(ed_patch_type) , intent(inout), target :: new_patch ! New Patch + real(r8), intent(in) :: fraction_to_keep ! fraction of currentPatch to keep, the rest goes to newpatch + + ! first we need to make the new patch + call create_patch(currentSite, new_patch, 0._r8, & + currentPatch%area * (1._r8 - fraction_to_keep), currentPatch%land_use_label, currentPatch%nocomp_pft_label) + + ! Initialize the litter pools to zero, these + ! pools will be populated shortly + do el=1,num_elements + call new_patch%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + + new_patch%tallest => null() + new_patch%shortest => null() + + ! Copy any means or timers from the original patch to the new patch + ! These values will inherit all info from the original patch + ! -------------------------------------------------------------------------- + call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) + call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) + call new_patch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) + + currentPatch%burnt_frac_litter(:) = 0._r8 + call TransLitterNewPatch( currentSite, currentPatch, new_patch, currentPatch%area * fraction_to_keep) + + ! Next, we loop through the cohorts in the donor patch, copy them with + ! area modified number density into the new-patch, and apply survivorship. + ! ------------------------------------------------------------------------- + + currentCohort => currentPatch%shortest + do while(associated(currentCohort)) + + allocate(nc) + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,nc) + + ! Initialize the PARTEH object and point to the + ! correct boundary condition fields + nc%prt => null() + call InitPRTObject(nc%prt) + call InitPRTBoundaryConditions(nc) + + ! (Keeping as an example) + ! Allocate running mean functions + !allocate(nc%tveg_lpa) + !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) + + call zero_cohort(nc) + + ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort + ! is the curent cohort that stays in the donor patch (currentPatch) + call copy_cohort(currentCohort, nc) + + ! Number of members in the new patch + nc%n = currentCohort%n * fraction_to_keep + + ! loss of individuals from source patch due to area shrinking + currentCohort%n = currentCohort%n * (1._r8 - fraction_to_keep) + + storebigcohort => new_patch%tallest + storesmallcohort => new_patch%shortest + if(associated(new_patch%tallest))then + tnull = 0 + else + tnull = 1 + new_patch%tallest => nc + nc%taller => null() + endif + + if(associated(new_patch%shortest))then + snull = 0 + else + snull = 1 + new_patch%shortest => nc + nc%shorter => null() + endif + nc%patchptr => new_patch + call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & + tnull, snull, storebigcohort, storesmallcohort) + + new_patch%tallest => storebigcohort + new_patch%shortest => storesmallcohort + + currentCohort => currentCohort%taller + enddo ! currentCohort + + call sort_cohorts(currentPatch) + + !update area of donor patch + currentPatch%area = currentPatch%area * (1._r8 - fraction_to_keep) + + end subroutine split_patch + + ! ============================================================================ + subroutine check_patch_area( currentSite ) ! ! !DESCRIPTION: From 255e7094efe382df29dab9783187c601624ca4a4 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Mon, 31 Jul 2023 11:47:47 -0700 Subject: [PATCH 005/300] refactored and reused logic to put new patches into linked list --- biogeochem/EDPatchDynamicsMod.F90 | 119 ++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 41 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ab7cc37d76..af2b7e8799 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -463,7 +463,6 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: leaf_burn_frac ! fraction of leaves burned in fire ! for both woody and grass species real(r8) :: leaf_m ! leaf mass during partial burn calculations - logical :: found_youngest_landuselabel ! logical for finding the first primary forest patch integer :: min_nocomp_pft, max_nocomp_pft, i_nocomp_pft integer :: i_disturbance_type, i_dist2 ! iterators for looping over disturbance types integer :: i_landusechange_receiverpatchlabel ! iterator for the land use change types @@ -1197,44 +1196,8 @@ subroutine spawn_patches( currentSite, bc_in) !*************************/ if ( site_areadis .gt. nearzero) then - currentPatch => currentSite%youngest_patch - - ! Insert new patch as the youngest patch in the group of patches with the same land use type. - ! On a given site, the patches are grouped together by land use type. The order of the - ! groups within the site doesn't matter, except that the older patch group are primarylands. - - if (currentPatch%land_use_label .eq. new_patch%land_use_label ) then - found_youngest_landuselabel = .false. - do while(associated(currentPatch) .and. .not. found_youngest_landuselabel) - currentPatch => currentPatch%older - if (associated(currentPatch)) then - if (currentPatch%land_use_label .eq. new_patch%land_use_label) then - found_youngest_landuselabel = .true. - endif - endif - end do - if (associated(currentPatch)) then - ! the case where we've found a youngest patch type matching the new patch type - new_patch%older => currentPatch - new_patch%younger => currentPatch%younger - currentPatch%younger%older => new_patch - currentPatch%younger => new_patch - else - ! the case where we haven't, because the patches are all non-primaryland, - ! and are putting a primaryland patch at the oldest end of the - ! linked list (not sure how this could happen, but who knows...) - new_patch%older => null() - new_patch%younger => currentSite%oldest_patch - currentSite%oldest_patch%older => new_patch - currentSite%oldest_patch => new_patch - endif - else - ! the case where the youngest patch on the site matches the new patch type - new_patch%older => currentPatch - new_patch%younger => null() - currentPatch%younger => new_patch - currentSite%youngest_patch => new_patch - endif + + call insert_patch_into_sitelist(currentSite, new_patch) ! sort out the cohorts, since some of them may be so small as to need removing. ! the first call to terminate cohorts removes sparse number densities, @@ -1331,11 +1294,20 @@ subroutine spawn_patches( currentSite, bc_in) ! split buffer patch in two, keeping the smaller buffer patch to put into new patches call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) - ! put the new patch into the linked list cdkcdk TODO + ! give the new patch the intended nocomp PFT label + temp_patch%nocomp_pft_label = i_pft + + ! put the new patch into the linked list + call insert_patch_into_sitelist(currentSite, temp_patch) + + ! CDK QUESTION: HOW DO WE ERASE OUT THE TEMP_PATCH INFO SO THAT IT CAN HOLD A NEW PATCH WHEN IT GOES BACK THROUGH THE LOOP? else + ! give the buffer patch the intended nocomp PFT label + buffer_patch%nocomp_pft_label = i_pft - ! put the buffer patch directly into the linked list cdkcdk TODO + ! put the buffer patch directly into the linked list + call insert_patch_into_sitelist(currentSite, buffer_patch) end if @@ -1358,6 +1330,63 @@ subroutine spawn_patches( currentSite, bc_in) return end subroutine spawn_patches + ! ----------------------------------------------------------------------------------------- + + subroutine insert_patch_into_sitelist(currentSite, new_patch) + ! + ! !DESCRIPTION: + ! Insert a new patch into the site linked list structure. + ! + ! !USES: + ! + ! !ARGUMENTS: + type(ed_site_type),intent(in) :: currentSite + type(ed_patch_type) , intent(inout), target :: new_patch ! New Patch + ! + ! !LOCAL VARIABLES: + type (ed_patch_type) , pointer :: currentPatch + logical :: found_youngest_landuselabel ! logical for finding the first primary forest patch + + currentPatch => currentSite%youngest_patch + + ! Insert new patch as the youngest patch in the group of patches with the same land use type. + ! On a given site, the patches are grouped together by land use type. The order of the + ! groups within the site doesn't matter, except that the older patch group are primarylands. + + if (currentPatch%land_use_label .eq. new_patch%land_use_label ) then + found_youngest_landuselabel = .false. + do while(associated(currentPatch) .and. .not. found_youngest_landuselabel) + currentPatch => currentPatch%older + if (associated(currentPatch)) then + if (currentPatch%land_use_label .eq. new_patch%land_use_label) then + found_youngest_landuselabel = .true. + endif + endif + end do + if (associated(currentPatch)) then + ! the case where we've found a youngest patch type matching the new patch type + new_patch%older => currentPatch + new_patch%younger => currentPatch%younger + currentPatch%younger%older => new_patch + currentPatch%younger => new_patch + else + ! the case where we haven't, because the patches are all non-primaryland, + ! and are putting a primaryland patch at the oldest end of the + ! linked list (not sure how this could happen, but who knows...) + new_patch%older => null() + new_patch%younger => currentSite%oldest_patch + currentSite%oldest_patch%older => new_patch + currentSite%oldest_patch => new_patch + endif + else + ! the case where the youngest patch on the site matches the new patch type + new_patch%older => currentPatch + new_patch%younger => null() + currentPatch%younger => new_patch + currentSite%youngest_patch => new_patch + endif + + end subroutine insert_patch_into_sitelist ! ============================================================================ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) @@ -1372,6 +1401,14 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) type(ed_patch_type) , intent(inout), target :: currentPatch ! Donor Patch type(ed_patch_type) , intent(inout), target :: new_patch ! New Patch real(r8), intent(in) :: fraction_to_keep ! fraction of currentPatch to keep, the rest goes to newpatch + ! + ! !LOCAL VARIABLES: + integer :: el ! element loop index + type (ed_cohort_type), pointer :: nc + type (ed_cohort_type), pointer :: storesmallcohort + type (ed_cohort_type), pointer :: storebigcohort + integer :: tnull ! is there a tallest cohort? + integer :: snull ! is there a shortest cohort? ! first we need to make the new patch call create_patch(currentSite, new_patch, 0._r8, & From b4159dc214dccb08a3a5efe5d9deb0c92009be2c Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Tue, 8 Aug 2023 18:03:34 -0700 Subject: [PATCH 006/300] some compile-time bugfixes --- biogeochem/EDPatchDynamicsMod.F90 | 18 +++++++++++++----- main/EDInitMod.F90 | 19 ++++++++++--------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index af2b7e8799..1368468fae 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -473,6 +473,12 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: oldarea ! old patch area prior to disturbance logical :: clearing_matrix(n_landuse_cats,n_landuse_cats) ! do we clear vegetation when transferring from one LU type to another? type (ed_patch_type) , pointer :: buffer_patch, temp_patch + real(r8) :: nocomp_pft_area_vector(numpft) + real(r8) :: nocomp_pft_area_vector_allocated(numpft) + real(r8) :: fraction_to_keep + integer :: i_land_use_label + integer :: i_pft + real(r8) :: newp_area !--------------------------------------------------------------------- @@ -1220,7 +1226,7 @@ subroutine spawn_patches( currentSite, bc_in) end do nocomp_pft_loop - nocomp_and_luh_if: if ( use_fates_nocomp .eq. itrue .and. use_fates_luh .eq. itrue ) then + nocomp_and_luh_if: if ( hlm_use_nocomp .eq. itrue .and. hlm_use_luh .eq. itrue ) then ! disturbance has just hapopened, and now the nocomp PFT identities of the newly-disturbed patches ! need to be remapped to those associated with the new land use type. @@ -1283,7 +1289,7 @@ subroutine spawn_patches( currentSite, bc_in) end do ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list - nocomp_pft_loop: do i_pft = 1, numpft + nocomp_pft_loop_2: do i_pft = 1, numpft if (nocomp_pft_area_vector_allocated(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * area) then @@ -1313,7 +1319,7 @@ subroutine spawn_patches( currentSite, bc_in) end if - end do nocomp_pft_loop + end do nocomp_pft_loop_2 end do lu_loop @@ -1340,7 +1346,7 @@ subroutine insert_patch_into_sitelist(currentSite, new_patch) ! !USES: ! ! !ARGUMENTS: - type(ed_site_type),intent(in) :: currentSite + type(ed_site_type),intent(inout) :: currentSite type(ed_patch_type) , intent(inout), target :: new_patch ! New Patch ! ! !LOCAL VARIABLES: @@ -1397,7 +1403,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) ! !USES: ! ! !ARGUMENTS: - type(ed_site_type),intent(in) :: currentSite + type(ed_site_type),intent(inout) :: currentSite type(ed_patch_type) , intent(inout), target :: currentPatch ! Donor Patch type(ed_patch_type) , intent(inout), target :: new_patch ! New Patch real(r8), intent(in) :: fraction_to_keep ! fraction of currentPatch to keep, the rest goes to newpatch @@ -1407,9 +1413,11 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) type (ed_cohort_type), pointer :: nc type (ed_cohort_type), pointer :: storesmallcohort type (ed_cohort_type), pointer :: storebigcohort + type (ed_cohort_type), pointer :: currentCohort integer :: tnull ! is there a tallest cohort? integer :: snull ! is there a shortest cohort? + ! first we need to make the new patch call create_patch(currentSite, new_patch, 0._r8, & currentPatch%area * (1._r8 - fraction_to_keep), currentPatch%land_use_label, currentPatch%nocomp_pft_label) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 5e0d1c5939..ee9ca85017 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -83,6 +83,7 @@ module EDInitMod use FatesSizeAgeTypeIndicesMod,only : get_age_class_index use DamageMainMod, only : undamaged_class use FatesInterfaceTypesMod , only : hlm_num_luh2_transitions + use FatesConstantsMod, only : nocomp_bareground_land, nocomp_bareground ! CIME GLOBALS use shr_log_mod , only : errMsg => shr_log_errMsg @@ -408,7 +409,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) if(hlm_use_fixed_biogeog.eq.itrue)then - use_fates_luh_if: if (use_fates_luh .eq. itrue.) then + use_fates_luh_if: if (hlm_use_luh .eq. itrue) then ! MAPPING OF FATES PFTs on to HLM_PFTs with land use ! add up the area associated with each FATES PFT ! where pft_areafrac_lu is the area of land in each HLM PFT and land use type (from surface dataset) @@ -417,14 +418,14 @@ subroutine set_site_properties( nsites, sites,bc_in ) do hlm_pft = 1,fates_hlm_num_natpfts do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts sites(s)%area_pft(fates_pft,i_landusetype) = sites(s)%area_pft(fates_pft,i_landusetype) + & - EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac_luh(hlm_pft,i_landusetype) + EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac_lu(hlm_pft,i_landusetype) end do end do !hlm_pft end do sites(s)%area_bareground = bc_in(s)%baregroundfrac * area - else use_fates_luh_if + else ! MAPPING OF FATES PFTs on to HLM_PFTs ! add up the area associated with each FATES PFT ! where pft_areafrac is the area of land in each HLM PFT and (from surface dataset) @@ -432,7 +433,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) do hlm_pft = 1,size( EDPftvarcon_inst%hlm_pft_map,2) do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts - sites(s)%area_pft(fates_pft,primarylands) = sites(s)%area_pft(fates_pft,primarylands) + & + sites(s)%area_pft(fates_pft,primaryland) = sites(s)%area_pft(fates_pft,primaryland) + & EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac(hlm_pft) end do sites(s)%area_bareground = bc_in(s)%pft_areafrac(0) @@ -464,7 +465,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%area_pft(ft, i_landusetype) = sites(s)%area_pft(ft, i_landusetype)/sumarea else ! if no PFT area in primary lands, set bare ground fraction to one. - if ( i_landusetype .eq. primarylands) then + if ( i_landusetype .eq. primaryland) then sites(s)%area_bareground = 1._r8 endif end if @@ -476,7 +477,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) do ft = 1,numpft ! Setting this to true ensures that all pfts ! are used for nocomp with no biogeog - sites(s)%use_this_pft(ft) = itrues + sites(s)%use_this_pft(ft) = itrue if(hlm_use_fixed_biogeog.eq.itrue)then if(any(sites(s)%area_pft(ft,:).gt.0.0_r8))then sites(s)%use_this_pft(ft) = itrue @@ -532,7 +533,7 @@ subroutine init_patches( nsites, sites, bc_in) real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] integer :: i_lu, i_lu_state integer :: n_active_landuse_cats - + integer :: end_landuse_idx type(ed_site_type), pointer :: sitep type(ed_patch_type), pointer :: newppft(:) @@ -637,7 +638,7 @@ subroutine init_patches( nsites, sites, bc_in) end do endif make_bareground_patch_if - if (use_fates_luh2 .eq. itrue) then + if (hlm_use_luh .eq. itrue) then end_landuse_idx = n_landuse_cats else end_landuse_idx = 1 @@ -664,7 +665,7 @@ subroutine init_patches( nsites, sites, bc_in) if(hlm_use_fixed_biogeog.eq.itrue)then newparea = sites(s)%area_pft(nocomp_pft,i_lu_state) * area / state_vector(i_lu_state) else - newparea = area / ( numpft * vector(i_lu_state)) + newparea = area / ( numpft * state_vector(i_lu_state)) end if else ! The default case is initialized w/ one patch with the area of the whole site. newparea = area / state_vector(i_lu_state) From 148eaf47ba6db1bb56c96f527ab779465fdddb80 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Tue, 8 Aug 2023 19:51:56 -0700 Subject: [PATCH 007/300] more compile-time bugfixes --- biogeochem/EDPatchDynamicsMod.F90 | 1 + main/EDInitMod.F90 | 2 +- main/FatesRestartInterfaceMod.F90 | 29 ++++++++++++++++------------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 1368468fae..0b19c8ea23 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1401,6 +1401,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) ! Split a patch into two patches that are identical except in their areas ! ! !USES: + use EDCohortDynamicsMod , only : zero_cohort, copy_cohort ! ! !ARGUMENTS: type(ed_site_type),intent(inout) :: currentSite diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index ee9ca85017..98ae998b4a 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -55,7 +55,7 @@ module EDInitMod use FatesInterfaceTypesMod , only : nlevdamage use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : nlevage - + use FatesInterfaceTypesMod , only : fates_hlm_num_natpfts use FatesAllometryMod , only : h2d_allom use FatesAllometryMod , only : bagw_allom use FatesAllometryMod , only : bbgw_allom diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index aaf4d51729..85c7a2c262 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -10,6 +10,7 @@ module FatesRestartInterfaceMod use FatesConstantsMod, only : fates_unset_r8, fates_unset_int use FatesConstantsMod, only : primaryland use FatesConstantsMod, only : nearzero + use FatesConstantsMod, only : n_landuse_cats use FatesGlobals, only : fates_log use FatesGlobals, only : endrun => fates_endrun use FatesIODimensionsMod, only : fates_io_dimension_type @@ -1886,7 +1887,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) integer :: i_cdam ! loop counter for damage integer :: icdi ! loop counter for damage integer :: icdj ! loop counter for damage - + integer :: i_landuse,i_pflu ! loop counter for land use class + type(fates_restart_variable_type) :: rvar type(ed_patch_type),pointer :: cpatch type(ed_cohort_type),pointer :: ccohort @@ -2042,9 +2044,13 @@ subroutine set_restart_vectors(this,nc,nsites,sites) end do do i_pft = 1,numpft - rio_area_pft_sift(io_idx_co_1st+i_pft-1) = sites(s)%area_pft(i_pft) + do i_landuse = 1, n_landuse_cats + i_pflu = i_landuse + (i_pft - 1) * n_landuse_cats + rio_area_pft_sift(io_idx_co_1st+i_pflu-1) = sites(s)%area_pft(i_pft, i_landuse) + end do end do + !! need to restart area_bareground if(hlm_use_sp.eq.ifalse)then do el = 1, num_elements @@ -2792,7 +2798,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) integer :: i_cacls ! loop counter for cohort age class integer :: i_cdam ! loop counter for damage class integer :: icdj ! loop counter for damage class - integer :: icdi ! loop counter for damage class + integer :: icdi ! loop counter for damage class + integer :: i_landuse,i_pflu ! loop counter for land use class associate( rio_npatch_si => this%rvars(ir_npatch_si)%int1d, & rio_cd_status_si => this%rvars(ir_cd_status_si)%int1d, & @@ -2932,18 +2939,14 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! variables for fixed biogeography mode. These are currently used in restart even when this is off. do i_pft = 1,numpft sites(s)%use_this_pft(i_pft) = rio_use_this_pft_sift(io_idx_co_1st+i_pft-1) - sites(s)%area_pft(i_pft) = rio_area_pft_sift(io_idx_co_1st+i_pft-1) + do i_landuse = 1, n_landuse_cats + i_pflu = i_landuse + (i_pft - 1) * n_landuse_cats + sites(s)%area_pft(i_pft, i_landuse) = rio_area_pft_sift(io_idx_co_1st+i_pflu-1) + end do enddo - ! calculate the bareground area for the pft in no competition + fixed biogeo modes - if (hlm_use_nocomp .eq. itrue .and. hlm_use_fixed_biogeog .eq. itrue) then - if (area-sum(sites(s)%area_pft(1:numpft)) .gt. nearzero) then - sites(s)%area_pft(0) = area - sum(sites(s)%area_pft(1:numpft)) - else - sites(s)%area_pft(0) = 0.0_r8 - endif - endif - + !! need to restart area_bareground + ! Mass balance and diagnostics across elements at the site level if(hlm_use_sp.eq.ifalse)then do el = 1, num_elements From c594f807872769ae0b94a6033830786b316c9848 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Wed, 9 Aug 2023 10:56:02 -0700 Subject: [PATCH 008/300] adding logic to clean up temporary patches --- biogeochem/EDPatchDynamicsMod.F90 | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 0b19c8ea23..34debf93e8 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -479,6 +479,7 @@ subroutine spawn_patches( currentSite, bc_in) integer :: i_land_use_label integer :: i_pft real(r8) :: newp_area + logical :: buffer_patch_in_linked_list !--------------------------------------------------------------------- @@ -1249,7 +1250,10 @@ subroutine spawn_patches( currentSite, bc_in) ! create buffer patch to put all of the pieces carved off of other patches call create_patch(currentSite, buffer_patch, 0._r8, & - 0._r8, i_land_use_label, 0) + 0._r8, i_land_use_label, 0) + + ! make a note that this buffer patch has not been put into the linked list + buffer_patch_in_linked_list = .false. ! Initialize the litter pools to zero do el=1,num_elements @@ -1306,7 +1310,9 @@ subroutine spawn_patches( currentSite, bc_in) ! put the new patch into the linked list call insert_patch_into_sitelist(currentSite, temp_patch) - ! CDK QUESTION: HOW DO WE ERASE OUT THE TEMP_PATCH INFO SO THAT IT CAN HOLD A NEW PATCH WHEN IT GOES BACK THROUGH THE LOOP? + ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be + ! refilled the next time through the loop. + temp_patch => null() else ! give the buffer patch the intended nocomp PFT label @@ -1314,6 +1320,8 @@ subroutine spawn_patches( currentSite, bc_in) ! put the buffer patch directly into the linked list call insert_patch_into_sitelist(currentSite, buffer_patch) + + buffer_patch_in_linked_list = .true. end if @@ -1321,6 +1329,24 @@ subroutine spawn_patches( currentSite, bc_in) end do nocomp_pft_loop_2 + ! now we want to make sure that either the buffer_patch either has zero area (presumably it was never used), in which case it should be deallocated, + ! or else it does have area but it has been put into the site linked list, and so buffer patch should be nulled before next pass through outer loop. + ! if either of those, that means everything worked properly, if not, then something has gone wrong. + if (buffer_patch_in_linked_list) then + buffer_patch => null() + else if (buffer_patch%area .lt. fates_tiny) then + ! here we need to deallocate the buffer patch so that we don't get a memory leak/ + call dealloc_patch(buffer_patch) + deallocate(buffer_patch, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + else + write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' + write(fates_log(),*) 'buffer_patch%area', buffer_patch%area + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if end do lu_loop endif nocomp_and_luh_if From e842bddf25a4874818d70182760de06d01f8ac23 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 9 Aug 2023 17:05:03 -0700 Subject: [PATCH 009/300] adding logic to handle crop PFTs on crop land use types --- main/EDInitMod.F90 | 17 +++++++++++------ main/FatesConstantsMod.F90 | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 98ae998b4a..f62956b50b 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -415,12 +415,17 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! where pft_areafrac_lu is the area of land in each HLM PFT and land use type (from surface dataset) ! hlm_pft_map is the area of that land in each FATES PFT (from param file) do i_landusetype = 1, n_landuse_cats - do hlm_pft = 1,fates_hlm_num_natpfts - do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts - sites(s)%area_pft(fates_pft,i_landusetype) = sites(s)%area_pft(fates_pft,i_landusetype) + & - EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac_lu(hlm_pft,i_landusetype) - end do - end do !hlm_pft + if (.not. is_crop(i_landusetype)) then + do hlm_pft = 1,fates_hlm_num_natpfts + do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts + sites(s)%area_pft(fates_pft,i_landusetype) = sites(s)%area_pft(fates_pft,i_landusetype) + & + EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac_lu(hlm_pft,i_landusetype) + end do + end do !hlm_pft + else + ! for crops, we need to use different logic because the bc_in(s)%pft_areafrac_lu() information only exists for natural PFTs + sites(s)%area_pft(EDPftvarcon_inst%crop_lu_pft_vector(i_landusetype),i_landusetype) = 1._r8 + endif end do sites(s)%area_bareground = bc_in(s)%baregroundfrac * area diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 35b2ee42b2..44fb45eb0f 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -30,13 +30,14 @@ module FatesConstantsMod ! Integer equivalent of false (in case come compilers dont auto convert) integer, parameter, public :: ifalse = 0 - ! Labels for patch disturbance history + ! Labels for patch land use type information integer, parameter, public :: n_landuse_cats = 5 integer, parameter, public :: primaryland = 1 integer, parameter, public :: secondaryland = 2 integer, parameter, public :: rangeland = 3 integer, parameter, public :: pastureland = 4 integer, parameter, public :: cropland = 5 + logical, parameter, dimension(n_landuse_cats), public :: is_crop = [.false.,.false.,.false.,.false.,.true.] ! Bareground nocomp land use label integer, parameter, public :: nocomp_bareground_land = 0 ! not a real land use type, only for labeling any bare-ground nocomp patches From 74fefd3628a034bd24eaab9772453b04fab89e90 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 10 Aug 2023 16:15:56 -0700 Subject: [PATCH 010/300] adding logic for crops at recruitmetn step --- biogeochem/EDPhysiologyMod.F90 | 23 ++++++++++++++++++++--- main/FatesConstantsMod.F90 | 2 +- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5c63524ef0..a129e8f771 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -24,6 +24,7 @@ module EDPhysiologyMod use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : nocomp_bareground + use FatesConstantsMod, only : is_crop use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params use EDPftvarcon , only : GetDecompyFrac @@ -120,7 +121,8 @@ module EDPhysiologyMod use FatesParameterDerivedMod, only : param_derived use FatesPlantHydraulicsMod, only : InitHydrCohort use PRTInitParamsFatesMod, only : NewRecruitTotalStoichiometry - + use FatesInterfaceTypesMod , only : hlm_use_luh + implicit none private @@ -2022,6 +2024,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) real(r8) :: mass_demand ! Total mass demanded by the plant to achieve the stoichiometric targets ! of all the organs in the recruits. Used for both [kg per plant] and [kg per cohort] real(r8) :: stem_drop_fraction + logical :: use_this_pft !---------------------------------------------------------------------- @@ -2031,13 +2034,27 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) do ft = 1,numpft - ! The following if block is for the prescribed biogeography and/or nocomp modes. + ! The following if block is for the prescribed biogeography and/or nocomp modes and/or crop land use types ! Since currentSite%use_this_pft is a site-level quantity and thus only limits whether a given PFT ! is permitted on a given gridcell or not, it applies to the prescribed biogeography case only. ! If nocomp is enabled, then we must determine whether a given PFT is allowed on a given patch or not. + ! Whether or not nocomp or prescribed biogeography is enabled, if land use change is enabled, then we only want to + ! allow crop PFTs on patches with crop land use types + use_this_pft = .false. if(currentSite%use_this_pft(ft).eq.itrue & .and. ((hlm_use_nocomp .eq. ifalse) .or. (ft .eq. currentPatch%nocomp_pft_label)))then + use_this_pft = .true. + end if + + if ((hlm_use_luh .eq. itrue) .and. (is_crop(currentPatch%land_use_label))) then + if ( EDPftvarcon_inst%crop_lu_pft_vector(currentPatch%land_use_label) .eq. ft ) then + use_this_pft = .true. + else + use_this_pft = .false. + end if + + use_this_pft_if: if(use_this_pft) then temp_cohort%canopy_trim = init_recruit_trim temp_cohort%pft = ft @@ -2284,7 +2301,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) endif any_recruits - endif !use_this_pft + endif use_this_pft_if enddo !pft loop deallocate(temp_cohort, stat=istat, errmsg=smsg) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 44fb45eb0f..a4934321c6 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -37,7 +37,7 @@ module FatesConstantsMod integer, parameter, public :: rangeland = 3 integer, parameter, public :: pastureland = 4 integer, parameter, public :: cropland = 5 - logical, parameter, dimension(n_landuse_cats), public :: is_crop = [.false.,.false.,.false.,.false.,.true.] + logical, parameter, dimension(0:n_landuse_cats), public :: is_crop = [.false., .false.,.false.,.false.,.false.,.true.] ! Bareground nocomp land use label integer, parameter, public :: nocomp_bareground_land = 0 ! not a real land use type, only for labeling any bare-ground nocomp patches From 66a5b2dbd33cbb06a68b14e117c319b924b446bc Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 10 Aug 2023 16:24:51 -0700 Subject: [PATCH 011/300] pasted code from grazing branch for adding land use dimension to paramter file --- main/FatesParametersInterface.F90 | 1 + parameter_files/fates_params_default.cdl | 11 +++++++++++ tools/modify_fates_paramfile.py | 2 +- tools/ncvarsort.py | 7 +++++-- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index aa13150c4a..3bb0f9a30b 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -38,6 +38,7 @@ module FatesParametersInterface character(len=*), parameter, public :: dimension_name_hlm_pftno = 'fates_hlm_pftno' character(len=*), parameter, public :: dimension_name_history_damage_bins = 'fates_history_damage_bins' character(len=*), parameter, public :: dimension_name_damage = 'fates_damage_class' + character(len=*), parameter, public :: dimension_name_landuse = 'fates_landuseclass' ! Dimensions in the host namespace: character(len=*), parameter, public :: dimension_name_host_allpfts = 'allpfts' diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 408ca1e9ab..0a89e8edd6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -8,6 +8,7 @@ dimensions: fates_history_size_bins = 13 ; fates_hlm_pftno = 14 ; fates_hydr_organs = 4 ; + fates_landuseclass = 5 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; @@ -47,6 +48,9 @@ variables: char fates_litterclass_name(fates_litterclass, fates_string_length) ; fates_litterclass_name:units = "unitless - string" ; fates_litterclass_name:long_name = "Name of the litter classes, for variables associated with dimension fates_litterclass" ; + char fates_landuseclass_name(fates_landuseclass, fates_string_length) ; + fates_landuseclass_name:units = "unitless - string" ; + fates_landuseclass_name:long_name = "Name of the land use classes, for variables associated with dimension fates_landuseclass" ; double fates_alloc_organ_priority(fates_plant_organs, fates_pft) ; fates_alloc_organ_priority:units = "index" ; fates_alloc_organ_priority:long_name = "Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance" ; @@ -860,6 +864,13 @@ data: "dead leaves ", "live grass " ; + fates_landuseclass_name = + "primaryland ", + "secondaryland ", + "rangeland ", + "pastureland ", + "cropland " ; + fates_alloc_organ_priority = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, diff --git a/tools/modify_fates_paramfile.py b/tools/modify_fates_paramfile.py index adacb2457b..85f7c449ea 100755 --- a/tools/modify_fates_paramfile.py +++ b/tools/modify_fates_paramfile.py @@ -141,7 +141,7 @@ def main(): 'fates_history_damage_bins', 'fates_NCWD','fates_litterclass','fates_leafage_class', \ 'fates_plant_organs','fates_hydr_organs','fates_hlm_pftno', \ - 'fates_leafage_class']: + 'fates_leafage_class','fates_landuse_class']: otherdimpresent = True otherdimname = var.dimensions[i] otherdimlength = var.shape[i] diff --git a/tools/ncvarsort.py b/tools/ncvarsort.py index 327dd84a96..6583700ae3 100755 --- a/tools/ncvarsort.py +++ b/tools/ncvarsort.py @@ -30,7 +30,7 @@ def main(): # make empty lists to hold the variable names in. the first of these is a list of sub-lists, # one for each type of variable (based on dimensionality). # the second is the master list that will contain all variables. - varnames_list = [[],[],[],[],[],[],[],[],[],[],[],[],[]] + varnames_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[]] varnames_list_sorted = [] # # sort the variables by dimensionality, but mix the PFT x other dimension in with the regular PFT-indexed variables @@ -48,6 +48,7 @@ def main(): (u'fates_prt_organs', u'fates_string_length'):7, (u'fates_plant_organs', u'fates_string_length'):7, (u'fates_litterclass', u'fates_string_length'):7, + (u'fates_landuseclass', u'fates_string_length'):7, (u'fates_pft',):8, (u'fates_hydr_organs', u'fates_pft'):8, (u'fates_leafage_class', u'fates_pft'):8, @@ -56,7 +57,9 @@ def main(): (u'fates_hlm_pftno', u'fates_pft'):9, (u'fates_litterclass',):10, (u'fates_NCWD',):11, - ():12} + (u'fates_landuseclass',):12, + (u'fates_landuseclass', u'fates_pft'):12, + ():13} # # go through each of the variables and assign it to one of the sub-lists based on its dimensionality for v_name, varin in dsin.variables.items(): From 6c43b6175bbf6d39fe25ed396d2321fc82ba7ba5 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 10 Aug 2023 17:32:40 -0700 Subject: [PATCH 012/300] passing crop landuse/PFT info through parameter interface --- biogeochem/EDPhysiologyMod.F90 | 5 +++-- main/EDInitMod.F90 | 4 +++- main/EDParamsMod.F90 | 11 ++++++++++- parameter_files/fates_params_default.cdl | 5 +++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index a129e8f771..05e0df320a 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1984,7 +1984,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! !USES: use FatesInterfaceTypesMod, only : hlm_use_ed_prescribed_phys use FatesLitterMod , only : ncwd - + use EDParamsMod , only : crop_lu_pft_vector ! ! !ARGUMENTS type(ed_site_type), intent(inout) :: currentSite @@ -2048,10 +2048,11 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) end if if ((hlm_use_luh .eq. itrue) .and. (is_crop(currentPatch%land_use_label))) then - if ( EDPftvarcon_inst%crop_lu_pft_vector(currentPatch%land_use_label) .eq. ft ) then + if ( crop_lu_pft_vector(currentPatch%land_use_label) .eq. ft ) then use_this_pft = .true. else use_this_pft = .false. + end if end if use_this_pft_if: if(use_this_pft) then diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index f62956b50b..1651c727c2 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -11,6 +11,7 @@ module EDInitMod use FatesConstantsMod , only : primaryland use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : n_landuse_cats + use FatesConstantsMod , only : is_crop use FatesGlobals , only : endrun => fates_endrun use EDTypesMod , only : nclmax use FatesGlobals , only : fates_log @@ -332,6 +333,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! !DESCRIPTION: ! ! !USES: + use EDParamsMod, only : crop_lu_pft_vector ! ! !ARGUMENTS @@ -424,7 +426,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) end do !hlm_pft else ! for crops, we need to use different logic because the bc_in(s)%pft_areafrac_lu() information only exists for natural PFTs - sites(s)%area_pft(EDPftvarcon_inst%crop_lu_pft_vector(i_landusetype),i_landusetype) = 1._r8 + sites(s)%area_pft(crop_lu_pft_vector(i_landusetype),i_landusetype) = 1._r8 endif end do diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 9a54a45db5..57ddc9a20e 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -86,6 +86,7 @@ module EDParamsMod real(r8),protected,allocatable,public :: ED_val_history_height_bin_edges(:) real(r8),protected,allocatable,public :: ED_val_history_coageclass_bin_edges(:) real(r8),protected,allocatable,public :: ED_val_history_damage_bin_edges(:) + real(r8),protected,allocatable,public :: crop_lu_pft_vector(:) ! Switch that defines the current pressure-volume and pressure-conductivity model ! to be used at each node (compartment/organ) @@ -133,6 +134,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_history_height_bin_edges= "fates_history_height_bin_edges" character(len=param_string_length),parameter,public :: ED_name_history_coageclass_bin_edges = "fates_history_coageclass_bin_edges" character(len=param_string_length),parameter,public :: ED_name_history_damage_bin_edges = "fates_history_damage_bin_edges" + character(len=param_string_length),parameter,public :: ED_name_crop_lu_pft_vector = "fates_landuse_crop_lu_pft_vector" ! Hydraulics Control Parameters (ONLY RELEVANT WHEN USE_FATES_HYDR = TRUE) ! ---------------------------------------------------------------------------------------------- @@ -341,7 +343,7 @@ subroutine FatesRegisterParams(fates_params) use FatesParametersInterface, only : dimension_name_history_size_bins, dimension_name_history_age_bins use FatesParametersInterface, only : dimension_name_history_height_bins, dimension_name_hydr_organs use FatesParametersInterface, only : dimension_name_history_coage_bins, dimension_name_history_damage_bins - use FatesParametersInterface, only : dimension_shape_scalar + use FatesParametersInterface, only : dimension_shape_scalar, dimension_name_landuse implicit none @@ -355,6 +357,7 @@ subroutine FatesRegisterParams(fates_params) character(len=param_string_length), parameter :: dim_names_coageclass(1) = (/dimension_name_history_coage_bins/) character(len=param_string_length), parameter :: dim_names_hydro_organs(1) = (/dimension_name_hydr_organs/) character(len=param_string_length), parameter :: dim_names_damageclass(1)= (/dimension_name_history_damage_bins/) + character(len=param_string_length), parameter :: dim_names_landuse(1)= (/dimension_name_landuse/) call FatesParamsInit() @@ -558,6 +561,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_history_damage_bin_edges, dimension_shape=dimension_shape_1d, & dimension_names=dim_names_damageclass) + call fates_params%RegisterParameter(name=ED_name_crop_lu_pft_vector, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names_landuse) + end subroutine FatesRegisterParams @@ -787,6 +793,9 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetrieveParameterAllocate(name=ED_name_history_damage_bin_edges, & data=ED_val_history_damage_bin_edges) + call fates_params%RetrieveParameterAllocate(name=ED_name_crop_lu_pft_vector, & + data=crop_lu_pft_vector) + call fates_params%RetrieveParameterAllocate(name=ED_name_hydr_htftype_node, & data=hydr_htftype_real) allocate(hydr_htftype_node(size(hydr_htftype_real))) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 0a89e8edd6..30ad56fe84 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -591,6 +591,9 @@ variables: double fates_frag_cwd_frac(fates_NCWD) ; fates_frag_cwd_frac:units = "fraction" ; fates_frag_cwd_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_landuse_crop_lu_pft_vector(fates_landuseclass) ; + fates_landuse_crop_lu_pft_vector:units = "NA" ; + fates_landuse_crop_lu_pft_vector:long_name = "What FATES PFT index to use on a given crop land-use type? (dummy value of -999 for non-crop types)" ; double fates_canopy_closure_thresh ; fates_canopy_closure_thresh:units = "unitless" ; fates_canopy_closure_thresh:long_name = "tree canopy coverage at which crown area allometry changes from savanna to forest value" ; @@ -1437,6 +1440,8 @@ data: fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + fates_landuse_crop_lu_pft_vector = -999, -999, -999, -999, 11 ; + fates_canopy_closure_thresh = 0.8 ; fates_cnp_eca_plant_escalar = 1.25e-05 ; From 6b462cc4611bbfddc93e76a43906c91e3e40c398 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Tue, 5 Sep 2023 21:45:04 -0700 Subject: [PATCH 013/300] added logic to handle transitioning from a restart with no-land-use to land-use --- biogeochem/EDLoggingMortalityMod.F90 | 177 +++++++++++++------------ biogeochem/EDMortalityFunctionsMod.F90 | 2 +- biogeochem/EDPatchDynamicsMod.F90 | 38 ++++-- biogeochem/FatesLandUseChangeMod.F90 | 45 +++++++ main/EDInitMod.F90 | 2 + main/EDMainMod.F90 | 5 + main/EDTypesMod.F90 | 2 + main/FatesRestartInterfaceMod.F90 | 18 +++ 8 files changed, 193 insertions(+), 96 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index bf6ab7443c..9c843cbf71 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -195,7 +195,7 @@ end subroutine IsItLoggingTime ! ====================================================================================== - subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & + subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, lmort_direct, & lmort_collateral,lmort_infra, l_degrad, & hlm_harvest_rates, hlm_harvest_catnames, & hlm_harvest_units, & @@ -203,7 +203,8 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & frac_site_primary, harvestable_forest_c, & harvest_tag) - ! Arguments + ! Arguments + type(ed_site_type), intent(in), target :: currentSite ! site structure integer, intent(in) :: pft_i ! pft index real(r8), intent(in) :: dbh ! diameter at breast height (cm) integer, intent(in) :: canopy_layer ! canopy layer of this cohort @@ -239,109 +240,117 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! todo: check outputs against the LUH2 carbon data ! todo: eventually set up distinct harvest practices, each with a set of input paramaeters ! todo: implement harvested carbon inputs - - if (logging_time) then - ! Pass logging rates to cohort level - - if (hlm_use_lu_harvest == ifalse) then - ! 0=use fates logging parameters directly when logging_time == .true. - ! this means harvest the whole cohort area - harvest_rate = 1._r8 - - else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_area_fraction) then - ! We are harvesting based on areal fraction, not carbon/biomass terms. - ! 1=use area fraction from hlm - ! combine forest and non-forest fracs and then apply: - ! primary and secondary area fractions to the logging rates, which are fates parameters - - ! Definitions of the underlying harvest land category variables - ! these are hardcoded to match the LUH input data via landuse.timseries file (see dynHarvestMod) - ! these are fractions of vegetated area harvested, split into five land category variables - ! HARVEST_VH1 = harvest from primary forest - ! HARVEST_VH2 = harvest from primary non-forest - ! HARVEST_SH1 = harvest from secondary mature forest - ! HARVEST_SH2 = harvest from secondary young forest - ! HARVEST_SH3 = harvest from secondary non-forest (assume this is young for biomass) - - ! Get the area-based harvest rates based on info passed to FATES from the boundary condition - call get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, & - hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) - - ! For area-based harvest, harvest_tag shall always be 2 (not applicable). - harvest_tag = 2 - cur_harvest_tag = 2 - - if (fates_global_verbose()) then - write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate - end if + if (.not. currentSite%transition_landuse_from_off_to_on) then + if (logging_time) then + + ! Pass logging rates to cohort level + + if (hlm_use_lu_harvest == ifalse) then + ! 0=use fates logging parameters directly when logging_time == .true. + ! this means harvest the whole cohort area + harvest_rate = 1._r8 + + else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_area_fraction) then + ! We are harvesting based on areal fraction, not carbon/biomass terms. + ! 1=use area fraction from hlm + ! combine forest and non-forest fracs and then apply: + ! primary and secondary area fractions to the logging rates, which are fates parameters + + ! Definitions of the underlying harvest land category variables + ! these are hardcoded to match the LUH input data via landuse.timseries file (see dynHarvestMod) + ! these are fractions of vegetated area harvested, split into five land category variables + ! HARVEST_VH1 = harvest from primary forest + ! HARVEST_VH2 = harvest from primary non-forest + ! HARVEST_SH1 = harvest from secondary mature forest + ! HARVEST_SH2 = harvest from secondary young forest + ! HARVEST_SH3 = harvest from secondary non-forest (assume this is young for biomass) + + ! Get the area-based harvest rates based on info passed to FATES from the boundary condition + call get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, & + hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) + + ! For area-based harvest, harvest_tag shall always be 2 (not applicable). + harvest_tag = 2 + cur_harvest_tag = 2 + + if (fates_global_verbose()) then + write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate + end if - else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_carbon) then - ! 2=use carbon from hlm - ! shall call another subroutine, which transfers biomass/carbon into fraction + else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_carbon) then + ! 2=use carbon from hlm + ! shall call another subroutine, which transfers biomass/carbon into fraction - call get_harvest_rate_carbon (patch_land_use_label, hlm_harvest_catnames, & - hlm_harvest_rates, secondary_age, harvestable_forest_c, & - harvest_rate, harvest_tag, cur_harvest_tag) + call get_harvest_rate_carbon (patch_land_use_label, hlm_harvest_catnames, & + hlm_harvest_rates, secondary_age, harvestable_forest_c, & + harvest_rate, harvest_tag, cur_harvest_tag) - if (fates_global_verbose()) then - write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate, harvestable_forest_c - end if - - endif - - ! transfer of area to secondary land is based on overall area affected, not just logged crown area - ! l_degrad accounts for the affected area between logged crowns - if(prt_params%woody(pft_i) == itrue)then ! only set logging rates for trees - if (cur_harvest_tag == 0) then - ! direct logging rates, based on dbh min and max criteria - if (dbh >= logging_dbhmin .and. .not. & - ((logging_dbhmax < fates_check_param_set) .and. (dbh >= logging_dbhmax )) ) then - ! the logic of the above line is a bit unintuitive but allows turning off the dbhmax comparison entirely. - ! since there is an .and. .not. after the first conditional, the dbh:dbhmax comparison needs to be - ! the opposite of what would otherwise be expected... - lmort_direct = harvest_rate * logging_direct_frac + if (fates_global_verbose()) then + write(fates_log(), *) 'Successfully Read Harvest Rate from HLM.', hlm_harvest_rates(:), harvest_rate, harvestable_forest_c + end if + + endif + + ! transfer of area to secondary land is based on overall area affected, not just logged crown area + ! l_degrad accounts for the affected area between logged crowns + if(prt_params%woody(pft_i) == itrue)then ! only set logging rates for trees + if (cur_harvest_tag == 0) then + ! direct logging rates, based on dbh min and max criteria + if (dbh >= logging_dbhmin .and. .not. & + ((logging_dbhmax < fates_check_param_set) .and. (dbh >= logging_dbhmax )) ) then + ! the logic of the above line is a bit unintuitive but allows turning off the dbhmax comparison entirely. + ! since there is an .and. .not. after the first conditional, the dbh:dbhmax comparison needs to be + ! the opposite of what would otherwise be expected... + lmort_direct = harvest_rate * logging_direct_frac + else + lmort_direct = 0.0_r8 + end if else lmort_direct = 0.0_r8 end if - else - lmort_direct = 0.0_r8 - end if - ! infrastructure (roads, skid trails, etc) mortality rates - if (dbh >= logging_dbhmax_infra) then - lmort_infra = 0.0_r8 - else + ! infrastructure (roads, skid trails, etc) mortality rates + if (dbh >= logging_dbhmax_infra) then + lmort_infra = 0.0_r8 + else + lmort_infra = harvest_rate * logging_mechanical_frac + end if + + ! Collateral damage to smaller plants below the direct logging size threshold + ! will be applied via "understory_death" via the disturbance algorithm + if (canopy_layer .eq. 1) then + lmort_collateral = harvest_rate * logging_collateral_frac + else + lmort_collateral = 0._r8 + endif + + else ! non-woody plants still killed by infrastructure + lmort_direct = 0.0_r8 + lmort_collateral = 0.0_r8 lmort_infra = harvest_rate * logging_mechanical_frac end if - ! Collateral damage to smaller plants below the direct logging size threshold - ! will be applied via "understory_death" via the disturbance algorithm + ! the area occupied by all plants in the canopy that aren't killed is still disturbed at the harvest rate if (canopy_layer .eq. 1) then - lmort_collateral = harvest_rate * logging_collateral_frac + l_degrad = harvest_rate - (lmort_direct + lmort_infra + lmort_collateral) ! fraction passed to 'degraded' forest. else - lmort_collateral = 0._r8 + l_degrad = 0._r8 endif - else ! non-woody plants still killed by infrastructure + else lmort_direct = 0.0_r8 lmort_collateral = 0.0_r8 - lmort_infra = harvest_rate * logging_mechanical_frac + lmort_infra = 0.0_r8 + l_degrad = 0.0_r8 end if - - ! the area occupied by all plants in the canopy that aren't killed is still disturbed at the harvest rate - if (canopy_layer .eq. 1) then - l_degrad = harvest_rate - (lmort_direct + lmort_infra + lmort_collateral) ! fraction passed to 'degraded' forest. - else - l_degrad = 0._r8 - endif - - else - lmort_direct = 0.0_r8 + else + call get_init_landuse_harvest_rate(bc_in, harvest_rate) + lmort_direct = harvest_rate lmort_collateral = 0.0_r8 lmort_infra = 0.0_r8 l_degrad = 0.0_r8 - end if + endif end subroutine LoggingMortality_frac diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index b979be5eab..5136af67f0 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -281,7 +281,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, btran_ft, & !if trees are in the canopy, then their death is 'disturbance'. This probably needs a different terminology call mortality_rates(currentCohort,bc_in,btran_ft, mean_temp, & cmort,hmort,bmort,frmort, smort, asmort, dgmort) - call LoggingMortality_frac(ipft, currentCohort%dbh, currentCohort%canopy_layer, & + call LoggingMortality_frac(currentSite, bc_in, ipft, currentCohort%dbh, currentCohort%canopy_layer, & currentCohort%lmort_direct, & currentCohort%lmort_collateral, & currentCohort%lmort_infra, & diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3243857f4c..12747d9ed8 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -222,6 +222,14 @@ subroutine disturbance_rates( site_in, bc_in) ! first calculate the fraction of the site that is primary land call get_frac_site_primary(site_in, frac_site_primary) + ! check status of transition_landuse_from_off_to_on flag, and do some error checking on it + if(site_in%transition_landuse_from_off_to_on) then + if (abs(frac_site_primary - 1._r8) .gt. fates_tiny) then + write(fates_log(),*) 'flag for transition_landuse_from_off_to_on is set to true but site is not entirely primaryland' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + endif + ! get available biomass for harvest for all patches call get_harvestable_carbon(site_in, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c) @@ -248,7 +256,8 @@ subroutine disturbance_rates( site_in, bc_in) currentCohort%asmort = asmort currentCohort%dgmort = dgmort - call LoggingMortality_frac(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_layer, & + call LoggingMortality_frac(site_in, bc_in, currentCohort%pft, & + currentCohort%dbh, currentCohort%canopy_layer, & lmort_direct,lmort_collateral,lmort_infra,l_degrad,& bc_in%hlm_harvest_rates, & bc_in%hlm_harvest_catnames, & @@ -272,8 +281,12 @@ subroutine disturbance_rates( site_in, bc_in) call get_harvest_debt(site_in, bc_in, harvest_tag) - call get_landuse_transition_rates(bc_in, landuse_transition_matrix) - + if(.not. site_in%transition_landuse_from_off_to_on) then + call get_landuse_transition_rates(bc_in, landuse_transition_matrix) + else + call get_init_landuse_transition_rates(bc_in, landuse_transition_matrix) + endif + ! calculate total area in each landuse category current_fates_landuse_state_vector(:) = 0._r8 currentPatch => site_in%oldest_patch @@ -359,14 +372,18 @@ subroutine disturbance_rates( site_in, bc_in) (currentPatch%area - currentPatch%total_canopy_area) .gt. fates_tiny ) then ! The canopy is NOT closed. - if(bc_in%hlm_harvest_units == hlm_harvest_carbon) then - call get_harvest_rate_carbon (currentPatch%land_use_label, bc_in%hlm_harvest_catnames, & - bc_in%hlm_harvest_rates, currentPatch%age_since_anthro_disturbance, harvestable_forest_c, & - harvest_rate, harvest_tag) + if (.not. site_in%transition_landuse_from_off_to_on) then + if(bc_in%hlm_harvest_units == hlm_harvest_carbon) then + call get_harvest_rate_carbon (currentPatch%land_use_label, bc_in%hlm_harvest_catnames, & + bc_in%hlm_harvest_rates, currentPatch%age_since_anthro_disturbance, harvestable_forest_c, & + harvest_rate, harvest_tag) + else + call get_harvest_rate_area (currentPatch%land_use_label, bc_in%hlm_harvest_catnames, & + bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate) + end if else - call get_harvest_rate_area (currentPatch%land_use_label, bc_in%hlm_harvest_catnames, & - bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate) - end if + call get_init_landuse_harvest_rate(bc_in, harvest_rate) + endif currentPatch%disturbance_rates(dtype_ilog) = currentPatch%disturbance_rates(dtype_ilog) + & (currentPatch%area - currentPatch%total_canopy_area) * harvest_rate / currentPatch%area @@ -436,7 +453,6 @@ subroutine spawn_patches( currentSite, bc_in) use EDParamsMod , only : ED_val_understorey_death, logging_coll_under_frac use EDCohortDynamicsMod , only : terminate_cohorts use FatesConstantsMod , only : rsnbl_math_prec - use FatesLandUseChangeMod, only : get_landuse_transition_rates use FatesLandUseChangeMod, only : get_landusechange_rules ! ! !ARGUMENTS: diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 6adf6d4852..d3d7bd5d2c 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -298,4 +298,49 @@ subroutine CheckLUHData(luh_vector,modified_flag) end subroutine CheckLUHData + + subroutine get_init_landuse_harvest_rate(bc_in, harvest_rate) + + ! the purpose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use + ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for + ! the hrvest rate from primary lands, i.e. the transition from primary to secondary lands. thus instead of using the harvest + ! dataset tself, it only uses the state vector for what land use compositoin we want to achieve, and log the forests accordingly. + + ! !ARGUMENTS: + type(bc_in_type) , intent(in) :: bc_in + real(r8), intent(out) :: harvest_rate ! [m2/ m2 / day] + + ! LOCALS + real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] + + call get_luh_statedata(bc_in, state_vector) + + harvest_rate = state_vector(secondaryland) + + end subroutine get_init_landuse_harvest_rate + + subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) + + ! The purose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use + ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for + ! the transitions other than harvest, i.e. from primary lands to all other categories aside from secondary lands. + + ! !ARGUMENTS: + type(bc_in_type) , intent(in) :: bc_in + real(r8), intent(inout) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! [m2/m2/day] + + ! LOCALS + real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] + integer :: i + + landuse_transition_matrix(:,:) = 0._r8 + + call get_luh_statedata(bc_in, state_vector) + + do i = secondaryland+1,n_landuse_cats + landuse_transition_matrix(1,i) = state_vector(i) + end do + + end subroutine get_landuse_transition_rates + end module FatesLandUseChangeMod diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 24bb860788..961404bc1e 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -343,6 +343,8 @@ subroutine zero_site( site_in ) site_in%use_this_pft(:) = fates_unset_int site_in%area_by_age(:) = 0._r8 + site_in%transition_landuse_from_off_to_on = .false. + end subroutine zero_site ! ============================================================================ diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 39b425a9ee..eca4bb3f1a 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -225,6 +225,11 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) ! Integrate state variables from annual rates to daily timestep call ed_integrate_state_variables(currentSite, bc_in, bc_out ) + ! at this point in the call sequence, if flag to transition_landuse_from_off_to_on was set, unset it as it is no longer needed + if(currentSite%transition_landuse_from_off_to_on) then + currentSite%transition_landuse_from_off_to_on = .false + endif + else ! ed_intergrate_state_variables is where the new cohort flag ! is set. This flag designates wether a cohort has diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index b1ba28b8b4..bb02cf89d9 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -426,6 +426,8 @@ module EDTypesMod real(r8) :: primary_land_patchfusion_error ! error term in total area of primary patches associated with patch fusion [m2/m2/day] real(r8) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! land use transition matrix as read in from HLM and aggregated to FATES land use types [m2/m2/year] + logical :: transition_landuse_from_off_to_on ! special flag to use only when reading restarts, which triggers procedure to initialize land use + end type ed_site_type ! Make public necessary subroutines and functions diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index be9ef01815..cfce367952 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -25,6 +25,7 @@ module FatesRestartInterfaceMod use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : hlm_use_sp use FatesInterfaceTypesMod, only : hlm_use_nocomp, hlm_use_fixed_biogeog + use FatesInterfaceTypesMod, only : hlm_use_luh use FatesInterfaceTypesMod, only : fates_maxElementsPerSite use FatesInterfaceTypesMod, only : hlm_use_tree_damage use FatesHydraulicsMemMod, only : nshell @@ -98,6 +99,7 @@ module FatesRestartInterfaceMod integer :: ir_gdd_si integer :: ir_snow_depth_si integer :: ir_trunk_product_si + integer :: ir_landuse_config_si integer :: ir_ncohort_pa integer :: ir_canopy_layer_co integer :: ir_canopy_layer_yesterday_co @@ -704,6 +706,10 @@ subroutine define_restart_vars(this, initialize_variables) units='kgC/m2', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_trunk_product_si ) + call this%set_restart_var(vname='fates_landuse_config_site', vtype=site_r8, & + long_name='hlm_use_luh status of run that created this restart file', & + units='kgC/m2', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_landuse_config_si ) ! ----------------------------------------------------------------------------------- ! Variables stored within cohort vectors @@ -1991,6 +1997,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & + rio_landuse_config_s => this%rvars(ir_landuse_config_si)%int1d, & rio_ncohort_pa => this%rvars(ir_ncohort_pa)%int1d, & rio_fcansno_pa => this%rvars(ir_fcansno_pa)%r81d, & rio_solar_zenith_flag_pa => this%rvars(ir_solar_zenith_flag_pa)%int1d, & @@ -2575,6 +2582,10 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! Accumulated trunk product rio_trunk_product_si(io_idx_si) = sites(s)%resources_management%trunk_product_site + + ! land use flag + rio_landuse_config_si(io_idx_si) = hlm_use_luh + ! set numpatches for this column rio_npatch_si(io_idx_si) = patchespersite @@ -2935,6 +2946,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & + rio_landuse_config_si => this%rvars(ir_landuse_config_si)%int1d, & rio_ncohort_pa => this%rvars(ir_ncohort_pa)%int1d, & rio_fcansno_pa => this%rvars(ir_fcansno_pa)%r81d, & rio_solar_zenith_flag_pa => this%rvars(ir_solar_zenith_flag_pa)%int1d, & @@ -3546,6 +3558,12 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%snow_depth = rio_snow_depth_si(io_idx_si) sites(s)%resources_management%trunk_product_site = rio_trunk_product_si(io_idx_si) + ! if needed, trigger the special procedure to initialize land use structure from a + ! restart run that did not include land use. + if (rio_landuse_config_si(io_idx_si) .eq. ifalse .and. hlm_use_luh .eq. itrue) then + sites(s)%transition_landuse_from_off_to_on = .true. + endif + end do if ( debug ) then From a441e93e0122ecd1e20573e4fc0098913fc13d0b Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Mon, 18 Sep 2023 16:48:14 -0700 Subject: [PATCH 014/300] added edparamsmod changed to merge --- main/EDParamsMod.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index bb987b947f..9d3391ada3 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -838,7 +838,9 @@ subroutine FatesReceiveParams(fates_params) data=ED_val_history_damage_bin_edges) call fates_params%RetrieveParameterAllocate(name=ED_name_crop_lu_pft_vector, & - data=crop_lu_pft_vector) + data=tmp_vector_by_landuse) + + crop_lu_pft_vector(:) = nint(tmp_vector_by_landuse(:)) call fates_params%RetrieveParameter(name=ED_name_maxpatches_by_landuse, & data=tmp_vector_by_landuse) From b94fefa9f8864c5b4a204a541a75a82348f748f7 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Mon, 18 Sep 2023 16:58:47 -0700 Subject: [PATCH 015/300] fixed merged conflict --- parameter_files/fates_params_default.cdl | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 8e4b829389..155c087ecb 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -52,9 +52,6 @@ variables: char fates_litterclass_name(fates_litterclass, fates_string_length) ; fates_litterclass_name:units = "unitless - string" ; fates_litterclass_name:long_name = "Name of the litter classes, for variables associated with dimension fates_litterclass" ; - char fates_landuseclass_name(fates_landuseclass, fates_string_length) ; - fates_landuseclass_name:units = "unitless - string" ; - fates_landuseclass_name:long_name = "Name of the land use classes, for variables associated with dimension fates_landuseclass" ; double fates_alloc_organ_priority(fates_plant_organs, fates_pft) ; fates_alloc_organ_priority:units = "index" ; fates_alloc_organ_priority:long_name = "Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance" ; @@ -953,13 +950,6 @@ data: "dead leaves ", "live grass " ; - fates_landuseclass_name = - "primaryland ", - "secondaryland ", - "rangeland ", - "pastureland ", - "cropland " ; - fates_alloc_organ_priority = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, From c39b11f7d022e6aa0992fa7c326ef18cee1f9285 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Thu, 5 Oct 2023 13:25:33 -0700 Subject: [PATCH 016/300] update default allometries for tree PFTs --- .../api27.0.0_062823_fates_params_default.cdl | 1735 +++++++++++++++++ .../archive/api27.0.0_062823_prxxx.xml | 53 + parameter_files/fates_params_default.cdl | 32 +- 3 files changed, 1805 insertions(+), 15 deletions(-) create mode 100644 parameter_files/archive/api27.0.0_062823_fates_params_default.cdl create mode 100644 parameter_files/archive/api27.0.0_062823_prxxx.xml diff --git a/parameter_files/archive/api27.0.0_062823_fates_params_default.cdl b/parameter_files/archive/api27.0.0_062823_fates_params_default.cdl new file mode 100644 index 0000000000..72a7e75c8c --- /dev/null +++ b/parameter_files/archive/api27.0.0_062823_fates_params_default.cdl @@ -0,0 +1,1735 @@ +netcdf fates_params_default { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + char fates_litterclass_name(fates_litterclass, fates_string_length) ; + fates_litterclass_name:units = "unitless - string" ; + fates_litterclass_name:long_name = "Name of the litter classes, for variables associated with dimension fates_litterclass" ; + double fates_alloc_organ_priority(fates_plant_organs, fates_pft) ; + fates_alloc_organ_priority:units = "index" ; + fates_alloc_organ_priority:long_name = "Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + double fates_damage_recovery_scalar(fates_pft) ; + fates_damage_recovery_scalar:units = "unitless" ; + fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; + double fates_dev_arbitrary_pft(fates_pft) ; + fates_dev_arbitrary_pft:units = "unknown" ; + fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + double fates_hydro_vg_n_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_n_node:units = "unitless" ; + fates_hydro_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_maintresp_reduction_upthresh(fates_pft) ; + fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; + fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_mort_upthresh_cstarvation(fates_pft) ; + fates_mort_upthresh_cstarvation:units = "unitless" ; + fates_mort_upthresh_cstarvation:long_name = "threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_drought_threshold(fates_pft) ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; + double fates_phen_mindaysoff(fates_pft) ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; + double fates_phen_moist_threshold(fates_pft) ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_seed_dispersal_fraction(fates_pft) ; + fates_seed_dispersal_fraction:units = "fraction" ; + fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; + double fates_seed_dispersal_max_dist(fates_pft) ; + fates_seed_dispersal_max_dist:units = "m" ; + fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; + double fates_seed_dispersal_pdf_scale(fates_pft) ; + fates_seed_dispersal_pdf_scale:units = "unitless" ; + fates_seed_dispersal_pdf_scale:long_name = "seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016" ; + double fates_seed_dispersal_pdf_shape(fates_pft) ; + fates_seed_dispersal_pdf_shape:units = "unitless" ; + fates_seed_dispersal_pdf_shape:long_name = "seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_trs_repro_alloc_a(fates_pft) ; + fates_trs_repro_alloc_a:units = "fraction" ; + fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_alloc_b(fates_pft) ; + fates_trs_repro_alloc_b:units = "fraction" ; + fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_frac_seed(fates_pft) ; + fates_trs_repro_frac_seed:units = "fraction" ; + fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; + double fates_trs_seedling_a_emerg(fates_pft) ; + fates_trs_seedling_a_emerg:units = "day -1" ; + fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; + double fates_trs_seedling_b_emerg(fates_pft) ; + fates_trs_seedling_b_emerg:units = "day -1" ; + fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; + double fates_trs_seedling_background_mort(fates_pft) ; + fates_trs_seedling_background_mort:units = "yr-1" ; + fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; + double fates_trs_seedling_h2o_mort_a(fates_pft) ; + fates_trs_seedling_h2o_mort_a:units = "-" ; + fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_b(fates_pft) ; + fates_trs_seedling_h2o_mort_b:units = "-" ; + fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_c(fates_pft) ; + fates_trs_seedling_h2o_mort_c:units = "-" ; + fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_light_mort_a(fates_pft) ; + fates_trs_seedling_light_mort_a:units = "-" ; + fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_mort_b(fates_pft) ; + fates_trs_seedling_light_mort_b:units = "-" ; + fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_rec_a(fates_pft) ; + fates_trs_seedling_light_rec_a:units = "-" ; + fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_light_rec_b(fates_pft) ; + fates_trs_seedling_light_rec_b:units = "-" ; + fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_mdd_crit(fates_pft) ; + fates_trs_seedling_mdd_crit:units = "mm H2O day" ; + fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; + double fates_trs_seedling_par_crit_germ(fates_pft) ; + fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; + fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; + double fates_trs_seedling_psi_crit(fates_pft) ; + fates_trs_seedling_psi_crit:units = "mm H2O" ; + fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; + double fates_trs_seedling_psi_emerg(fates_pft) ; + fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; + fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; + double fates_trs_seedling_root_depth(fates_pft) ; + fates_trs_seedling_root_depth:units = "m" ; + fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + double fates_frag_cwd_frac(fates_NCWD) ; + fates_frag_cwd_frac:units = "fraction" ; + fates_frag_cwd_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_canopy_closure_thresh ; + fates_canopy_closure_thresh:units = "unitless" ; + fates_canopy_closure_thresh:long_name = "tree canopy coverage at which crown area allometry changes from savanna to forest value" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + double fates_hydro_solver ; + fates_hydro_solver:units = "unitless" ; + fates_hydro_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard, 3 = 2D Newton (deprecated)" ; + double fates_landuse_logging_coll_under_frac ; + fates_landuse_logging_coll_under_frac:units = "fraction" ; + fates_landuse_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_thome_time ; + fates_leaf_photo_temp_acclim_thome_time:units = "years" ; + fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_maxpatch_primary ; + fates_maxpatch_primary:units = "count" ; + fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; + double fates_maxpatch_secondary ; + fates_maxpatch_secondary:units = "count" ; + fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_rad_model ; + fates_rad_model:units = "unitless" ; + fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; + double fates_regeneration_model ; + fates_regeneration_model:units = "-" ; + fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_trs_seedling2sap_par_timescale ; + fates_trs_seedling2sap_par_timescale:units = "days" ; + fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; + double fates_trs_seedling_emerg_h2o_timescale ; + fates_trs_seedling_emerg_h2o_timescale:units = "days" ; + fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; + double fates_trs_seedling_mdd_timescale ; + fates_trs_seedling_mdd_timescale:units = "days" ; + fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; + double fates_trs_seedling_mort_par_timescale ; + fates_trs_seedling_mort_par_timescale:units = "days" ; + fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + fates_alloc_organ_priority = + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; + + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_upthresh_cstarvation = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_scale = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_shape = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, + 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; + + fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, + -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; + + fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, + 0.24, 0.24, 0.24, 0.24 ; + + fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, + 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; + + fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371 ; + + fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; + + fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; + + fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; + + fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; + + fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063 ; + + fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, + 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; + + fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, + 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; + + fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, + 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; + + fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, + 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; + + fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7 ; + + fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65 ; + + fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.06, 0.06, 0.06, 0.06 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_thome_time = 30 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; + + fates_maxcohort = 100 ; + + fates_maxpatch_primary = 10 ; + + fates_maxpatch_secondary = 4 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindayson = 90 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_rad_model = 1 ; + + fates_regeneration_model = 1 ; + + fates_soil_salinity = 0.4 ; + + fates_trs_seedling2sap_par_timescale = 32 ; + + fates_trs_seedling_emerg_h2o_timescale = 7 ; + + fates_trs_seedling_mdd_timescale = 126 ; + + fates_trs_seedling_mort_par_timescale = 32 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} \ No newline at end of file diff --git a/parameter_files/archive/api27.0.0_062823_prxxx.xml b/parameter_files/archive/api27.0.0_062823_prxxx.xml new file mode 100644 index 0000000000..5378ce3026 --- /dev/null +++ b/parameter_files/archive/api27.0.0_062823_prxxx.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + archive/api.27.0.0_062823_fates_params_default.cdl + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, 0.07286975, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 + + + 0.976, 0.94490413, 1.08733502, 0.83213205, 0.976, 1.03732112, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 + + + 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 + + + -0.12366731, -0.3447603, -0.31791391, -0.21568348, -0.12366731, -0.3521357, 0, 0, 0, 0, 0, 0 + + + 78.40877039, 306.842667, 106.8745821, 104.3586841, 78.40877039, 29.69929379, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 + + + 0.81243829, 0.75237703, 0.94713018, 1.11469727, 0.81243829, 1.12959569, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 + + + 47.66661644, 196.6865691, 93.97904614, 160.6835089, 47.66661644, 25.12579143, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 + + + 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, 0.35, 0.35, 0.3 + + + 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 + + + 0.548327, 0.442350, 0.454845, 0.754336, 0.548327, 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index f170fe2275..8090347958 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -950,11 +950,11 @@ data: fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + fates_allom_agb1 = 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, 0.07286975, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; + fates_allom_agb2 = 0.976, 0.94490413, 1.08733502, 0.83213205, 0.976, + 1.03732112, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; @@ -965,9 +965,10 @@ data: fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_allom_blca_expnt_diff = -0.12366731, -0.3447603, -0.31791391, -0.21568348, + -0.12366731, -0.3521357, 0, 0, 0, 0, 0, 0 ; fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -991,16 +992,17 @@ data: 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119 ; - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; + fates_allom_d2h1 = 78.40877039, 306.842667, 106.8745821, 104.3586841, + 78.40877039, 29.69929379, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; + fates_allom_d2h2 = 0.81243829, 0.75237703, 0.94713018, 1.11469727, + 0.81243829, 1.12959569, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; + fates_allom_d2h3 = 47.66661644, 196.6865691, 93.97904614, 160.6835089, + 47.66661644, 25.12579143, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; - fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, + 3, 3, 2, 0.35, 0.35, 0.3 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1012,7 +1014,7 @@ data: fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1548,8 +1550,8 @@ data: fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; + fates_wood_density = 0.548327, 0.442350, 0.454845, 0.754336, 0.548327, + 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; From fff8c759dda213708985d7381c7847ec72fa0a94 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Thu, 5 Oct 2023 13:50:56 -0700 Subject: [PATCH 017/300] update xml file with PR number --- .../{api27.0.0_062823_prxxx.xml => api27.0.0_062823_pr1093.xml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename parameter_files/archive/{api27.0.0_062823_prxxx.xml => api27.0.0_062823_pr1093.xml} (96%) diff --git a/parameter_files/archive/api27.0.0_062823_prxxx.xml b/parameter_files/archive/api27.0.0_062823_pr1093.xml similarity index 96% rename from parameter_files/archive/api27.0.0_062823_prxxx.xml rename to parameter_files/archive/api27.0.0_062823_pr1093.xml index 5378ce3026..ab8225cacf 100644 --- a/parameter_files/archive/api27.0.0_062823_prxxx.xml +++ b/parameter_files/archive/api27.0.0_062823_pr1093.xml @@ -1,7 +1,7 @@ - + From cd4750e29808022b11d70e90c863a52d0493f007 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Fri, 6 Oct 2023 09:11:32 -0700 Subject: [PATCH 018/300] fix xml file --- .../archive/api27.0.0_062823_pr1093.xml | 22 +++++++++++----- parameter_files/fates_params_default.cdl | 26 +++++++++---------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/parameter_files/archive/api27.0.0_062823_pr1093.xml b/parameter_files/archive/api27.0.0_062823_pr1093.xml index ab8225cacf..b375ac8654 100644 --- a/parameter_files/archive/api27.0.0_062823_pr1093.xml +++ b/parameter_files/archive/api27.0.0_062823_pr1093.xml @@ -15,38 +15,48 @@ the variables --> - archive/api.27.0.0_062823_fates_params_default.cdl + archive/api27.0.0_062823_fates_params_default.cdl fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12 - 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, 0.07286975, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 + fates_pft + 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, 0.07286975, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 - 0.976, 0.94490413, 1.08733502, 0.83213205, 0.976, 1.03732112, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 + fates_pft + 0.976, 0.94490413, 1.08733502, 0.83213205, 0.976, 1.03732112, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 - 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 + fates_pft + 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 + fates_pft -0.12366731, -0.3447603, -0.31791391, -0.21568348, -0.12366731, -0.3521357, 0, 0, 0, 0, 0, 0 + fates_pft 78.40877039, 306.842667, 106.8745821, 104.3586841, 78.40877039, 29.69929379, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 - 0.81243829, 0.75237703, 0.94713018, 1.11469727, 0.81243829, 1.12959569, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 + fates_pft + 0.81243829, 0.75237703, 0.94713018, 1.11469727, 0.81243829, 1.12959569, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 + fates_pft 47.66661644, 196.6865691, 93.97904614, 160.6835089, 47.66661644, 25.12579143, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 - 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, 0.35, 0.35, 0.3 + fates_pft + 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, 0.35, 0.35, 0.35 + fates_pft 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 + fates_pft 0.548327, 0.442350, 0.454845, 0.754336, 0.548327, 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 8090347958..d311244e2e 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -950,10 +950,10 @@ data: fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; - fates_allom_agb1 = 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, 0.07286975, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + fates_allom_agb1 = 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, + 0.07286975, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.976, 0.94490413, 1.08733502, 0.83213205, 0.976, + fates_allom_agb2 = 0.976, 0.94490413, 1.08733502, 0.83213205, 0.976, 1.03732112, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, @@ -967,8 +967,8 @@ data: fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; - fates_allom_blca_expnt_diff = -0.12366731, -0.3447603, -0.31791391, -0.21568348, - -0.12366731, -0.3521357, 0, 0, 0, 0, 0, 0 ; + fates_allom_blca_expnt_diff = -0.12366731, -0.3447603, -0.31791391, + -0.21568348, -0.12366731, -0.3521357, 0, 0, 0, 0, 0, 0 ; fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -992,17 +992,17 @@ data: 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119 ; - fates_allom_d2h1 = 78.40877039, 306.842667, 106.8745821, 104.3586841, + fates_allom_d2h1 = 78.40877039, 306.842667, 106.8745821, 104.3586841, 78.40877039, 29.69929379, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.81243829, 0.75237703, 0.94713018, 1.11469727, + fates_allom_d2h2 = 0.81243829, 0.75237703, 0.94713018, 1.11469727, 0.81243829, 1.12959569, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = 47.66661644, 196.6865691, 93.97904614, 160.6835089, + fates_allom_d2h3 = 47.66661644, 196.6865691, 93.97904614, 160.6835089, 47.66661644, 25.12579143, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; - fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, - 3, 3, 2, 0.35, 0.35, 0.3 ; + fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, + 0.35, 0.35, 0.35 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1550,8 +1550,8 @@ data: fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.548327, 0.442350, 0.454845, 0.754336, 0.548327, - 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; + fates_wood_density = 0.548327, 0.44235, 0.454845, 0.754336, 0.548327, + 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; From 49de604d43b0f6e37476aae5778528d8cddff6f5 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 9 Oct 2023 09:00:21 -0700 Subject: [PATCH 019/300] change name of default parameter file back --- parameter_files/fates_params_default.cdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index d311244e2e..a6667f9c3c 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf tmp { +netcdf fates_params_default { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; From 71deea8343f1abe2c9b5121ff0159cd032aa2bc5 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Thu, 12 Oct 2023 15:33:28 -0700 Subject: [PATCH 020/300] added logic to handle case where nocomp and land use are on but not enough patches for a given land use type to acomodate all PFTs prescribed --- main/EDInitMod.F90 | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index d68a7652fd..96ee34dbff 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -354,6 +354,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! ! !USES: use EDParamsMod, only : crop_lu_pft_vector + use EDParamsMod, only : maxpatches_by_landuse ! ! !ARGUMENTS @@ -383,6 +384,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) integer :: hlm_pft ! used in fixed biogeog mode integer :: fates_pft ! used in fixed biogeog mode integer :: i_landusetype + real(r8) :: temp_vec(numpft) ! temporary vector !---------------------------------------------------------------------- @@ -486,13 +488,17 @@ subroutine set_site_properties( nsites, sites,bc_in ) endif use_fates_luh_if + ! handle some edge cases do i_landusetype = 1, n_landuse_cats do ft = 1,numpft + + ! remove tiny patches to prevent numerical errors in terminate patches if(sites(s)%area_pft(ft, i_landusetype).lt.0.01_r8.and.sites(s)%area_pft(ft, i_landusetype).gt.0.0_r8)then if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,i_landusetype,sites(s)%area_pft(ft, i_landusetype) sites(s)%area_pft(ft, i_landusetype)=0.0_r8 - ! remove tiny patches to prevent numerical errors in terminate patches endif + + ! if any areas are negative, then end run if(sites(s)%area_pft(ft, i_landusetype).lt.0._r8)then write(fates_log(),*) 'negative area',s,ft,i_landusetype,sites(s)%area_pft(ft, i_landusetype) call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -500,9 +506,34 @@ subroutine set_site_properties( nsites, sites,bc_in ) end do end do + ! if in nocomp mode, and the number of nocomp PFTs of a given land use type is greater than the maximum number of patches + ! allowed to be allocated for that land use type, then only keep the number of PFTs correspondign to the number of patches + ! allowed on that land use type, starting with the PFTs with greatest area coverage and working down + if (hlm_use_nocomp .eq. itrue) then + do i_landusetype = 1, n_landuse_cats + ! count how many PFTs have areas greater than zero and compare to the number of patches allowed + if (COUNT(sites(s)%area_pft(ft, i_landusetype) .gt. 0._r8) > maxpatches_by_landuse(i_landusetype)) then + ! write current vector to log file + if(debug) write(fates_log(),*) 'too many PFTs for LU type ', i_landusetype, i_landusetype,sites(s)%area_pft(:, i_landusetype) + + ! start from largest area, put that PFT's area into a temp vector, and then work down to successively smaller-area PFTs, + ! at the end replace the original vector with the temp vector + temp_vec(:) = 0._r8 + do i_pftcount = 1, maxpatches_by_landuse(i_landusetype) + temp_vec(MAXLOC(sites(s)%area_pft(:, i_landusetype))) = & + sites(s)%area_pft(MAXLOC(sites(s)%area_pft(:, i_landusetype)), i_landusetype) + sites(s)%area_pft(MAXLOC(sites(s)%area_pft(:, i_landusetype)), i_landusetype) = 0._r8 + end do + sites(s)%area_pft(:, i_landusetype) = temp_vec(:) + + ! write adjusted vector to log file + if(debug) write(fates_log(),*) 'new PFT vector for LU type', i_landusetype, i_landusetype,sites(s)%area_pft(:, i_landusetype) + endif + end do + end if + ! re-normalize PFT area to ensure it sums to one for each (active) land use type ! for nocomp cases, track bare ground area as a separate quantity - do i_landusetype = 1, n_landuse_cats sumarea = sum(sites(s)%area_pft(1:numpft,i_landusetype)) do ft = 1,numpft From 01212d112edddf471a1b063fae4ed9809dfc7328 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Thu, 12 Oct 2023 15:50:21 -0700 Subject: [PATCH 021/300] error/edge-case handling for if the LU x PFT area dataset has NaNs --- main/EDInitMod.F90 | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 96ee34dbff..78bfcd8875 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -95,6 +95,7 @@ module EDInitMod ! CIME GLOBALS use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_infnan_mod , only : isnan => shr_infnan_isnan implicit none private @@ -456,21 +457,36 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! add up the area associated with each FATES PFT ! where pft_areafrac_lu is the area of land in each HLM PFT and land use type (from surface dataset) ! hlm_pft_map is the area of that land in each FATES PFT (from param file) - do i_landusetype = 1, n_landuse_cats - if (.not. is_crop(i_landusetype)) then - do hlm_pft = 1,fates_hlm_num_natpfts - do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts - sites(s)%area_pft(fates_pft,i_landusetype) = sites(s)%area_pft(fates_pft,i_landusetype) + & - EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac_lu(hlm_pft,i_landusetype) - end do - end do !hlm_pft + + ! first check for NaNs in bc_in(s)%pft_areafrac_lu. if so, make everything bare ground. + if ( .not. any( isnan( bc_in(s)%pft_areafrac_lu (:,:) ))) then + do i_landusetype = 1, n_landuse_cats + if (.not. is_crop(i_landusetype)) then + do hlm_pft = 1,fates_hlm_num_natpfts + do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts + sites(s)%area_pft(fates_pft,i_landusetype) = sites(s)%area_pft(fates_pft,i_landusetype) + & + EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac_lu(hlm_pft,i_landusetype) + end do + end do !hlm_pft + else + ! for crops, we need to use different logic because the bc_in(s)%pft_areafrac_lu() information only exists for natural PFTs + sites(s)%area_pft(crop_lu_pft_vector(i_landusetype),i_landusetype) = 1._r8 + endif + end do + + sites(s)%area_bareground = bc_in(s)%baregroundfrac * area + else + if ( all( isnan( bc_in(s)%pft_areafrac_lu (:,:) ))) then + ! if given all NaNs, then make everything bare ground + sites(s)%area_bareground = 1._r8 + sites(s)%area_pft(:,:) = 0._r8 else - ! for crops, we need to use different logic because the bc_in(s)%pft_areafrac_lu() information only exists for natural PFTs - sites(s)%area_pft(crop_lu_pft_vector(i_landusetype),i_landusetype) = 1._r8 + ! if only some things are NaN but not all, then something terrible has probably happened. crash. + write(fates_log(),*) 'some but, not all, of the data in the PFT by LU matrix at this site is NaN.' + write(fates_log(),*) 'recommend checking the dataset to see what has happened.' + call endrun(msg=errMsg(sourcefile, __LINE__)) endif - end do - - sites(s)%area_bareground = bc_in(s)%baregroundfrac * area + endif else ! MAPPING OF FATES PFTs on to HLM_PFTs From 110ef78c8c4c17ded8b065ec903d8ab7998074dc Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Thu, 12 Oct 2023 16:54:20 -0700 Subject: [PATCH 022/300] startign to add logic to handle PFT_level harvest parameters for both logging and land use change --- biogeochem/EDLoggingMortalityMod.F90 | 31 ++++++++++++++++++------ biogeochem/EDPatchDynamicsMod.F90 | 2 +- biogeochem/EDPhysiologyMod.F90 | 2 +- main/EDMainMod.F90 | 6 +++-- main/EDTypesMod.F90 | 8 ++++-- main/FatesHistoryInterfaceMod.F90 | 25 +++++++++++++------ main/FatesRestartInterfaceMod.F90 | 20 ++++++++++----- parameter_files/fates_params_default.cdl | 11 +++++---- 8 files changed, 73 insertions(+), 32 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 9c843cbf71..79a4085000 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -69,6 +69,7 @@ module EDLoggingMortalityMod use FatesConstantsMod , only : hlm_harvest_area_fraction use FatesConstantsMod , only : hlm_harvest_carbon use FatesConstantsMod, only : fates_check_param_set + use FatesInterfaceTypesMod , only : numpft implicit none private @@ -992,7 +993,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ag_wood * logging_export_frac ! This is for checking the total mass balance [kg/site/day] - site_mass%wood_product = site_mass%wood_product + & + site_mass%wood_product_harvest(pft) = site_mass%wood_product_harvest(pft) + & ag_wood * logging_export_frac new_litt%ag_cwd(ncwd) = new_litt%ag_cwd(ncwd) + ag_wood * & @@ -1122,6 +1123,7 @@ subroutine UpdateHarvestC(currentSite,bc_out) type(bc_out_type), intent(inout) :: bc_out integer :: icode + integer :: i_pft real(r8) :: unit_trans_factor @@ -1132,13 +1134,26 @@ subroutine UpdateHarvestC(currentSite,bc_out) ! Calculate the unit transfer factor (from kgC m-2 day-1 to gC m-2 s-1) unit_trans_factor = g_per_kg * days_per_sec - bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & - currentSite%mass_balance(element_pos(carbon12_element))%wood_product * & - AREA_INV * pprodharv10_forest_mean * unit_trans_factor - bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & - currentSite%mass_balance(element_pos(carbon12_element))%wood_product * & - AREA_INV * (1._r8 - pprodharv10_forest_mean) * unit_trans_factor - + ! harvest-associated wood product pools + do i_pft = 1,numpft + bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & + currentSite%mass_balance(element_pos(carbon12_element))%wood_product_harvest(i_pft) * & + AREA_INV * harvest_pprod10(i_pft) * unit_trans_factor + bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & + currentSite%mass_balance(element_pos(carbon12_element))%wood_product_harvest(i_pft) * & + AREA_INV * (1._r8 - harvest_pprod10(i_pft)) * unit_trans_factor + end do + + ! land-use-change-associated wood product pools + do i_pft = 1,numpft + bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & + currentSite%mass_balance(element_pos(carbon12_element))%wood_product_landusechange(i_pft) * & + AREA_INV * landusechange_pprod10(i_pft) * unit_trans_factor + bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & + currentSite%mass_balance(element_pos(carbon12_element))%wood_product_landusechange(i_pft) * & + AREA_INV * (1._r8 - landusechange_pprod10(i_pft)) * unit_trans_factor + end do + return end subroutine UpdateHarvestC diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 92d7853c97..75a95c9ceb 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2633,7 +2633,7 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & trunk_product_site = trunk_product_site + & woodproduct_mass - site_mass%wood_product = site_mass%wood_product + & + site_mass%wood_product_landusechange(pft) = site_mass%wood_product_landusechange(pft) + & woodproduct_mass endif new_litt%ag_cwd(c) = new_litt%ag_cwd(c) + donatable_mass * donate_m2 diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 7fe9c3bccd..8dc9510ee3 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -3022,7 +3022,7 @@ subroutine CWDInput( currentSite, currentPatch, litt, bc_in) SF_val_CWD_frac_adj(c) * dead_n_dlogging * & prt_params%allom_agb_frac(pft) - site_mass%wood_product = site_mass%wood_product + & + site_mass%wood_product_harvest(pft) = site_mass%wood_product_harvest(pft) + & trunk_wood * currentPatch%area * logging_export_frac ! Add AG wood to litter from the non-exported fraction of wood diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index fd2b7da13a..97b54c5dba 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -914,7 +914,8 @@ subroutine TotalBalanceCheck (currentSite, call_index ) site_mass%flux_generic_in + & site_mass%patch_resize_err - flux_out = site_mass%wood_product + & + flux_out = sum(site_mass%wood_product_harvest(:)) + & + sum(site_mass%wood_product_landusechange(:)) + & site_mass%burn_flux_to_atm + & site_mass%seed_out + & site_mass%flux_generic_out + & @@ -944,7 +945,8 @@ subroutine TotalBalanceCheck (currentSite, call_index ) write(fates_log(),*) 'net_root_uptake: ',site_mass%net_root_uptake write(fates_log(),*) 'gpp_acc: ',site_mass%gpp_acc write(fates_log(),*) 'flux_generic_in: ',site_mass%flux_generic_in - write(fates_log(),*) 'wood_product: ',site_mass%wood_product + write(fates_log(),*) 'wood_product_harvest: ',site_mass%wood_product_harvest(:) + write(fates_log(),*) 'wood_product_landusechange: ',site_mass%wood_product_landusechange(:) write(fates_log(),*) 'error from patch resizing: ',site_mass%patch_resize_err write(fates_log(),*) 'burn_flux_to_atm: ',site_mass%burn_flux_to_atm write(fates_log(),*) 'seed_out: ',site_mass%seed_out diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index bb02cf89d9..1617ee3b41 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -204,7 +204,10 @@ module EDTypesMod real(r8) :: frag_out ! Litter and coarse woody debris fragmentation flux [kg/site/day] - real(r8) :: wood_product ! Total mass exported as wood product [kg/site/day] + real(r8) :: wood_product_harvest(maxpft) ! Total mass exported as wood product from wood harvest [kg/site/day] + + real(r8) :: wood_product_landusechange(maxpft) ! Total mass exported as wood product from land use change [kg/site/day] + real(r8) :: burn_flux_to_atm ! Total mass burned and exported to the atmosphere [kg/site/day] real(r8) :: flux_generic_in ! Used for prescribed or artificial input fluxes @@ -471,7 +474,8 @@ subroutine ZeroMassBalFlux(this) this%seed_in = 0._r8 this%seed_out = 0._r8 this%frag_out = 0._r8 - this%wood_product = 0._r8 + this%wood_product_harvest(:) = 0._r8 + this%wood_product_landusechange(:) = 0._r8 this%burn_flux_to_atm = 0._r8 this%flux_generic_in = 0._r8 this%flux_generic_out = 0._r8 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 01566c9b4b..64982e3561 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -312,7 +312,8 @@ module FatesHistoryInterfaceMod integer :: ih_fire_disturbance_rate_si integer :: ih_logging_disturbance_rate_si integer :: ih_fall_disturbance_rate_si - integer :: ih_harvest_carbonflux_si + integer :: ih_harvest_woodproduct_carbonflux_si + integer :: ih_landusechange_woodproduct_carbonflux_si integer :: ih_harvest_debt_si integer :: ih_harvest_debt_sec_si @@ -2389,7 +2390,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_fire_disturbance_rate_si => this%hvars(ih_fire_disturbance_rate_si)%r81d, & hio_logging_disturbance_rate_si => this%hvars(ih_logging_disturbance_rate_si)%r81d, & hio_fall_disturbance_rate_si => this%hvars(ih_fall_disturbance_rate_si)%r81d, & - hio_harvest_carbonflux_si => this%hvars(ih_harvest_carbonflux_si)%r81d, & + hio_harvest_woodproduct_carbonflux_si => this%hvars(ih_harvest_woodproduct_carbonflux_si)%r81d, & + hio_landusechange_woodproduct_carbonflux_si => this%hvars(ih_woodproduct_carbonflux_si)%r81d, & hio_harvest_debt_si => this%hvars(ih_harvest_debt_si)%r81d, & hio_harvest_debt_sec_si => this%hvars(ih_harvest_debt_sec_si)%r81d, & hio_gpp_si_scpf => this%hvars(ih_gpp_si_scpf)%r82d, & @@ -2759,8 +2761,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_fall_disturbance_rate_si(io_si) = sum(sites(s)%disturbance_rates(dtype_ifall,1:n_landuse_cats,1:n_landuse_cats)) * & days_per_year - hio_harvest_carbonflux_si(io_si) = sites(s)%mass_balance(element_pos(carbon12_element))%wood_product * AREA_INV - + hio_harvest_woodproduct_carbonflux_si(io_si) = sum(sites(s)%mass_balance(element_pos(carbon12_element))%wood_product_harvest(1:numpft)) * AREA_INV + + hio_landusechange_woodproduct_carbonflux_si(io_si) = sum(sites(s)%mass_balance(element_pos(carbon12_element))%wood_product_landusechange(1:numpft)) * AREA_INV + ! Loop through patches to sum up diagonistics ipa = 0 cpatch => sites(s)%oldest_patch @@ -6444,12 +6448,19 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_fall_disturbance_rate_si) - call this%set_history_var(vname='FATES_HARVEST_CARBON_FLUX', & + call this%set_history_var(vname='FATES_HARVEST_WOODPROD_C_FLUX', & + units='kg m-2 yr-1', & + long='harvest-associated wood product carbon flux in kg carbon per m2 per year', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_harvest_woodproduct_carbonflux_si) + + call this%set_history_var(vname='FATES_LANDUSECHANGE_WOODPROD_C_FLUX', & units='kg m-2 yr-1', & - long='harvest carbon flux in kg carbon per m2 per year', & + long='land-use-change-associated wood product carbon flux in kg carbon per m2 per year', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_harvest_carbonflux_si) + index = ih_landusechange_woodproduct_carbonflux_si) ! Canopy Resistance diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 83d5ad114f..089534d347 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -262,7 +262,8 @@ module FatesRestartInterfaceMod integer :: ir_rootlittin_flxdg integer :: ir_oldstock_mbal integer :: ir_errfates_mbal - integer :: ir_woodprod_mbal + integer :: ir_woodprod_harvest_mbal + integer :: ir_woodprod_landusechange_mbal integer :: ir_prt_base ! Base index for all PRT variables ! Damage x damage or damage x size @@ -1124,10 +1125,15 @@ subroutine define_restart_vars(this, initialize_variables) end if - call this%RegisterCohortVector(symbol_base='fates_woodproduct', vtype=site_r8, & - long_name_base='Current wood product flux', & + call this%RegisterCohortVector(symbol_base='fates_woodproduct_harvest', vtype=cohort_r8, & + long_name_base='Current wood product flux from harvest', & units='kg/m2/day', veclength=num_elements, flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_woodprod_mbal) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_woodprod_harvest_mbal) + + call this%RegisterCohortVector(symbol_base='fates_woodproduct_landusechange', vtype=cohort_r8, & + long_name_base='Current wood product flux from land use change', & + units='kg/m2/day', veclength=num_elements, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_woodprod_landusechange_mbal) ! Only register satellite phenology related restart variables if it is turned on! @@ -2225,12 +2231,13 @@ subroutine set_restart_vectors(this,nc,nsites,sites) 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_woodprod_harvest_mbal+el-1)%r81d(io_idx_si_pft) = sites(s)%mass_balance(el)%wood_product_harvest(i_pft) + this%rvars(ir_woodprod_landusechange_mbal+el-1)%r81d(io_idx_si_pft) = sites(s)%mass_balance(el)%wood_product_landusechange(i_pft) io_idx_si_pft = io_idx_si_pft + 1 end do this%rvars(ir_oldstock_mbal+el-1)%r81d(io_idx_si) = sites(s)%mass_balance(el)%old_stock 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 end do end if @@ -3177,12 +3184,13 @@ subroutine get_restart_vectors(this, nc, nsites, sites) 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)%mass_balance(el)%wood_product_harvest(i_pft) = this%rvars(ir_woodprod_harvest_mbal+el-1)%r81d(io_idx_si_pft) + sites(s)%mass_balance(el)%wood_product_landusechange(i_pft) = this%rvars(ir_woodprod_landusechange_mbal+el-1)%r81d(io_idx_si_pft) io_idx_si_pft = io_idx_si_pft + 1 end do 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) end do end if diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 6742ffb9a3..1ad7488bf5 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -342,6 +342,12 @@ variables: double fates_hydro_vg_n_node(fates_hydr_organs, fates_pft) ; fates_hydro_vg_n_node:units = "unitless" ; fates_hydro_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_landuse_harvest_pprod10(fates_pft) ; + fates_landuse_harvest_pprod10:units = "fraction" ; + fates_landuse_harvest_pprod10:long_name = "fraction of harvest wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; + double fates_landuse_landusechange_pprod10(fates_pft) ; + fates_landuse_landusechange_pprod10:units = "fraction" ; + fates_landuse_landusechange_pprod10:long_name = "fraction of land use change wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; double fates_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; @@ -792,9 +798,6 @@ variables: double fates_landuse_logging_mechanical_frac ; fates_landuse_logging_mechanical_frac:units = "fraction" ; fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_landuse_pprodharv10_forest_mean ; - fates_landuse_pprodharv10_forest_mean:units = "fraction" ; - fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; double fates_leaf_photo_temp_acclim_thome_time ; fates_leaf_photo_temp_acclim_thome_time:units = "years" ; fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; @@ -1680,8 +1683,6 @@ data: fates_landuse_logging_mechanical_frac = 0.05 ; - fates_landuse_pprodharv10_forest_mean = 0.8125 ; - fates_leaf_photo_temp_acclim_thome_time = 30 ; fates_leaf_photo_temp_acclim_timescale = 30 ; From 94ed7762e4f6fa4fed650c46a3e54f3e30d13b5f Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Fri, 13 Oct 2023 10:59:41 -0700 Subject: [PATCH 023/300] adding parameter values and passing to land use change and logging subroutines --- biogeochem/EDLoggingMortalityMod.F90 | 9 +++--- biogeochem/EDPatchDynamicsMod.F90 | 27 ++++++++-------- main/EDPftvarcon.F90 | 39 +++++++++++++++++++++++- parameter_files/fates_params_default.cdl | 17 +++++++++++ 4 files changed, 74 insertions(+), 18 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 79a4085000..c6e8ea92fb 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -1116,7 +1116,6 @@ subroutine UpdateHarvestC(currentSite,bc_out) use PRTGenericMod , only : element_pos use PRTGenericMod , only : carbon12_element use FatesInterfaceTypesMod , only : bc_out_type - use EDParamsMod , only : pprodharv10_forest_mean ! Arguments type(ed_site_type), intent(inout), target :: currentSite ! site structure @@ -1138,20 +1137,20 @@ subroutine UpdateHarvestC(currentSite,bc_out) do i_pft = 1,numpft bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & currentSite%mass_balance(element_pos(carbon12_element))%wood_product_harvest(i_pft) * & - AREA_INV * harvest_pprod10(i_pft) * unit_trans_factor + AREA_INV * EDPftvarcon_inst%harvest_pprod10(i_pft) * unit_trans_factor bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & currentSite%mass_balance(element_pos(carbon12_element))%wood_product_harvest(i_pft) * & - AREA_INV * (1._r8 - harvest_pprod10(i_pft)) * unit_trans_factor + AREA_INV * (1._r8 - EDPftvarcon_inst%harvest_pprod10(i_pft)) * unit_trans_factor end do ! land-use-change-associated wood product pools do i_pft = 1,numpft bc_out%hrv_deadstemc_to_prod10c = bc_out%hrv_deadstemc_to_prod10c + & currentSite%mass_balance(element_pos(carbon12_element))%wood_product_landusechange(i_pft) * & - AREA_INV * landusechange_pprod10(i_pft) * unit_trans_factor + AREA_INV * EDPftvarcon_inst%landusechange_pprod10(i_pft) * unit_trans_factor bc_out%hrv_deadstemc_to_prod100c = bc_out%hrv_deadstemc_to_prod100c + & currentSite%mass_balance(element_pos(carbon12_element))%wood_product_landusechange(i_pft) * & - AREA_INV * (1._r8 - landusechange_pprod10(i_pft)) * unit_trans_factor + AREA_INV * (1._r8 - EDPftvarcon_inst%landusechange_pprod10(i_pft)) * unit_trans_factor end do return diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 75a95c9ceb..21770fb234 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -2458,10 +2458,6 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & ! (note we are accumulating over the patch, but scale is site level) real(r8) :: woodproduct_mass ! mass that ends up in wood products [kg] - ! the following two parameters are new to this logic. - real(r8), parameter :: burn_frac_landusetransition = 0.5_r8 ! what fraction of plant fines are burned during a land use transition? - real(r8), parameter :: woodproduct_frac_landusetransition = 0.5_r8 ! what fraction of trunk carbon is turned into wood products during a land use transition? - !--------------------------------------------------------------------- clear_veg_if: if (clearing_matrix_element) then @@ -2550,10 +2546,10 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & ! Contribution of dead trees to leaf litter donatable_mass = num_dead_trees * (leaf_m+repro_m) * & - (1.0_r8-burn_frac_landusetransition) + (1.0_r8-EDPftvarcon_inst%landusechange_frac_burned(pft)) ! Contribution of dead trees to leaf burn-flux - burned_mass = num_dead_trees * (leaf_m+repro_m) * burn_frac_landusetransition + burned_mass = num_dead_trees * (leaf_m+repro_m) * EDPftvarcon_inst%landusechange_frac_burned(pft) do dcmpy=1,ndcmpy dcmpy_frac = GetDecompyFrac(pft,leaf_organ,dcmpy) @@ -2583,7 +2579,7 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & ! Track as diagnostic fluxes flux_diags%leaf_litter_input(pft) = & flux_diags%leaf_litter_input(pft) + & - num_dead_trees * (leaf_m+repro_m) * (1.0_r8-burn_frac_landusetransition) + num_dead_trees * (leaf_m+repro_m) * (1.0_r8-EDPftvarcon_inst%landusechange_frac_burned(pft)) flux_diags%root_litter_input(pft) = & flux_diags%root_litter_input(pft) + & @@ -2619,16 +2615,23 @@ subroutine landusechange_litter_fluxes(currentSite, currentPatch, & do c = 1,ncwd donatable_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem if (c == 1 .or. c == 2) then ! these pools can burn - donatable_mass = donatable_mass * (1.0_r8-burn_frac_landusetransition) + donatable_mass = donatable_mass * (1.0_r8-EDPftvarcon_inst%landusechange_frac_burned(pft)) burned_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem * & - burn_frac_landusetransition + EDPftvarcon_inst%landusechange_frac_burned(pft) site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass - else ! all other pools can end up as timber products but not burn - donatable_mass = donatable_mass * (1.0_r8-woodproduct_frac_landusetransition) + else ! all other pools can end up as timber products or burn or go to litter + donatable_mass = donatable_mass * (1.0_r8-EDPftvarcon_inst%landusechange_frac_exported(pft)) * & + (1.0_r8-EDPftvarcon_inst%landusechange_frac_burned(pft)) + + burned_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem * & + (1.0_r8-EDPftvarcon_inst%landusechange_frac_exported(pft)) * & + EDPftvarcon_inst%landusechange_frac_burned(pft) woodproduct_mass = num_dead_trees * SF_val_CWD_frac(c) * bstem * & - woodproduct_frac_landusetransition + EDPftvarcon_inst%landusechange_frac_exported(pft) + + site_mass%burn_flux_to_atm = site_mass%burn_flux_to_atm + burned_mass trunk_product_site = trunk_product_site + & woodproduct_mass diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index bdd670b671..3fb833060c 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -265,9 +265,14 @@ module EDPftvarcon real(r8), allocatable :: hydr_thetas_node(:,:) ! saturated water content (cm3/cm3) ! Table that maps HLM pfts to FATES pfts for fixed biogeography mode - ! The values are area fractions (NOT IMPLEMENTED) + ! The values are area fractions real(r8), allocatable :: hlm_pft_map(:,:) + ! Land-use and land-use change related PFT parameters + real(r8), allocatable :: harvest_pprod10(:) ! fraction of harvest wood product that goes to 10-year product pool (remainder goes to 100-year pool) + real(r8), allocatable :: landusechange_frac_burned(:) ! fraction of land use change-generated and not-exported material that is burned (the remainder goes to litter) + real(r8), allocatable :: landusechange_frac_exported(:) ! fraction of land use change-generated wood material that is exported to wood product (the remainder is either burned or goes to litter) + real(r8), allocatable :: landusechange_pprod10(:) ! fraction of land use change wood product that goes to 10-year product pool (remainder goes to 100-year pool) contains procedure, public :: Init => EDpftconInit @@ -760,6 +765,22 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_landuse_harvest_pprod10' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_landuse_landusechange_frac_burned' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_landuse_landusechange_frac_exported' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_landuse_landusechange_pprod10' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_dev_arbitrary_pft' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -1204,6 +1225,22 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%hlm_pft_map) + name = 'fates_landuse_harvest_pprod10' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%harvest_pprod10) + + name = 'fates_landuse_landusechange_frac_burned' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%landusechange_frac_burned) + + name = 'fates_landuse_landusechange_frac_exported' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%landusechange_frac_exported) + + name = 'fates_landuse_landusechange_pprod10' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%landusechange_pprod10) + end subroutine Receive_PFT !----------------------------------------------------------------------- diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 1ad7488bf5..cc145f31c6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -345,6 +345,12 @@ variables: double fates_landuse_harvest_pprod10(fates_pft) ; fates_landuse_harvest_pprod10:units = "fraction" ; fates_landuse_harvest_pprod10:long_name = "fraction of harvest wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; + double fates_landuse_landusechange_frac_burned(fates_pft) ; + fates_landuse_landusechange_frac_burned:units = "fraction" ; + fates_landuse_landusechange_frac_burned:long_name = "fraction of land use change-generated and not-exported material that is burned (the remainder goes to litter)" ; + double fates_landuse_landusechange_frac_exported(fates_pft) ; + fates_landuse_landusechange_frac_exported:units = "fraction" ; + fates_landuse_landusechange_frac_exported:long_name = "fraction of land use change-generated wood material that is exported to wood product (the remainder is either burned or goes to litter)" ; double fates_landuse_landusechange_pprod10(fates_pft) ; fates_landuse_landusechange_pprod10:units = "fraction" ; fates_landuse_landusechange_pprod10:long_name = "fraction of land use change wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; @@ -1272,6 +1278,17 @@ data: 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + fates_landuse_harvest_pprod10 = 1, 0.75, 0.75, 0.75, 1, 0.75, 1, 1, 1, 1, 1, 1 ; + + fates_landuse_landusechange_frac_burned = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_landuse_landusechange_frac_exported = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.2, 0.2, 0.2, 0, 0, 0 ; + + fates_landuse_landusechange_pprod10 = 1, 0.75, 0.75, 0.75, 1, 0.75, 1, 1, 1, + 1, 1, 1 ; + fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, From c823fb6ad13c51da6c7b2dd5427a03a8088ff710 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Fri, 13 Oct 2023 13:04:21 -0700 Subject: [PATCH 024/300] do nocomp PFT shuffle for newly secondary lands as well in case primary and secondary PFT maps differ --- biogeochem/EDPatchDynamicsMod.F90 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 21770fb234..0908b1944c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -710,6 +710,11 @@ subroutine spawn_patches( currentSite, bc_in) case (dtype_ilog) call logging_litter_fluxes(currentSite, currentPatch, & newPatch, patch_site_areadis,bc_in) + + ! if transitioning from primary to secondary, then may need to change nocomp pft, so tag as having transitioned LU + if ( i_disturbance_type .eq. ilog .and. i_donorpatch_landuse_type .eq. primarylands) then + newPatch%changed_landuse_this_ts = .true. + end if case (dtype_ifire) call fire_litter_fluxes(currentSite, currentPatch, & newPatch, patch_site_areadis,bc_in) @@ -721,6 +726,7 @@ subroutine spawn_patches( currentSite, bc_in) newPatch, patch_site_areadis,bc_in, & clearing_matrix(i_donorpatch_landuse_type,i_landusechange_receiverpatchlabel)) + ! if land use change, then may need to change nocomp pft, so tag as having transitioned LU new_patch%changed_landuse_this_ts = .true. case default write(fates_log(),*) 'unknown disturbance mode?' @@ -1430,6 +1436,13 @@ subroutine spawn_patches( currentSite, bc_in) end if end do lu_loop + else + ! if not using a configuration where the changed_landuse_this_ts is relevant, loop through all patches and reset it + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + currentPatch%changed_landuse_this_ts = .false. + currentPatch => currentPatch%younger + end do endif nocomp_and_luh_if !zero disturbance rate trackers on all patches From 4c70855adbe6ea3e9491877dfbc335e686828232 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 16 Oct 2023 10:24:50 -0700 Subject: [PATCH 025/300] add old values as comment in xml patch file --- .../archive/api27.0.0_062823_pr1093.xml | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/parameter_files/archive/api27.0.0_062823_pr1093.xml b/parameter_files/archive/api27.0.0_062823_pr1093.xml index b375ac8654..6373af493d 100644 --- a/parameter_files/archive/api27.0.0_062823_pr1093.xml +++ b/parameter_files/archive/api27.0.0_062823_pr1093.xml @@ -21,42 +21,62 @@ fates_pft - 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, 0.07286975, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 + + 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, 0.07286975, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 fates_pft + 0.976, 0.94490413, 1.08733502, 0.83213205, 0.976, 1.03732112, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 fates_pft + 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 fates_pft + -0.12366731, -0.3447603, -0.31791391, -0.21568348, -0.12366731, -0.3521357, 0, 0, 0, 0, 0, 0 fates_pft + 78.40877039, 306.842667, 106.8745821, 104.3586841, 78.40877039, 29.69929379, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 fates_pft + 0.81243829, 0.75237703, 0.94713018, 1.11469727, 0.81243829, 1.12959569, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 fates_pft + 47.66661644, 196.6865691, 93.97904614, 160.6835089, 47.66661644, 25.12579143, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 fates_pft + 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, 0.35, 0.35, 0.35 fates_pft + 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 fates_pft + 0.548327, 0.442350, 0.454845, 0.754336, 0.548327, 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 From 75df884de9bb96b7b1db5a77af61c7b7771064e1 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 18 Oct 2023 12:42:05 -0700 Subject: [PATCH 026/300] various compile-time bugfixes --- biogeochem/EDLoggingMortalityMod.F90 | 6 +++-- biogeochem/EDPatchDynamicsMod.F90 | 39 ++++++++++++++-------------- biogeochem/FatesLandUseChangeMod.F90 | 7 ++--- main/EDInitMod.F90 | 3 ++- main/EDMainMod.F90 | 2 +- main/EDParamsMod.F90 | 7 +++-- main/FatesHistoryInterfaceMod.F90 | 2 +- main/FatesRestartInterfaceMod.F90 | 1 + 8 files changed, 37 insertions(+), 30 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index c6e8ea92fb..9eb7fa615f 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -70,7 +70,8 @@ module EDLoggingMortalityMod use FatesConstantsMod , only : hlm_harvest_carbon use FatesConstantsMod, only : fates_check_param_set use FatesInterfaceTypesMod , only : numpft - + use FatesLandUseChangeMod, only : get_init_landuse_harvest_rate + implicit none private @@ -205,7 +206,8 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, harvest_tag) ! Arguments - type(ed_site_type), intent(in), target :: currentSite ! site structure + type(ed_site_type), intent(in), target :: currentSite ! site structure + type(bc_in_type), intent(in) :: bc_in integer, intent(in) :: pft_i ! pft index real(r8), intent(in) :: dbh ! diameter at breast height (cm) integer, intent(in) :: canopy_layer ! canopy layer of this cohort diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 93efa77793..cf6713009c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -72,6 +72,7 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : get_harvest_rate_carbon use EDLoggingMortalityMod, only : get_harvestable_carbon use EDLoggingMortalityMod, only : get_harvest_debt + use FatesLandUseChangeMod, only : get_init_landuse_harvest_rate use EDParamsMod , only : fates_mortality_disturbance_fraction use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction @@ -83,6 +84,7 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : primaryland, secondaryland, pastureland, rangeland, cropland use FatesConstantsMod , only : n_landuse_cats use FatesLandUseChangeMod, only : get_landuse_transition_rates + use FatesLandUseChangeMod, only : get_init_landuse_transition_rates use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : hlm_harvest_carbon @@ -498,7 +500,7 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: disturbance_rate ! rate of disturbance being resolved [fraction of patch area / day] real(r8) :: oldarea ! old patch area prior to disturbance logical :: clearing_matrix(n_landuse_cats,n_landuse_cats) ! do we clear vegetation when transferring from one LU type to another? - type (ed_patch_type) , pointer :: buffer_patch, temp_patch + type (fates_patch_type) , pointer :: buffer_patch, temp_patch real(r8) :: nocomp_pft_area_vector(numpft) real(r8) :: nocomp_pft_area_vector_allocated(numpft) real(r8) :: fraction_to_keep @@ -712,7 +714,7 @@ subroutine spawn_patches( currentSite, bc_in) newPatch, patch_site_areadis,bc_in) ! if transitioning from primary to secondary, then may need to change nocomp pft, so tag as having transitioned LU - if ( i_disturbance_type .eq. ilog .and. i_donorpatch_landuse_type .eq. primarylands) then + if ( i_disturbance_type .eq. dtype_ilog .and. i_donorpatch_landuse_type .eq. primaryland) then newPatch%changed_landuse_this_ts = .true. end if case (dtype_ifire) @@ -727,7 +729,7 @@ subroutine spawn_patches( currentSite, bc_in) clearing_matrix(i_donorpatch_landuse_type,i_landusechange_receiverpatchlabel)) ! if land use change, then may need to change nocomp pft, so tag as having transitioned LU - new_patch%changed_landuse_this_ts = .true. + newPatch%changed_landuse_this_ts = .true. case default write(fates_log(),*) 'unknown disturbance mode?' write(fates_log(),*) 'i_disturbance_type: ',i_disturbance_type @@ -1222,7 +1224,7 @@ subroutine spawn_patches( currentSite, bc_in) newPatch%shortest => nc nc%shorter => null() endif - !nc%patchptr => new_patch + call insert_cohort(newPatch, nc, newPatch%tallest, newPatch%shortest, & tnull, snull, storebigcohort, storesmallcohort) @@ -1335,7 +1337,7 @@ subroutine spawn_patches( currentSite, bc_in) end do ! create buffer patch to put all of the pieces carved off of other patches - buffer_patch%Create(0._r8, 0._r8, i_land_use_label, 0, & + call buffer_patch%Create(0._r8, 0._r8, i_land_use_label, 0, & hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & regeneration_model) @@ -1463,27 +1465,24 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) ! !DESCRIPTION: ! Split a patch into two patches that are identical except in their areas ! - ! !USES: - use EDCohortDynamicsMod , only : zero_cohort, copy_cohort - ! ! !ARGUMENTS: type(ed_site_type),intent(inout) :: currentSite - type(ed_patch_type) , intent(inout), target :: currentPatch ! Donor Patch - type(ed_patch_type) , intent(inout), target :: new_patch ! New Patch + type(fates_patch_type) , intent(inout), target :: currentPatch ! Donor Patch + type(fates_patch_type) , intent(inout), target :: new_patch ! New Patch real(r8), intent(in) :: fraction_to_keep ! fraction of currentPatch to keep, the rest goes to newpatch ! ! !LOCAL VARIABLES: integer :: el ! element loop index - type (ed_cohort_type), pointer :: nc - type (ed_cohort_type), pointer :: storesmallcohort - type (ed_cohort_type), pointer :: storebigcohort - type (ed_cohort_type), pointer :: currentCohort + type (fates_cohort_type), pointer :: nc + type (fates_cohort_type), pointer :: storesmallcohort + type (fates_cohort_type), pointer :: storebigcohort + type (fates_cohort_type), pointer :: currentCohort integer :: tnull ! is there a tallest cohort? integer :: snull ! is there a shortest cohort? ! first we need to make the new patch - new_patch%Create(0._r8, & + call new_patch%Create(0._r8, & currentPatch%area * (1._r8 - fraction_to_keep), currentPatch%land_use_label, currentPatch%nocomp_pft_label, & hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & regeneration_model) @@ -1533,11 +1532,11 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) !allocate(nc%tveg_lpa) !call nc%tveg_lpa%InitRMean(ema_lpa,init_value=new_patch%tveg_lpa%GetMean()) - call zero_cohort(nc) + call nc%ZeroValues() ! nc is the new cohort that goes in the disturbed patch (new_patch)... currentCohort ! is the curent cohort that stays in the donor patch (currentPatch) - call copy_cohort(currentCohort, nc) + call currentCohort%Copy(nc) ! Number of members in the new patch nc%n = currentCohort%n * fraction_to_keep @@ -1562,8 +1561,8 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) new_patch%shortest => nc nc%shorter => null() endif - nc%patchptr => new_patch - call insert_cohort(nc, new_patch%tallest, new_patch%shortest, & + + call insert_cohort(new_patch, nc, new_patch%tallest, new_patch%shortest, & tnull, snull, storebigcohort, storesmallcohort) new_patch%tallest => storebigcohort @@ -3595,7 +3594,7 @@ subroutine InsertPatch(currentSite, newPatch) ! In the case in which we get to the end of the list and haven't found ! a landuse label match. - ! If the new patch is primarylands add it to the oldest end of the list + ! If the new patch is primaryland add it to the oldest end of the list if (newPatch%land_use_label .eq. primaryland) then newPatch%older => null() newPatch%younger => currentSite%oldest_patch diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 65451f8b6c..3331410b24 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -29,7 +29,8 @@ module FatesLandUseChangeMod public :: get_landuse_transition_rates public :: get_landusechange_rules public :: get_luh_statedata - + public :: get_init_landuse_transition_rates + public :: get_init_landuse_harvest_rate ! module data integer, parameter :: max_luh2_types_per_fates_lu_type = 5 @@ -323,7 +324,7 @@ subroutine get_init_landuse_harvest_rate(bc_in, harvest_rate) end subroutine get_init_landuse_harvest_rate - subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) + subroutine get_init_landuse_transition_rates(bc_in, landuse_transition_matrix) ! The purose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for @@ -345,6 +346,6 @@ subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) landuse_transition_matrix(1,i) = state_vector(i) end do - end subroutine get_landuse_transition_rates + end subroutine get_init_landuse_transition_rates end module FatesLandUseChangeMod diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 78bfcd8875..7f49e1aa27 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -386,6 +386,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) integer :: fates_pft ! used in fixed biogeog mode integer :: i_landusetype real(r8) :: temp_vec(numpft) ! temporary vector + integer :: i_pftcount !---------------------------------------------------------------------- @@ -528,7 +529,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) if (hlm_use_nocomp .eq. itrue) then do i_landusetype = 1, n_landuse_cats ! count how many PFTs have areas greater than zero and compare to the number of patches allowed - if (COUNT(sites(s)%area_pft(ft, i_landusetype) .gt. 0._r8) > maxpatches_by_landuse(i_landusetype)) then + if (COUNT(sites(s)%area_pft(:, i_landusetype) .gt. 0._r8) > maxpatches_by_landuse(i_landusetype)) then ! write current vector to log file if(debug) write(fates_log(),*) 'too many PFTs for LU type ', i_landusetype, i_landusetype,sites(s)%area_pft(:, i_landusetype) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 97b54c5dba..745110ff9a 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -227,7 +227,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) ! at this point in the call sequence, if flag to transition_landuse_from_off_to_on was set, unset it as it is no longer needed if(currentSite%transition_landuse_from_off_to_on) then - currentSite%transition_landuse_from_off_to_on = .false + currentSite%transition_landuse_from_off_to_on = .false. endif else diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 9d3391ada3..dbdf75dcbe 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -147,7 +147,6 @@ module EDParamsMod real(r8),protected,allocatable,public :: ED_val_history_height_bin_edges(:) real(r8),protected,allocatable,public :: ED_val_history_coageclass_bin_edges(:) real(r8),protected,allocatable,public :: ED_val_history_damage_bin_edges(:) - real(r8),protected,allocatable,public :: crop_lu_pft_vector(:) ! Switch that defines the current pressure-volume and pressure-conductivity model ! to be used at each node (compartment/organ) @@ -256,6 +255,9 @@ module EDParamsMod integer, public :: maxpatches_by_landuse(n_landuse_cats) integer, public :: maxpatch_total + ! which crops can be grown on a given crop land use type + real(r8),protected,public :: crop_lu_pft_vector(n_landuse_cats) + ! Maximum allowable cohorts per patch integer, protected, public :: max_cohort_per_patch character(len=param_string_length), parameter, public :: maxcohort_name = "fates_maxcohort" @@ -631,7 +633,7 @@ subroutine FatesReceiveParams(fates_params) real(r8) :: tmpreal ! local real variable for changing type on read real(r8), allocatable :: hydr_htftype_real(:) - real(r8) :: tmp_vector_by_landuse(n_landuse_cats) ! local real vector for changing type on read + real(r8), allocatable :: tmp_vector_by_landuse(:) ! local real vector for changing type on read call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) @@ -841,6 +843,7 @@ subroutine FatesReceiveParams(fates_params) data=tmp_vector_by_landuse) crop_lu_pft_vector(:) = nint(tmp_vector_by_landuse(:)) + deallocate(tmp_vector_by_landuse) call fates_params%RetrieveParameter(name=ED_name_maxpatches_by_landuse, & data=tmp_vector_by_landuse) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 60bcabc7be..f600a6f977 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2391,7 +2391,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_logging_disturbance_rate_si => this%hvars(ih_logging_disturbance_rate_si)%r81d, & hio_fall_disturbance_rate_si => this%hvars(ih_fall_disturbance_rate_si)%r81d, & hio_harvest_woodproduct_carbonflux_si => this%hvars(ih_harvest_woodproduct_carbonflux_si)%r81d, & - hio_landusechange_woodproduct_carbonflux_si => this%hvars(ih_woodproduct_carbonflux_si)%r81d, & + hio_landusechange_woodproduct_carbonflux_si => this%hvars(ih_landusechange_woodproduct_carbonflux_si)%r81d, & hio_harvest_debt_si => this%hvars(ih_harvest_debt_si)%r81d, & hio_harvest_debt_sec_si => this%hvars(ih_harvest_debt_sec_si)%r81d, & hio_gpp_si_scpf => this%hvars(ih_gpp_si_scpf)%r82d, & diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 089534d347..741425caf6 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -2104,6 +2104,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_abg_fmort_flux_siscpf => this%rvars(ir_abg_fmort_flux_siscpf)%r81d, & rio_abg_term_flux_siscpf => this%rvars(ir_abg_term_flux_siscpf)%r81d, & rio_disturbance_rates_siluludi => this%rvars(ir_disturbance_rates_siluludi)%r81d, & + rio_landuse_config_si => this%rvars(ir_landuse_config_si)%int1d, & rio_imortrate_sicdpf => this%rvars(ir_imortrate_sicdpf)%r81d, & rio_imortcflux_sicdsc => this%rvars(ir_imortcflux_sicdsc)%r81d, & From b2e427d63c6795b739e4765a2b46fc34195a7a6a Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 18 Oct 2023 16:50:32 -0700 Subject: [PATCH 027/300] more compile-time bugfixes --- biogeochem/EDPatchDynamicsMod.F90 | 4 ++-- main/EDInitMod.F90 | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index cf6713009c..79620c170f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1425,7 +1425,7 @@ subroutine spawn_patches( currentSite, bc_in) buffer_patch => null() else if (buffer_patch%area .lt. fates_tiny) then ! here we need to deallocate the buffer patch so that we don't get a memory leak/ - call dealloc_patch(buffer_patch) + call buffer_patch%FreeMemory(regeneration_model, numpft) deallocate(buffer_patch, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) @@ -1525,7 +1525,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) ! correct boundary condition fields nc%prt => null() call InitPRTObject(nc%prt) - call InitPRTBoundaryConditions(nc) + call nc%InitPRTBoundaryConditions() ! (Keeping as an example) ! Allocate running mean functions diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 7f49e1aa27..2cb6b77d12 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -712,7 +712,9 @@ subroutine init_patches( nsites, sites, bc_in) allocate(newp) - call create_patch(sites(s), newp, age, newparea, nocomp_bareground_land, nocomp_bareground) + call newp%Create(age, newparea, nocomp_bareground_land, nocomp_bareground, & + hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod, & + regeneration_model) ! set poointers for first patch (or only patch, if nocomp is false) newp%patchno = 1 From a967b7f83217d64c628b54e1e64e23c58ec2b5a7 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 19 Oct 2023 20:31:53 -0700 Subject: [PATCH 028/300] various runtime-failure fixes and attempted fixes --- biogeochem/EDLoggingMortalityMod.F90 | 18 +++--- biogeochem/EDMortalityFunctionsMod.F90 | 5 +- biogeochem/EDPatchDynamicsMod.F90 | 39 ++++++++++-- biogeochem/FatesLandUseChangeMod.F90 | 2 +- main/EDInitMod.F90 | 78 ++++++++++++++---------- main/EDMainMod.F90 | 5 +- main/EDParamsMod.F90 | 29 +++------ main/EDPftvarcon.F90 | 12 ++-- main/FatesConstantsMod.F90 | 3 + parameter_files/fates_params_default.cdl | 33 +++++----- 10 files changed, 132 insertions(+), 92 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 9eb7fa615f..8f7359a7cb 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -202,7 +202,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, hlm_harvest_rates, hlm_harvest_catnames, & hlm_harvest_units, & patch_land_use_label, secondary_age, & - frac_site_primary, harvestable_forest_c, & + frac_site_primary, frac_site_secondary, harvestable_forest_c, & harvest_tag) ! Arguments @@ -219,6 +219,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, real(r8), intent(in) :: harvestable_forest_c(:) ! total harvestable forest carbon ! of all hlm harvest categories real(r8), intent(in) :: frac_site_primary + real(r8), intent(in) :: frac_site_secondary real(r8), intent(out) :: lmort_direct ! direct (harvestable) mortality fraction real(r8), intent(out) :: lmort_collateral ! collateral damage mortality fraction real(r8), intent(out) :: lmort_infra ! infrastructure mortality fraction @@ -271,7 +272,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, ! Get the area-based harvest rates based on info passed to FATES from the boundary condition call get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, & - hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) + hlm_harvest_rates, frac_site_primary, frac_site_secondary, secondary_age, harvest_rate) ! For area-based harvest, harvest_tag shall always be 2 (not applicable). harvest_tag = 2 @@ -361,7 +362,7 @@ end subroutine LoggingMortality_frac ! ============================================================================ subroutine get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, hlm_harvest_rates, & - frac_site_primary, secondary_age, harvest_rate) + frac_site_primary, frac_site_secondary, secondary_age, harvest_rate) ! ------------------------------------------------------------------------------------------- @@ -376,6 +377,7 @@ subroutine get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, hl integer, intent(in) :: patch_land_use_label ! patch level land_use_label real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance real(r8), intent(in) :: frac_site_primary + real(r8), intent(in) :: frac_site_secondary real(r8), intent(out) :: harvest_rate ! Local Variables @@ -414,13 +416,15 @@ subroutine get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, hl else harvest_rate = 0._r8 endif - else - if ((1._r8-frac_site_primary) .gt. fates_tiny) then - harvest_rate = min((harvest_rate / (1._r8-frac_site_primary)),& - (1._r8-frac_site_primary)) + else if (patch_land_use_label .eq. secondaryland) then + if (frac_site_secondary .gt. fates_tiny) then + harvest_rate = min((harvest_rate / frac_site_secondary), frac_site_secondary) else harvest_rate = 0._r8 endif + else + write(fates_log(),*) 'errror - trying to log from patches that are neither primary nor secondary' + call endrun(msg=errMsg(sourcefile, __LINE__)) endif ! calculate today's harvest rate diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 5136af67f0..71cccb03ad 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -233,7 +233,7 @@ end subroutine mortality_rates subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, btran_ft, & mean_temp, land_use_label, age_since_anthro_disturbance, & - frac_site_primary, harvestable_forest_c, harvest_tag) + frac_site_primary, frac_site_secondary, harvestable_forest_c, harvest_tag) ! ! !DESCRIPTION: @@ -253,6 +253,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, btran_ft, & integer, intent(in) :: land_use_label real(r8), intent(in) :: age_since_anthro_disturbance real(r8), intent(in) :: frac_site_primary + real(r8), intent(in) :: frac_site_secondary real(r8), intent(in) :: harvestable_forest_c(:) ! total carbon available for logging, kgC site-1 integer, intent(out) :: harvest_tag(:) ! tag to record the harvest status @@ -291,7 +292,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, btran_ft, & bc_in%hlm_harvest_units, & land_use_label, & age_since_anthro_disturbance, & - frac_site_primary, harvestable_forest_c, harvest_tag) + frac_site_primary, frac_site_secondary, harvestable_forest_c, harvest_tag) if (currentCohort%canopy_layer > 1)then ! Include understory logging mortality rates not associated with disturbance diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 79620c170f..3a9aa44aad 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -43,6 +43,7 @@ module EDPatchDynamicsMod use FatesLitterMod , only : dl_sf use FatesConstantsMod , only : N_DIST_TYPES use EDTypesMod , only : AREA_INV + use EDTypesMod , only : dump_site use FatesConstantsMod , only : rsnbl_math_prec use FatesConstantsMod , only : fates_tiny use FatesConstantsMod , only : nocomp_bareground @@ -207,6 +208,7 @@ subroutine disturbance_rates( site_in, bc_in) integer :: i_dist integer :: h_index real(r8) :: frac_site_primary + real(r8) :: frac_site_secondary real(r8) :: harvest_rate real(r8) :: tempsum real(r8) :: mean_temp @@ -220,7 +222,7 @@ subroutine disturbance_rates( site_in, bc_in) !---------------------------------------------------------------------------------------------- ! first calculate the fraction of the site that is primary land - call get_frac_site_primary(site_in, frac_site_primary) + call get_frac_site_primary(site_in, frac_site_primary, frac_site_secondary) ! check status of transition_landuse_from_off_to_on flag, and do some error checking on it if(site_in%transition_landuse_from_off_to_on) then @@ -265,6 +267,7 @@ subroutine disturbance_rates( site_in, bc_in) currentPatch%land_use_label, & currentPatch%age_since_anthro_disturbance, & frac_site_primary, & + frac_site_secondary, & harvestable_forest_c, & harvest_tag) @@ -383,7 +386,8 @@ subroutine disturbance_rates( site_in, bc_in) harvest_rate, harvest_tag) else call get_harvest_rate_area (currentPatch%land_use_label, bc_in%hlm_harvest_catnames, & - bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate) + bc_in%hlm_harvest_rates, frac_site_primary, frac_site_secondary, & + currentPatch%age_since_anthro_disturbance, harvest_rate) end if else call get_init_landuse_harvest_rate(bc_in, harvest_rate) @@ -1337,6 +1341,8 @@ subroutine spawn_patches( currentSite, bc_in) end do ! create buffer patch to put all of the pieces carved off of other patches + allocate(buffer_patch) + call buffer_patch%Create(0._r8, 0._r8, i_land_use_label, 0, & hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & regeneration_model) @@ -1367,6 +1373,8 @@ subroutine spawn_patches( currentSite, bc_in) elseif (fraction_to_keep .lt. (1._r8 - nearzero)) then ! we have more patch are of this PFT than we want, but we do want to keep some of it. ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. + + allocate(temp_patch) call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep) ! temp_patch%nocomp_pft_label = 0 @@ -1391,6 +1399,7 @@ subroutine spawn_patches( currentSite, bc_in) if (newp_area .lt. buffer_patch%area) then ! split buffer patch in two, keeping the smaller buffer patch to put into new patches + allocate(temp_patch) call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) ! give the new patch the intended nocomp PFT label @@ -3217,7 +3226,7 @@ subroutine terminate_patches(currentSite) if ( .not. gotfused ) then !! somehow didn't find a patch to fuse with. write(fates_log(),*) 'Warning. small nocomp patch wasnt able to find another patch to fuse with.', & - currentPatch%nocomp_pft_label, currentPatch%land_use_label + currentPatch%nocomp_pft_label, currentPatch%land_use_label, currentPatch%area endif else nocomp_if @@ -3326,7 +3335,15 @@ subroutine terminate_patches(currentSite) write(fates_log(),*) 'is very very small. You can test your luck by' write(fates_log(),*) 'disabling the endrun statement following this message.' write(fates_log(),*) 'FATES may or may not continue to operate within error' - write(fates_log(),*) 'tolerances, but will generate another fail if it does not.' + write(fates_log(),*) 'tolerances, but will generate another fail if it does not.' + write(fates_log(),*) 'otherwise, dumping some diagnostics.' + write(fates_log(),*) currentPatch%area, currentPatch%nocomp_pft_label, currentPatch%land_use_label + call dump_site(currentSite) + patchpointer => currentSite%youngest_patch + do while(associated(patchpointer)) + write(fates_log(),*) patchpointer%area, patchpointer%nocomp_pft_label, patchpointer%land_use_label + patchpointer => patchpointer%older + end do call endrun(msg=errMsg(sourcefile, __LINE__)) ! Note to user. If you DO decide to remove the end-run above this line @@ -3464,11 +3481,11 @@ end function countPatches ! ===================================================================================== - subroutine get_frac_site_primary(site_in, frac_site_primary) + subroutine get_frac_site_primary(site_in, frac_site_primary, frac_site_secondary) ! ! !DESCRIPTION: - ! Calculate how much of a site is primary land + ! Calculate how much of a site is primary land and secondary land ! ! !USES: use EDTypesMod , only : ed_site_type @@ -3476,6 +3493,7 @@ subroutine get_frac_site_primary(site_in, frac_site_primary) ! !ARGUMENTS: type(ed_site_type) , intent(in), target :: site_in real(r8) , intent(out) :: frac_site_primary + real(r8) , intent(out) :: frac_site_secondary ! !LOCAL VARIABLES: type (fates_patch_type), pointer :: currentPatch @@ -3489,6 +3507,15 @@ subroutine get_frac_site_primary(site_in, frac_site_primary) currentPatch => currentPatch%younger end do + frac_site_secondary = 0._r8 + currentPatch => site_in%oldest_patch + do while (associated(currentPatch)) + if (currentPatch%land_use_label .eq. secondaryland) then + frac_site_secondary = frac_site_secondary + currentPatch%area * AREA_INV + endif + currentPatch => currentPatch%younger + end do + end subroutine get_frac_site_primary ! ===================================================================================== diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 3331410b24..b3d6522940 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -263,7 +263,7 @@ subroutine get_luh_statedata(bc_in, state_vector) ! check to ensure total area == 1, and correct if not if ( abs(sum(state_vector(:)) - 1._r8) .gt. nearzero ) then write(fates_log(),*) 'warning: sum(state_vector) = ', sum(state_vector(:)) - state_vector = state_vector / sum(state_vector) + state_vector = state_vector(:) / sum(state_vector(:)) end if end subroutine get_luh_statedata diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 2cb6b77d12..567a6c1bfe 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -10,6 +10,8 @@ module EDInitMod use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : primaryland use FatesConstantsMod , only : nearzero + use FatesConstantsMod , only : rsnbl_math_prec + use FatesConstantsMod , only : min_init_patch_size use FatesConstantsMod , only : n_landuse_cats use FatesConstantsMod , only : is_crop use FatesConstantsMod , only : fates_unset_r8 @@ -100,7 +102,7 @@ module EDInitMod implicit none private - logical :: debug = .false. + logical :: debug = .true. integer :: istat ! return status code character(len=255) :: smsg ! Message string for deallocation errors @@ -475,12 +477,13 @@ subroutine set_site_properties( nsites, sites,bc_in ) endif end do - sites(s)%area_bareground = bc_in(s)%baregroundfrac * area + sites(s)%area_bareground = bc_in(s)%baregroundfrac else if ( all( isnan( bc_in(s)%pft_areafrac_lu (:,:) ))) then ! if given all NaNs, then make everything bare ground sites(s)%area_bareground = 1._r8 sites(s)%area_pft(:,:) = 0._r8 + sites(s)%area_pft(1,:) = 1._r8 else ! if only some things are NaN but not all, then something terrible has probably happened. crash. write(fates_log(),*) 'some but, not all, of the data in the PFT by LU matrix at this site is NaN.' @@ -617,13 +620,13 @@ subroutine init_patches( nsites, sites, bc_in) real(r8) :: seed_stock integer :: n integer :: start_patch - integer :: num_new_patches + integer :: num_nocomp_pfts integer :: nocomp_pft real(r8) :: newparea, newparea_withlanduse real(r8) :: total !check on area real(r8) :: litt_init !invalid for satphen, 0 otherwise real(r8) :: old_carea - integer :: is_first_patch + logical :: is_first_patch ! integer :: n_luh_states ! integer :: luh_state_counter real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] @@ -682,9 +685,9 @@ subroutine init_patches( nsites, sites, bc_in) sites(s)%spread = init_spread_near_bare_ground if(hlm_use_nocomp.eq.itrue)then - num_new_patches = numpft + num_nocomp_pfts = numpft else !default - num_new_patches = 1 + num_nocomp_pfts = 1 end if !nocomp ! read in luh state data to determine initial land use types @@ -704,10 +707,20 @@ subroutine init_patches( nsites, sites, bc_in) state_vector(primaryland) = 1._r8 endif - is_first_patch = itrue + ! confirm that state vector sums to 1. + if (abs(sum(state_vector(:))-1._r8) .gt. rsnbl_math_prec) then + write(fates_log(),*) 'error that the state vector must sum to 1, but doesnt' + write(fates_log(),*) 'sum(state_vector)', sum(state_vector) + write(fates_log(),*) state_vector + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + is_first_patch = .true. ! first make a bare-ground patch if one is needed. - make_bareground_patch_if: if (hlm_use_nocomp.eq.itrue .and. hlm_use_fixed_biogeog .eq.itrue .and. sites(s)%area_bareground .gt. 0._r8) then + make_bareground_patch_if: if (hlm_use_nocomp.eq.itrue .and. hlm_use_fixed_biogeog .eq.itrue .and. & + (area*sites(s)%area_bareground) .gt. min_init_patch_size) then + newparea = area * sites(s)%area_bareground allocate(newp) @@ -722,7 +735,7 @@ subroutine init_patches( nsites, sites, bc_in) newp%older => null() sites(s)%youngest_patch => newp sites(s)%oldest_patch => newp - is_first_patch = ifalse + is_first_patch = .false. ! Initialize the litter pools to zero, these ! pools will be populated by looping over the existing patches @@ -744,9 +757,9 @@ subroutine init_patches( nsites, sites, bc_in) endif ! now make one or more vegetated patches based on nocomp and land use logic - new_patch_nocomp_loop: do n = 1, num_new_patches - luh_state_loop: do i_lu_state = 1, end_landuse_idx - lu_state_present_if: if (state_vector(i_lu_state) .gt. nearzero) then + luh_state_loop: do i_lu_state = 1, end_landuse_idx + lu_state_present_if: if (state_vector(i_lu_state) .gt. rsnbl_math_prec) then + new_patch_nocomp_loop: do n = 1, num_nocomp_pfts ! set the PFT index for patches if in nocomp mode. if(hlm_use_nocomp.eq.itrue)then nocomp_pft = n @@ -762,32 +775,32 @@ subroutine init_patches( nsites, sites, bc_in) ! i.e. each grid cell is divided exactly into the number of FATES PFTs. if(hlm_use_fixed_biogeog.eq.itrue)then - newparea = sites(s)%area_pft(nocomp_pft,i_lu_state) * area / state_vector(i_lu_state) + newparea = sites(s)%area_pft(nocomp_pft,i_lu_state) * area * state_vector(i_lu_state) & + * (1._r8 - sites(s)%area_bareground) else - newparea = area / ( numpft * state_vector(i_lu_state)) + newparea = area * state_vector(i_lu_state) / numpft end if else ! The default case is initialized w/ one patch with the area of the whole site. - newparea = area / state_vector(i_lu_state) + newparea = area * state_vector(i_lu_state) end if !nocomp mode - ! for now, spread nocomp PFTs evenly across land use types - new_patch_area_gt_zero: if(newparea.gt.0._r8)then ! Stop patches being initilialized when PFT not present in nocomop mode + new_patch_area_gt_zero: if(newparea .gt. min_init_patch_size) then ! Stop patches being initilialized when PFT not present in nocomop mode allocate(newp) call newp%Create(age, newparea, i_lu_state, nocomp_pft, & hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod, & regeneration_model) - if(is_first_patch.eq.itrue)then !is this the first patch? + if (is_first_patch) then !is this the first patch? ! set poointers for first patch (or only patch, if nocomp is false) newp%patchno = 1 newp%younger => null() newp%older => null() sites(s)%youngest_patch => newp sites(s)%oldest_patch => newp - is_first_patch = ifalse + is_first_patch = .false. else - ! Set pointers for N>1 patches. Note this only happens when nocomp mode s on. + ! Set pointers for N>1 patches. Note this only happens when nocomp mode is on, or land use is on. ! The new patch is the 'youngest' one, arbitrarily. newp%patchno = nocomp_pft + (i_lu_state-1) * numpft newp%older => sites(s)%youngest_patch @@ -817,9 +830,9 @@ subroutine init_patches( nsites, sites, bc_in) call init_cohorts(sitep, newp, bc_in(s)) end if new_patch_area_gt_zero - end if lu_state_present_if - end do luh_state_loop - end do new_patch_nocomp_loop !no new patches + end do new_patch_nocomp_loop + end if lu_state_present_if + end do luh_state_loop !check if the total area adds to the same as site area total = 0.0_r8 @@ -832,22 +845,21 @@ subroutine init_patches( nsites, sites, bc_in) area_diff = total - area if (abs(area_diff) > nearzero) then if (abs(area_diff) < area_error_4) then ! this is a precision error - if (sites(s)%oldest_patch%area > area_diff + nearzero) then - ! remove or add extra area - ! if the oldest patch has enough area, use that - sites(s)%oldest_patch%area = sites(s)%oldest_patch%area - area_diff - if (debug) write(fates_log(),*) 'fixing patch precision - oldest', s, area_diff - else ! or otherwise take the area from the youngest patch. - sites(s)%youngest_patch%area = sites(s)%youngest_patch%area - area_diff - if (debug) write(fates_log(),*) 'fixing patch precision -youngest ', s, area_diff - end if + + ! adjust areas of all patches so that they add up to total area + newp => sites(s)%oldest_patch + do while (associated(newp)) + newp%area = newp%area * (area / total) + newp => newp%younger + end do + else !this is a big error not just a precision error. write(fates_log(),*) 'issue with patch area in EDinit', area_diff, total call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! big error end if ! too much patch area - ! we might have messed up patch area now - need to correct if SP mode + ! we might have messed up crown areas now - need to correct if SP mode if (hlm_use_sp .eq. itrue) then newp => sites(s)%oldest_patch do while (associated(newp)) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 745110ff9a..324cac5bd5 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -376,6 +376,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! because it inherited them (such as daily carbon balance) real(r8) :: target_leaf_c real(r8) :: frac_site_primary + real(r8) :: frac_site_secondary real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) @@ -411,7 +412,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) !----------------------------------------------------------------------- - call get_frac_site_primary(currentSite, frac_site_primary) + call get_frac_site_primary(currentSite, frac_site_primary, frac_site_secondary) ! Clear site GPP and AR passing to HLM bc_out%gpp_site = 0._r8 @@ -477,7 +478,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentPatch%btran_ft, mean_temp, & currentPatch%land_use_label, & currentPatch%age_since_anthro_disturbance, frac_site_primary, & - harvestable_forest_c, harvest_tag) + frac_site_secondary, harvestable_forest_c, harvest_tag) ! ----------------------------------------------------------------------------- ! Apply Plant Allocation and Reactive Transport diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index dbdf75dcbe..415059681e 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -299,10 +299,6 @@ module EDParamsMod ! leftovers will be left onsite as large CWD character(len=param_string_length),parameter,public :: logging_name_export_frac ="fates_landuse_logging_export_frac" - real(r8),protected,public :: pprodharv10_forest_mean ! "mean harvest mortality proportion of deadstem to 10-yr - ! product pool (pprodharv10) of all woody PFT types - character(len=param_string_length),parameter,public :: logging_name_pprodharv10="fates_landuse_pprodharv10_forest_mean" - real(r8),protected,public :: eca_plant_escalar ! scaling factor for plant fine root biomass to ! calculate nutrient carrier enzyme abundance (ECA) @@ -376,7 +372,6 @@ subroutine FatesParamsInit() logging_event_code = nan logging_dbhmax_infra = nan logging_export_frac = nan - pprodharv10_forest_mean = nan eca_plant_escalar = nan q10_mr = nan q10_froz = nan @@ -565,9 +560,6 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=logging_name_export_frac, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=logging_name_pprodharv10, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=eca_name_plant_escalar, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -633,8 +625,9 @@ subroutine FatesReceiveParams(fates_params) real(r8) :: tmpreal ! local real variable for changing type on read real(r8), allocatable :: hydr_htftype_real(:) - real(r8), allocatable :: tmp_vector_by_landuse(:) ! local real vector for changing type on read - + real(r8), allocatable :: tmp_vector_by_landuse1(:) ! local real vector for changing type on read + real(r8), allocatable :: tmp_vector_by_landuse2(:) ! local real vector for changing type on read + call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) @@ -787,9 +780,6 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetrieveParameter(name=logging_name_export_frac, & data=logging_export_frac) - call fates_params%RetrieveParameter(name=logging_name_pprodharv10, & - data=pprodharv10_forest_mean) - call fates_params%RetrieveParameter(name=eca_name_plant_escalar, & data=eca_plant_escalar) @@ -840,16 +830,17 @@ subroutine FatesReceiveParams(fates_params) data=ED_val_history_damage_bin_edges) call fates_params%RetrieveParameterAllocate(name=ED_name_crop_lu_pft_vector, & - data=tmp_vector_by_landuse) + data=tmp_vector_by_landuse1) - crop_lu_pft_vector(:) = nint(tmp_vector_by_landuse(:)) - deallocate(tmp_vector_by_landuse) + crop_lu_pft_vector(:) = nint(tmp_vector_by_landuse1(:)) + deallocate(tmp_vector_by_landuse1) - call fates_params%RetrieveParameter(name=ED_name_maxpatches_by_landuse, & - data=tmp_vector_by_landuse) + call fates_params%RetrieveParameterAllocate(name=ED_name_maxpatches_by_landuse, & + data=tmp_vector_by_landuse2) - maxpatches_by_landuse(:) = nint(tmp_vector_by_landuse(:)) + maxpatches_by_landuse(:) = nint(tmp_vector_by_landuse2(:)) maxpatch_total = sum(maxpatches_by_landuse(:)) + deallocate(tmp_vector_by_landuse2) call fates_params%RetrieveParameterAllocate(name=ED_name_hydr_htftype_node, & data=hydr_htftype_real) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 3fb833060c..26d1e03d6b 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -769,15 +769,15 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_landuse_landusechange_frac_burned' + name = 'fates_landuse_luc_frac_burned' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_landuse_landusechange_frac_exported' + name = 'fates_landuse_luc_frac_exported' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_landuse_landusechange_pprod10' + name = 'fates_landuse_luc_pprod10' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -1229,15 +1229,15 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%harvest_pprod10) - name = 'fates_landuse_landusechange_frac_burned' + name = 'fates_landuse_luc_frac_burned' call fates_params%RetrieveParameterAllocate(name=name, & data=this%landusechange_frac_burned) - name = 'fates_landuse_landusechange_frac_exported' + name = 'fates_landuse_luc_frac_exported' call fates_params%RetrieveParameterAllocate(name=name, & data=this%landusechange_frac_exported) - name = 'fates_landuse_landusechange_pprod10' + name = 'fates_landuse_luc_pprod10' call fates_params%RetrieveParameterAllocate(name=name, & data=this%landusechange_pprod10) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 8aeb51ffb9..c0790da103 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -178,6 +178,9 @@ module FatesConstantsMod ! precisions are preventing perfect zero in comparison real(fates_r8), parameter, public :: nearzero = 1.0e-30_fates_r8 + ! minimum init patch size for initialization in nocomp and/or land-use cases + real(fates_r8), parameter, public :: min_init_patch_size = 1.0e-2_fates_r8 + ! Unit conversion constants: ! Conversion factor umols of Carbon -> kg of Carbon (1 mol = 12g) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index cc145f31c6..48b46660c5 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -345,15 +345,15 @@ variables: double fates_landuse_harvest_pprod10(fates_pft) ; fates_landuse_harvest_pprod10:units = "fraction" ; fates_landuse_harvest_pprod10:long_name = "fraction of harvest wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; - double fates_landuse_landusechange_frac_burned(fates_pft) ; - fates_landuse_landusechange_frac_burned:units = "fraction" ; - fates_landuse_landusechange_frac_burned:long_name = "fraction of land use change-generated and not-exported material that is burned (the remainder goes to litter)" ; - double fates_landuse_landusechange_frac_exported(fates_pft) ; - fates_landuse_landusechange_frac_exported:units = "fraction" ; - fates_landuse_landusechange_frac_exported:long_name = "fraction of land use change-generated wood material that is exported to wood product (the remainder is either burned or goes to litter)" ; - double fates_landuse_landusechange_pprod10(fates_pft) ; - fates_landuse_landusechange_pprod10:units = "fraction" ; - fates_landuse_landusechange_pprod10:long_name = "fraction of land use change wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; + double fates_landuse_luc_frac_burned(fates_pft) ; + fates_landuse_luc_frac_burned:units = "fraction" ; + fates_landuse_luc_frac_burned:long_name = "fraction of land use change-generated and not-exported material that is burned (the remainder goes to litter)" ; + double fates_landuse_luc_frac_exported(fates_pft) ; + fates_landuse_luc_frac_exported:units = "fraction" ; + fates_landuse_luc_frac_exported:long_name = "fraction of land use change-generated wood material that is exported to wood product (the remainder is either burned or goes to litter)" ; + double fates_landuse_luc_pprod10(fates_pft) ; + fates_landuse_luc_pprod10:units = "fraction" ; + fates_landuse_luc_pprod10:long_name = "fraction of land use change wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; double fates_leaf_c3psn(fates_pft) ; fates_leaf_c3psn:units = "flag" ; fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; @@ -899,7 +899,9 @@ variables: fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: - :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; + :history = "This file was generated by BatchPatchParams.py:\n", + "CDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\n", + "XML patch file = archive/api24.1.0_101722_patch_params.xml" ; data: fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; @@ -1280,14 +1282,13 @@ data: fates_landuse_harvest_pprod10 = 1, 0.75, 0.75, 0.75, 1, 0.75, 1, 1, 1, 1, 1, 1 ; - fates_landuse_landusechange_frac_burned = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5 ; + fates_landuse_luc_frac_burned = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; - fates_landuse_landusechange_frac_exported = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, - 0.2, 0.2, 0.2, 0, 0, 0 ; + fates_landuse_luc_frac_exported = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.2, 0.2, + 0.2, 0, 0, 0 ; - fates_landuse_landusechange_pprod10 = 1, 0.75, 0.75, 0.75, 1, 0.75, 1, 1, 1, - 1, 1, 1 ; + fates_landuse_luc_pprod10 = 1, 0.75, 0.75, 0.75, 1, 0.75, 1, 1, 1, 1, 1, 1 ; fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; From e1813e89c6f4b113052698346f3133e2cdca70aa Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Fri, 20 Oct 2023 12:35:01 -0700 Subject: [PATCH 029/300] more runtime bugfixes --- biogeochem/EDPatchDynamicsMod.F90 | 37 +++++++++++++++++++++---------- biogeochem/EDPhysiologyMod.F90 | 15 ++++++++----- main/EDInitMod.F90 | 3 +++ main/FatesConstantsMod.F90 | 3 ++- main/FatesHistoryInterfaceMod.F90 | 8 ++++--- main/FatesInterfaceMod.F90 | 3 ++- 6 files changed, 46 insertions(+), 23 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3a9aa44aad..906c4c08e0 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -83,6 +83,7 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : years_per_day use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : primaryland, secondaryland, pastureland, rangeland, cropland + use FatesConstantsMod , only : nocomp_bareground_land use FatesConstantsMod , only : n_landuse_cats use FatesLandUseChangeMod, only : get_landuse_transition_rates use FatesLandUseChangeMod, only : get_init_landuse_transition_rates @@ -298,9 +299,11 @@ subroutine disturbance_rates( site_in, bc_in) current_fates_landuse_state_vector(:) = 0._r8 currentPatch => site_in%oldest_patch do while (associated(currentPatch)) - current_fates_landuse_state_vector(currentPatch%land_use_label) = & - current_fates_landuse_state_vector(currentPatch%land_use_label) + & - currentPatch%area/AREA + if (currentPatch%land_use_label .gt. nocomp_bareground_land) then + current_fates_landuse_state_vector(currentPatch%land_use_label) = & + current_fates_landuse_state_vector(currentPatch%land_use_label) + & + currentPatch%area/AREA + end if currentPatch => currentPatch%younger end do @@ -331,8 +334,8 @@ subroutine disturbance_rates( site_in, bc_in) dist_rate_ldist_notharvested = 0.0_r8 - ! Avoid this calculation to avoid NaN due to division by zero result if luh is not used - if (hlm_use_luh .eq. itrue) then + ! Avoid this calculation to avoid NaN due to division by zero result if luh is not used or applying to bare ground + if (hlm_use_luh .eq. itrue .and. currentPatch%land_use_label .gt. nocomp_bareground_land) then currentPatch%landuse_transition_rates(1:n_landuse_cats) = min(1._r8, & landuse_transition_matrix(currentPatch%land_use_label,1:n_landuse_cats) / & current_fates_landuse_state_vector(currentPatch%land_use_label)) @@ -2712,6 +2715,7 @@ subroutine fuse_patches( csite, bc_in ) integer :: i_pftlabel !nocomp pft iterator real(r8) :: primary_land_fraction_beforefusion,primary_land_fraction_afterfusion integer :: pftlabelmin, pftlabelmax + integer :: num_bareground_patches ! !--------------------------------------------------------------------- @@ -2723,20 +2727,29 @@ subroutine fuse_patches( csite, bc_in ) primary_land_fraction_afterfusion = 0._r8 nopatches(1:n_landuse_cats) = 0 - + num_bareground_patches = 0 + currentPatch => currentSite%youngest_patch do while(associated(currentPatch)) - nopatches(currentPatch%land_use_label) = & - nopatches(currentPatch%land_use_label) + 1 + if ( currentPatch%land_use_label .gt. nocomp_bareground_land) then + nopatches(currentPatch%land_use_label) = & + nopatches(currentPatch%land_use_label) + 1 - if (currentPatch%land_use_label .eq. primaryland) then - primary_land_fraction_beforefusion = primary_land_fraction_beforefusion + & - currentPatch%area * AREA_INV + if (currentPatch%land_use_label .eq. primaryland) then + primary_land_fraction_beforefusion = primary_land_fraction_beforefusion + & + currentPatch%area * AREA_INV + endif + else + num_bareground_patches = num_bareground_patches + 1 endif - currentPatch => currentPatch%older enddo + if (num_bareground_patches .gt. 1 ) then + write(fates_log(),*) 'somehow there is more than one bare ground patch. this shouldnt have happened.' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + pftlabelmin = 0 if ( hlm_use_nocomp .eq. itrue ) then pftlabelmax = numpft diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 8dc9510ee3..26d6687f67 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -35,6 +35,7 @@ module EDPhysiologyMod use FatesConstantsMod, only : g_per_kg use FatesConstantsMod, only : ndays_per_year use FatesConstantsMod, only : nocomp_bareground + use FatesConstantsMod, only : nocomp_bareground_land use FatesConstantsMod, only : is_crop use FatesConstantsMod, only : area_error_2 use EDPftvarcon , only : EDPftvarcon_inst @@ -2497,13 +2498,15 @@ subroutine recruitment(currentSite, currentPatch, bc_in) use_this_pft = .true. end if - if ((hlm_use_luh .eq. itrue) .and. (is_crop(currentPatch%land_use_label))) then - if ( crop_lu_pft_vector(currentPatch%land_use_label) .eq. ft ) then - use_this_pft = .true. - else - use_this_pft = .false. + if ( currentPatch%land_use_label .ne. nocomp_bareground_land ) then ! cdk + if ((hlm_use_luh .eq. itrue) .and. (is_crop(currentPatch%land_use_label))) then + if ( crop_lu_pft_vector(currentPatch%land_use_label) .eq. ft ) then + use_this_pft = .true. + else + use_this_pft = .false. + end if end if - end if + endif use_this_pft_if: if(use_this_pft) then hite = EDPftvarcon_inst%hgt_min(ft) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 567a6c1bfe..8f0978e1f7 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -94,6 +94,7 @@ module EDInitMod use DamageMainMod, only : undamaged_class use FatesInterfaceTypesMod , only : hlm_num_luh2_transitions use FatesConstantsMod, only : nocomp_bareground_land, nocomp_bareground + use EdtTypesMod, only : dump_site ! CIME GLOBALS use shr_log_mod , only : errMsg => shr_log_errMsg @@ -484,6 +485,8 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%area_bareground = 1._r8 sites(s)%area_pft(:,:) = 0._r8 sites(s)%area_pft(1,:) = 1._r8 + write(fates_log(),*) 'Nan values for pftareafrac. dumping site info.' + call dump_site(currentSite) else ! if only some things are NaN but not all, then something terrible has probably happened. crash. write(fates_log(),*) 'some but, not all, of the data in the PFT by LU matrix at this site is NaN.' diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index c0790da103..3fa91d8847 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -54,7 +54,8 @@ module FatesConstantsMod integer, parameter, public :: rangeland = 3 integer, parameter, public :: pastureland = 4 integer, parameter, public :: cropland = 5 - logical, parameter, dimension(0:n_landuse_cats), public :: is_crop = [.false., .false.,.false.,.false.,.false.,.true.] + logical, parameter, dimension(n_landuse_cats), public :: is_crop = [.false., .false.,.false.,.false.,.true.] + integer, parameter, public :: n_crop_lu_types = 1 ! Bareground nocomp land use label integer, parameter, public :: nocomp_bareground_land = 0 ! not a real land use type, only for labeling any bare-ground nocomp patches diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f600a6f977..0679e216e2 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -84,7 +84,7 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : grav_earth use FatesLitterMod , only : litter_type use FatesConstantsMod , only : secondaryland - + use FatesConstantsMod , only : nocomp_bareground_land use PRTGenericMod , only : leaf_organ, fnrt_organ, sapw_organ use PRTGenericMod , only : struct_organ, store_organ, repro_organ use PRTGenericMod , only : carbon12_element @@ -2782,8 +2782,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_area_si_age(io_si,cpatch%age_class) = hio_area_si_age(io_si,cpatch%age_class) & + cpatch%area * AREA_INV - hio_area_si_landuse(io_si, cpatch%land_use_label) = hio_area_si_landuse(io_si, cpatch%land_use_label)& - + cpatch%area * AREA_INV + if (cpatch%land_use_label .gt. nocomp_bareground_land) then ! ignore land use info on nocomp bareground (where landuse label = 0) + hio_area_si_landuse(io_si, cpatch%land_use_label) = hio_area_si_landuse(io_si, cpatch%land_use_label)& + + cpatch%area * AREA_INV + end if ! 24hr veg temperature hio_tveg24(io_si) = hio_tveg24(io_si) + & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index be57bcbf41..6959ccde23 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -43,6 +43,7 @@ module FatesInterfaceMod use FatesConstantsMod , only : n_landuse_cats use FatesConstantsMod , only : primaryland use FatesConstantsMod , only : secondaryland + use FatesConstantsMod , only : n_crop_lu_types use FatesGlobals , only : fates_global_verbose use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun @@ -557,7 +558,7 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, if ( hlm_use_fixed_biogeog .eq. itrue) then if (hlm_use_luh .gt. 0 ) then - allocate(bc_in%pft_areafrac_lu(fates_hlm_num_natpfts,num_luh2_states)) + allocate(bc_in%pft_areafrac_lu(fates_hlm_num_natpfts,num_luh2_states-n_crop_lu_types)) else allocate(bc_in%pft_areafrac(surfpft_lb:surfpft_ub)) endif From 7d5ce7ee559686ed7576d63a48ed189de274138c Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Fri, 20 Oct 2023 18:42:03 -0700 Subject: [PATCH 030/300] tiny bugfixes --- main/EDInitMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 8f0978e1f7..1ea223f9b4 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -94,7 +94,7 @@ module EDInitMod use DamageMainMod, only : undamaged_class use FatesInterfaceTypesMod , only : hlm_num_luh2_transitions use FatesConstantsMod, only : nocomp_bareground_land, nocomp_bareground - use EdtTypesMod, only : dump_site + use EdTypesMod, only : dump_site ! CIME GLOBALS use shr_log_mod , only : errMsg => shr_log_errMsg @@ -486,7 +486,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%area_pft(:,:) = 0._r8 sites(s)%area_pft(1,:) = 1._r8 write(fates_log(),*) 'Nan values for pftareafrac. dumping site info.' - call dump_site(currentSite) + call dump_site(sites(s)) else ! if only some things are NaN but not all, then something terrible has probably happened. crash. write(fates_log(),*) 'some but, not all, of the data in the PFT by LU matrix at this site is NaN.' From 7d632a09f37a9941d0c8c5a0e4446ad572307668 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Fri, 27 Oct 2023 16:19:00 -0700 Subject: [PATCH 031/300] various bugfixes and the diagnostics used to identify them --- biogeochem/EDLoggingMortalityMod.F90 | 10 + biogeochem/EDPatchDynamicsMod.F90 | 191 ++++++++++--------- biogeochem/FatesLandUseChangeMod.F90 | 6 + main/EDInitMod.F90 | 270 +++++++++++++++------------ main/EDMainMod.F90 | 1 + main/FatesConstantsMod.F90 | 2 +- main/FatesInterfaceMod.F90 | 8 +- main/FatesInterfaceTypesMod.F90 | 3 - 8 files changed, 267 insertions(+), 224 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 8f7359a7cb..d956a9b141 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -445,6 +445,11 @@ subroutine get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, hl end if end if + ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! !!CDKCDK WARNING WARNING WARNING THIS NEEDS TO BE REVERTED. IT TURNS OFF LOGGING ENTIRELY. + harvest_rate = 0._r8 + ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + end subroutine get_harvest_rate_area @@ -693,6 +698,11 @@ subroutine get_harvest_rate_carbon (patch_land_use_label, hlm_harvest_catnames, end if end if + ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! !!CDKCDK WARNING WARNING WARNING THIS NEEDS TO BE REVERTED. IT TURNS OFF LOGGING ENTIRELY. + harvest_rate = 0._r8 + ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + end subroutine get_harvest_rate_carbon ! ============================================================================ diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 906c4c08e0..1b387b0af4 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1324,7 +1324,7 @@ subroutine spawn_patches( currentSite, bc_in) nocomp_and_luh_if: if ( hlm_use_nocomp .eq. itrue .and. hlm_use_luh .eq. itrue ) then - ! disturbance has just hapopened, and now the nocomp PFT identities of the newly-disturbed patches + ! disturbance has just happened, and now the nocomp PFT identities of the newly-disturbed patches ! need to be remapped to those associated with the new land use type. ! logic: loop over land use types. figure out the nocomp PFT fractions for all newly-disturbed patches that have become that land use type. @@ -1337,118 +1337,119 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) - if (currentPatch%changed_landuse_this_ts) then + if (currentPatch%changed_landuse_this_ts .and. currentPatch%land_use_label .eq. i_land_use_label) then nocomp_pft_area_vector(currentPatch%nocomp_pft_label) = nocomp_pft_area_vector(currentPatch%nocomp_pft_label) + currentPatch%area end if currentPatch => currentPatch%younger end do - ! create buffer patch to put all of the pieces carved off of other patches - allocate(buffer_patch) - - call buffer_patch%Create(0._r8, 0._r8, i_land_use_label, 0, & - hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & - regeneration_model) - - ! make a note that this buffer patch has not been put into the linked list - buffer_patch_in_linked_list = .false. - - ! Initialize the litter pools to zero - do el=1,num_elements - call buffer_patch%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - buffer_patch%tallest => null() - buffer_patch%shortest => null() + patch_area_to_reallocate_if: if ( sum(nocomp_pft_area_vector(:)) .gt. nearzero ) then + ! create buffer patch to put all of the pieces carved off of other patches + allocate(buffer_patch) + + call buffer_patch%Create(0._r8, 0._r8, i_land_use_label, 0, & + hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & + regeneration_model) + + ! make a note that this buffer patch has not been put into the linked list + buffer_patch_in_linked_list = .false. + + ! Initialize the litter pools to zero + do el=1,num_elements + call buffer_patch%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + buffer_patch%tallest => null() + buffer_patch%shortest => null() - currentPatch => currentSite%oldest_patch - do while(associated(currentPatch)) - if (currentPatch%changed_landuse_this_ts) then - fraction_to_keep = currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * area / nocomp_pft_area_vector(currentPatch%nocomp_pft_label) - if (fraction_to_keep .lt. nearzero) then - ! we don't want any patch area with this PFT idendity at all anymore. Fuse it into the buffer patch. - currentPatch%nocomp_pft_label = 0 - call fuse_2_patches(currentSite, currentPatch, buffer_patch) - elseif (fraction_to_keep .lt. (1._r8 - nearzero)) then - ! we have more patch are of this PFT than we want, but we do want to keep some of it. - ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. - - allocate(temp_patch) - call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep) - ! - temp_patch%nocomp_pft_label = 0 - call fuse_2_patches(currentSite, temp_patch, buffer_patch) - else - ! we want to keep all of this patch (and possibly more) - nocomp_pft_area_vector_allocated(currentPatch%nocomp_pft_label) = & - nocomp_pft_area_vector_allocated(currentPatch%nocomp_pft_label) + currentPatch%area - currentPatch%changed_landuse_this_ts = .false. - endif - end if - currentPatch => currentPatch%younger - end do - - ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list - nocomp_pft_loop_2: do i_pft = 1, numpft + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + if (currentPatch%changed_landuse_this_ts) then + fraction_to_keep = currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * area / nocomp_pft_area_vector(currentPatch%nocomp_pft_label) + if (fraction_to_keep .lt. nearzero) then + ! we don't want any patch area with this PFT idendity at all anymore. Fuse it into the buffer patch. + currentPatch%nocomp_pft_label = 0 + call fuse_2_patches(currentSite, currentPatch, buffer_patch) + elseif (fraction_to_keep .lt. (1._r8 - nearzero)) then + ! we have more patch are of this PFT than we want, but we do want to keep some of it. + ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. + + allocate(temp_patch) + call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep) + ! + temp_patch%nocomp_pft_label = 0 + call fuse_2_patches(currentSite, temp_patch, buffer_patch) + else + ! we want to keep all of this patch (and possibly more) + nocomp_pft_area_vector_allocated(currentPatch%nocomp_pft_label) = & + nocomp_pft_area_vector_allocated(currentPatch%nocomp_pft_label) + currentPatch%area + currentPatch%changed_landuse_this_ts = .false. + endif + end if + currentPatch => currentPatch%younger + end do - if (nocomp_pft_area_vector_allocated(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * area) then + ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list + nocomp_pft_loop_2: do i_pft = 1, numpft + ! + if (nocomp_pft_area_vector_allocated(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then - newp_area = currentSite%area_pft(i_pft,i_land_use_label) * area - nocomp_pft_area_vector_allocated(i_pft) + newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_allocated(i_pft) - if (newp_area .lt. buffer_patch%area) then + if (newp_area .lt. buffer_patch%area) then - ! split buffer patch in two, keeping the smaller buffer patch to put into new patches - allocate(temp_patch) - call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) + ! split buffer patch in two, keeping the smaller buffer patch to put into new patches + allocate(temp_patch) + call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) - ! give the new patch the intended nocomp PFT label - temp_patch%nocomp_pft_label = i_pft + ! give the new patch the intended nocomp PFT label + temp_patch%nocomp_pft_label = i_pft - ! put the new patch into the linked list - call InsertPatch(currentSite, temp_patch) + ! put the new patch into the linked list + call InsertPatch(currentSite, temp_patch) - ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be - ! refilled the next time through the loop. - temp_patch => null() + ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be + ! refilled the next time through the loop. + temp_patch => null() - else - ! give the buffer patch the intended nocomp PFT label - buffer_patch%nocomp_pft_label = i_pft + else + ! give the buffer patch the intended nocomp PFT label + buffer_patch%nocomp_pft_label = i_pft - ! put the buffer patch directly into the linked list - call InsertPatch(currentSite, buffer_patch) + ! put the buffer patch directly into the linked list + call InsertPatch(currentSite, buffer_patch) - buffer_patch_in_linked_list = .true. + buffer_patch_in_linked_list = .true. - end if + end if - end if + end if - end do nocomp_pft_loop_2 - - ! now we want to make sure that either the buffer_patch either has zero area (presumably it was never used), in which case it should be deallocated, - ! or else it does have area but it has been put into the site linked list, and so buffer patch should be nulled before next pass through outer loop. - ! if either of those, that means everything worked properly, if not, then something has gone wrong. - if (buffer_patch_in_linked_list) then - buffer_patch => null() - else if (buffer_patch%area .lt. fates_tiny) then - ! here we need to deallocate the buffer patch so that we don't get a memory leak/ - call buffer_patch%FreeMemory(regeneration_model, numpft) - deallocate(buffer_patch, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) + end do nocomp_pft_loop_2 + + ! now we want to make sure that either the buffer_patch either has zero area (presumably it was never used), in which case it should be deallocated, + ! or else it does have area but it has been put into the site linked list, and so buffer patch should be nulled before next pass through outer loop. + ! if either of those, that means everything worked properly, if not, then something has gone wrong. + if (buffer_patch_in_linked_list) then + buffer_patch => null() + else if (buffer_patch%area .lt. fates_tiny) then + ! here we need to deallocate the buffer patch so that we don't get a memory leak/ + call buffer_patch%FreeMemory(regeneration_model, numpft) + deallocate(buffer_patch, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + else + write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' + write(fates_log(),*) 'buffer_patch%area', buffer_patch%area call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - else - write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' - write(fates_log(),*) 'buffer_patch%area', buffer_patch%area - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - + end if + end if patch_area_to_reallocate_if end do lu_loop else ! if not using a configuration where the changed_landuse_this_ts is relevant, loop through all patches and reset it @@ -3206,6 +3207,7 @@ subroutine terminate_patches(currentSite) integer :: count_cycles logical :: gotfused logical :: current_patch_is_youngest_lutype + integer :: i_landuse, i_pft real(r8) areatot ! variable for checking whether the total patch area is wrong. !--------------------------------------------------------------------- @@ -3352,6 +3354,9 @@ subroutine terminate_patches(currentSite) write(fates_log(),*) 'otherwise, dumping some diagnostics.' write(fates_log(),*) currentPatch%area, currentPatch%nocomp_pft_label, currentPatch%land_use_label call dump_site(currentSite) + + write(fates_log(),*) 'currentSite%area_bareground', currentSite%area_bareground + write(fates_log(),*) 'currentSite%%area_pft(:,:)', currentSite%area_pft(:,:) patchpointer => currentSite%youngest_patch do while(associated(patchpointer)) write(fates_log(),*) patchpointer%area, patchpointer%nocomp_pft_label, patchpointer%land_use_label diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index b3d6522940..785992e5a2 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -114,6 +114,12 @@ subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) end if end do transitions_loop + + ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! CDKCDK WARNING WARNING WARNING REVERT. THIS TURNS OFF ALL TRANSITIONS + landuse_transition_matrix(:,:) = 0._r8 + ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + end subroutine get_landuse_transition_rates !---------------------------------------------------------------------------------------------------- diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 1ea223f9b4..26507bfda0 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -65,7 +65,6 @@ module EDInitMod use FatesInterfaceTypesMod , only : nlevdamage use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : nlevage - use FatesInterfaceTypesMod , only : fates_hlm_num_natpfts use FatesAllometryMod , only : h2d_allom use FatesAllometryMod , only : bagw_allom use FatesAllometryMod , only : bbgw_allom @@ -463,10 +462,10 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! hlm_pft_map is the area of that land in each FATES PFT (from param file) ! first check for NaNs in bc_in(s)%pft_areafrac_lu. if so, make everything bare ground. - if ( .not. any( isnan( bc_in(s)%pft_areafrac_lu (:,:) ))) then + if ( .not. (any( isnan( bc_in(s)%pft_areafrac_lu (:,:) )) .or. isnan( bc_in(s)%baregroundfrac))) then do i_landusetype = 1, n_landuse_cats if (.not. is_crop(i_landusetype)) then - do hlm_pft = 1,fates_hlm_num_natpfts + do hlm_pft = 1,size( EDPftvarcon_inst%hlm_pft_map,2) do fates_pft = 1,numpft ! loop round all fates pfts for all hlm pfts sites(s)%area_pft(fates_pft,i_landusetype) = sites(s)%area_pft(fates_pft,i_landusetype) + & EDPftvarcon_inst%hlm_pft_map(fates_pft,hlm_pft) * bc_in(s)%pft_areafrac_lu(hlm_pft,i_landusetype) @@ -480,19 +479,18 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%area_bareground = bc_in(s)%baregroundfrac else - if ( all( isnan( bc_in(s)%pft_areafrac_lu (:,:) ))) then + !if ( all( isnan( bc_in(s)%pft_areafrac_lu (:,:))) .and. isnan(bc_in(s)%baregroundfrac)) then ! if given all NaNs, then make everything bare ground sites(s)%area_bareground = 1._r8 sites(s)%area_pft(:,:) = 0._r8 - sites(s)%area_pft(1,:) = 1._r8 write(fates_log(),*) 'Nan values for pftareafrac. dumping site info.' call dump_site(sites(s)) - else - ! if only some things are NaN but not all, then something terrible has probably happened. crash. - write(fates_log(),*) 'some but, not all, of the data in the PFT by LU matrix at this site is NaN.' - write(fates_log(),*) 'recommend checking the dataset to see what has happened.' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif + !else + ! ! if only some things are NaN but not all, then something terrible has probably happened. crash. + ! write(fates_log(),*) 'some but, not all, of the data in the PFT by LU matrix at this site is NaN.' + ! write(fates_log(),*) 'recommend checking the dataset to see what has happened.' + ! call endrun(msg=errMsg(sourcefile, __LINE__)) + !endif endif else @@ -516,7 +514,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) do ft = 1,numpft ! remove tiny patches to prevent numerical errors in terminate patches - if(sites(s)%area_pft(ft, i_landusetype).lt.0.01_r8.and.sites(s)%area_pft(ft, i_landusetype).gt.0.0_r8)then + if(sites(s)%area_pft(ft, i_landusetype).lt.0.01_r8.and.sites(s)%area_pft(ft, i_landusetype).gt.nearzero)then if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,i_landusetype,sites(s)%area_pft(ft, i_landusetype) sites(s)%area_pft(ft, i_landusetype)=0.0_r8 endif @@ -537,7 +535,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! count how many PFTs have areas greater than zero and compare to the number of patches allowed if (COUNT(sites(s)%area_pft(:, i_landusetype) .gt. 0._r8) > maxpatches_by_landuse(i_landusetype)) then ! write current vector to log file - if(debug) write(fates_log(),*) 'too many PFTs for LU type ', i_landusetype, i_landusetype,sites(s)%area_pft(:, i_landusetype) + if(debug) write(fates_log(),*) 'too many PFTs for LU type ', i_landusetype, sites(s)%area_pft(:, i_landusetype) ! start from largest area, put that PFT's area into a temp vector, and then work down to successively smaller-area PFTs, ! at the end replace the original vector with the temp vector @@ -560,7 +558,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) do i_landusetype = 1, n_landuse_cats sumarea = sum(sites(s)%area_pft(1:numpft,i_landusetype)) do ft = 1,numpft - if(sumarea.gt.0._r8)then + if(sumarea.gt.nearzero)then sites(s)%area_pft(ft, i_landusetype) = sites(s)%area_pft(ft, i_landusetype)/sumarea else ! if no PFT area in primary lands, set bare ground fraction to one. @@ -616,6 +614,7 @@ subroutine init_patches( nsites, sites, bc_in) real(r8) :: age !notional age of this patch integer :: ageclass real(r8) :: area_diff + real(r8) :: area_error ! dummy locals real(r8) :: biomass_stock @@ -677,6 +676,12 @@ subroutine init_patches( nsites, sites, bc_in) ! state_vector(:) = 0._r8 + if(hlm_use_nocomp.eq.itrue)then + num_nocomp_pfts = numpft + else !default + num_nocomp_pfts = 1 + end if !nocomp + sites_loop: do s = 1, nsites sites(s)%sp_tlai(:) = 0._r8 sites(s)%sp_tsai(:) = 0._r8 @@ -687,12 +692,6 @@ subroutine init_patches( nsites, sites, bc_in) ! have smaller spread factors than bare ground (they are crowded) sites(s)%spread = init_spread_near_bare_ground - if(hlm_use_nocomp.eq.itrue)then - num_nocomp_pfts = numpft - else !default - num_nocomp_pfts = 1 - end if !nocomp - ! read in luh state data to determine initial land use types if (hlm_use_luh .eq. itrue) then @@ -720,37 +719,41 @@ subroutine init_patches( nsites, sites, bc_in) is_first_patch = .true. + area_error = 0._r8 ! first make a bare-ground patch if one is needed. - make_bareground_patch_if: if (hlm_use_nocomp.eq.itrue .and. hlm_use_fixed_biogeog .eq.itrue .and. & - (area*sites(s)%area_bareground) .gt. min_init_patch_size) then + make_bareground_patch_if: if (hlm_use_nocomp.eq.itrue .and. hlm_use_fixed_biogeog .eq.itrue) then newparea = area * sites(s)%area_bareground - - allocate(newp) + if (newparea .gt. min_init_patch_size) then + + allocate(newp) - call newp%Create(age, newparea, nocomp_bareground_land, nocomp_bareground, & - hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod, & - regeneration_model) - - ! set poointers for first patch (or only patch, if nocomp is false) - newp%patchno = 1 - newp%younger => null() - newp%older => null() - sites(s)%youngest_patch => newp - sites(s)%oldest_patch => newp - is_first_patch = .false. - - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - do el=1,num_elements - call newp%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do + call newp%Create(age, newparea, nocomp_bareground_land, nocomp_bareground, & + hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod, & + regeneration_model) + + ! set poointers for first patch (or only patch, if nocomp is false) + newp%patchno = 1 + newp%younger => null() + newp%older => null() + sites(s)%youngest_patch => newp + sites(s)%oldest_patch => newp + is_first_patch = .false. + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + do el=1,num_elements + call newp%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + else + area_error = area_error + newparea + endif endif make_bareground_patch_if if (hlm_use_luh .eq. itrue) then @@ -759,84 +762,97 @@ subroutine init_patches( nsites, sites, bc_in) end_landuse_idx = 1 endif - ! now make one or more vegetated patches based on nocomp and land use logic - luh_state_loop: do i_lu_state = 1, end_landuse_idx - lu_state_present_if: if (state_vector(i_lu_state) .gt. rsnbl_math_prec) then - new_patch_nocomp_loop: do n = 1, num_nocomp_pfts - ! set the PFT index for patches if in nocomp mode. - if(hlm_use_nocomp.eq.itrue)then - nocomp_pft = n - else - nocomp_pft = fates_unset_int - end if - - if(hlm_use_nocomp.eq.itrue)then - ! In no competition mode, if we are using the fixed_biogeog filter - ! then each PFT has the area dictated by the surface dataset. - - ! If we are not using fixed biogeog model, each PFT gets the same area. - ! i.e. each grid cell is divided exactly into the number of FATES PFTs. - - if(hlm_use_fixed_biogeog.eq.itrue)then - newparea = sites(s)%area_pft(nocomp_pft,i_lu_state) * area * state_vector(i_lu_state) & - * (1._r8 - sites(s)%area_bareground) - else - newparea = area * state_vector(i_lu_state) / numpft - end if - else ! The default case is initialized w/ one patch with the area of the whole site. - newparea = area * state_vector(i_lu_state) - end if !nocomp mode - - new_patch_area_gt_zero: if(newparea .gt. min_init_patch_size) then ! Stop patches being initilialized when PFT not present in nocomop mode - allocate(newp) - - call newp%Create(age, newparea, i_lu_state, nocomp_pft, & - hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod, & - regeneration_model) - - if (is_first_patch) then !is this the first patch? - ! set poointers for first patch (or only patch, if nocomp is false) - newp%patchno = 1 - newp%younger => null() - newp%older => null() - sites(s)%youngest_patch => newp - sites(s)%oldest_patch => newp - is_first_patch = .false. + not_all_baregground_if: if ((1._r8 - sites(s)%area_bareground) .gt. nearzero) then + ! now make one or more vegetated patches based on nocomp and land use logic + luh_state_loop: do i_lu_state = 1, end_landuse_idx + lu_state_present_if: if (state_vector(i_lu_state) .gt. rsnbl_math_prec) then + new_patch_nocomp_loop: do n = 1, num_nocomp_pfts + ! set the PFT index for patches if in nocomp mode. + if(hlm_use_nocomp.eq.itrue)then + nocomp_pft = n else - ! Set pointers for N>1 patches. Note this only happens when nocomp mode is on, or land use is on. - ! The new patch is the 'youngest' one, arbitrarily. - newp%patchno = nocomp_pft + (i_lu_state-1) * numpft - newp%older => sites(s)%youngest_patch - newp%younger => null() - sites(s)%youngest_patch%younger => newp - sites(s)%youngest_patch => newp + nocomp_pft = fates_unset_int end if - ! Initialize the litter pools to zero, these - ! pools will be populated by looping over the existing patches - ! and transfering in mass - if(hlm_use_sp.eq.itrue)then - litt_init = fates_unset_r8 - else - litt_init = 0._r8 - end if - do el=1,num_elements - call newp%litter(el)%InitConditions(init_leaf_fines=litt_init, & - init_root_fines=litt_init, & - init_ag_cwd=litt_init, & - init_bg_cwd=litt_init, & - init_seed=litt_init, & - init_seed_germ=litt_init) - end do - - sitep => sites(s) - call init_cohorts(sitep, newp, bc_in(s)) - - end if new_patch_area_gt_zero - end do new_patch_nocomp_loop - end if lu_state_present_if - end do luh_state_loop + if(hlm_use_nocomp.eq.itrue)then + ! In no competition mode, if we are using the fixed_biogeog filter + ! then each PFT has the area dictated by the surface dataset. + + ! If we are not using fixed biogeog model, each PFT gets the same area. + ! i.e. each grid cell is divided exactly into the number of FATES PFTs. + + if(hlm_use_fixed_biogeog.eq.itrue)then + newparea = sites(s)%area_pft(nocomp_pft,i_lu_state) * area * state_vector(i_lu_state) & + * (1._r8 - sites(s)%area_bareground) + else + newparea = area * state_vector(i_lu_state) / numpft + end if + else ! The default case is initialized w/ one patch with the area of the whole site. + newparea = area * state_vector(i_lu_state) + end if !nocomp mode + + new_patch_area_gt_zero: if(newparea .gt. min_init_patch_size) then ! Stop patches being initilialized when PFT not present in nocomop mode + allocate(newp) + + call newp%Create(age, newparea, i_lu_state, nocomp_pft, & + hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod, & + regeneration_model) + + if (is_first_patch) then !is this the first patch? + ! set poointers for first patch (or only patch, if nocomp is false) + newp%patchno = 1 + newp%younger => null() + newp%older => null() + sites(s)%youngest_patch => newp + sites(s)%oldest_patch => newp + is_first_patch = .false. + else + ! Set pointers for N>1 patches. Note this only happens when nocomp mode is on, or land use is on. + ! The new patch is the 'youngest' one, arbitrarily. + newp%patchno = nocomp_pft + (i_lu_state-1) * numpft + newp%older => sites(s)%youngest_patch + newp%younger => null() + sites(s)%youngest_patch%younger => newp + sites(s)%youngest_patch => newp + end if + + ! Initialize the litter pools to zero, these + ! pools will be populated by looping over the existing patches + ! and transfering in mass + if(hlm_use_sp.eq.itrue)then + litt_init = fates_unset_r8 + else + litt_init = 0._r8 + end if + do el=1,num_elements + call newp%litter(el)%InitConditions(init_leaf_fines=litt_init, & + init_root_fines=litt_init, & + init_ag_cwd=litt_init, & + init_bg_cwd=litt_init, & + init_seed=litt_init, & + init_seed_germ=litt_init) + end do + + sitep => sites(s) + call init_cohorts(sitep, newp, bc_in(s)) + else + area_error = area_error+ newparea + end if new_patch_area_gt_zero + end do new_patch_nocomp_loop + end if lu_state_present_if + end do luh_state_loop + end if not_all_baregground_if + + ! if we had to skip small patches above, resize things accordingly + if ( area_error .gt. nearzero) then + newp => sites(s)%oldest_patch + do while (associated(newp)) + newp%area = newp%area * area/ (area - area_error) + newp => newp%younger + end do + endif + !check if the total area adds to the same as site area total = 0.0_r8 newp => sites(s)%oldest_patch @@ -930,6 +946,18 @@ subroutine init_patches( nsites, sites, bc_in) end do end if + ! check to make sure there are no very tiny patches + do s = 1, nsites + currentPatch => sites(s)%youngest_patch + do while(associated(currentPatch)) + if (currentPatch%area .lt. min_init_patch_size) then + write(fates_log(),*) 'edinit somehow making tiny patches',currentPatch%land_use_label, currentPatch%nocomp_pft_label, currentPatch%area + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + currentPatch => currentPatch%older + end do + end do + return end subroutine init_patches diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 324cac5bd5..e9c984f200 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -292,6 +292,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) ! make new patches from disturbed land if (do_patch_dynamics.eq.itrue ) then + call spawn_patches(currentSite, bc_in) call TotalBalanceCheck(currentSite,3) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 3fa91d8847..e98f2cb63f 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -180,7 +180,7 @@ module FatesConstantsMod real(fates_r8), parameter, public :: nearzero = 1.0e-30_fates_r8 ! minimum init patch size for initialization in nocomp and/or land-use cases - real(fates_r8), parameter, public :: min_init_patch_size = 1.0e-2_fates_r8 + real(fates_r8), parameter, public :: min_init_patch_size = 1.0e-4_fates_r8 ! Unit conversion constants: diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 6959ccde23..b4d900de02 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -557,8 +557,8 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, end if if ( hlm_use_fixed_biogeog .eq. itrue) then - if (hlm_use_luh .gt. 0 ) then - allocate(bc_in%pft_areafrac_lu(fates_hlm_num_natpfts,num_luh2_states-n_crop_lu_types)) + if (hlm_use_luh .eq. itrue ) then + allocate(bc_in%pft_areafrac_lu(size( EDPftvarcon_inst%hlm_pft_map,2),num_luh2_states-n_crop_lu_types)) else allocate(bc_in%pft_areafrac(surfpft_lb:surfpft_ub)) endif @@ -796,10 +796,6 @@ subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) fates_maxPatchesPerSite = max(surf_numpft+surf_numcft,maxpatch_total+1) - ! if this is nocomp with land use, track things differently. - ! we want the number of natpfts minus the bare ground PFT. - fates_hlm_num_natpfts = surf_numpft -1 - else ! If we are using fixed biogeography or no-comp then we diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 47a382a22f..30cd52270f 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -226,9 +226,6 @@ module FatesInterfaceTypesMod ! the prior so that we can hold the LAI data integer, public :: fates_maxPatchesPerSite - ! the number of natural PFTs tracked by the host model; NOT INCLUDING EITHER CROPS OR BARE GROUND - integer, public :: fates_hlm_num_natpfts - integer, public :: max_comp_per_site ! This is the maximum number of nutrient aquisition ! competitors that will be generated on each site From fbcaa3326d1e385105e964c0ed657e78822e167b Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Fri, 27 Oct 2023 16:54:28 -0700 Subject: [PATCH 032/300] moar bugfix --- main/FatesRestartInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 741425caf6..ecf6acaf4b 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -711,7 +711,7 @@ subroutine define_restart_vars(this, initialize_variables) units='kgC/m2', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_trunk_product_si ) - call this%set_restart_var(vname='fates_landuse_config_site', vtype=site_r8, & + call this%set_restart_var(vname='fates_landuse_config_site', vtype=site_int, & long_name='hlm_use_luh status of run that created this restart file', & units='kgC/m2', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_landuse_config_si ) From 308990935fd25098f0aca708951b0d30d927c5de Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 30 Oct 2023 10:46:31 -0400 Subject: [PATCH 033/300] Updated parameter change tool names --- ...ms_default.cdl => api28.0.0_103023_fates_params_default.cdl} | 0 ...{api27.0.0_062823_pr1093.xml => api28.0.0_103023_pr1093.xml} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename parameter_files/archive/{api27.0.0_062823_fates_params_default.cdl => api28.0.0_103023_fates_params_default.cdl} (100%) rename parameter_files/archive/{api27.0.0_062823_pr1093.xml => api28.0.0_103023_pr1093.xml} (98%) diff --git a/parameter_files/archive/api27.0.0_062823_fates_params_default.cdl b/parameter_files/archive/api28.0.0_103023_fates_params_default.cdl similarity index 100% rename from parameter_files/archive/api27.0.0_062823_fates_params_default.cdl rename to parameter_files/archive/api28.0.0_103023_fates_params_default.cdl diff --git a/parameter_files/archive/api27.0.0_062823_pr1093.xml b/parameter_files/archive/api28.0.0_103023_pr1093.xml similarity index 98% rename from parameter_files/archive/api27.0.0_062823_pr1093.xml rename to parameter_files/archive/api28.0.0_103023_pr1093.xml index 6373af493d..8a3a957fe6 100644 --- a/parameter_files/archive/api27.0.0_062823_pr1093.xml +++ b/parameter_files/archive/api28.0.0_103023_pr1093.xml @@ -15,7 +15,7 @@ the variables --> - archive/api27.0.0_062823_fates_params_default.cdl + archive/api28.0.0_103023_fates_params_default.cdl fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12 From f698158bcf6908f8b12736d3b62ae52f184b4d62 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Mon, 30 Oct 2023 16:19:14 -0700 Subject: [PATCH 034/300] fixed anothe rbug and turning disturbance back on --- biogeochem/EDLoggingMortalityMod.F90 | 10 ---------- biogeochem/FatesLandUseChangeMod.F90 | 5 ----- main/EDInitMod.F90 | 23 +++++++++++++++++------ main/FatesConstantsMod.F90 | 3 --- 4 files changed, 17 insertions(+), 24 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index d956a9b141..8f7359a7cb 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -445,11 +445,6 @@ subroutine get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, hl end if end if - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ! !!CDKCDK WARNING WARNING WARNING THIS NEEDS TO BE REVERTED. IT TURNS OFF LOGGING ENTIRELY. - harvest_rate = 0._r8 - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - end subroutine get_harvest_rate_area @@ -698,11 +693,6 @@ subroutine get_harvest_rate_carbon (patch_land_use_label, hlm_harvest_catnames, end if end if - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ! !!CDKCDK WARNING WARNING WARNING THIS NEEDS TO BE REVERTED. IT TURNS OFF LOGGING ENTIRELY. - harvest_rate = 0._r8 - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - end subroutine get_harvest_rate_carbon ! ============================================================================ diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 785992e5a2..d8f5cdf2e1 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -115,11 +115,6 @@ subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) end do transitions_loop - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ! CDKCDK WARNING WARNING WARNING REVERT. THIS TURNS OFF ALL TRANSITIONS - landuse_transition_matrix(:,:) = 0._r8 - ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - end subroutine get_landuse_transition_rates !---------------------------------------------------------------------------------------------------- diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 26507bfda0..34a73ffbc7 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -11,7 +11,7 @@ module EDInitMod use FatesConstantsMod , only : primaryland use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : rsnbl_math_prec - use FatesConstantsMod , only : min_init_patch_size + use EDTypesMod , only : min_patch_area_forced use FatesConstantsMod , only : n_landuse_cats use FatesConstantsMod , only : is_crop use FatesConstantsMod , only : fates_unset_r8 @@ -102,7 +102,7 @@ module EDInitMod implicit none private - logical :: debug = .true. + logical :: debug = .false. integer :: istat ! return status code character(len=255) :: smsg ! Message string for deallocation errors @@ -724,7 +724,7 @@ subroutine init_patches( nsites, sites, bc_in) make_bareground_patch_if: if (hlm_use_nocomp.eq.itrue .and. hlm_use_fixed_biogeog .eq.itrue) then newparea = area * sites(s)%area_bareground - if (newparea .gt. min_init_patch_size) then + if (newparea .gt. min_patch_area_forced) then allocate(newp) @@ -765,7 +765,7 @@ subroutine init_patches( nsites, sites, bc_in) not_all_baregground_if: if ((1._r8 - sites(s)%area_bareground) .gt. nearzero) then ! now make one or more vegetated patches based on nocomp and land use logic luh_state_loop: do i_lu_state = 1, end_landuse_idx - lu_state_present_if: if (state_vector(i_lu_state) .gt. rsnbl_math_prec) then + lu_state_present_if: if (state_vector(i_lu_state) .gt. nearzero) then new_patch_nocomp_loop: do n = 1, num_nocomp_pfts ! set the PFT index for patches if in nocomp mode. if(hlm_use_nocomp.eq.itrue)then @@ -791,7 +791,7 @@ subroutine init_patches( nsites, sites, bc_in) newparea = area * state_vector(i_lu_state) end if !nocomp mode - new_patch_area_gt_zero: if(newparea .gt. min_init_patch_size) then ! Stop patches being initilialized when PFT not present in nocomop mode + new_patch_area_gt_zero: if(newparea .gt. min_patch_area_forced) then ! Stop patches being initilialized when PFT not present in nocomop mode allocate(newp) call newp%Create(age, newparea, i_lu_state, nocomp_pft, & @@ -874,6 +874,17 @@ subroutine init_patches( nsites, sites, bc_in) else !this is a big error not just a precision error. write(fates_log(),*) 'issue with patch area in EDinit', area_diff, total + newp => sites(s)%oldest_patch + do while (associated(newp)) + write(fates_log(),*) newp%area, newp%nocomp_pft_label, newp%land_use_label + newp => newp%younger + end do + write(fates_log(),*) 'state_vector', state_vector + write(fates_log(),*) 'area_error', area_error + write(fates_log(),*) 'area_bareground', sites(s)%area_bareground + do i_lu_state = 1, end_landuse_idx + write(fates_log(),*) 'sites(s)%area_pft(:,i_lu_state)',i_lu_state, sites(s)%area_pft(:,i_lu_state) + end do call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! big error end if ! too much patch area @@ -950,7 +961,7 @@ subroutine init_patches( nsites, sites, bc_in) do s = 1, nsites currentPatch => sites(s)%youngest_patch do while(associated(currentPatch)) - if (currentPatch%area .lt. min_init_patch_size) then + if (currentPatch%area .lt. min_patch_area_forced) then write(fates_log(),*) 'edinit somehow making tiny patches',currentPatch%land_use_label, currentPatch%nocomp_pft_label, currentPatch%area call endrun(msg=errMsg(sourcefile, __LINE__)) end if diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index e98f2cb63f..cb778e4ba5 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -179,9 +179,6 @@ module FatesConstantsMod ! precisions are preventing perfect zero in comparison real(fates_r8), parameter, public :: nearzero = 1.0e-30_fates_r8 - ! minimum init patch size for initialization in nocomp and/or land-use cases - real(fates_r8), parameter, public :: min_init_patch_size = 1.0e-4_fates_r8 - ! Unit conversion constants: ! Conversion factor umols of Carbon -> kg of Carbon (1 mol = 12g) From ac4b61d3cfc03b428d71300d4846659dd35e707e Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Tue, 31 Oct 2023 08:45:06 -0700 Subject: [PATCH 035/300] more bugfixes; add diagnostic for transition matrix; zeroed diags on matrix --- biogeochem/EDLoggingMortalityMod.F90 | 3 +-- biogeochem/EDPatchDynamicsMod.F90 | 31 ++++++++++++++++++++++++++-- biogeochem/FatesLandUseChangeMod.F90 | 3 ++- main/FatesHistoryInterfaceMod.F90 | 27 ++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 8f7359a7cb..6117dc49bf 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -423,8 +423,7 @@ subroutine get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, hl harvest_rate = 0._r8 endif else - write(fates_log(),*) 'errror - trying to log from patches that are neither primary nor secondary' - call endrun(msg=errMsg(sourcefile, __LINE__)) + harvest_rate = 0._r8 endif ! calculate today's harvest rate diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 1b387b0af4..0e2e625cac 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1365,7 +1365,24 @@ subroutine spawn_patches( currentSite, bc_in) end do buffer_patch%tallest => null() buffer_patch%shortest => null() - + + ! Copy any means or timers from the original patch to the new patch + ! These values will inherit all info from the original patch + ! -------------------------------------------------------------------------- + call buffer_patch%tveg24%CopyFromDonor(currentPatch%tveg24) + call buffer_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) + call buffer_patch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) + + if ( regeneration_model == TRS_regeneration ) then + call buffer_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) + call buffer_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) + call buffer_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) + do pft = 1,numpft + call buffer_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) + call buffer_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) + enddo + end if + currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) if (currentPatch%changed_landuse_this_ts) then @@ -1492,7 +1509,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) type (fates_cohort_type), pointer :: currentCohort integer :: tnull ! is there a tallest cohort? integer :: snull ! is there a shortest cohort? - + integer :: pft ! first we need to make the new patch call new_patch%Create(0._r8, & @@ -1521,6 +1538,16 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) call new_patch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) + if ( regeneration_model == TRS_regeneration ) then + call new_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) + call new_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) + call new_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) + do pft = 1,numpft + call new_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) + call new_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) + enddo + end if + currentPatch%burnt_frac_litter(:) = 0._r8 call TransLitterNewPatch( currentSite, currentPatch, new_patch, currentPatch%area * fraction_to_keep) diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index d8f5cdf2e1..3cf6d19528 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -107,7 +107,8 @@ subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) i_receiver = lumap%GetIndex(receiver_name) ! Avoid transitions with 'urban' as those are handled seperately - if (.not.(i_donor .eq. fates_unset_int .or. i_receiver .eq. fates_unset_int)) then + ! Also ignore diagonal elements of transition matrix. + if (.not.(i_donor .eq. fates_unset_int .or. i_receiver .eq. fates_unset_int .or. i_donor .eq. i_receiver)) then landuse_transition_matrix(i_donor,i_receiver) = & landuse_transition_matrix(i_donor,i_receiver) + temp_vector(i_luh2_transitions) * years_per_day / (1._r8 - urban_fraction) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 0679e216e2..4af0b7806f 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -53,6 +53,8 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : nlevcoage use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog + use FatesInterfaceTypesMod , only : hlm_use_luh + use FatesLandUseChangeMod, only : get_landuse_transition_rates, get_init_landuse_transition_rates use FatesAllometryMod , only : CrownDepth use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : set_root_fraction @@ -309,6 +311,7 @@ module FatesHistoryInterfaceMod integer :: ih_primaryland_fusion_error_si integer :: ih_area_si_landuse integer :: ih_disturbance_rate_si_lulu + integer :: ih_transition_matrix_si_lulu integer :: ih_fire_disturbance_rate_si integer :: ih_logging_disturbance_rate_si integer :: ih_fall_disturbance_rate_si @@ -2322,6 +2325,8 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) integer :: tmp + real(r8) :: landuse_transition_matrix(n_landuse_cats,n_landuse_cats) + associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & @@ -2387,6 +2392,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_understory_biomass_si => this%hvars(ih_understory_biomass_si)%r81d, & hio_primaryland_fusion_error_si => this%hvars(ih_primaryland_fusion_error_si)%r81d, & hio_disturbance_rate_si_lulu => this%hvars(ih_disturbance_rate_si_lulu)%r82d, & + hio_transition_matrix_si_lulu => this%hvars(ih_transition_matrix_si_lulu)%r82d, & hio_fire_disturbance_rate_si => this%hvars(ih_fire_disturbance_rate_si)%r81d, & hio_logging_disturbance_rate_si => this%hvars(ih_logging_disturbance_rate_si)%r81d, & hio_fall_disturbance_rate_si => this%hvars(ih_fall_disturbance_rate_si)%r81d, & @@ -2750,6 +2756,22 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end do end do + ! get the land sue transition matrix and output that to history. (mainly a sanity check, can maybe remove before integration) + if ( hlm_use_luh .eq. itrue ) then + if(.not. sites(s)%transition_landuse_from_off_to_on) then + call get_landuse_transition_rates(bc_in(s), landuse_transition_matrix) + else + call get_init_landuse_transition_rates(bc_in(s), landuse_transition_matrix) + endif + else + landuse_transition_matrix(:,:) = 0._r8 + endif + do i_dist = 1, n_landuse_cats + do j_dist = 1, n_landuse_cats + hio_transition_matrix_si_lulu(io_si, i_dist+n_landuse_cats*(j_dist-1)) = landuse_transition_matrix(i_dist, j_dist) + end do + end do + ! output site-level disturbance rates [m2 m-2 day-1] -> [m2 m-2 yr-1] - TO DO rework this hio_fire_disturbance_rate_si(io_si) = sum(sites(s)%disturbance_rates(dtype_ifire,1:n_landuse_cats,1:n_landuse_cats)) * & @@ -5753,6 +5775,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_lulu_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index=ih_disturbance_rate_si_lulu) + call this%set_history_var(vname='FATES_TRANSITION_MATRIX_LULU', units='m2 m-2 yr-1', & + long='land use transition matrix', use_default='active', & + avgflag='A', vtype=site_lulu_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index=ih_transition_matrix_si_lulu) + ! Secondary forest area and age diagnostics call this%set_history_var(vname='FATES_SECONDARY_FOREST_FRACTION', & From 46717980a2a01824ce0993fc84890790c73730e7 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Tue, 31 Oct 2023 13:46:05 -0700 Subject: [PATCH 036/300] moving storage of transition matrix to site variable to simplify history output --- biogeochem/EDPatchDynamicsMod.F90 | 9 ++++----- main/FatesHistoryInterfaceMod.F90 | 16 ++-------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 0e2e625cac..352799c091 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -215,7 +215,6 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: mean_temp real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) - real(r8) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! [m2/m2/day] real(r8) :: current_fates_landuse_state_vector(n_landuse_cats) ! [m2/m2] !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) @@ -287,12 +286,12 @@ subroutine disturbance_rates( site_in, bc_in) if ( hlm_use_luh .eq. itrue ) then if(.not. site_in%transition_landuse_from_off_to_on) then - call get_landuse_transition_rates(bc_in, landuse_transition_matrix) + call get_landuse_transition_rates(bc_in, site_in%landuse_transition_matrix) else - call get_init_landuse_transition_rates(bc_in, landuse_transition_matrix) + call get_init_landuse_transition_rates(bc_in, site_in%landuse_transition_matrix) endif else - landuse_transition_matrix(:,:) = 0._r8 + site_in%landuse_transition_matrix(:,:) = 0._r8 endif ! calculate total area in each landuse category @@ -337,7 +336,7 @@ subroutine disturbance_rates( site_in, bc_in) ! Avoid this calculation to avoid NaN due to division by zero result if luh is not used or applying to bare ground if (hlm_use_luh .eq. itrue .and. currentPatch%land_use_label .gt. nocomp_bareground_land) then currentPatch%landuse_transition_rates(1:n_landuse_cats) = min(1._r8, & - landuse_transition_matrix(currentPatch%land_use_label,1:n_landuse_cats) / & + site_in%landuse_transition_matrix(currentPatch%land_use_label,1:n_landuse_cats) / & current_fates_landuse_state_vector(currentPatch%land_use_label)) else currentPatch%landuse_transition_rates = 0.0_r8 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 4af0b7806f..85651d778b 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -54,7 +54,6 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog use FatesInterfaceTypesMod , only : hlm_use_luh - use FatesLandUseChangeMod, only : get_landuse_transition_rates, get_init_landuse_transition_rates use FatesAllometryMod , only : CrownDepth use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : set_root_fraction @@ -2325,8 +2324,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) integer :: tmp - real(r8) :: landuse_transition_matrix(n_landuse_cats,n_landuse_cats) - associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & @@ -2756,19 +2753,10 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end do end do - ! get the land sue transition matrix and output that to history. (mainly a sanity check, can maybe remove before integration) - if ( hlm_use_luh .eq. itrue ) then - if(.not. sites(s)%transition_landuse_from_off_to_on) then - call get_landuse_transition_rates(bc_in(s), landuse_transition_matrix) - else - call get_init_landuse_transition_rates(bc_in(s), landuse_transition_matrix) - endif - else - landuse_transition_matrix(:,:) = 0._r8 - endif + ! get the land use transition matrix and output that to history. (mainly a sanity check, can maybe remove before integration) do i_dist = 1, n_landuse_cats do j_dist = 1, n_landuse_cats - hio_transition_matrix_si_lulu(io_si, i_dist+n_landuse_cats*(j_dist-1)) = landuse_transition_matrix(i_dist, j_dist) + hio_transition_matrix_si_lulu(io_si, i_dist+n_landuse_cats*(j_dist-1)) = sites(s)%landuse_transition_matrix(i_dist, j_dist) end do end do From 3af29362d058082b40043475e4f941d028f55c56 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 1 Nov 2023 13:10:46 -0700 Subject: [PATCH 037/300] added use_fates_potentialveg flag and logic based on it --- biogeochem/FatesLandUseChangeMod.F90 | 107 +++++++++++++++------------ main/FatesInterfaceMod.F90 | 6 ++ main/FatesInterfaceTypesMod.F90 | 1 + main/FatesRestartInterfaceMod.F90 | 8 +- 4 files changed, 69 insertions(+), 53 deletions(-) diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 3cf6d19528..9a8fc57eda 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -16,6 +16,7 @@ module FatesLandUseChangeMod use FatesInterfaceTypesMod , only : hlm_num_luh2_states use FatesInterfaceTypesMod , only : hlm_num_luh2_transitions use EDTypesMod , only : area_site => area + use FatesInterfaceTypesMod , only : hlm_use_potentialveg ! CIME globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -84,37 +85,41 @@ subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) landuse_transition_matrix(:,:) = 0._r8 urban_fraction = 0._r8 - ! Check the LUH data incoming to see if any of the transitions are NaN - temp_vector = bc_in%hlm_luh_transitions - call CheckLUHData(temp_vector,modified_flag) - if (.not. modified_flag) then - ! identify urban fraction so that it can be factored into the land use state output - urban_fraction = bc_in%hlm_luh_states(findloc(bc_in%hlm_luh_state_names,'urban',dim=1)) - end if + ! if we are using potential veg only, then keep all transitions equal to zero. + if ( .not. hlm_use_potentialveg ) then - !!TODO: may need some logic here to ask whether or not ot perform land use change on this timestep. current code occurs every day. - !!If not doing transition every day, need to update units. + ! Check the LUH data incoming to see if any of the transitions are NaN + temp_vector = bc_in%hlm_luh_transitions + call CheckLUHData(temp_vector,modified_flag) + if (.not. modified_flag) then + ! identify urban fraction so that it can be factored into the land use state output + urban_fraction = bc_in%hlm_luh_states(findloc(bc_in%hlm_luh_state_names,'urban',dim=1)) + end if - transitions_loop: do i_luh2_transitions = 1, hlm_num_luh2_transitions + !!TODO: may need some logic here to ask whether or not ot perform land use change on this timestep. current code occurs every day. + !!If not doing transition every day, need to update units. - ! transition names are written in form xxxxx_to_yyyyy where x and y are donor and receiver state names - transition_name = bc_in%hlm_luh_transition_names(i_luh2_transitions) - donor_name = transition_name(1:5) - receiver_name = transition_name(10:14) + transitions_loop: do i_luh2_transitions = 1, hlm_num_luh2_transitions - ! Get the fates land use type index associated with the luh2 state types - i_donor= lumap%GetIndex(donor_name) - i_receiver = lumap%GetIndex(receiver_name) + ! transition names are written in form xxxxx_to_yyyyy where x and y are donor and receiver state names + transition_name = bc_in%hlm_luh_transition_names(i_luh2_transitions) + donor_name = transition_name(1:5) + receiver_name = transition_name(10:14) - ! Avoid transitions with 'urban' as those are handled seperately - ! Also ignore diagonal elements of transition matrix. - if (.not.(i_donor .eq. fates_unset_int .or. i_receiver .eq. fates_unset_int .or. i_donor .eq. i_receiver)) then - landuse_transition_matrix(i_donor,i_receiver) = & - landuse_transition_matrix(i_donor,i_receiver) + temp_vector(i_luh2_transitions) * years_per_day / (1._r8 - urban_fraction) + ! Get the fates land use type index associated with the luh2 state types + i_donor= lumap%GetIndex(donor_name) + i_receiver = lumap%GetIndex(receiver_name) - end if - end do transitions_loop + ! Avoid transitions with 'urban' as those are handled seperately + ! Also ignore diagonal elements of transition matrix. + if (.not.(i_donor .eq. fates_unset_int .or. i_receiver .eq. fates_unset_int .or. i_donor .eq. i_receiver)) then + landuse_transition_matrix(i_donor,i_receiver) = & + landuse_transition_matrix(i_donor,i_receiver) + temp_vector(i_luh2_transitions) * years_per_day / (1._r8 - urban_fraction) + end if + end do transitions_loop + + end if end subroutine get_landuse_transition_rates @@ -239,33 +244,37 @@ subroutine get_luh_statedata(bc_in, state_vector) state_vector(:) = 0._r8 urban_fraction = 0._r8 - ! Check to see if the incoming state vector is NaN. - temp_vector = bc_in%hlm_luh_states - call CheckLUHData(temp_vector,modified_flag) - if (.not. modified_flag) then - ! identify urban fraction so that it can be factored into the land use state output - urban_fraction = bc_in%hlm_luh_states(findloc(bc_in%hlm_luh_state_names,'urban',dim=1)) - end if - - ! loop over all states and add up the ones that correspond to a given fates land use type - do i_luh2_states = 1, hlm_num_luh2_states - - ! Get the luh2 state name and determine fates aggregated land use - ! type index from the state to lutype map - state_name = bc_in%hlm_luh_state_names(i_luh2_states) - ii = lumap%GetIndex(state_name) - - ! Avoid 'urban' states whose indices have been given unset values - if (ii .ne. fates_unset_int) then - state_vector(ii) = state_vector(ii) + & - temp_vector(i_luh2_states) / (1._r8 - urban_fraction) + if ( .not. hlm_use_potentialveg ) then + ! Check to see if the incoming state vector is NaN. + temp_vector = bc_in%hlm_luh_states + call CheckLUHData(temp_vector,modified_flag) + if (.not. modified_flag) then + ! identify urban fraction so that it can be factored into the land use state output + urban_fraction = bc_in%hlm_luh_states(findloc(bc_in%hlm_luh_state_names,'urban',dim=1)) end if - end do - ! check to ensure total area == 1, and correct if not - if ( abs(sum(state_vector(:)) - 1._r8) .gt. nearzero ) then - write(fates_log(),*) 'warning: sum(state_vector) = ', sum(state_vector(:)) - state_vector = state_vector(:) / sum(state_vector(:)) + ! loop over all states and add up the ones that correspond to a given fates land use type + do i_luh2_states = 1, hlm_num_luh2_states + + ! Get the luh2 state name and determine fates aggregated land use + ! type index from the state to lutype map + state_name = bc_in%hlm_luh_state_names(i_luh2_states) + ii = lumap%GetIndex(state_name) + + ! Avoid 'urban' states whose indices have been given unset values + if (ii .ne. fates_unset_int) then + state_vector(ii) = state_vector(ii) + & + temp_vector(i_luh2_states) / (1._r8 - urban_fraction) + end if + end do + + ! check to ensure total area == 1, and correct if not + if ( abs(sum(state_vector(:)) - 1._r8) .gt. nearzero ) then + write(fates_log(),*) 'warning: sum(state_vector) = ', sum(state_vector(:)) + state_vector = state_vector(:) / sum(state_vector(:)) + end if + else + state_vector(primaryland) = 1._r8 end if end subroutine get_luh_statedata diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index b4d900de02..ca32a10217 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1891,6 +1891,12 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_use_luh = ',ival,' to FATES' end if + case('use_potentialveg') + hlm_use_potentialveg = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_use_potentialveg = ',ival,' to FATES' + end if + case('num_luh2_states') hlm_num_luh2_states = ival if (fates_global_verbose()) then diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 30cd52270f..31861c262e 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -121,6 +121,7 @@ module FatesInterfaceTypesMod ! bc_in%hlm_harvest_rates and bc_in%hlm_harvest_catnames integer, public :: hlm_use_luh ! flag to signal whether or not to use luh2 drivers + integer, public :: hlm_use_potentialveg ! flag to signal whether or not to use potential vegetation only integer, public :: hlm_num_luh2_states ! number of land use state types provided in LUH2 forcing dataset integer, public :: hlm_num_luh2_transitions ! number of land use transition types provided in LUH2 forcing dataset diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index ecf6acaf4b..157c7261ae 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -25,7 +25,7 @@ module FatesRestartInterfaceMod use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : hlm_use_sp use FatesInterfaceTypesMod, only : hlm_use_nocomp, hlm_use_fixed_biogeog - use FatesInterfaceTypesMod, only : hlm_use_luh + use FatesInterfaceTypesMod, only : hlm_use_potentialveg use FatesInterfaceTypesMod, only : fates_maxElementsPerSite use FatesInterfaceTypesMod, only : hlm_use_tree_damage use FatesHydraulicsMemMod, only : nshell @@ -712,7 +712,7 @@ subroutine define_restart_vars(this, initialize_variables) hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_trunk_product_si ) call this%set_restart_var(vname='fates_landuse_config_site', vtype=site_int, & - long_name='hlm_use_luh status of run that created this restart file', & + long_name='hlm_use_potentialveg status of run that created this restart file', & units='kgC/m2', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_landuse_config_si ) @@ -2614,7 +2614,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_trunk_product_si(io_idx_si) = sites(s)%resources_management%trunk_product_site ! land use flag - rio_landuse_config_si(io_idx_si) = hlm_use_luh + rio_landuse_config_si(io_idx_si) = hlm_use_potentialveg ! set numpatches for this column @@ -3605,7 +3605,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! if needed, trigger the special procedure to initialize land use structure from a ! restart run that did not include land use. - if (rio_landuse_config_si(io_idx_si) .eq. ifalse .and. hlm_use_luh .eq. itrue) then + if (rio_landuse_config_si(io_idx_si) .eq. itrue .and. hlm_use_potentialveg .eq. ifalse) then sites(s)%transition_landuse_from_off_to_on = .true. endif From 0269b2249febf3ce161e1d62e08af8504b3d2014 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 1 Nov 2023 16:59:51 -0700 Subject: [PATCH 038/300] buggfix and added a print statement --- biogeochem/EDPatchDynamicsMod.F90 | 3 ++- main/FatesInterfaceMod.F90 | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 352799c091..0747d09be5 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -110,7 +110,7 @@ module EDPatchDynamicsMod use FatesRunningMeanMod, only : ema_sdlng_mdd use FatesRunningMeanMod, only : ema_sdlng_emerg_h2o, ema_sdlng_mort_par, ema_sdlng2sap_par use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa, ema_longterm - + ! CIME globals use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use shr_log_mod , only : errMsg => shr_log_errMsg @@ -288,6 +288,7 @@ subroutine disturbance_rates( site_in, bc_in) if(.not. site_in%transition_landuse_from_off_to_on) then call get_landuse_transition_rates(bc_in, site_in%landuse_transition_matrix) else + write(fates_log(),*) 'transitioning from potential vegetation to actual land use' call get_init_landuse_transition_rates(bc_in, site_in%landuse_transition_matrix) endif else diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index ca32a10217..99d7ef56d3 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1891,7 +1891,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_use_luh = ',ival,' to FATES' end if - case('use_potentialveg') + case('use_fates_potentialveg') hlm_use_potentialveg = ival if (fates_global_verbose()) then write(fates_log(),*) 'Transfering hlm_use_potentialveg = ',ival,' to FATES' From c9414d23fdc70957531a146ffc23e1ab64651d94 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 1 Nov 2023 21:39:04 -0700 Subject: [PATCH 039/300] moar bugs --- biogeochem/EDPatchDynamicsMod.F90 | 121 ++++++++++++++---------------- main/EDMainMod.F90 | 12 +-- main/FatesRestartInterfaceMod.F90 | 1 + 3 files changed, 65 insertions(+), 69 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 0747d09be5..f8fbc45ac2 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -127,7 +127,7 @@ module EDPatchDynamicsMod public :: check_patch_area public :: set_patchno private:: fuse_2_patches - public :: get_frac_site_primary + public :: get_current_landuse_statevector character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -208,8 +208,6 @@ subroutine disturbance_rates( site_in, bc_in) integer :: threshold_sizeclass integer :: i_dist integer :: h_index - real(r8) :: frac_site_primary - real(r8) :: frac_site_secondary real(r8) :: harvest_rate real(r8) :: tempsum real(r8) :: mean_temp @@ -222,12 +220,13 @@ subroutine disturbance_rates( site_in, bc_in) !---------------------------------------------------------------------------------------------- ! first calculate the fraction of the site that is primary land - call get_frac_site_primary(site_in, frac_site_primary, frac_site_secondary) + call get_current_landuse_statevector(site_in, current_fates_landuse_state_vector) ! check status of transition_landuse_from_off_to_on flag, and do some error checking on it if(site_in%transition_landuse_from_off_to_on) then - if (abs(frac_site_primary - 1._r8) .gt. fates_tiny) then + if (sum(current_fates_landuse_state_vector(secondaryland:cropland)) .gt. nearzero) then write(fates_log(),*) 'flag for transition_landuse_from_off_to_on is set to true but site is not entirely primaryland' + write(fates_log(), *) current_fates_landuse_state_vector call endrun(msg=errMsg(sourcefile, __LINE__)) endif endif @@ -266,8 +265,8 @@ subroutine disturbance_rates( site_in, bc_in) bc_in%hlm_harvest_units, & currentPatch%land_use_label, & currentPatch%age_since_anthro_disturbance, & - frac_site_primary, & - frac_site_secondary, & + current_fates_landuse_state_vector(primaryland), & + current_fates_landuse_state_vector(secondaryland), & harvestable_forest_c, & harvest_tag) @@ -295,18 +294,6 @@ subroutine disturbance_rates( site_in, bc_in) site_in%landuse_transition_matrix(:,:) = 0._r8 endif - ! calculate total area in each landuse category - current_fates_landuse_state_vector(:) = 0._r8 - currentPatch => site_in%oldest_patch - do while (associated(currentPatch)) - if (currentPatch%land_use_label .gt. nocomp_bareground_land) then - current_fates_landuse_state_vector(currentPatch%land_use_label) = & - current_fates_landuse_state_vector(currentPatch%land_use_label) + & - currentPatch%area/AREA - end if - currentPatch => currentPatch%younger - end do - ! --------------------------------------------------------------------------------------------- ! Calculate Disturbance Rates based on the mortality rates just calculated ! --------------------------------------------------------------------------------------------- @@ -389,7 +376,8 @@ subroutine disturbance_rates( site_in, bc_in) harvest_rate, harvest_tag) else call get_harvest_rate_area (currentPatch%land_use_label, bc_in%hlm_harvest_catnames, & - bc_in%hlm_harvest_rates, frac_site_primary, frac_site_secondary, & + bc_in%hlm_harvest_rates, current_fates_landuse_state_vector(primaryland), & + current_fates_landuse_state_vector(secondaryland), & currentPatch%age_since_anthro_disturbance, harvest_rate) end if else @@ -1369,17 +1357,17 @@ subroutine spawn_patches( currentSite, bc_in) ! Copy any means or timers from the original patch to the new patch ! These values will inherit all info from the original patch ! -------------------------------------------------------------------------- - call buffer_patch%tveg24%CopyFromDonor(currentPatch%tveg24) - call buffer_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - call buffer_patch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) + call buffer_patch%tveg24%CopyFromDonor(currentSite%oldest_patch%tveg24) + call buffer_patch%tveg_lpa%CopyFromDonor(currentSite%oldest_patch%tveg_lpa) + call buffer_patch%tveg_longterm%CopyFromDonor(currentSite%oldest_patch%tveg_longterm) if ( regeneration_model == TRS_regeneration ) then - call buffer_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) - call buffer_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) - call buffer_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) + call buffer_patch%seedling_layer_par24%CopyFromDonor(currentSite%oldest_patch%seedling_layer_par24) + call buffer_patch%sdlng_mort_par%CopyFromDonor(currentSite%oldest_patch%sdlng_mort_par) + call buffer_patch%sdlng2sap_par%CopyFromDonor(currentSite%oldest_patch%sdlng2sap_par) do pft = 1,numpft - call buffer_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) - call buffer_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) + call buffer_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentSite%oldest_patch%sdlng_emerg_smp(pft)%p) + call buffer_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentSite%oldest_patch%sdlng_mdd(pft)%p) enddo end if @@ -2744,6 +2732,7 @@ subroutine fuse_patches( csite, bc_in ) real(r8) :: primary_land_fraction_beforefusion,primary_land_fraction_afterfusion integer :: pftlabelmin, pftlabelmax integer :: num_bareground_patches + integer :: i ! !--------------------------------------------------------------------- @@ -2991,6 +2980,17 @@ subroutine fuse_patches( csite, bc_in ) write(fates_log(),*) 'profile tolerance is too big, this shouldnt happen.' write(fates_log(),*) 'probably this means there are too many distinct categorical ' write(fates_log(),*) 'patch types for the maximum number of patches' + call dump_site(currentSite) + write(fates_log(),*) 'currentSite%area_bareground', currentSite%area_bareground + do i = 1, n_landuse_cats + write(fates_log(),*) 'i, currentSite%area_pft(:,i)',i, currentSite%area_pft(:,i) + end do + tmpptr => currentSite%youngest_patch + do while(associated(tmpptr)) + write(fates_log(),*) tmpptr%area, tmpptr%nocomp_pft_label, tmpptr%land_use_label + tmpptr => tmpptr%older + end do + call endrun(msg=errMsg(sourcefile, __LINE__)) endif else @@ -3526,42 +3526,37 @@ end function countPatches ! ===================================================================================== - subroutine get_frac_site_primary(site_in, frac_site_primary, frac_site_secondary) - - ! - ! !DESCRIPTION: - ! Calculate how much of a site is primary land and secondary land - ! - ! !USES: - use EDTypesMod , only : ed_site_type - ! - ! !ARGUMENTS: - type(ed_site_type) , intent(in), target :: site_in - real(r8) , intent(out) :: frac_site_primary - real(r8) , intent(out) :: frac_site_secondary - - ! !LOCAL VARIABLES: - type (fates_patch_type), pointer :: currentPatch + subroutine get_current_landuse_statevector(site_in, current_state_vector) + + ! + ! !DESCRIPTION: + ! Calculate how much of a site is each land use category. + ! this does not include bare ground when nocomp + fixed biogeography is on, + ! so will not sum to one in that case. otherwise it will sum to one. + ! + ! !USES: + use EDTypesMod , only : ed_site_type + ! + ! !ARGUMENTS: + type(ed_site_type) , intent(in), target :: site_in + real(r8) , intent(out) :: current_state_vector(n_landuse_cats) + + ! !LOCAL VARIABLES: + type (fates_patch_type), pointer :: currentPatch + + current_state_vector(:) = 0._r8 + + currentPatch => site_in%oldest_patch + do while (associated(currentPatch)) + if (currentPatch%land_use_label .gt. nocomp_bareground_land) then + current_state_vector(currentPatch%land_use_label) = & + current_state_vector(currentPatch%land_use_label) + & + currentPatch%area/AREA + end if + currentPatch => currentPatch%younger + end do - frac_site_primary = 0._r8 - currentPatch => site_in%oldest_patch - do while (associated(currentPatch)) - if (currentPatch%land_use_label .eq. primaryland) then - frac_site_primary = frac_site_primary + currentPatch%area * AREA_INV - endif - currentPatch => currentPatch%younger - end do - - frac_site_secondary = 0._r8 - currentPatch => site_in%oldest_patch - do while (associated(currentPatch)) - if (currentPatch%land_use_label .eq. secondaryland) then - frac_site_secondary = frac_site_secondary + currentPatch%area * AREA_INV - endif - currentPatch => currentPatch%younger - end do - - end subroutine get_frac_site_primary + end subroutine get_current_landuse_statevector ! ===================================================================================== diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index e9c984f200..edb9241dd1 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -75,6 +75,7 @@ module EDMainMod use EDTypesMod , only : phen_dstat_timeon use FatesConstantsMod , only : itrue,ifalse use FatesConstantsMod , only : primaryland, secondaryland + use FatesConstantsMod , only : n_landuse_cats use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : m2_per_ha use FatesConstantsMod , only : sec_per_day @@ -88,7 +89,7 @@ module EDMainMod use EDLoggingMortalityMod , only : IsItLoggingTime use EDLoggingMortalityMod , only : get_harvestable_carbon use DamageMainMod , only : IsItDamageTime - use EDPatchDynamicsMod , only : get_frac_site_primary + use EDPatchDynamicsMod , only : get_current_landuse_statevector use FatesGlobals , only : endrun => fates_endrun use ChecksBalancesMod , only : SiteMassStock use EDMortalityFunctionsMod , only : Mortality_Derivative @@ -376,8 +377,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) ! a lowered damage state. This cohort should bypass several calculations ! because it inherited them (such as daily carbon balance) real(r8) :: target_leaf_c - real(r8) :: frac_site_primary - real(r8) :: frac_site_secondary + real(r8) :: current_fates_landuse_state_vector(n_landuse_cats) real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) @@ -413,7 +413,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) !----------------------------------------------------------------------- - call get_frac_site_primary(currentSite, frac_site_primary, frac_site_secondary) + call get_current_landuse_statevector(currentSite, current_fates_landuse_state_vector) ! Clear site GPP and AR passing to HLM bc_out%gpp_site = 0._r8 @@ -478,8 +478,8 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) call Mortality_Derivative(currentSite, currentCohort, bc_in, & currentPatch%btran_ft, mean_temp, & currentPatch%land_use_label, & - currentPatch%age_since_anthro_disturbance, frac_site_primary, & - frac_site_secondary, harvestable_forest_c, harvest_tag) + currentPatch%age_since_anthro_disturbance, current_fates_landuse_state_vector(primaryland), & + current_fates_landuse_state_vector(secondaryland), harvestable_forest_c, harvest_tag) ! ----------------------------------------------------------------------------- ! Apply Plant Allocation and Reactive Transport diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 157c7261ae..259ed8c201 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -3606,6 +3606,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! if needed, trigger the special procedure to initialize land use structure from a ! restart run that did not include land use. if (rio_landuse_config_si(io_idx_si) .eq. itrue .and. hlm_use_potentialveg .eq. ifalse) then + write(fates_log(),*), 'setting transition_landuse_from_off_to_on flag based on restart potentialveg value.' sites(s)%transition_landuse_from_off_to_on = .true. endif From 39ecc274d5784cb45f2e35006724d5187b6a8e3a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 1 Nov 2023 22:16:09 -0700 Subject: [PATCH 040/300] fix true/false check for the potential veg --- biogeochem/FatesLandUseChangeMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 9a8fc57eda..99f1b8a611 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -86,7 +86,7 @@ subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) urban_fraction = 0._r8 ! if we are using potential veg only, then keep all transitions equal to zero. - if ( .not. hlm_use_potentialveg ) then + if (hlm_use_potentialveg .eq. ifalse) then ! Check the LUH data incoming to see if any of the transitions are NaN temp_vector = bc_in%hlm_luh_transitions @@ -244,7 +244,7 @@ subroutine get_luh_statedata(bc_in, state_vector) state_vector(:) = 0._r8 urban_fraction = 0._r8 - if ( .not. hlm_use_potentialveg ) then + if (hlm_use_potentialveg .eq. ifalse) then ! Check to see if the incoming state vector is NaN. temp_vector = bc_in%hlm_luh_states call CheckLUHData(temp_vector,modified_flag) From 1b42aeba5d267877fa2613b76814201add22283b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 1 Nov 2023 23:10:19 -0700 Subject: [PATCH 041/300] identify patch with matching land use to copy from for the buffer patch This also fixes an issue in which the current patch is fused and then deallocated causing the next iteration of the do loop to fail when trying to find current patch. --- biogeochem/EDPatchDynamicsMod.F90 | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 0747d09be5..87c03c8190 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -507,7 +507,7 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: disturbance_rate ! rate of disturbance being resolved [fraction of patch area / day] real(r8) :: oldarea ! old patch area prior to disturbance logical :: clearing_matrix(n_landuse_cats,n_landuse_cats) ! do we clear vegetation when transferring from one LU type to another? - type (fates_patch_type) , pointer :: buffer_patch, temp_patch + type (fates_patch_type) , pointer :: buffer_patch, temp_patch, copyPatch, previousPatch real(r8) :: nocomp_pft_area_vector(numpft) real(r8) :: nocomp_pft_area_vector_allocated(numpft) real(r8) :: fraction_to_keep @@ -1339,6 +1339,7 @@ subroutine spawn_patches( currentSite, bc_in) do while(associated(currentPatch)) if (currentPatch%changed_landuse_this_ts .and. currentPatch%land_use_label .eq. i_land_use_label) then nocomp_pft_area_vector(currentPatch%nocomp_pft_label) = nocomp_pft_area_vector(currentPatch%nocomp_pft_label) + currentPatch%area + copyPatch => currentPatch end if currentPatch => currentPatch%younger end do @@ -1369,17 +1370,17 @@ subroutine spawn_patches( currentSite, bc_in) ! Copy any means or timers from the original patch to the new patch ! These values will inherit all info from the original patch ! -------------------------------------------------------------------------- - call buffer_patch%tveg24%CopyFromDonor(currentPatch%tveg24) - call buffer_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - call buffer_patch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) + call buffer_patch%tveg24%CopyFromDonor(copyPatch%tveg24) + call buffer_patch%tveg_lpa%CopyFromDonor(copyPatch%tveg_lpa) + call buffer_patch%tveg_longterm%CopyFromDonor(copyPatch%tveg_longterm) if ( regeneration_model == TRS_regeneration ) then - call buffer_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) - call buffer_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) - call buffer_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) + call buffer_patch%seedling_layer_par24%CopyFromDonor(copyPatch%seedling_layer_par24) + call buffer_patch%sdlng_mort_par%CopyFromDonor(copyPatch%sdlng_mort_par) + call buffer_patch%sdlng2sap_par%CopyFromDonor(copyPatch%sdlng2sap_par) do pft = 1,numpft - call buffer_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) - call buffer_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) + call buffer_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(copyPatch%sdlng_emerg_smp(pft)%p) + call buffer_patch%sdlng_mdd(pft)%p%CopyFromDonor(copyPatch%sdlng_mdd(pft)%p) enddo end if @@ -1390,7 +1391,9 @@ subroutine spawn_patches( currentSite, bc_in) if (fraction_to_keep .lt. nearzero) then ! we don't want any patch area with this PFT idendity at all anymore. Fuse it into the buffer patch. currentPatch%nocomp_pft_label = 0 + previousPatch => currentPatch%older call fuse_2_patches(currentSite, currentPatch, buffer_patch) + currentPatch => previousPatch elseif (fraction_to_keep .lt. (1._r8 - nearzero)) then ! we have more patch are of this PFT than we want, but we do want to keep some of it. ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. From 321616bba099e54b6d2cd25f2273cb1adc1e4fc4 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 2 Nov 2023 09:15:26 -0700 Subject: [PATCH 042/300] some cleanup but still not working --- biogeochem/EDPatchDynamicsMod.F90 | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 2ac7320b8a..9f251c0667 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -497,7 +497,7 @@ subroutine spawn_patches( currentSite, bc_in) logical :: clearing_matrix(n_landuse_cats,n_landuse_cats) ! do we clear vegetation when transferring from one LU type to another? type (fates_patch_type) , pointer :: buffer_patch, temp_patch, copyPatch, previousPatch real(r8) :: nocomp_pft_area_vector(numpft) - real(r8) :: nocomp_pft_area_vector_allocated(numpft) + real(r8) :: nocomp_pft_area_vector_filled(numpft) real(r8) :: fraction_to_keep integer :: i_land_use_label integer :: i_pft @@ -1321,7 +1321,7 @@ subroutine spawn_patches( currentSite, bc_in) lu_loop: do i_land_use_label = 1, n_landuse_cats nocomp_pft_area_vector(:) = 0._r8 - nocomp_pft_area_vector_allocated(:) = 0._r8 + nocomp_pft_area_vector_filled(:) = 0._r8 currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) @@ -1375,14 +1375,17 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) if (currentPatch%changed_landuse_this_ts) then + + ! !!! CDKCDK I think this next line is wrong. Need to fix it. !!!!!!!!!!!!!!!!!!!!!!! + fraction_to_keep = currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * area / nocomp_pft_area_vector(currentPatch%nocomp_pft_label) - if (fraction_to_keep .lt. nearzero) then - ! we don't want any patch area with this PFT idendity at all anymore. Fuse it into the buffer patch. + if (fraction_to_keep .le. nearzero) then + ! we don't want any patch area with this PFT identity at all anymore. Fuse it into the buffer patch. currentPatch%nocomp_pft_label = 0 previousPatch => currentPatch%older call fuse_2_patches(currentSite, currentPatch, buffer_patch) currentPatch => previousPatch - elseif (fraction_to_keep .lt. (1._r8 - nearzero)) then + elseif (fraction_to_keep .le. (1._r8 - nearzero)) then ! we have more patch are of this PFT than we want, but we do want to keep some of it. ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. @@ -1391,10 +1394,14 @@ subroutine spawn_patches( currentSite, bc_in) ! temp_patch%nocomp_pft_label = 0 call fuse_2_patches(currentSite, temp_patch, buffer_patch) + ! + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) = & + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + currentPatch%area + currentPatch%changed_landuse_this_ts = .false. else ! we want to keep all of this patch (and possibly more) - nocomp_pft_area_vector_allocated(currentPatch%nocomp_pft_label) = & - nocomp_pft_area_vector_allocated(currentPatch%nocomp_pft_label) + currentPatch%area + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) = & + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + currentPatch%area currentPatch%changed_landuse_this_ts = .false. endif end if @@ -1404,9 +1411,9 @@ subroutine spawn_patches( currentSite, bc_in) ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list nocomp_pft_loop_2: do i_pft = 1, numpft ! - if (nocomp_pft_area_vector_allocated(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then + if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then - newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_allocated(i_pft) + newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) if (newp_area .lt. buffer_patch%area) then From 8493d5b848782a303955fdfc38c7e455b0c81e0b Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 2 Nov 2023 09:59:23 -0700 Subject: [PATCH 043/300] possible fix to raction_to_keep logic --- biogeochem/EDPatchDynamicsMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 9f251c0667..2ebb0efaea 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1376,9 +1376,9 @@ subroutine spawn_patches( currentSite, bc_in) do while(associated(currentPatch)) if (currentPatch%changed_landuse_this_ts) then - ! !!! CDKCDK I think this next line is wrong. Need to fix it. !!!!!!!!!!!!!!!!!!!!!!! - - fraction_to_keep = currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * area / nocomp_pft_area_vector(currentPatch%nocomp_pft_label) + fraction_to_keep = (currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * sum(nocomp_pft_area_vector(:)) & + - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label)) / currentPatch%area + if (fraction_to_keep .le. nearzero) then ! we don't want any patch area with this PFT identity at all anymore. Fuse it into the buffer patch. currentPatch%nocomp_pft_label = 0 From b01960debe123b66e8aadb05bf0e8585df3cc0e2 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 2 Nov 2023 10:35:17 -0700 Subject: [PATCH 044/300] fix for fusing a patch that isn't part of the linked list structure into one that is --- biogeochem/EDPatchDynamicsMod.F90 | 46 +++++++++++++++++-------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 2ebb0efaea..917f4c1137 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -3197,29 +3197,33 @@ subroutine fuse_2_patches(csite, dp, rp) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - if(associated(youngerp))then - ! Update the younger patch's new older patch (because it isn't dp anymore) - youngerp%older => olderp - else - ! There was no younger patch than dp, so the head of the young order needs - ! to be set, and it is set as the patch older than dp. That patch - ! already knows it's older patch (so no need to set or change it) - csite%youngest_patch => olderp - olderp%younger => null() - end if + ! if neither youngerp nor olderp are associated, that means that the patch we are no longer tracking + ! is not part of the linked-list structure, and so no further action needs to be taken. + if(associated(youngerp) .or. associated(olderp))then + + if(associated(youngerp))then + ! Update the younger patch's new older patch (because it isn't dp anymore) + youngerp%older => olderp + else + ! There was no younger patch than dp, so the head of the young order needs + ! to be set, and it is set as the patch older than dp. That patch + ! already knows it's older patch (so no need to set or change it) + csite%youngest_patch => olderp + olderp%younger => null() + end if - - if(associated(olderp))then - ! Update the older patch's new younger patch (becuase it isn't dp anymore) - olderp%younger => youngerp - else - ! There was no patch older than dp, so the head of the old patch order needs - ! to be set, and it is set as the patch younger than dp. That patch already - ! knows it's younger patch, no need to set - csite%oldest_patch => youngerp - youngerp%older => null() - end if + if(associated(olderp))then + ! Update the older patch's new younger patch (becuase it isn't dp anymore) + olderp%younger => youngerp + else + ! There was no patch older than dp, so the head of the old patch order needs + ! to be set, and it is set as the patch younger than dp. That patch already + ! knows it's younger patch, no need to set + csite%oldest_patch => youngerp + youngerp%older => null() + end if + end if end subroutine fuse_2_patches From fe43f5c7b85f90c3db90d90d98980c301e7cc189 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 2 Nov 2023 10:44:44 -0700 Subject: [PATCH 045/300] another fix in the patch nocomp-pft reweighting after land use change section --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 917f4c1137..96c65779ab 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1374,7 +1374,7 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) - if (currentPatch%changed_landuse_this_ts) then + if (currentPatch%changed_landuse_this_ts .and. currentPatch%land_use_label .eq. i_land_use_label) then fraction_to_keep = (currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * sum(nocomp_pft_area_vector(:)) & - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label)) / currentPatch%area From a7b8d888508ffeaf0a2141f7904d64788b6809a8 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 2 Nov 2023 12:00:14 -0700 Subject: [PATCH 046/300] fixed another thing that was wrong --- biogeochem/EDPatchDynamicsMod.F90 | 56 ++++++++++++++++++------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 96c65779ab..d200df2994 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1411,39 +1411,47 @@ subroutine spawn_patches( currentSite, bc_in) ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list nocomp_pft_loop_2: do i_pft = 1, numpft ! - if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then + if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero) then + ! + if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then + ! + newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) + ! + if (newp_area .lt. buffer_patch%area) then - newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) + ! split buffer patch in two, keeping the smaller buffer patch to put into new patches + allocate(temp_patch) + call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) - if (newp_area .lt. buffer_patch%area) then + ! give the new patch the intended nocomp PFT label + temp_patch%nocomp_pft_label = i_pft - ! split buffer patch in two, keeping the smaller buffer patch to put into new patches - allocate(temp_patch) - call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + temp_patch%area - ! give the new patch the intended nocomp PFT label - temp_patch%nocomp_pft_label = i_pft + ! put the new patch into the linked list + call InsertPatch(currentSite, temp_patch) - ! put the new patch into the linked list - call InsertPatch(currentSite, temp_patch) + ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be + ! refilled the next time through the loop. + temp_patch => null() - ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be - ! refilled the next time through the loop. - temp_patch => null() - - else - ! give the buffer patch the intended nocomp PFT label - buffer_patch%nocomp_pft_label = i_pft + else + ! give the buffer patch the intended nocomp PFT label + buffer_patch%nocomp_pft_label = i_pft - ! put the buffer patch directly into the linked list - call InsertPatch(currentSite, buffer_patch) + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area - buffer_patch_in_linked_list = .true. - - end if + ! put the buffer patch directly into the linked list + call InsertPatch(currentSite, buffer_patch) - end if + buffer_patch_in_linked_list = .true. + + end if + end if + end if end do nocomp_pft_loop_2 ! now we want to make sure that either the buffer_patch either has zero area (presumably it was never used), in which case it should be deallocated, @@ -1451,7 +1459,7 @@ subroutine spawn_patches( currentSite, bc_in) ! if either of those, that means everything worked properly, if not, then something has gone wrong. if (buffer_patch_in_linked_list) then buffer_patch => null() - else if (buffer_patch%area .lt. fates_tiny) then + else if (buffer_patch%area .lt. rsnbl_math_prec) then ! here we need to deallocate the buffer patch so that we don't get a memory leak/ call buffer_patch%FreeMemory(regeneration_model, numpft) deallocate(buffer_patch, stat=istat, errmsg=smsg) From 998aa48efc875a163cc42d397e83cb3bfdbf5a40 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Mon, 6 Nov 2023 10:47:37 -0800 Subject: [PATCH 047/300] more bugfixes, attempted bugfixes, and diagnostics --- biogeochem/EDPatchDynamicsMod.F90 | 349 +++++++++++++++++---------- biogeochem/FatesLandUseChangeMod.F90 | 12 +- main/EDInitMod.F90 | 6 +- main/FatesConstantsMod.F90 | 3 + main/FatesRestartInterfaceMod.F90 | 1 - 5 files changed, 233 insertions(+), 138 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index d200df2994..88a5e9b6f6 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1,4 +1,3 @@ - module EDPatchDynamicsMod ! ============================================================================ ! Controls formation, creation, fusing and termination of patch level processes. @@ -214,6 +213,7 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) real(r8) :: current_fates_landuse_state_vector(n_landuse_cats) ! [m2/m2] + real(r8), parameter :: max_daily_disturbance_rate = 0.999_r8 !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) ! And the same rates in understory plants have already been applied to %dndt @@ -287,7 +287,6 @@ subroutine disturbance_rates( site_in, bc_in) if(.not. site_in%transition_landuse_from_off_to_on) then call get_landuse_transition_rates(bc_in, site_in%landuse_transition_matrix) else - write(fates_log(),*) 'transitioning from potential vegetation to actual land use' call get_init_landuse_transition_rates(bc_in, site_in%landuse_transition_matrix) endif else @@ -414,13 +413,14 @@ subroutine disturbance_rates( site_in, bc_in) endif ! if the sum of all disturbance rates is such that they will exceed total patch area on this day, then reduce them all proportionally. - if ( (sum(currentPatch%disturbance_rates(:)) + sum(currentPatch%landuse_transition_rates(1:n_landuse_cats))) .gt. 1.0_r8 ) then + if ( (sum(currentPatch%disturbance_rates(:)) + sum(currentPatch%landuse_transition_rates(1:n_landuse_cats))) .gt. & + max_daily_disturbance_rate ) then tempsum = sum(currentPatch%disturbance_rates(:)) + sum(currentPatch%landuse_transition_rates(1:n_landuse_cats)) do i_dist = 1,N_DIST_TYPES - currentPatch%disturbance_rates(i_dist) = currentPatch%disturbance_rates(i_dist) / tempsum + currentPatch%disturbance_rates(i_dist) = max_daily_disturbance_rate * currentPatch%disturbance_rates(i_dist) / tempsum end do do i_dist = 1,n_landuse_cats - currentPatch%landuse_transition_rates(i_dist) = currentPatch%landuse_transition_rates(i_dist) / tempsum + currentPatch%landuse_transition_rates(i_dist) = max_daily_disturbance_rate * currentPatch%landuse_transition_rates(i_dist) / tempsum end do endif @@ -503,6 +503,9 @@ subroutine spawn_patches( currentSite, bc_in) integer :: i_pft real(r8) :: newp_area logical :: buffer_patch_in_linked_list + real(r8) :: tmp, tmp2 + integer :: n_pfts_by_landuse + integer :: which_pft_allowed !--------------------------------------------------------------------- @@ -522,7 +525,7 @@ subroutine spawn_patches( currentSite, bc_in) ! get rules for vegetation clearing during land use change call get_landusechange_rules(clearing_matrix) - + ! in the nocomp cases, since every patch has a PFT identity, it can only receive patch area from patches ! that have the same identity. In order to allow this, we have this very high level loop over nocomp PFTs ! and only do the disturbance for any patches that have that nocomp PFT identity. @@ -1311,6 +1314,7 @@ subroutine spawn_patches( currentSite, bc_in) end do nocomp_pft_loop nocomp_and_luh_if: if ( hlm_use_nocomp .eq. itrue .and. hlm_use_luh .eq. itrue ) then + ! CDK test nocomp_and_luh_if: if ( .false. ) then ! disturbance has just happened, and now the nocomp PFT identities of the newly-disturbed patches ! need to be remapped to those associated with the new land use type. @@ -1318,7 +1322,7 @@ subroutine spawn_patches( currentSite, bc_in) ! logic: loop over land use types. figure out the nocomp PFT fractions for all newly-disturbed patches that have become that land use type. ! if the - lu_loop: do i_land_use_label = 1, n_landuse_cats + lu_loop: do i_land_use_label = n_landuse_cats, 1, -1 nocomp_pft_area_vector(:) = 0._r8 nocomp_pft_area_vector_filled(:) = 0._r8 @@ -1332,147 +1336,223 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch => currentPatch%younger end do - patch_area_to_reallocate_if: if ( sum(nocomp_pft_area_vector(:)) .gt. nearzero ) then - ! create buffer patch to put all of the pieces carved off of other patches - allocate(buffer_patch) - - call buffer_patch%Create(0._r8, 0._r8, i_land_use_label, 0, & - hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & - regeneration_model) - - ! make a note that this buffer patch has not been put into the linked list - buffer_patch_in_linked_list = .false. - - ! Initialize the litter pools to zero - do el=1,num_elements - call buffer_patch%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) - end do - buffer_patch%tallest => null() - buffer_patch%shortest => null() - - ! Copy any means or timers from the original patch to the new patch - ! These values will inherit all info from the original patch - ! -------------------------------------------------------------------------- - call buffer_patch%tveg24%CopyFromDonor(copyPatch%tveg24) - call buffer_patch%tveg_lpa%CopyFromDonor(copyPatch%tveg_lpa) - call buffer_patch%tveg_longterm%CopyFromDonor(copyPatch%tveg_longterm) - - if ( regeneration_model == TRS_regeneration ) then - call buffer_patch%seedling_layer_par24%CopyFromDonor(copyPatch%seedling_layer_par24) - call buffer_patch%sdlng_mort_par%CopyFromDonor(copyPatch%sdlng_mort_par) - call buffer_patch%sdlng2sap_par%CopyFromDonor(copyPatch%sdlng2sap_par) - do pft = 1,numpft - call buffer_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(copyPatch%sdlng_emerg_smp(pft)%p) - call buffer_patch%sdlng_mdd(pft)%p%CopyFromDonor(copyPatch%sdlng_mdd(pft)%p) - enddo + ! figure out how may PFTs on each land use type. if only 1, then the next calculation is much simpler: we just need to know which PFT is allowed. + n_pfts_by_landuse = 0 + do i_pft = 1,numpft + if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero) then + n_pfts_by_landuse = n_pfts_by_landuse + 1 + which_pft_allowed = i_pft end if - - currentPatch => currentSite%oldest_patch - do while(associated(currentPatch)) - if (currentPatch%changed_landuse_this_ts .and. currentPatch%land_use_label .eq. i_land_use_label) then + end do + if ( n_pfts_by_landuse .ne. 1) then + which_pft_allowed = fates_unset_int + endif - fraction_to_keep = (currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * sum(nocomp_pft_area_vector(:)) & - - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label)) / currentPatch%area - - if (fraction_to_keep .le. nearzero) then - ! we don't want any patch area with this PFT identity at all anymore. Fuse it into the buffer patch. - currentPatch%nocomp_pft_label = 0 - previousPatch => currentPatch%older - call fuse_2_patches(currentSite, currentPatch, buffer_patch) - currentPatch => previousPatch - elseif (fraction_to_keep .le. (1._r8 - nearzero)) then - ! we have more patch are of this PFT than we want, but we do want to keep some of it. - ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. - - allocate(temp_patch) - call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep) - ! - temp_patch%nocomp_pft_label = 0 - call fuse_2_patches(currentSite, temp_patch, buffer_patch) - ! - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) = & - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + currentPatch%area - currentPatch%changed_landuse_this_ts = .false. - else - ! we want to keep all of this patch (and possibly more) - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) = & - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + currentPatch%area - currentPatch%changed_landuse_this_ts = .false. - endif + patch_area_to_reallocate_if: if ( sum(nocomp_pft_area_vector(:)) .gt. nearzero ) then + more_than_1_pft_to_handle_if: if ( n_pfts_by_landuse .ne. 1 ) then + ! create buffer patch to put all of the pieces carved off of other patches + allocate(buffer_patch) + + call buffer_patch%Create(0._r8, 0._r8, i_land_use_label, 0, & + hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & + regeneration_model) + + ! make a note that this buffer patch has not been put into the linked list + buffer_patch_in_linked_list = .false. + + ! Initialize the litter pools to zero + do el=1,num_elements + call buffer_patch%litter(el)%InitConditions(init_leaf_fines=0._r8, & + init_root_fines=0._r8, & + init_ag_cwd=0._r8, & + init_bg_cwd=0._r8, & + init_seed=0._r8, & + init_seed_germ=0._r8) + end do + buffer_patch%tallest => null() + buffer_patch%shortest => null() + + ! Copy any means or timers from the original patch to the new patch + ! These values will inherit all info from the original patch + ! -------------------------------------------------------------------------- + call buffer_patch%tveg24%CopyFromDonor(copyPatch%tveg24) + call buffer_patch%tveg_lpa%CopyFromDonor(copyPatch%tveg_lpa) + call buffer_patch%tveg_longterm%CopyFromDonor(copyPatch%tveg_longterm) + + if ( regeneration_model == TRS_regeneration ) then + call buffer_patch%seedling_layer_par24%CopyFromDonor(copyPatch%seedling_layer_par24) + call buffer_patch%sdlng_mort_par%CopyFromDonor(copyPatch%sdlng_mort_par) + call buffer_patch%sdlng2sap_par%CopyFromDonor(copyPatch%sdlng2sap_par) + do pft = 1,numpft + call buffer_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(copyPatch%sdlng_emerg_smp(pft)%p) + call buffer_patch%sdlng_mdd(pft)%p%CopyFromDonor(copyPatch%sdlng_mdd(pft)%p) + enddo + end if + + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + if (currentPatch%changed_landuse_this_ts .and. currentPatch%land_use_label .eq. i_land_use_label) then + + fraction_to_keep = (currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * sum(nocomp_pft_area_vector(:)) & + - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label)) / currentPatch%area + + if (fraction_to_keep .lt. (-1._r8 * nearzero)) then + write(fates_log(),*) 'negative fraction_to_keep', fraction_to_keep + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + if (fraction_to_keep .le. nearzero) then + ! we don't want any patch area with this PFT identity at all anymore. Fuse it into the buffer patch. + currentPatch%nocomp_pft_label = 0 + previousPatch => currentPatch%older + call fuse_2_patches(currentSite, currentPatch, buffer_patch) + currentPatch => previousPatch + elseif (fraction_to_keep .lt. 1._r8) then + ! we have more patch are of this PFT than we want, but we do want to keep some of it. + ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. + + allocate(temp_patch) + call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep) + ! + temp_patch%nocomp_pft_label = 0 + call fuse_2_patches(currentSite, temp_patch, buffer_patch) + ! + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) = & + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + currentPatch%area + currentPatch%changed_landuse_this_ts = .false. + else + ! we want to keep all of this patch (and possibly more) + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) = & + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + currentPatch%area + currentPatch%changed_landuse_this_ts = .false. + endif + end if + currentPatch => currentPatch%younger + end do + + ! at this point, lets check that the total patch area remaining to be relabelled equals what we think that it is. + tmp = 0._r8 + tmp2 = 0._r8 + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + tmp2 = tmp + currentPatch%area + if (currentPatch%changed_landuse_this_ts .and. currentPatch%land_use_label .eq. i_land_use_label) then + tmp = tmp + currentPatch%area + end if + currentPatch => currentPatch%younger + end do + if (abs(sum(nocomp_pft_area_vector(:)) - sum(nocomp_pft_area_vector_filled(:)) - tmp) .gt. rsnbl_math_prec) then + write(fates_log(),*) 'midway through patch reallocation and things are already not adding up.' + write(fates_log(),*) currentSite%area_pft(:,i_land_use_label) + write(fates_log(),*) '-----' + write(fates_log(),*) nocomp_pft_area_vector_filled + write(fates_log(),*) '-----' + write(fates_log(),*) nocomp_pft_area_vector + write(fates_log(),*) '-----' + write(fates_log(),*) tmp2, tmp2 + buffer_patch%area + write(fates_log(),*) buffer_patch%area, buffer_patch%land_use_label, buffer_patch%nocomp_pft_label + write(fates_log(),*) tmp, sum(nocomp_pft_area_vector(:)) - sum(nocomp_pft_area_vector_filled(:)) - tmp + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + write(fates_log(),*) currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label + currentPatch => currentPatch%younger + end do + call endrun(msg=errMsg(sourcefile, __LINE__)) end if - currentPatch => currentPatch%younger - end do - ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list - nocomp_pft_loop_2: do i_pft = 1, numpft - ! - if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero) then + + ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list + nocomp_pft_loop_2: do i_pft = 1, numpft ! - if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then + if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero) then ! - newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) - ! - if (newp_area .lt. buffer_patch%area) then + if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then + ! + newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) + ! + if (newp_area .lt. buffer_patch%area) then - ! split buffer patch in two, keeping the smaller buffer patch to put into new patches - allocate(temp_patch) - call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) + ! split buffer patch in two, keeping the smaller buffer patch to put into new patches + allocate(temp_patch) + call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) - ! give the new patch the intended nocomp PFT label - temp_patch%nocomp_pft_label = i_pft + ! give the new patch the intended nocomp PFT label + temp_patch%nocomp_pft_label = i_pft - ! track that we have added this patch area - nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + temp_patch%area + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + temp_patch%area - ! put the new patch into the linked list - call InsertPatch(currentSite, temp_patch) + ! put the new patch into the linked list + call InsertPatch(currentSite, temp_patch) - ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be - ! refilled the next time through the loop. - temp_patch => null() + ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be + ! refilled the next time through the loop. + temp_patch => null() - else - ! give the buffer patch the intended nocomp PFT label - buffer_patch%nocomp_pft_label = i_pft + else + ! give the buffer patch the intended nocomp PFT label + buffer_patch%nocomp_pft_label = i_pft - ! track that we have added this patch area - nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area - ! put the buffer patch directly into the linked list - call InsertPatch(currentSite, buffer_patch) + ! put the buffer patch directly into the linked list + call InsertPatch(currentSite, buffer_patch) - buffer_patch_in_linked_list = .true. + buffer_patch_in_linked_list = .true. - end if + end if + end if end if + end do nocomp_pft_loop_2 + + ! now we want to make sure that either the buffer_patch either has zero area (presumably it was never used), in which case it should be deallocated, + ! or else it does have area but it has been put into the site linked list, and so buffer patch should be nulled before next pass through outer loop. + ! if either of those, that means everything worked properly, if not, then something has gone wrong. + if (buffer_patch_in_linked_list) then + buffer_patch => null() + else if (buffer_patch%area .lt. rsnbl_math_prec) then + ! here we need to deallocate the buffer patch so that we don't get a memory leak/ + call buffer_patch%FreeMemory(regeneration_model, numpft) + deallocate(buffer_patch, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + else + write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' + write(fates_log(),*) 'buffer_patch%area', buffer_patch%area + call endrun(msg=errMsg(sourcefile, __LINE__)) end if - end do nocomp_pft_loop_2 - - ! now we want to make sure that either the buffer_patch either has zero area (presumably it was never used), in which case it should be deallocated, - ! or else it does have area but it has been put into the site linked list, and so buffer patch should be nulled before next pass through outer loop. - ! if either of those, that means everything worked properly, if not, then something has gone wrong. - if (buffer_patch_in_linked_list) then - buffer_patch => null() - else if (buffer_patch%area .lt. rsnbl_math_prec) then - ! here we need to deallocate the buffer patch so that we don't get a memory leak/ - call buffer_patch%FreeMemory(regeneration_model, numpft) - deallocate(buffer_patch, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) + + ! check that the area we have added is the same as the area we have taken away. if not, crash. + if ( abs(sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:))) .gt. rsnbl_math_prec) then + write(fates_log(),*) 'patch reallocation logic doesnt add up. difference is: ', sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:)) + write(fates_log(),*) nocomp_pft_area_vector_filled + write(fates_log(),*) nocomp_pft_area_vector + write(fates_log(),*) i_land_use_label + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + write(fates_log(),*) currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label + currentPatch => currentPatch%younger + end do call endrun(msg=errMsg(sourcefile, __LINE__)) - endif + end if else - write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' - write(fates_log(),*) 'buffer_patch%area', buffer_patch%area - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + ! if there is only one PFT allowed on this land use type, then all we need to do is relabel all of the patches that just changed + ! land use type and let patch fusion take care of the rest. + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + if (currentPatch%changed_landuse_this_ts .and. currentPatch%land_use_label .eq. i_land_use_label) then + currentPatch%nocomp_pft_label = which_pft_allowed + currentPatch%changed_landuse_this_ts = .false. + end if + currentPatch => currentPatch%younger + end do + endif more_than_1_pft_to_handle_if end if patch_area_to_reallocate_if + call check_patch_area(currentSite) end do lu_loop else ! if not using a configuration where the changed_landuse_this_ts is relevant, loop through all patches and reset it @@ -1555,7 +1635,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) end if currentPatch%burnt_frac_litter(:) = 0._r8 - call TransLitterNewPatch( currentSite, currentPatch, new_patch, currentPatch%area * fraction_to_keep) + call TransLitterNewPatch( currentSite, currentPatch, new_patch, currentPatch%area * (1.-fraction_to_keep)) ! Next, we loop through the cohorts in the donor patch, copy them with ! area modified number density into the new-patch, and apply survivorship. @@ -1585,10 +1665,10 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) call currentCohort%Copy(nc) ! Number of members in the new patch - nc%n = currentCohort%n * fraction_to_keep + nc%n = currentCohort%n * (1._r8 - fraction_to_keep) ! loss of individuals from source patch due to area shrinking - currentCohort%n = currentCohort%n * (1._r8 - fraction_to_keep) + currentCohort%n = currentCohort%n * fraction_to_keep storebigcohort => new_patch%tallest storesmallcohort => new_patch%shortest @@ -1620,7 +1700,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) call sort_cohorts(currentPatch) !update area of donor patch - currentPatch%area = currentPatch%area * (1._r8 - fraction_to_keep) + currentPatch%area = currentPatch%area * fraction_to_keep end subroutine split_patch @@ -1669,6 +1749,13 @@ subroutine check_patch_area( currentSite ) if ( abs(areatot-area_site) > area_error_fail ) then write(fates_log(),*) 'Patch areas do not sum to 10000 within tolerance' write(fates_log(),*) 'Total area: ',areatot,'absolute error: ',areatot-area_site + + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + write(fates_log(),*) 'area, LU, PFT', currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label + currentPatch => currentPatch%younger + end do + call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -3205,7 +3292,7 @@ subroutine fuse_2_patches(csite, dp, rp) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - ! if neither youngerp nor olderp are associated, that means that the patch we are no longer tracking + ! if neither youngerp nor olderp are associated, that means that the patch we are fusing into ! is not part of the linked-list structure, and so no further action needs to be taken. if(associated(youngerp) .or. associated(olderp))then diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 99f1b8a611..57c361e2e8 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -270,8 +270,8 @@ subroutine get_luh_statedata(bc_in, state_vector) ! check to ensure total area == 1, and correct if not if ( abs(sum(state_vector(:)) - 1._r8) .gt. nearzero ) then - write(fates_log(),*) 'warning: sum(state_vector) = ', sum(state_vector(:)) - state_vector = state_vector(:) / sum(state_vector(:)) + !write(fates_log(),*) 'warning: sum(state_vector) = ', sum(state_vector(:)) + state_vector(:) = state_vector(:) / sum(state_vector(:)) end if else state_vector(primaryland) = 1._r8 @@ -331,7 +331,9 @@ subroutine get_init_landuse_harvest_rate(bc_in, harvest_rate) call get_luh_statedata(bc_in, state_vector) - harvest_rate = state_vector(secondaryland) + if ( state_vector(secondaryland) .gt. 0.01) then + harvest_rate = state_vector(secondaryland) + endif end subroutine get_init_landuse_harvest_rate @@ -354,7 +356,9 @@ subroutine get_init_landuse_transition_rates(bc_in, landuse_transition_matrix) call get_luh_statedata(bc_in, state_vector) do i = secondaryland+1,n_landuse_cats - landuse_transition_matrix(1,i) = state_vector(i) + if ( state_vector(i) .gt. 0.01) then + landuse_transition_matrix(1,i) = state_vector(i) + end if end do end subroutine get_init_landuse_transition_rates diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 34a73ffbc7..97d66dbe3a 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -93,6 +93,7 @@ module EDInitMod use DamageMainMod, only : undamaged_class use FatesInterfaceTypesMod , only : hlm_num_luh2_transitions use FatesConstantsMod, only : nocomp_bareground_land, nocomp_bareground + use FatesConstantsMod, only : min_nocomp_pftfrac_perlanduse use EdTypesMod, only : dump_site ! CIME GLOBALS @@ -514,8 +515,9 @@ subroutine set_site_properties( nsites, sites,bc_in ) do ft = 1,numpft ! remove tiny patches to prevent numerical errors in terminate patches - if(sites(s)%area_pft(ft, i_landusetype).lt.0.01_r8.and.sites(s)%area_pft(ft, i_landusetype).gt.nearzero)then - if(debug) write(fates_log(),*) 'removing small pft patches',s,ft,i_landusetype,sites(s)%area_pft(ft, i_landusetype) + if (sites(s)%area_pft(ft, i_landusetype) .lt. min_nocomp_pftfrac_perlanduse & + .and. sites(s)%area_pft(ft, i_landusetype) .gt. nearzero) then + if(debug) write(fates_log(),*) 'removing small numbers in site%area_pft',s,ft,i_landusetype,sites(s)%area_pft(ft, i_landusetype) sites(s)%area_pft(ft, i_landusetype)=0.0_r8 endif diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index cb778e4ba5..c33026630e 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -171,6 +171,9 @@ module FatesConstantsMod ! of magnitude of buffer error (ie instead of 1e-15) real(fates_r8), parameter, public :: rsnbl_math_prec = 1.0e-12_fates_r8 + ! in nocomp simulations, what is the minimum PFT fraction for any given land use type? + real(fates_r8), parameter, public :: min_nocomp_pftfrac_perlanduse = 0.01_fates_r8 + ! This is the precision of 8byte reals (~1e-308) real(fates_r8), parameter, public :: tinyr8 = tiny(1.0_fates_r8) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 259ed8c201..157c7261ae 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -3606,7 +3606,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! if needed, trigger the special procedure to initialize land use structure from a ! restart run that did not include land use. if (rio_landuse_config_si(io_idx_si) .eq. itrue .and. hlm_use_potentialveg .eq. ifalse) then - write(fates_log(),*), 'setting transition_landuse_from_off_to_on flag based on restart potentialveg value.' sites(s)%transition_landuse_from_off_to_on = .true. endif From cce0963e0702ad01bd986935a82fe2ea86682e0c Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Mon, 6 Nov 2023 16:24:59 -0800 Subject: [PATCH 048/300] i think maybe it works now? --- biogeochem/EDPatchDynamicsMod.F90 | 77 ++++++++++++++----------------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 88a5e9b6f6..033246aa11 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -503,7 +503,6 @@ subroutine spawn_patches( currentSite, bc_in) integer :: i_pft real(r8) :: newp_area logical :: buffer_patch_in_linked_list - real(r8) :: tmp, tmp2 integer :: n_pfts_by_landuse integer :: which_pft_allowed @@ -1314,8 +1313,6 @@ subroutine spawn_patches( currentSite, bc_in) end do nocomp_pft_loop nocomp_and_luh_if: if ( hlm_use_nocomp .eq. itrue .and. hlm_use_luh .eq. itrue ) then - ! CDK test nocomp_and_luh_if: if ( .false. ) then - ! disturbance has just happened, and now the nocomp PFT identities of the newly-disturbed patches ! need to be remapped to those associated with the new land use type. @@ -1404,21 +1401,26 @@ subroutine spawn_patches( currentSite, bc_in) if (fraction_to_keep .le. nearzero) then ! we don't want any patch area with this PFT identity at all anymore. Fuse it into the buffer patch. currentPatch%nocomp_pft_label = 0 - previousPatch => currentPatch%older + previousPatch => currentPatch%older + call fuse_2_patches(currentSite, currentPatch, buffer_patch) currentPatch => previousPatch + elseif (fraction_to_keep .lt. 1._r8) then ! we have more patch are of this PFT than we want, but we do want to keep some of it. ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. allocate(temp_patch) + call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep) ! temp_patch%nocomp_pft_label = 0 + call fuse_2_patches(currentSite, temp_patch, buffer_patch) ! nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) = & nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + currentPatch%area + currentPatch%changed_landuse_this_ts = .false. else ! we want to keep all of this patch (and possibly more) @@ -1431,36 +1433,24 @@ subroutine spawn_patches( currentSite, bc_in) end do ! at this point, lets check that the total patch area remaining to be relabelled equals what we think that it is. - tmp = 0._r8 - tmp2 = 0._r8 - currentPatch => currentSite%oldest_patch - do while(associated(currentPatch)) - tmp2 = tmp + currentPatch%area - if (currentPatch%changed_landuse_this_ts .and. currentPatch%land_use_label .eq. i_land_use_label) then - tmp = tmp + currentPatch%area - end if - currentPatch => currentPatch%younger - end do - if (abs(sum(nocomp_pft_area_vector(:)) - sum(nocomp_pft_area_vector_filled(:)) - tmp) .gt. rsnbl_math_prec) then - write(fates_log(),*) 'midway through patch reallocation and things are already not adding up.' + if (abs(sum(nocomp_pft_area_vector(:)) - sum(nocomp_pft_area_vector_filled(:)) - buffer_patch%area) .gt. rsnbl_math_prec) then + write(fates_log(),*) 'midway through patch reallocation and things are already not adding up.', i_land_use_label write(fates_log(),*) currentSite%area_pft(:,i_land_use_label) write(fates_log(),*) '-----' write(fates_log(),*) nocomp_pft_area_vector_filled write(fates_log(),*) '-----' write(fates_log(),*) nocomp_pft_area_vector write(fates_log(),*) '-----' - write(fates_log(),*) tmp2, tmp2 + buffer_patch%area write(fates_log(),*) buffer_patch%area, buffer_patch%land_use_label, buffer_patch%nocomp_pft_label - write(fates_log(),*) tmp, sum(nocomp_pft_area_vector(:)) - sum(nocomp_pft_area_vector_filled(:)) - tmp currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) write(fates_log(),*) currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label currentPatch => currentPatch%younger end do + call dump_site(currentSite) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list nocomp_pft_loop_2: do i_pft = 1, numpft ! @@ -1469,40 +1459,42 @@ subroutine spawn_patches( currentSite, bc_in) if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then ! newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) - ! - if (newp_area .lt. buffer_patch%area) then + ! only bother doing this if the new new patch area needed is greater than some tiny amount + if ( newp_area .gt. rsnbl_math_prec) then + ! + if (buffer_patch%area - newp_area .gt. rsnbl_math_prec) then - ! split buffer patch in two, keeping the smaller buffer patch to put into new patches - allocate(temp_patch) - call split_patch(currentSite, buffer_patch, temp_patch, newp_area/buffer_patch%area) + ! split buffer patch in two, keeping the smaller buffer patch to put into new patches + allocate(temp_patch) - ! give the new patch the intended nocomp PFT label - temp_patch%nocomp_pft_label = i_pft + call split_patch(currentSite, buffer_patch, temp_patch, (1._r8 - newp_area/buffer_patch%area)) - ! track that we have added this patch area - nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + temp_patch%area + ! give the new patch the intended nocomp PFT label + temp_patch%nocomp_pft_label = i_pft - ! put the new patch into the linked list - call InsertPatch(currentSite, temp_patch) + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + temp_patch%area - ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be - ! refilled the next time through the loop. - temp_patch => null() + ! put the new patch into the linked list + call InsertPatch(currentSite, temp_patch) - else - ! give the buffer patch the intended nocomp PFT label - buffer_patch%nocomp_pft_label = i_pft + ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be + ! refilled the next time through the loop. - ! track that we have added this patch area - nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area + else + ! give the buffer patch the intended nocomp PFT label + buffer_patch%nocomp_pft_label = i_pft - ! put the buffer patch directly into the linked list - call InsertPatch(currentSite, buffer_patch) + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area - buffer_patch_in_linked_list = .true. + ! put the buffer patch directly into the linked list + call InsertPatch(currentSite, buffer_patch) - end if + buffer_patch_in_linked_list = .true. + end if + end if end if end if end do nocomp_pft_loop_2 @@ -1523,6 +1515,7 @@ subroutine spawn_patches( currentSite, bc_in) else write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' write(fates_log(),*) 'buffer_patch%area', buffer_patch%area + write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)), sum(nocomp_pft_area_vector(:)) call endrun(msg=errMsg(sourcefile, __LINE__)) end if From 6e608d46cd007b7ae384a360527947ecf0644cca Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 8 Nov 2023 14:47:49 -0800 Subject: [PATCH 049/300] made the minimum land use fraction a named variable that depends on site-elvel baer ground fraction --- biogeochem/EDLoggingMortalityMod.F90 | 2 +- biogeochem/EDPatchDynamicsMod.F90 | 6 +++--- biogeochem/FatesLandUseChangeMod.F90 | 28 ++++++++++++++++++++-------- main/EDInitMod.F90 | 12 ++++++++++++ main/EDTypesMod.F90 | 1 + 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 6117dc49bf..63303b8bf7 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -349,7 +349,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, l_degrad = 0.0_r8 end if else - call get_init_landuse_harvest_rate(bc_in, harvest_rate) + call get_init_landuse_harvest_rate(bc_in, currentSite%min_allowed_landuse_fraction, harvest_rate) lmort_direct = harvest_rate lmort_collateral = 0.0_r8 lmort_infra = 0.0_r8 diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 033246aa11..056523b46e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -285,9 +285,9 @@ subroutine disturbance_rates( site_in, bc_in) if ( hlm_use_luh .eq. itrue ) then if(.not. site_in%transition_landuse_from_off_to_on) then - call get_landuse_transition_rates(bc_in, site_in%landuse_transition_matrix) + call get_landuse_transition_rates(bc_in, site_in%min_allowed_landuse_fraction, site_in%landuse_transition_matrix) else - call get_init_landuse_transition_rates(bc_in, site_in%landuse_transition_matrix) + call get_init_landuse_transition_rates(bc_in, site_in%min_allowed_landuse_fraction, site_in%landuse_transition_matrix) endif else site_in%landuse_transition_matrix(:,:) = 0._r8 @@ -380,7 +380,7 @@ subroutine disturbance_rates( site_in, bc_in) currentPatch%age_since_anthro_disturbance, harvest_rate) end if else - call get_init_landuse_harvest_rate(bc_in, harvest_rate) + call get_init_landuse_harvest_rate(bc_in, site_in%min_allowed_landuse_fraction, harvest_rate) endif currentPatch%disturbance_rates(dtype_ilog) = currentPatch%disturbance_rates(dtype_ilog) + & diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 57c361e2e8..482367e92c 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -61,7 +61,7 @@ module FatesLandUseChangeMod contains ! ============================================================================ - subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) + subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix) ! The purpose of this routine is to ingest the land use transition rate information that the host model has read in from a dataset, @@ -70,7 +70,8 @@ subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) ! !ARGUMENTS: type(bc_in_type) , intent(in) :: bc_in - real(r8), intent(inout) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! [m2/m2/day] + real(r8), intent(in) :: min_allowed_landuse_fraction + real(r8), intent(inout) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! [m2/m2/day] ! !LOCAL VARIABLES: type(luh2_fates_lutype_map) :: lumap @@ -80,6 +81,8 @@ subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) real(r8) :: urban_fraction real(r8) :: temp_vector(hlm_num_luh2_transitions) logical :: modified_flag + real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] + integer :: i_lu ! zero the transition matrix and the urban fraction landuse_transition_matrix(:,:) = 0._r8 @@ -119,6 +122,13 @@ subroutine get_landuse_transition_rates(bc_in, landuse_transition_matrix) end if end do transitions_loop + ! zero all transitions where the state vector is less than the minimum allowed + call get_luh_statedata(bc_in, state_vector) + do i_lu = 1, n_landuse_cats + if ( state_vector(i_lu) .le. min_allowed_landuse_fraction) then + landuse_transition_matrix(:,i_lu) = 0._r8 + end if + end do end if end subroutine get_landuse_transition_rates @@ -315,7 +325,7 @@ subroutine CheckLUHData(luh_vector,modified_flag) end subroutine CheckLUHData - subroutine get_init_landuse_harvest_rate(bc_in, harvest_rate) + subroutine get_init_landuse_harvest_rate(bc_in, min_allowed_landuse_fraction, harvest_rate) ! the purpose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for @@ -324,20 +334,21 @@ subroutine get_init_landuse_harvest_rate(bc_in, harvest_rate) ! !ARGUMENTS: type(bc_in_type) , intent(in) :: bc_in - real(r8), intent(out) :: harvest_rate ! [m2/ m2 / day] + real(r8), intent(in) :: min_allowed_landuse_fraction + real(r8), intent(out) :: harvest_rate ! [m2/ m2 / day] ! LOCALS real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] call get_luh_statedata(bc_in, state_vector) - if ( state_vector(secondaryland) .gt. 0.01) then + if ( state_vector(secondaryland) .gt. min_allowed_landuse_fraction) then harvest_rate = state_vector(secondaryland) endif end subroutine get_init_landuse_harvest_rate - subroutine get_init_landuse_transition_rates(bc_in, landuse_transition_matrix) + subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix) ! The purose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for @@ -345,7 +356,8 @@ subroutine get_init_landuse_transition_rates(bc_in, landuse_transition_matrix) ! !ARGUMENTS: type(bc_in_type) , intent(in) :: bc_in - real(r8), intent(inout) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! [m2/m2/day] + real(r8), intent(in) :: min_allowed_landuse_fraction + real(r8), intent(inout) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! [m2/m2/day] ! LOCALS real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] @@ -356,7 +368,7 @@ subroutine get_init_landuse_transition_rates(bc_in, landuse_transition_matrix) call get_luh_statedata(bc_in, state_vector) do i = secondaryland+1,n_landuse_cats - if ( state_vector(i) .gt. 0.01) then + if ( state_vector(i) .gt. min_allowed_landuse_fraction) then landuse_transition_matrix(1,i) = state_vector(i) end if end do diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 97d66dbe3a..c6ee791dc5 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -588,6 +588,18 @@ subroutine set_site_properties( nsites, sites,bc_in ) end do !site loop end if !restart + ! need to set the minimum amount of allowable land-use fraction on a given site. this is a function of the minimum allowable patch size, + ! and for nocomp simulations also the bare ground fraction and the minimum pft fraction for a given land-use type. + if (hlm_use_nocomp .eq. itrue ) then + if ( sites(s)%area_bareground .gt. nearzero) then + sites(s)%min_allowed_landuse_fraction = min_patch_area_forced / (AREA * min_nocomp_pftfrac_perlanduse * (1._r8 - sites(s)%area_bareground)) + else + ! if all bare ground, shouldn't matter. but make it one anyway to really ignore land use (which should all be NaNs anyway) + sites(s)%min_allowed_landuse_fraction = 1._r8 + endif + else + sites(s)%min_allowed_landuse_fraction = min_patch_area_forced / AREA + endif return end subroutine set_site_properties diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 1617ee3b41..c0c49d1619 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -429,6 +429,7 @@ module EDTypesMod real(r8) :: primary_land_patchfusion_error ! error term in total area of primary patches associated with patch fusion [m2/m2/day] real(r8) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! land use transition matrix as read in from HLM and aggregated to FATES land use types [m2/m2/year] + real(r8) :: min_allowed_landuse_fraction ! minimum amount of land-use type below which the resulting patches would be too small [m2/m2] logical :: transition_landuse_from_off_to_on ! special flag to use only when reading restarts, which triggers procedure to initialize land use end type ed_site_type From 9574a1c6ed89b199d5f09b64abcf6c17c708cbc3 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 8 Nov 2023 16:46:04 -0800 Subject: [PATCH 050/300] added new parameter fates_max_nocomp_pfts_by_landuse and using instead of just fates_maxpatches_by_landuse --- main/EDInitMod.F90 | 6 +++--- main/EDParamsMod.F90 | 12 ++++++++++++ main/EDPftvarcon.F90 | 19 +++++++++++++++++++ parameter_files/fates_params_default.cdl | 7 ++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index c6ee791dc5..48d2f84ac5 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -358,7 +358,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! ! !USES: use EDParamsMod, only : crop_lu_pft_vector - use EDParamsMod, only : maxpatches_by_landuse + use EDParamsMod, only : max_nocomp_pfts_by_landuse ! ! !ARGUMENTS @@ -535,14 +535,14 @@ subroutine set_site_properties( nsites, sites,bc_in ) if (hlm_use_nocomp .eq. itrue) then do i_landusetype = 1, n_landuse_cats ! count how many PFTs have areas greater than zero and compare to the number of patches allowed - if (COUNT(sites(s)%area_pft(:, i_landusetype) .gt. 0._r8) > maxpatches_by_landuse(i_landusetype)) then + if (COUNT(sites(s)%area_pft(:, i_landusetype) .gt. 0._r8) > max_nocomp_pfts_by_landuse(i_landusetype)) then ! write current vector to log file if(debug) write(fates_log(),*) 'too many PFTs for LU type ', i_landusetype, sites(s)%area_pft(:, i_landusetype) ! start from largest area, put that PFT's area into a temp vector, and then work down to successively smaller-area PFTs, ! at the end replace the original vector with the temp vector temp_vec(:) = 0._r8 - do i_pftcount = 1, maxpatches_by_landuse(i_landusetype) + do i_pftcount = 1, max_nocomp_pfts_by_landuse(i_landusetype) temp_vec(MAXLOC(sites(s)%area_pft(:, i_landusetype))) = & sites(s)%area_pft(MAXLOC(sites(s)%area_pft(:, i_landusetype)), i_landusetype) sites(s)%area_pft(MAXLOC(sites(s)%area_pft(:, i_landusetype)), i_landusetype) = 0._r8 diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 415059681e..7732327a1d 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -200,6 +200,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_history_damage_bin_edges = "fates_history_damage_bin_edges" character(len=param_string_length),parameter,public :: ED_name_crop_lu_pft_vector = "fates_landuse_crop_lu_pft_vector" character(len=param_string_length),parameter,public :: ED_name_maxpatches_by_landuse = "fates_maxpatches_by_landuse" + character(len=param_string_length),parameter,public :: ED_name_max_nocomp_pfts_by_landuse = "fates_max_nocomp_pfts_by_landuse" ! Hydraulics Control Parameters (ONLY RELEVANT WHEN USE_FATES_HYDR = TRUE) ! ---------------------------------------------------------------------------------------------- @@ -253,6 +254,7 @@ module EDParamsMod ! thus they are not protected here. integer, public :: maxpatches_by_landuse(n_landuse_cats) + integer, public :: max_nocomp_pfts_by_landuse(n_landuse_cats) integer, public :: maxpatch_total ! which crops can be grown on a given crop land use type @@ -610,6 +612,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_maxpatches_by_landuse, dimension_shape=dimension_shape_1d, & dimension_names=dim_names_landuse) + call fates_params%RegisterParameter(name=ED_name_max_nocomp_pfts_by_landuse, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names_landuse) + end subroutine FatesRegisterParams @@ -627,6 +632,7 @@ subroutine FatesReceiveParams(fates_params) real(r8), allocatable :: hydr_htftype_real(:) real(r8), allocatable :: tmp_vector_by_landuse1(:) ! local real vector for changing type on read real(r8), allocatable :: tmp_vector_by_landuse2(:) ! local real vector for changing type on read + real(r8), allocatable :: tmp_vector_by_landuse3(:) ! local real vector for changing type on read call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) @@ -842,6 +848,12 @@ subroutine FatesReceiveParams(fates_params) maxpatch_total = sum(maxpatches_by_landuse(:)) deallocate(tmp_vector_by_landuse2) + call fates_params%RetrieveParameterAllocate(name=ED_name_max_nocomp_pfts_by_landuse, & + data=tmp_vector_by_landuse3) + + max_nocomp_pfts_by_landuse(:) = nint(tmp_vector_by_landuse3(:)) + deallocate(tmp_vector_by_landuse3) + call fates_params%RetrieveParameterAllocate(name=ED_name_hydr_htftype_node, & data=hydr_htftype_real) allocate(hydr_htftype_node(size(hydr_htftype_real))) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 26d1e03d6b..72e0975a21 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1759,6 +1759,9 @@ subroutine FatesCheckParams(is_master) use EDParamsMod , only : radiation_model use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name use FatesInterfaceTypesMod, only : hlm_use_inventory_init + use FatesInterfaceTypesMod, only : hlm_use_nocomp + use EDParamsMod , only : max_nocomp_pfts_by_landuse, maxpatches_by_landuse + use FatesConstantsMod , only : n_landuse_cats ! Argument logical, intent(in) :: is_master ! Only log if this is the master proc @@ -1772,6 +1775,7 @@ subroutine FatesCheckParams(is_master) integer :: norgans ! size of the plant organ dimension integer :: hlm_pft ! used in fixed biogeog mode integer :: fates_pft ! used in fixed biogeog mode + integer :: i_lu ! land use index real(r8) :: sumarea ! area of PFTs in nocomp mode. @@ -2068,6 +2072,21 @@ subroutine FatesCheckParams(is_master) end do !ipft + ! if nocomp is enabled, check to make sure the max number of nocomp PFTs per land use is + ! less than or equal to the max number of patches per land use. + if ( hlm_use_nocomp .eq. itrue ) then + do i_lu = 1, n_landuse_cats + if (max_nocomp_pfts_by_landuse(i_lu) .gt. maxpatches_by_landuse(i_lu)) then + write(fates_log(),*) 'The max number of nocomp PFTs must all be less than or equal to the number of patches, for a given land use type' + write(fates_log(),*) 'land use index:',i_lu + write(fates_log(),*) 'max_nocomp_pfts_by_landuse(i_lu):', max_nocomp_pfts_by_landuse(i_lu) + write(fates_log(),*) 'maxpatches_by_landuse(i_lu):', maxpatches_by_landuse(i_lu) + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end do + endif + !! ! Checks for HYDRO !! if( hlm_use_planthydro == itrue ) then !! diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 48b46660c5..68d22bd0c6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -687,6 +687,9 @@ variables: double fates_landuse_crop_lu_pft_vector(fates_landuseclass) ; fates_landuse_crop_lu_pft_vector:units = "NA" ; fates_landuse_crop_lu_pft_vector:long_name = "What FATES PFT index to use on a given crop land-use type? (dummy value of -999 for non-crop types)" ; + double fates_max_nocomp_pfts_by_landuse(fates_landuseclass) ; + fates_max_nocomp_pfts_by_landuse:units = "count" ; + fates_max_nocomp_pfts_by_landuse:long_name = "maximum number of nocomp PFTs on each land use type (only used in nocomp mode)" ; double fates_maxpatches_by_landuse(fates_landuseclass) ; fates_maxpatches_by_landuse:units = "count" ; fates_maxpatches_by_landuse:long_name = "maximum number of patches per site on each land use type" ; @@ -1623,7 +1626,9 @@ data: fates_landuse_crop_lu_pft_vector = -999, -999, -999, -999, 11 ; - fates_maxpatches_by_landuse = 10, 4, 1, 1, 1 ; + fates_max_nocomp_pfts_by_landuse = 4, 4, 2, 2, 1 ; + + fates_maxpatches_by_landuse = 10, 6, 2, 2, 1 ; fates_canopy_closure_thresh = 0.8 ; From 5a6c0bd43e1c236cb75d3b0509a37ebca584e95b Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 8 Nov 2023 21:47:37 -0800 Subject: [PATCH 051/300] bugfix --- main/EDInitMod.F90 | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 48d2f84ac5..3efd6fe68e 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -585,21 +585,23 @@ subroutine set_site_properties( nsites, sites,bc_in ) end if !area end if !SBG end do !ft + + ! need to set the minimum amount of allowable land-use fraction on a given site. this is a function of the minimum allowable patch size, + ! and for nocomp simulations also the bare ground fraction and the minimum pft fraction for a given land-use type. + if (hlm_use_nocomp .eq. itrue ) then + if ( (1._r8 - sites(s)%area_bareground) .gt. nearzero) then + sites(s)%min_allowed_landuse_fraction = min_patch_area_forced / (AREA * min_nocomp_pftfrac_perlanduse * (1._r8 - sites(s)%area_bareground)) + else + ! if all bare ground, shouldn't matter. but make it one anyway to really ignore land use (which should all be NaNs anyway) + sites(s)%min_allowed_landuse_fraction = 1._r8 + endif + else + sites(s)%min_allowed_landuse_fraction = min_patch_area_forced / AREA + endif + end do !site loop end if !restart - ! need to set the minimum amount of allowable land-use fraction on a given site. this is a function of the minimum allowable patch size, - ! and for nocomp simulations also the bare ground fraction and the minimum pft fraction for a given land-use type. - if (hlm_use_nocomp .eq. itrue ) then - if ( sites(s)%area_bareground .gt. nearzero) then - sites(s)%min_allowed_landuse_fraction = min_patch_area_forced / (AREA * min_nocomp_pftfrac_perlanduse * (1._r8 - sites(s)%area_bareground)) - else - ! if all bare ground, shouldn't matter. but make it one anyway to really ignore land use (which should all be NaNs anyway) - sites(s)%min_allowed_landuse_fraction = 1._r8 - endif - else - sites(s)%min_allowed_landuse_fraction = min_patch_area_forced / AREA - endif return end subroutine set_site_properties From d7d989e182dca4dfcf5812438c19a7e672a21300 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 9 Nov 2023 09:44:20 -0800 Subject: [PATCH 052/300] adding min_allowed_landuse_fraction to restart files, and other error diagnostics --- biogeochem/EDPatchDynamicsMod.F90 | 12 ++++++++++-- biogeochem/FatesLandUseChangeMod.F90 | 16 +++++++++++----- main/EDMainMod.F90 | 2 +- main/FatesRestartInterfaceMod.F90 | 9 +++++++++ 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 056523b46e..c45501dcff 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -86,6 +86,7 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : n_landuse_cats use FatesLandUseChangeMod, only : get_landuse_transition_rates use FatesLandUseChangeMod, only : get_init_landuse_transition_rates + use FatesLandUseChangeMod, only : get_luh_statedata use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : hlm_harvest_carbon @@ -3317,7 +3318,7 @@ end subroutine fuse_2_patches ! ============================================================================ - subroutine terminate_patches(currentSite) + subroutine terminate_patches(currentSite, bc_in) ! ! !DESCRIPTION: ! Terminate Patches if they are too small @@ -3325,6 +3326,7 @@ subroutine terminate_patches(currentSite) ! ! !ARGUMENTS: type(ed_site_type), target, intent(inout) :: currentSite + type(bc_in_type), intent(in) :: bc_in ! ! !LOCAL VARIABLES: type(fates_patch_type), pointer :: currentPatch @@ -3338,7 +3340,8 @@ subroutine terminate_patches(currentSite) logical :: current_patch_is_youngest_lutype integer :: i_landuse, i_pft - real(r8) areatot ! variable for checking whether the total patch area is wrong. + real(r8) areatot ! variable for checking whether the total patch area is wrong. + real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] !--------------------------------------------------------------------- ! Initialize the count cycles @@ -3491,6 +3494,11 @@ subroutine terminate_patches(currentSite) write(fates_log(),*) patchpointer%area, patchpointer%nocomp_pft_label, patchpointer%land_use_label patchpointer => patchpointer%older end do + call get_current_landuse_statevector(currentSite, state_vector) + write(fates_log(),*) 'current landuse state vector: ', state_vector + call get_luh_statedata(bc_in, state_vector) + write(fates_log(),*) 'driver data landuse state vector: ', state_vector + write(fates_log(),*) 'min_allowed_landuse_fraction: ', currentSite%min_allowed_landuse_fraction call endrun(msg=errMsg(sourcefile, __LINE__)) ! Note to user. If you DO decide to remove the end-run above this line diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 482367e92c..04df7ebf8d 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -278,11 +278,17 @@ subroutine get_luh_statedata(bc_in, state_vector) end if end do - ! check to ensure total area == 1, and correct if not - if ( abs(sum(state_vector(:)) - 1._r8) .gt. nearzero ) then - !write(fates_log(),*) 'warning: sum(state_vector) = ', sum(state_vector(:)) - state_vector(:) = state_vector(:) / sum(state_vector(:)) - end if + ! if all zeros, make all primary lands + if ( sum(state_vector(:)) .gt. nearzero ) then + + ! check to ensure total area == 1, and correct if not + if ( abs(sum(state_vector(:)) - 1._r8) .gt. nearzero ) then + !write(fates_log(),*) 'warning: sum(state_vector) = ', sum(state_vector(:)) + state_vector(:) = state_vector(:) / sum(state_vector(:)) + end if + else + state_vector(primaryland) = 1._r8 + endif else state_vector(primaryland) = 1._r8 end if diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index edb9241dd1..f37f764da9 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -314,7 +314,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) call TotalBalanceCheck(currentSite,4) ! kill patches that are too small - call terminate_patches(currentSite) + call terminate_patches(currentSite, bc_in) end if call TotalBalanceCheck(currentSite,5) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 157c7261ae..08bf3e07f5 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -99,6 +99,7 @@ module FatesRestartInterfaceMod integer :: ir_phenmodeldate_si integer :: ir_acc_ni_si integer :: ir_gdd_si + integer :: ir_min_allowed_landuse_fraction_si integer :: ir_snow_depth_si integer :: ir_trunk_product_si integer :: ir_landuse_config_si @@ -702,6 +703,10 @@ subroutine define_restart_vars(this, initialize_variables) long_name='growing degree days at each site', units='degC days', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_gdd_si ) + call this%set_restart_var(vname='fates_min_allowed_landuse_fraction_site', vtype=site_r8, & + long_name='minimum allowed land use fraction at each site', units='degC days', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_min_allowed_landuse_fraction_si ) + call this%set_restart_var(vname='fates_snow_depth_site', vtype=site_r8, & long_name='average snow depth', units='m', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_snow_depth_si ) @@ -2011,6 +2016,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & + rio_min_allowed_landuse_fraction_si => this%rvars(ir_min_allowed_landuse_fraction_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & rio_landuse_config_s => this%rvars(ir_landuse_config_si)%int1d, & @@ -2602,6 +2608,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_cndaysleafon_si(io_idx_si) = sites(s)%cndaysleafon rio_cndaysleafoff_si(io_idx_si) = sites(s)%cndaysleafoff rio_gdd_si(io_idx_si) = sites(s)%grow_deg_days + rio_min_allowed_landuse_fraction_si(io_idx_si) = sites(s)%min_allowed_landuse_fraction rio_phenmodeldate_si(io_idx_si) = sites(s)%phen_model_date @@ -2976,6 +2983,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & + rio_min_allowed_landuse_fraction_si => this%rvars(ir_min_allowed_landuse_fraction_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & rio_landuse_config_si => this%rvars(ir_landuse_config_si)%int1d, & @@ -3595,6 +3603,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%cndaysleafon = rio_cndaysleafon_si(io_idx_si) sites(s)%cndaysleafoff = rio_cndaysleafoff_si(io_idx_si) sites(s)%grow_deg_days = rio_gdd_si(io_idx_si) + sites(s)%min_allowed_landuse_fraction = rio_min_allowed_landuse_fraction_si(io_idx_si) sites(s)%phen_model_date= rio_phenmodeldate_si(io_idx_si) From 7d79def33b9dea056d62fd99afa8a6e00ff2f6ba Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 9 Nov 2023 12:03:31 -0800 Subject: [PATCH 053/300] one bugfix and one temporary change to turn off all disturbance to secodnary lands --- biogeochem/EDPatchDynamicsMod.F90 | 3 ++- biogeochem/FatesLandUseChangeMod.F90 | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c45501dcff..dcccbbe94e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -365,6 +365,7 @@ subroutine disturbance_rates( site_in, bc_in) ! for non-closed-canopy areas subject to logging, add an additional increment of area disturbed ! equivalent to the fraction logged to account for transfer of interstitial ground area to new secondary lands + ! if ( (logging_time .or. site_in%transition_landuse_from_off_to_on) .and. & if ( logging_time .and. & (currentPatch%area - currentPatch%total_canopy_area) .gt. fates_tiny ) then ! The canopy is NOT closed. @@ -1394,7 +1395,7 @@ subroutine spawn_patches( currentSite, bc_in) fraction_to_keep = (currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * sum(nocomp_pft_area_vector(:)) & - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label)) / currentPatch%area - if (fraction_to_keep .lt. (-1._r8 * nearzero)) then + if (fraction_to_keep .lt. (-1._r8 * rsnbl_math_prec)) then write(fates_log(),*) 'negative fraction_to_keep', fraction_to_keep call endrun(msg=errMsg(sourcefile, __LINE__)) endif diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 04df7ebf8d..cc91ca11da 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -125,7 +125,7 @@ subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, lan ! zero all transitions where the state vector is less than the minimum allowed call get_luh_statedata(bc_in, state_vector) do i_lu = 1, n_landuse_cats - if ( state_vector(i_lu) .le. min_allowed_landuse_fraction) then + if ( state_vector(i_lu) .le. min_allowed_landuse_fraction .or. i_lu .eq. secondaryland) then !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CDK DEBUG landuse_transition_matrix(:,i_lu) = 0._r8 end if end do @@ -351,7 +351,9 @@ subroutine get_init_landuse_harvest_rate(bc_in, min_allowed_landuse_fraction, ha if ( state_vector(secondaryland) .gt. min_allowed_landuse_fraction) then harvest_rate = state_vector(secondaryland) endif - + +!!!!!!!!!!!!!!!!!!!! CDKCDK + harvest_rate = 0._r8 end subroutine get_init_landuse_harvest_rate subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix) From 8afbe4856be9cde34150d463fb7efee2568cc98b Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 9 Nov 2023 12:16:53 -0800 Subject: [PATCH 054/300] better bugfix --- biogeochem/EDPatchDynamicsMod.F90 | 5 ----- 1 file changed, 5 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index dcccbbe94e..24c7fdb9af 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1395,11 +1395,6 @@ subroutine spawn_patches( currentSite, bc_in) fraction_to_keep = (currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * sum(nocomp_pft_area_vector(:)) & - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label)) / currentPatch%area - if (fraction_to_keep .lt. (-1._r8 * rsnbl_math_prec)) then - write(fates_log(),*) 'negative fraction_to_keep', fraction_to_keep - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - if (fraction_to_keep .le. nearzero) then ! we don't want any patch area with this PFT identity at all anymore. Fuse it into the buffer patch. currentPatch%nocomp_pft_label = 0 From f8fe5ff062f54dad37c2d690176c5ab0214ce408 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 9 Nov 2023 14:35:48 -0800 Subject: [PATCH 055/300] added restart for site%bareground --- main/FatesRestartInterfaceMod.F90 | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 08bf3e07f5..28eaa652fe 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -100,6 +100,7 @@ module FatesRestartInterfaceMod integer :: ir_acc_ni_si integer :: ir_gdd_si integer :: ir_min_allowed_landuse_fraction_si + integer :: ir_area_bareground_si integer :: ir_snow_depth_si integer :: ir_trunk_product_si integer :: ir_landuse_config_si @@ -707,6 +708,10 @@ subroutine define_restart_vars(this, initialize_variables) long_name='minimum allowed land use fraction at each site', units='degC days', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_min_allowed_landuse_fraction_si ) + call this%set_restart_var(vname='fates_area_bareground_site', vtype=site_r8, & + long_name='minimum allowed land use fraction at each site', units='degC days', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_area_bareground_si ) + call this%set_restart_var(vname='fates_snow_depth_site', vtype=site_r8, & long_name='average snow depth', units='m', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_snow_depth_si ) @@ -2016,7 +2021,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & - rio_min_allowed_landuse_fraction_si => this%rvars(ir_min_allowed_landuse_fraction_si)%r81d, & + rio_min_allowed_landuse_fraction_si => this%rvars(ir_min_allowed_landuse_fraction_si)%r81d, & + rio_area_bareground_si => this%rvars(ir_area_bareground_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & rio_landuse_config_s => this%rvars(ir_landuse_config_si)%int1d, & @@ -2178,7 +2184,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) end do end do - !! need to restart area_bareground + rio_min_allowed_landuse_fraction_si(io_idx_si) = sites(s)%min_allowed_landuse_fraction + rio_area_bareground_si(io_idx_si) = sites(s)%area_bareground do i_scls = 1, nlevsclass do i_pft = 1, numpft @@ -2608,7 +2615,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_cndaysleafon_si(io_idx_si) = sites(s)%cndaysleafon rio_cndaysleafoff_si(io_idx_si) = sites(s)%cndaysleafoff rio_gdd_si(io_idx_si) = sites(s)%grow_deg_days - rio_min_allowed_landuse_fraction_si(io_idx_si) = sites(s)%min_allowed_landuse_fraction rio_phenmodeldate_si(io_idx_si) = sites(s)%phen_model_date @@ -2984,6 +2990,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_min_allowed_landuse_fraction_si => this%rvars(ir_min_allowed_landuse_fraction_si)%r81d, & + rio_area_bareground_si => this%rvars(ir_area_bareground_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & rio_landuse_config_si => this%rvars(ir_landuse_config_si)%int1d, & @@ -3132,7 +3139,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) end do enddo - !! need to restart area_bareground + sites(s)%min_allowed_landuse_fraction = rio_min_allowed_landuse_fraction_si(io_idx_si) + sites(s)%area_bareground = rio_area_bareground_si(io_idx_si) do i_scls = 1,nlevsclass do i_pft = 1, numpft @@ -3603,7 +3611,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%cndaysleafon = rio_cndaysleafon_si(io_idx_si) sites(s)%cndaysleafoff = rio_cndaysleafoff_si(io_idx_si) sites(s)%grow_deg_days = rio_gdd_si(io_idx_si) - sites(s)%min_allowed_landuse_fraction = rio_min_allowed_landuse_fraction_si(io_idx_si) sites(s)%phen_model_date= rio_phenmodeldate_si(io_idx_si) From c07fc03ab7206573f45155b272ed05d6fcb613ce Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 9 Nov 2023 16:20:06 -0800 Subject: [PATCH 056/300] fix bug related to bareground area in the application of the transition matrix --- biogeochem/EDPatchDynamicsMod.F90 | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 24c7fdb9af..cd5114a81a 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -321,10 +321,15 @@ subroutine disturbance_rates( site_in, bc_in) dist_rate_ldist_notharvested = 0.0_r8 + ! transitin matrix has units of area transitioned per unit area of the whole gridcell per time; + ! need to change to area transitioned per unit area of that land-use type per time; + ! because the land use state vector sums to one minus area bareground, need to also divide by that + ! (or rather, multiply since it is in the denominator of the denominator) ! Avoid this calculation to avoid NaN due to division by zero result if luh is not used or applying to bare ground if (hlm_use_luh .eq. itrue .and. currentPatch%land_use_label .gt. nocomp_bareground_land) then currentPatch%landuse_transition_rates(1:n_landuse_cats) = min(1._r8, & - site_in%landuse_transition_matrix(currentPatch%land_use_label,1:n_landuse_cats) / & + site_in%landuse_transition_matrix(currentPatch%land_use_label,1:n_landuse_cats) & + * (1._r8 - site_in%area_bareground) / & current_fates_landuse_state_vector(currentPatch%land_use_label)) else currentPatch%landuse_transition_rates = 0.0_r8 From eb0671b7caf70f5967b4fd6ca6499c85710488d5 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 9 Nov 2023 16:33:42 -0800 Subject: [PATCH 057/300] adding some documentation --- biogeochem/EDPatchDynamicsMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index cd5114a81a..a9c6891f2c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -326,6 +326,8 @@ subroutine disturbance_rates( site_in, bc_in) ! because the land use state vector sums to one minus area bareground, need to also divide by that ! (or rather, multiply since it is in the denominator of the denominator) ! Avoid this calculation to avoid NaN due to division by zero result if luh is not used or applying to bare ground + ! note that an alternative here might be to use what LUH thinks the state vector should be instead of what the FATES state vector is, + ! in order to not amplify small deviations between the two... if (hlm_use_luh .eq. itrue .and. currentPatch%land_use_label .gt. nocomp_bareground_land) then currentPatch%landuse_transition_rates(1:n_landuse_cats) = min(1._r8, & site_in%landuse_transition_matrix(currentPatch%land_use_label,1:n_landuse_cats) & From 32ee1bf551d08a5b91729217933dff03aaa97a07 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 9 Nov 2023 20:46:39 -0800 Subject: [PATCH 058/300] bugfixes: init logging rates, and handling when pft compositn doesnt change. --- biogeochem/EDLoggingMortalityMod.F90 | 19 +++- biogeochem/EDPatchDynamicsMod.F90 | 143 +++++++++++++++------------ biogeochem/FatesLandUseChangeMod.F90 | 4 +- 3 files changed, 95 insertions(+), 71 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 63303b8bf7..e6494afb1c 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -350,10 +350,21 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, end if else call get_init_landuse_harvest_rate(bc_in, currentSite%min_allowed_landuse_fraction, harvest_rate) - lmort_direct = harvest_rate - lmort_collateral = 0.0_r8 - lmort_infra = 0.0_r8 - l_degrad = 0.0_r8 + if(prt_params%woody(pft_i) == itrue)then + lmort_direct = harvest_rate + lmort_collateral = 0.0_r8 + lmort_infra = 0.0_r8 + l_degrad = 0.0_r8 + else + lmort_direct = 0.0_r8 + lmort_collateral = 0.0_r8 + lmort_infra = 0.0_r8 + if (canopy_layer .eq. 1) then + l_degrad = harvest_rate + else + l_degrad = 0.0_r8 + endif + endif endif end subroutine LoggingMortality_frac diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index a9c6891f2c..833b3497e9 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -372,8 +372,7 @@ subroutine disturbance_rates( site_in, bc_in) ! for non-closed-canopy areas subject to logging, add an additional increment of area disturbed ! equivalent to the fraction logged to account for transfer of interstitial ground area to new secondary lands - ! if ( (logging_time .or. site_in%transition_landuse_from_off_to_on) .and. & - if ( logging_time .and. & + if ( (logging_time .or. site_in%transition_landuse_from_off_to_on) .and. & (currentPatch%area - currentPatch%total_canopy_area) .gt. fates_tiny ) then ! The canopy is NOT closed. @@ -514,7 +513,7 @@ subroutine spawn_patches( currentSite, bc_in) logical :: buffer_patch_in_linked_list integer :: n_pfts_by_landuse integer :: which_pft_allowed - + logical :: buffer_patch_used !--------------------------------------------------------------------- storesmallcohort => null() ! storage of the smallest cohort for insertion routine @@ -1394,6 +1393,7 @@ subroutine spawn_patches( currentSite, bc_in) call buffer_patch%sdlng_mdd(pft)%p%CopyFromDonor(copyPatch%sdlng_mdd(pft)%p) enddo end if + buffer_patch_used = .false. currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) @@ -1410,7 +1410,9 @@ subroutine spawn_patches( currentSite, bc_in) call fuse_2_patches(currentSite, currentPatch, buffer_patch) currentPatch => previousPatch - elseif (fraction_to_keep .lt. 1._r8) then + buffer_patch_used = .true. + + elseif ( (1._r8 - fraction_to_keep) .gt. rsnbl_math_prec) then ! we have more patch are of this PFT than we want, but we do want to keep some of it. ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. @@ -1426,6 +1428,8 @@ subroutine spawn_patches( currentSite, bc_in) nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + currentPatch%area currentPatch%changed_landuse_this_ts = .false. + + buffer_patch_used = .true. else ! we want to keep all of this patch (and possibly more) nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) = & @@ -1436,91 +1440,102 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch => currentPatch%younger end do - ! at this point, lets check that the total patch area remaining to be relabelled equals what we think that it is. - if (abs(sum(nocomp_pft_area_vector(:)) - sum(nocomp_pft_area_vector_filled(:)) - buffer_patch%area) .gt. rsnbl_math_prec) then - write(fates_log(),*) 'midway through patch reallocation and things are already not adding up.', i_land_use_label - write(fates_log(),*) currentSite%area_pft(:,i_land_use_label) - write(fates_log(),*) '-----' - write(fates_log(),*) nocomp_pft_area_vector_filled - write(fates_log(),*) '-----' - write(fates_log(),*) nocomp_pft_area_vector - write(fates_log(),*) '-----' - write(fates_log(),*) buffer_patch%area, buffer_patch%land_use_label, buffer_patch%nocomp_pft_label - currentPatch => currentSite%oldest_patch - do while(associated(currentPatch)) - write(fates_log(),*) currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label - currentPatch => currentPatch%younger - end do - call dump_site(currentSite) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + if ( buffer_patch_used ) then + ! at this point, lets check that the total patch area remaining to be relabelled equals what we think that it is. + if (abs(sum(nocomp_pft_area_vector(:)) - sum(nocomp_pft_area_vector_filled(:)) - buffer_patch%area) .gt. rsnbl_math_prec) then + write(fates_log(),*) 'midway through patch reallocation and things are already not adding up.', i_land_use_label + write(fates_log(),*) currentSite%area_pft(:,i_land_use_label) + write(fates_log(),*) '-----' + write(fates_log(),*) nocomp_pft_area_vector_filled + write(fates_log(),*) '-----' + write(fates_log(),*) nocomp_pft_area_vector + write(fates_log(),*) '-----' + write(fates_log(),*) buffer_patch%area, buffer_patch%land_use_label, buffer_patch%nocomp_pft_label + write(fates_log(),*) sum(nocomp_pft_area_vector(:)), sum(nocomp_pft_area_vector_filled(:)), buffer_patch%area + currentPatch => currentSite%oldest_patch + do while(associated(currentPatch)) + write(fates_log(),*) currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label + currentPatch => currentPatch%younger + end do + call dump_site(currentSite) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list - nocomp_pft_loop_2: do i_pft = 1, numpft - ! - if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero) then + ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list + nocomp_pft_loop_2: do i_pft = 1, numpft ! - if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then + if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero) then ! - newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) - ! only bother doing this if the new new patch area needed is greater than some tiny amount - if ( newp_area .gt. rsnbl_math_prec) then + if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then ! - if (buffer_patch%area - newp_area .gt. rsnbl_math_prec) then + newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) + ! only bother doing this if the new new patch area needed is greater than some tiny amount + if ( newp_area .gt. rsnbl_math_prec) then + ! + if (buffer_patch%area - newp_area .gt. rsnbl_math_prec) then - ! split buffer patch in two, keeping the smaller buffer patch to put into new patches - allocate(temp_patch) + ! split buffer patch in two, keeping the smaller buffer patch to put into new patches + allocate(temp_patch) - call split_patch(currentSite, buffer_patch, temp_patch, (1._r8 - newp_area/buffer_patch%area)) + call split_patch(currentSite, buffer_patch, temp_patch, (1._r8 - newp_area/buffer_patch%area)) - ! give the new patch the intended nocomp PFT label - temp_patch%nocomp_pft_label = i_pft + ! give the new patch the intended nocomp PFT label + temp_patch%nocomp_pft_label = i_pft - ! track that we have added this patch area - nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + temp_patch%area + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + temp_patch%area - ! put the new patch into the linked list - call InsertPatch(currentSite, temp_patch) + ! put the new patch into the linked list + call InsertPatch(currentSite, temp_patch) - ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be - ! refilled the next time through the loop. + ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be + ! refilled the next time through the loop. - else - ! give the buffer patch the intended nocomp PFT label - buffer_patch%nocomp_pft_label = i_pft + else + ! give the buffer patch the intended nocomp PFT label + buffer_patch%nocomp_pft_label = i_pft - ! track that we have added this patch area - nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area - ! put the buffer patch directly into the linked list - call InsertPatch(currentSite, buffer_patch) + ! put the buffer patch directly into the linked list + call InsertPatch(currentSite, buffer_patch) - buffer_patch_in_linked_list = .true. + buffer_patch_in_linked_list = .true. + end if end if end if end if + end do nocomp_pft_loop_2 + + ! now we want to make sure that either the buffer_patch either has zero area (presumably it was never used), in which case it should be deallocated, + ! or else it does have area but it has been put into the site linked list, and so buffer patch should be nulled before next pass through outer loop. + ! if either of those, that means everything worked properly, if not, then something has gone wrong. + if (buffer_patch_in_linked_list) then + buffer_patch => null() + else if (buffer_patch%area .lt. rsnbl_math_prec) then + ! here we need to deallocate the buffer patch so that we don't get a memory leak/ + call buffer_patch%FreeMemory(regeneration_model, numpft) + deallocate(buffer_patch, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + else + write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' + write(fates_log(),*) 'buffer_patch%area', buffer_patch%area + write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)), sum(nocomp_pft_area_vector(:)) + call endrun(msg=errMsg(sourcefile, __LINE__)) end if - end do nocomp_pft_loop_2 - - ! now we want to make sure that either the buffer_patch either has zero area (presumably it was never used), in which case it should be deallocated, - ! or else it does have area but it has been put into the site linked list, and so buffer patch should be nulled before next pass through outer loop. - ! if either of those, that means everything worked properly, if not, then something has gone wrong. - if (buffer_patch_in_linked_list) then - buffer_patch => null() - else if (buffer_patch%area .lt. rsnbl_math_prec) then - ! here we need to deallocate the buffer patch so that we don't get a memory leak/ + else + ! buffer patch was never even used. deallocate. call buffer_patch%FreeMemory(regeneration_model, numpft) deallocate(buffer_patch, stat=istat, errmsg=smsg) if (istat/=0) then write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - else - write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' - write(fates_log(),*) 'buffer_patch%area', buffer_patch%area - write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)), sum(nocomp_pft_area_vector(:)) - call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! check that the area we have added is the same as the area we have taken away. if not, crash. diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index cc91ca11da..2ce8a28968 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -125,7 +125,7 @@ subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, lan ! zero all transitions where the state vector is less than the minimum allowed call get_luh_statedata(bc_in, state_vector) do i_lu = 1, n_landuse_cats - if ( state_vector(i_lu) .le. min_allowed_landuse_fraction .or. i_lu .eq. secondaryland) then !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CDK DEBUG + if ( state_vector(i_lu) .le. min_allowed_landuse_fraction ) then landuse_transition_matrix(:,i_lu) = 0._r8 end if end do @@ -352,8 +352,6 @@ subroutine get_init_landuse_harvest_rate(bc_in, min_allowed_landuse_fraction, ha harvest_rate = state_vector(secondaryland) endif -!!!!!!!!!!!!!!!!!!!! CDKCDK - harvest_rate = 0._r8 end subroutine get_init_landuse_harvest_rate subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix) From 8065433c48d34510555937e449591c314ffd51ae Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 10 Nov 2023 10:09:03 -0500 Subject: [PATCH 059/300] Partway through splitting out site level history diagnostics --- main/FatesHistoryInterfaceMod.F90 | 992 ++++++++++++++++++------------ main/FatesInterfaceMod.F90 | 21 + main/FatesInterfaceTypesMod.F90 | 13 + 3 files changed, 634 insertions(+), 392 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 9ddca1bf27..be94ab7a3d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -59,7 +59,8 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : hlm_use_nocomp use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog use FatesRadiationMemMod , only : ivis,inir - use FatesInterfaceTypesMod , only : hio_include_hifr_multi + use FatesInterfaceTypesMod , only : hlm_hist_level_hifrq,hlm_hist_level_dynam + use FatesAllometryMod , only : CrownDepth use FatesAllometryMod , only : bstore_allom @@ -101,6 +102,22 @@ module FatesHistoryInterfaceMod use PRTAllometricCNPMod , only : stoich_max,stoich_growth_min use FatesSizeAgeTypeIndicesMod, only : get_layersizetype_class_index use FatesSizeAgeTypeIndicesMod, only : get_age_class_index + + use FatesLitterMod , only : nfsc + use FatesLitterMod , only : ncwd + use FatesConstantsMod , only : ican_upper + use FatesConstantsMod , only : ican_ustory + use FatesSizeAgeTypeIndicesMod, only : get_sizeage_class_index + use FatesSizeAgeTypeIndicesMod, only : get_sizeagepft_class_index + use FatesSizeAgeTypeIndicesMod, only : get_agepft_class_index + use FatesSizeAgeTypeIndicesMod, only : get_agefuel_class_index + use FatesSizeAgeTypeIndicesMod, only : get_height_index + use FatesSizeAgeTypeIndicesMod, only : sizetype_class_index + use FatesSizeAgeTypeIndicesMod, only : get_cdamagesize_class_index + use FatesSizeAgeTypeIndicesMod, only : get_cdamagesizepft_class_index + use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index + use FatesInterfaceTypesMod , only : nlevdamage + implicit none private ! By default everything is private @@ -177,6 +194,11 @@ module FatesHistoryInterfaceMod ! index, etc via a call to the set_history_var method in the subroutine define_history_vars. ! + ! --STEPS-- TO CONVERT TO HISTORY LEVELS: + ! SPLIT INTO HIFRQ AND DYNAMICS + ! GO UP IN ORDER + + ! Indices to 1D Patch variables integer :: ih_storec_si @@ -368,7 +390,7 @@ module FatesHistoryInterfaceMod integer :: ih_cbal_err_fates_si - integer :: ih_err_fates_si + integer :: ih_err_fates_elem integer :: ih_npatches_si integer :: ih_npatches_sec_si @@ -2111,23 +2133,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! --------------------------------------------------------------------------------- - use FatesLitterMod , only : nfsc - use FatesLitterMod , only : ncwd - use FatesConstantsMod , only : ican_upper - use FatesConstantsMod , only : ican_ustory - use FatesSizeAgeTypeIndicesMod, only : get_sizeage_class_index - use FatesSizeAgeTypeIndicesMod, only : get_sizeagepft_class_index - use FatesSizeAgeTypeIndicesMod, only : get_agepft_class_index - use FatesSizeAgeTypeIndicesMod, only : get_agefuel_class_index - - use FatesSizeAgeTypeIndicesMod, only : get_height_index - use FatesSizeAgeTypeIndicesMod, only : sizetype_class_index - use FatesSizeAgeTypeIndicesMod, only : get_cdamagesize_class_index - use FatesSizeAgeTypeIndicesMod, only : get_cdamagesizepft_class_index - use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index - - - use FatesInterfaceTypesMod , only : nlevdamage + ! Arguments class(fates_history_interface_type) :: this @@ -2217,17 +2223,546 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) integer :: tmp + + ! If we don't have dynamics turned on, we just abort these diagnostics + ! CONVERT THIS TO FORCE DYNAM LEVEL 0 + + if (hlm_use_ed_st3.eq.itrue) return + + + if(hlm_hist_level_dynam>0) then + call update_history_dyn1(this,nc,nsites,sites,bc_in) + if(hlm_hist_level_dynam>1) then + call update_history_dyn2(this,nc,nsites,sites,bc_in) + if(hlm_hist_level_dynam>2) then + call update_history_dyn3(this,nc,nsites,sites,bc_in) + end if + end if + end if + return + end subroutine update_history_dyn + + ! ========================================================================= + + subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) + + ! Arguments + class(fates_history_interface_type) :: this + integer , intent(in) :: nc ! clump index + integer , intent(in) :: nsites + type(ed_site_type) , intent(inout), target :: sites(nsites) + type(bc_in_type) , intent(in) :: bc_in(nsites) + + real(r8) :: site_ba ! Site basal area used for weighting + real(r8) :: cohort_ba ! Cohort basal area + real(r8) :: site_ca ! Site crown area used for weighting + real(r8) :: store_max ! Maximum storage capacity for carbon and nutrients + associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & - hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & - hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & - hio_ncohorts_sec_si => this%hvars(ih_ncohorts_sec_si)%r81d, & - hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & - hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & - hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & - hio_fates_fraction_si => this%hvars(ih_fates_fraction_si)%r81d, & - hio_ba_weighted_height_si => this%hvars(ih_ba_weighted_height_si)%r81d, & - hio_ca_weighted_height_si => this%hvars(ih_ca_weighted_height_si)%r81d, & - hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & + hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & + hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & + hio_ncohorts_sec_si => this%hvars(ih_ncohorts_sec_si)%r81d, & + hio_trimming_si => this%hvars(ih_trimming_si)%r81d, & + hio_area_plant_si => this%hvars(ih_area_plant_si)%r81d, & + hio_area_trees_si => this%hvars(ih_area_trees_si)%r81d, & + hio_fates_fraction_si => this%hvars(ih_fates_fraction_si)%r81d, & + hio_ba_weighted_height_si => this%hvars(ih_ba_weighted_height_si)%r81d, & + hio_ca_weighted_height_si => this%hvars(ih_ca_weighted_height_si)%r81d, & + hio_canopy_spread_si => this%hvars(ih_canopy_spread_si)%r81d, & + hio_nesterov_fire_danger_si => this%hvars(ih_nesterov_fire_danger_si)%r81d, & + hio_fire_nignitions_si => this%hvars(ih_fire_nignitions_si)%r81d, & + hio_fire_fdi_si => this%hvars(ih_fire_fdi_si)%r81d, & + hio_spitfire_ros_si => this%hvars(ih_spitfire_ros_si)%r81d, & + hio_tfc_ros_si => this%hvars(ih_tfc_ros_si)%r81d, & + hio_effect_wspeed_si => this%hvars(ih_effect_wspeed_si)%r81d, & + hio_fire_intensity_si => this%hvars(ih_fire_intensity_si)%r81d, & + hio_fire_intensity_area_product_si => this%hvars(ih_fire_intensity_area_product_si)%r81d, & + hio_fire_area_si => this%hvars(ih_fire_area_si)%r81d, & + hio_fire_fuel_bulkd_si => this%hvars(ih_fire_fuel_bulkd_si)%r81d, & + hio_fire_fuel_eff_moist_si => this%hvars(ih_fire_fuel_eff_moist_si)%r81d, & + hio_fire_fuel_sav_si => this%hvars(ih_fire_fuel_sav_si)%r81d, & + hio_fire_fuel_mef_si => this%hvars(ih_fire_fuel_mef_si)%r81d, & + hio_sum_fuel_si => this%hvars(ih_sum_fuel_si)%r81d, & + hio_litter_in_si => this%hvars(ih_litter_in_si)%r81d, & + hio_litter_out_si => this%hvars(ih_litter_out_si)%r81d, & + hio_seed_bank_si => this%hvars(ih_seed_bank_si)%r81d, & + hio_ungerm_seed_bank_si => this%hvars(ih_ungerm_seed_bank_si)%r81d, & + hio_seedling_pool_si => this%hvars(ih_seedling_pool_si)%r81d, & + hio_seeds_in_si => this%hvars(ih_seeds_in_si)%r81d, & + hio_seeds_in_local_si => this%hvars(ih_seeds_in_local_si)%r81d, & + hio_bdead_si => this%hvars(ih_bdead_si)%r81d, & + hio_balive_si => this%hvars(ih_balive_si)%r81d, & + hio_agb_si => this%hvars(ih_agb_si)%r81d, & + hio_canopy_biomass_si => this%hvars(ih_canopy_biomass_si)%r81d, & + hio_understory_biomass_si => this%hvars(ih_understory_biomass_si)%r81d, & + hio_primaryland_fusion_error_si => this%hvars(ih_primaryland_fusion_error_si)%r81d, & + hio_disturbance_rate_p2p_si => this%hvars(ih_disturbance_rate_p2p_si)%r81d, & + hio_disturbance_rate_p2s_si => this%hvars(ih_disturbance_rate_p2s_si)%r81d, & + hio_disturbance_rate_s2s_si => this%hvars(ih_disturbance_rate_s2s_si)%r81d, & + hio_fire_disturbance_rate_si => this%hvars(ih_fire_disturbance_rate_si)%r81d, & + hio_logging_disturbance_rate_si => this%hvars(ih_logging_disturbance_rate_si)%r81d, & + hio_fall_disturbance_rate_si => this%hvars(ih_fall_disturbance_rate_si)%r81d, & + hio_potential_disturbance_rate_si => this%hvars(ih_potential_disturbance_rate_si)%r81d, & + hio_harvest_carbonflux_si => this%hvars(ih_harvest_carbonflux_si)%r81d, & + hio_harvest_debt_si => this%hvars(ih_harvest_debt_si)%r81d, & + hio_harvest_debt_sec_si => this%hvars(ih_harvest_debt_sec_si)%r81d, & + hio_npp_leaf_si => this%hvars(ih_npp_leaf_si)%r81d, & + hio_npp_seed_si => this%hvars(ih_npp_seed_si)%r81d, & + hio_npp_stem_si => this%hvars(ih_npp_stem_si)%r81d, & + hio_npp_froot_si => this%hvars(ih_npp_froot_si)%r81d, & + hio_npp_croot_si => this%hvars(ih_npp_croot_si)%r81d, & + hio_npp_stor_si => this%hvars(ih_npp_stor_si)%r81d, & + hio_canopy_mortality_crownarea_si => this%hvars(ih_canopy_mortality_crownarea_si)%r81d, & + hio_understory_mortality_crownarea_si => this%hvars(ih_understory_mortality_crownarea_si)%r81d, & + hio_fire_c_to_atm_si => this%hvars(ih_fire_c_to_atm_si)%r81d, & + hio_demotion_carbonflux_si => this%hvars(ih_demotion_carbonflux_si)%r81d, & + hio_promotion_carbonflux_si => this%hvars(ih_promotion_carbonflux_si)%r81d, & + hio_canopy_mortality_carbonflux_si => this%hvars(ih_canopy_mortality_carbonflux_si)%r81d, & + hio_understory_mortality_carbonflux_si => this%hvars(ih_understory_mortality_carbonflux_si)%r81d, & + hio_lai_secondary_si => this%hvars(ih_lai_secondary_si)%r81d, & + hio_fraction_secondary_forest_si => this%hvars(ih_fraction_secondary_forest_si)%r81d, & + hio_biomass_secondary_forest_si => this%hvars(ih_biomass_secondary_forest_si)%r81d, & + hio_woodproduct_si => this%hvars(ih_woodproduct_si)%r81d, & + hio_gdd_si => this%hvars(ih_gdd_si)%r81d, & + hio_site_ncolddays_si => this%hvars(ih_site_ncolddays_si)%r81d, & + hio_site_nchilldays_si => this%hvars(ih_site_nchilldays_si)%r81d, & + hio_site_cstatus_si => this%hvars(ih_site_cstatus_si)%r81d, & + hio_cleafoff_si => this%hvars(ih_cleafoff_si)%r81d, & + hio_cleafon_si => this%hvars(ih_cleafon_si)%r81d, & + hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & + + hio_lai_si => this%hvars(ih_lai_si)%r81d ) + + + model_day_int = nint(hlm_model_day) + + ! --------------------------------------------------------------------------------- + ! Loop through the FATES scale hierarchy and fill the history IO arrays + ! --------------------------------------------------------------------------------- + + siteloop: do s = 1,nsites + + io_si = sites(s)%h_gid + + site_ba = 0._r8 + site_ca = 0._r8 + + flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) + ! set the fates fraction to one, since it is zero on non-fates columns, & + ! the average is the total gridcell fates fraction + hio_fates_fraction_si(io_si) = 1._r8 + + ! Total carbon model error [kgC/day -> kgC/s] + 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 * & + ha_per_m2 * days_per_sec + + ! damage variables - site level - this needs to be OUT of the patch loop + if(hlm_use_tree_damage .eq. itrue) then + + this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) = & + this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) + & + sites(s)%crownarea_canopy_damage * days_per_year * 1 / m2_per_ha + + this%hvars(ih_crownarea_ustory_damage_si)%r81d(io_si) = & + this%hvars(ih_crownarea_ustory_damage_si)%r81d(io_si) + & + sites(s)%crownarea_ustory_damage * days_per_year * 1 / m2_per_ha + + end if + + ! Canopy spread index (0-1) + hio_canopy_spread_si(io_si) = sites(s)%spread + + ! Update the site status for cold deciduous (drought deciduous is now PFT dependent) + hio_site_cstatus_si(io_si) = real(sites(s)%cstatus,r8) + + ! Number of chill days and cold days + hio_site_nchilldays_si(io_si) = real(sites(s)%nchilldays,r8) + hio_site_ncolddays_si(io_si) = real(sites(s)%ncolddays,r8) + + ! Growing degree-days + hio_gdd_si(io_si) = sites(s)%grow_deg_days + + ! Model days elapsed since leaf on/off for cold-deciduous + hio_cleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafoffdate,r8) + hio_cleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafondate,r8) + + ! track total wood product accumulation at the site level + hio_woodproduct_si(io_si) = sites(s)%resources_management%trunk_product_site & + * AREA_INV + + ! site-level fire variables: + + ! Nesterov index (unitless) + hio_nesterov_fire_danger_si(io_si) = sites(s)%acc_NI + + ! number of ignitions [#/km2/day -> #/m2/s] + hio_fire_nignitions_si(io_si) = sites(s)%NF_successful / m2_per_km2 / & + sec_per_day + + ! Fire danger index (FDI) (0-1) + hio_fire_fdi_si(io_si) = sites(s)%FDI + + ! If hydraulics are turned on, track the error terms associated with + ! dynamics [kg/m2] + if(hlm_use_planthydro.eq.itrue)then + this%hvars(ih_h2oveg_dead_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_dead + this%hvars(ih_h2oveg_recruit_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_recruit + this%hvars(ih_h2oveg_growturn_err_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_growturn_err + end if + hio_harvest_debt_si(io_si) = sites(s)%resources_management%harvest_debt + hio_harvest_debt_sec_si(io_si) = sites(s)%resources_management%harvest_debt_sec + + ! error in primary lands from patch fusion [m2 m-2 day-1] -> [m2 m-2 yr-1] + hio_primaryland_fusion_error_si(io_si) = sites(s)%primary_land_patchfusion_error * days_per_year + + ! output site-level disturbance rates [m2 m-2 day-1] -> [m2 m-2 yr-1] + hio_disturbance_rate_p2p_si(io_si) = sum(sites(s)%disturbance_rates_primary_to_primary(1:N_DIST_TYPES)) * days_per_year + hio_disturbance_rate_p2s_si(io_si) = sum(sites(s)%disturbance_rates_primary_to_secondary(1:N_DIST_TYPES)) * days_per_year + hio_disturbance_rate_s2s_si(io_si) = sum(sites(s)%disturbance_rates_secondary_to_secondary(1:N_DIST_TYPES)) * days_per_year + + hio_fire_disturbance_rate_si(io_si) = (sites(s)%disturbance_rates_primary_to_primary(dtype_ifire) + & + sites(s)%disturbance_rates_primary_to_secondary(dtype_ifire) + & + sites(s)%disturbance_rates_secondary_to_secondary(dtype_ifire)) * & + days_per_year + + hio_logging_disturbance_rate_si(io_si) = (sites(s)%disturbance_rates_primary_to_primary(dtype_ilog) + & + sites(s)%disturbance_rates_primary_to_secondary(dtype_ilog) + & + sites(s)%disturbance_rates_secondary_to_secondary(dtype_ilog)) * & + days_per_year + + hio_fall_disturbance_rate_si(io_si) = (sites(s)%disturbance_rates_primary_to_primary(dtype_ifall) + & + sites(s)%disturbance_rates_primary_to_secondary(dtype_ifall) + & + sites(s)%disturbance_rates_secondary_to_secondary(dtype_ifall)) * & + days_per_year + + hio_potential_disturbance_rate_si(io_si) = sum(sites(s)%potential_disturbance_rates(1:N_DIST_TYPES)) * days_per_year + + hio_harvest_carbonflux_si(io_si) = sites(s)%mass_balance(element_pos(carbon12_element))%wood_product * AREA_INV + + ! Loop through patches to sum up diagonistics + ipa = 0 + cpatch => sites(s)%oldest_patch + patchloop: do while(associated(cpatch)) + + ! Increment the number of patches per site + hio_npatches_si(io_si) = hio_npatches_si(io_si) + 1._r8 + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_npatches_sec_si(io_si) = hio_npatches_sec_si(io_si) + 1._r8 + end if + + hio_lai_si(io_si) = hio_lai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%elai_profile(:,:,:) ) * & + cpatch%total_canopy_area * AREA_INV + + ! some diagnostics on secondary forest area and its age distribution + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_fraction_secondary_forest_si(io_si) = hio_fraction_secondary_forest_si(io_si) + & + cpatch%area * AREA_INV + + ! Secondary forest mean LAI + + hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) & + + sum(cpatch%tlai_profile(:,:,:)) * cpatch%total_canopy_area + end if + + ! Canopy trimming - degree to which canopy expansion is limited by leaf economics (0-1) + if(associated(cpatch%tallest))then + hio_trimming_si(io_si) = hio_trimming_si(io_si) + cpatch%tallest%canopy_trim * cpatch%area * AREA_INV + endif + + ! area occupied by plants and trees [m2/m2] + hio_area_plant_si(io_si) = hio_area_plant_si(io_si) + min(cpatch%total_canopy_area,cpatch%area) * AREA_INV + hio_area_trees_si(io_si) = hio_area_trees_si(io_si) + min(cpatch%total_tree_area,cpatch%area) * AREA_INV + + ! Patch specific variables that are already calculated + ! These things are all duplicated. Should they all be converted to LL or array structures RF? + ! define scalar to counteract the patch albedo scaling logic for conserved quantities + + ! Update Fire Variables + hio_spitfire_ros_si(io_si) = hio_spitfire_ros_si(io_si) + cpatch%ROS_front * cpatch%area * AREA_INV / sec_per_min + hio_effect_wspeed_si(io_si) = hio_effect_wspeed_si(io_si) + cpatch%effect_wspeed * cpatch%area * AREA_INV / sec_per_min + hio_tfc_ros_si(io_si) = hio_tfc_ros_si(io_si) + cpatch%TFC_ROS * cpatch%area * AREA_INV + hio_fire_intensity_si(io_si) = hio_fire_intensity_si(io_si) + cpatch%FI * cpatch%area * AREA_INV * J_per_kJ + hio_fire_area_si(io_si) = hio_fire_area_si(io_si) + cpatch%frac_burnt * cpatch%area * AREA_INV / sec_per_day + hio_fire_fuel_bulkd_si(io_si) = hio_fire_fuel_bulkd_si(io_si) + cpatch%fuel_bulkd * cpatch%area * AREA_INV + hio_fire_fuel_eff_moist_si(io_si) = hio_fire_fuel_eff_moist_si(io_si) + cpatch%fuel_eff_moist * cpatch%area * AREA_INV + hio_fire_fuel_sav_si(io_si) = hio_fire_fuel_sav_si(io_si) + cpatch%fuel_sav * cpatch%area * AREA_INV / m_per_cm + hio_fire_fuel_mef_si(io_si) = hio_fire_fuel_mef_si(io_si) + cpatch%fuel_mef * cpatch%area * AREA_INV + hio_sum_fuel_si(io_si) = hio_sum_fuel_si(io_si) + cpatch%sum_fuel * cpatch%area * AREA_INV + + hio_fire_intensity_area_product_si(io_si) = hio_fire_intensity_area_product_si(io_si) + & + cpatch%FI * cpatch%frac_burnt * cpatch%area * AREA_INV * J_per_kJ + + + ! loop through cohorts on patch + ccohort => cpatch%shortest + cohortloop: do while(associated(ccohort)) + + ft = ccohort%pft + n_perm2 = ccohort%n * AREA_INV + + ! Increment the number of cohorts per site + hio_ncohorts_si(io_si) = hio_ncohorts_si(io_si) + 1._r8 + + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_ncohorts_sec_si(io_si) = hio_ncohorts_sec_si(io_si) + 1._r8 + end if + + ! Update biomass components + ! Mass pools [kg] + elloop: do el = 1, num_elements + + sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) + struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) + fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) + store_m = ccohort%prt%GetState(store_organ, element_list(el)) + repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) + + alive_m = leaf_m + fnrt_m + sapw_m + total_m = alive_m + store_m + struct_m + + ! Plant multi-element states and fluxes + ! Zero states, and set the fluxes + if( element_list(el).eq.carbon12_element )then + + ! mass in different tissues [kg/ha] -> [kg/m2] + this%hvars(ih_storec_si)%r81d(io_si) = & + this%hvars(ih_storec_si)%r81d(io_si) + ccohort%n * & + store_m / m2_per_ha + this%hvars(ih_leafc_si)%r81d(io_si) = & + this%hvars(ih_leafc_si)%r81d(io_si) + ccohort%n * & + leaf_m / m2_per_ha + this%hvars(ih_fnrtc_si)%r81d(io_si) = & + this%hvars(ih_fnrtc_si)%r81d(io_si) + ccohort%n * & + fnrt_m / m2_per_ha + this%hvars(ih_reproc_si)%r81d(io_si) = & + this%hvars(ih_reproc_si)%r81d(io_si)+ ccohort%n * & + repro_m / m2_per_ha + this%hvars(ih_sapwc_si)%r81d(io_si) = & + this%hvars(ih_sapwc_si)%r81d(io_si) + ccohort%n * & + sapw_m / m2_per_ha + this%hvars(ih_totvegc_si)%r81d(io_si) = & + this%hvars(ih_totvegc_si)%r81d(io_si)+ ccohort%n * & + total_m / m2_per_ha + + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage,ccohort%canopy_trim, store_max) + + this%hvars(ih_storectfrac_si)%r81d(io_si) = & + this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max/m2_per_ha + + hio_bdead_si(io_si) = hio_bdead_si(io_si) + n_perm2 * struct_m + hio_balive_si(io_si) = hio_balive_si(io_si) + n_perm2 * alive_m + + hio_agb_si(io_si) = hio_agb_si(io_si) + n_perm2 * & + ( leaf_m + (sapw_m + struct_m + store_m) * prt_params%allom_agb_frac(ccohort%pft) ) + + ! track the total biomass on all secondary lands + if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + hio_biomass_secondary_forest_si(io_si) = hio_biomass_secondary_forest_si(io_si) + & + total_m * ccohort%n * AREA_INV + endif + + elseif(element_list(el).eq.nitrogen_element)then + + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) + + this%hvars(ih_storen_si)%r81d(io_si) = & + this%hvars(ih_storen_si)%r81d(io_si) + ccohort%n * & + store_m / m2_per_ha + this%hvars(ih_storentfrac_si)%r81d(io_si) = & + this%hvars(ih_storentfrac_si)%r81d(io_si) + ccohort%n * & + store_max / m2_per_ha + this%hvars(ih_leafn_si)%r81d(io_si) = & + this%hvars(ih_leafn_si)%r81d(io_si) + ccohort%n * & + leaf_m / m2_per_ha + this%hvars(ih_fnrtn_si)%r81d(io_si) = & + this%hvars(ih_fnrtn_si)%r81d(io_si) + ccohort%n * & + fnrt_m / m2_per_ha + this%hvars(ih_repron_si)%r81d(io_si) = & + this%hvars(ih_repron_si)%r81d(io_si) + ccohort%n * & + repro_m / m2_per_ha + this%hvars(ih_sapwn_si)%r81d(io_si) = & + this%hvars(ih_sapwn_si)%r81d(io_si) + ccohort%n * & + sapw_m / m2_per_ha + this%hvars(ih_totvegn_si)%r81d(io_si) = & + this%hvars(ih_totvegn_si)%r81d(io_si) + ccohort%n * & + total_m / m2_per_ha + + elseif(element_list(el).eq.phosphorus_element) then + + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) + + this%hvars(ih_storep_si)%r81d(io_si) = & + this%hvars(ih_storep_si)%r81d(io_si) + ccohort%n * & + store_m / m2_per_ha + this%hvars(ih_storeptfrac_si)%r81d(io_si) = & + this%hvars(ih_storeptfrac_si)%r81d(io_si) + ccohort%n * & + store_max / m2_per_ha + this%hvars(ih_leafp_si)%r81d(io_si) = & + this%hvars(ih_leafp_si)%r81d(io_si) + ccohort%n * & + leaf_m / m2_per_ha + this%hvars(ih_fnrtp_si)%r81d(io_si) = & + this%hvars(ih_fnrtp_si)%r81d(io_si) + ccohort%n * & + fnrt_m / m2_per_ha + this%hvars(ih_reprop_si)%r81d(io_si) = & + this%hvars(ih_reprop_si)%r81d(io_si) + ccohort%n * & + repro_m / m2_per_ha + this%hvars(ih_sapwp_si)%r81d(io_si) = & + this%hvars(ih_sapwp_si)%r81d(io_si) + ccohort%n * & + sapw_m / m2_per_ha + this%hvars(ih_totvegp_si)%r81d(io_si) = & + this%hvars(ih_totvegp_si)%r81d(io_si)+ ccohort%n * & + total_m / m2_per_ha + end if + end do elloop + + ! FLUXES --- + ! Flux Variables (cohorts must had experienced a day before any of these values + ! have any meaning, otherwise they are just inialization values + notnew: if( .not.(ccohort%isnew) ) then + + ! Turnover pools [kgC/day] * [day/yr] = [kgC/yr] + sapw_m_turnover = ccohort%prt%GetTurnover(sapw_organ, carbon12_element) * days_per_year + store_m_turnover = ccohort%prt%GetTurnover(store_organ, carbon12_element) * days_per_year + leaf_m_turnover = ccohort%prt%GetTurnover(leaf_organ, carbon12_element) * days_per_year + fnrt_m_turnover = ccohort%prt%GetTurnover(fnrt_organ, carbon12_element) * days_per_year + struct_m_turnover = ccohort%prt%GetTurnover(struct_organ, carbon12_element) * days_per_year + + ! Net change from allocation and transport [kgC/day] * [day/yr] = [kgC/yr] + sapw_m_net_alloc = ccohort%prt%GetNetAlloc(sapw_organ, carbon12_element) * days_per_year + store_m_net_alloc = ccohort%prt%GetNetAlloc(store_organ, carbon12_element) * days_per_year + leaf_m_net_alloc = ccohort%prt%GetNetAlloc(leaf_organ, carbon12_element) * days_per_year + fnrt_m_net_alloc = ccohort%prt%GetNetAlloc(fnrt_organ, carbon12_element) * days_per_year + struct_m_net_alloc = ccohort%prt%GetNetAlloc(struct_organ, carbon12_element) * days_per_year + repro_m_net_alloc = ccohort%prt%GetNetAlloc(repro_organ, carbon12_element) * days_per_year + + ! ecosystem-level, organ-partitioned NPP/allocation fluxes + ! [kgC/yr] -> [kgC/sec] + hio_npp_leaf_si(io_si) = hio_npp_leaf_si(io_si) + & + leaf_m_net_alloc * n_perm2 / days_per_year / sec_per_day + hio_npp_seed_si(io_si) = hio_npp_seed_si(io_si) + & + repro_m_net_alloc * n_perm2 / days_per_year / sec_per_day + hio_npp_stem_si(io_si) = hio_npp_stem_si(io_si) + & + (sapw_m_net_alloc + struct_m_net_alloc) * n_perm2 * & + (prt_params%allom_agb_frac(ccohort%pft)) / & + days_per_year / sec_per_day + hio_npp_froot_si(io_si) = hio_npp_froot_si(io_si) + & + fnrt_m_net_alloc * n_perm2 / days_per_year / sec_per_day + hio_npp_croot_si(io_si) = hio_npp_croot_si(io_si) + & + (sapw_m_net_alloc + struct_m_net_alloc) * n_perm2 * & + (1._r8-prt_params%allom_agb_frac(ccohort%pft)) / & + days_per_year / sec_per_day + hio_npp_stor_si(io_si) = hio_npp_stor_si(io_si) + & + store_m_net_alloc * n_perm2 / days_per_year / sec_per_day + + ! Woody State Variables (basal area growth increment) + if ( prt_params%woody(ft) == itrue) then + + cohort_ba = 0.25_r8*pi_const*((ccohort%dbh/100.0_r8)**2.0_r8)*ccohort%n + + hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) + & + ccohort%height * cohort_ba + + site_ba = site_ba + cohort_ba + + end if + + ! THIS NEEDS TO BE NORMALIZED (RGK) + hio_ca_weighted_height_si(io_si) = hio_ca_weighted_height_si(io_si) + & + ccohort%height * ccohort%c_area / m2_per_ha + + site_ca = site_ca + ccohort%c_area / m2_per_ha + + ! RGK - CANOPY/USTORY BIOMASS IS NOT A FLUX, NEED NOT BE CONDITIONED BY isnew + ! ---------------------------------------------------------------------------------- + if (ccohort%canopy_layer .eq. 1) then + hio_canopy_biomass_si(io_si) = hio_canopy_biomass_si(io_si) + n_perm2 * total_m + + hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & + ccohort%n * ha_per_m2 + + hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + ccohort%c_area + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%c_area * sec_per_day * days_per_year + + else + hio_ustory_biomass_si(io_si) = hio_ustory_biomass_si(io_si) + n_perm2 * total_m + + hio_ustory_mortality_carbonflux_si(io_si) = hio_ustory_mortality_carbonflux_si(io_si) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & + ccohort%n * ha_per_m2 + + hio_ustory_mortality_crownarea_si(io_si) = hio_ustory_mortality_crownarea_si(io_si) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + ccohort%c_area + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%c_area * sec_per_day * days_per_year + + end if + + end if notnew + + ccohort => ccohort%taller + enddo cohortloop ! cohort loop + + ipa = ipa + 1 + cpatch => cpatch%younger + end do patchloop !patch loop + + ! Perform any necessary normalizations + ! ---------------------------------------------------------------------------------------- + + ! divide basal-area-weighted height by basal area to get mean + if ( site_ba .gt. nearzero ) then + hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) / site_ba + else + hio_ba_weighted_height_si(io_si) = 0._r8 + endif + + elloop2: do el = 1, num_elements + if( element_list(el).eq.carbon12_element )then + if( this%hvars(ih_storectfrac_si)%r81d(io_si)>nearzero ) then + this%hvars(ih_storectfrac_si)%r81d(io_si) = this%hvars(ih_storec_si)%r81d(io_si) / & + this%hvars(ih_storectfrac_si)%r81d(io_si) + end if + elseif( element_list(el).eq.nitrogen_element )then + if( this%hvars(ih_storentfrac_si)%r81d(io_si)>nearzero ) then + this%hvars(ih_storentfrac_si)%r81d(io_si) = this%hvars(ih_storen_si)%r81d(io_si) / & + this%hvars(ih_storentfrac_si)%r81d(io_si) + end if + elseif( element_list(el).eq.phosphorus_element )then + if( this%hvars(ih_storeptfrac_si)%r81d(io_si)>nearzero ) then + this%hvars(ih_storeptfrac_si)%r81d(io_si) = this%hvars(ih_storep_si)%r81d(io_si) / & + this%hvars(ih_storeptfrac_si)%r81d(io_si) + end if + end if + end do elloop2 + + + end associate + return + end subroutine update_history_dyn1 + + ! ========================================================================================= + + + hio_err_fates_elem => this%hvars(ih_err_fates_elem)%r82d, & hio_biomass_si_pft => this%hvars(ih_biomass_si_pft)%r82d, & hio_biomass_sec_si_pft => this%hvars(ih_biomass_sec_si_pft)%r82d, & hio_leafbiomass_si_pft => this%hvars(ih_leafbiomass_si_pft)%r82d, & @@ -2248,28 +2783,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_gpp_sec_si_pft => this%hvars(ih_gpp_sec_si_pft)%r82d, & hio_npp_si_pft => this%hvars(ih_npp_si_pft)%r82d, & hio_npp_sec_si_pft => this%hvars(ih_npp_sec_si_pft)%r82d, & - hio_nesterov_fire_danger_si => this%hvars(ih_nesterov_fire_danger_si)%r81d, & - hio_fire_nignitions_si => this%hvars(ih_fire_nignitions_si)%r81d, & - hio_fire_fdi_si => this%hvars(ih_fire_fdi_si)%r81d, & - hio_spitfire_ros_si => this%hvars(ih_spitfire_ros_si)%r81d, & - hio_tfc_ros_si => this%hvars(ih_tfc_ros_si)%r81d, & - hio_effect_wspeed_si => this%hvars(ih_effect_wspeed_si)%r81d, & - hio_fire_intensity_si => this%hvars(ih_fire_intensity_si)%r81d, & - hio_fire_intensity_area_product_si => this%hvars(ih_fire_intensity_area_product_si)%r81d, & - hio_fire_area_si => this%hvars(ih_fire_area_si)%r81d, & - hio_fire_fuel_bulkd_si => this%hvars(ih_fire_fuel_bulkd_si)%r81d, & - hio_fire_fuel_eff_moist_si => this%hvars(ih_fire_fuel_eff_moist_si)%r81d, & - hio_fire_fuel_sav_si => this%hvars(ih_fire_fuel_sav_si)%r81d, & - hio_fire_fuel_mef_si => this%hvars(ih_fire_fuel_mef_si)%r81d, & - hio_sum_fuel_si => this%hvars(ih_sum_fuel_si)%r81d, & + hio_fragmentation_scaler_sl => this%hvars(ih_fragmentation_scaler_sl)%r82d, & - hio_litter_in_si => this%hvars(ih_litter_in_si)%r81d, & - hio_litter_out_si => this%hvars(ih_litter_out_si)%r81d, & - hio_seed_bank_si => this%hvars(ih_seed_bank_si)%r81d, & - hio_ungerm_seed_bank_si => this%hvars(ih_ungerm_seed_bank_si)%r81d, & - hio_seedling_pool_si => this%hvars(ih_seedling_pool_si)%r81d, & - hio_seeds_in_si => this%hvars(ih_seeds_in_si)%r81d, & - hio_seeds_in_local_si => this%hvars(ih_seeds_in_local_si)%r81d, & + hio_litter_in_elem => this%hvars(ih_litter_in_elem)%r82d, & hio_litter_out_elem => this%hvars(ih_litter_out_elem)%r82d, & hio_seed_bank_elem => this%hvars(ih_seed_bank_elem)%r82d, & @@ -2277,22 +2793,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_seed_in_extern_elem => this%hvars(ih_seeds_in_extern_elem)%r82d, & hio_seed_decay_elem => this%hvars(ih_seed_decay_elem)%r82d, & hio_seed_germ_elem => this%hvars(ih_seed_germ_elem)%r82d, & - hio_bdead_si => this%hvars(ih_bdead_si)%r81d, & - hio_balive_si => this%hvars(ih_balive_si)%r81d, & - hio_agb_si => this%hvars(ih_agb_si)%r81d, & - hio_canopy_biomass_si => this%hvars(ih_canopy_biomass_si)%r81d, & - hio_understory_biomass_si => this%hvars(ih_understory_biomass_si)%r81d, & - hio_primaryland_fusion_error_si => this%hvars(ih_primaryland_fusion_error_si)%r81d, & - hio_disturbance_rate_p2p_si => this%hvars(ih_disturbance_rate_p2p_si)%r81d, & - hio_disturbance_rate_p2s_si => this%hvars(ih_disturbance_rate_p2s_si)%r81d, & - hio_disturbance_rate_s2s_si => this%hvars(ih_disturbance_rate_s2s_si)%r81d, & - hio_fire_disturbance_rate_si => this%hvars(ih_fire_disturbance_rate_si)%r81d, & - hio_logging_disturbance_rate_si => this%hvars(ih_logging_disturbance_rate_si)%r81d, & - hio_fall_disturbance_rate_si => this%hvars(ih_fall_disturbance_rate_si)%r81d, & - hio_potential_disturbance_rate_si => this%hvars(ih_potential_disturbance_rate_si)%r81d, & - hio_harvest_carbonflux_si => this%hvars(ih_harvest_carbonflux_si)%r81d, & - hio_harvest_debt_si => this%hvars(ih_harvest_debt_si)%r81d, & - hio_harvest_debt_sec_si => this%hvars(ih_harvest_debt_sec_si)%r81d, & + hio_gpp_si_scpf => this%hvars(ih_gpp_si_scpf)%r82d, & hio_npp_totl_si_scpf => this%hvars(ih_npp_totl_si_scpf)%r82d, & hio_npp_leaf_si_scpf => this%hvars(ih_npp_leaf_si_scpf)%r82d, & @@ -2303,12 +2804,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_npp_agsw_si_scpf => this%hvars(ih_npp_agsw_si_scpf)%r82d, & hio_npp_agdw_si_scpf => this%hvars(ih_npp_agdw_si_scpf)%r82d, & hio_npp_stor_si_scpf => this%hvars(ih_npp_stor_si_scpf)%r82d, & - hio_npp_leaf_si => this%hvars(ih_npp_leaf_si)%r81d, & - hio_npp_seed_si => this%hvars(ih_npp_seed_si)%r81d, & - hio_npp_stem_si => this%hvars(ih_npp_stem_si)%r81d, & - hio_npp_froot_si => this%hvars(ih_npp_froot_si)%r81d, & - hio_npp_croot_si => this%hvars(ih_npp_croot_si)%r81d, & - hio_npp_stor_si => this%hvars(ih_npp_stor_si)%r81d, & + hio_bstor_canopy_si_scpf => this%hvars(ih_bstor_canopy_si_scpf)%r82d, & hio_bstor_understory_si_scpf => this%hvars(ih_bstor_understory_si_scpf)%r82d, & hio_bleaf_canopy_si_scpf => this%hvars(ih_bleaf_canopy_si_scpf)%r82d, & @@ -2322,8 +2818,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_m3_mortality_understory_si_scpf => this%hvars(ih_m3_mortality_understory_si_scpf)%r82d, & hio_m3_mortality_canopy_si_scls => this%hvars(ih_m3_mortality_canopy_si_scls)%r82d, & hio_m3_mortality_understory_si_scls => this%hvars(ih_m3_mortality_understory_si_scls)%r82d, & - hio_canopy_mortality_crownarea_si => this%hvars(ih_canopy_mortality_crownarea_si)%r81d, & - hio_understory_mortality_crownarea_si => this%hvars(ih_understory_mortality_crownarea_si)%r81d, & + hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & hio_nplant_understory_si_scpf => this%hvars(ih_nplant_understory_si_scpf)%r82d, & hio_ddbh_canopy_si_scpf => this%hvars(ih_ddbh_canopy_si_scpf)%r82d, & @@ -2360,7 +2855,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_abg_mortality_cflux_si_scpf => this%hvars(ih_abg_mortality_cflux_si_scpf)%r82d, & hio_abg_productivity_cflux_si_scpf => this%hvars(ih_abg_productivity_cflux_si_scpf)%r82d, & - hio_fire_c_to_atm_si => this%hvars(ih_fire_c_to_atm_si)%r81d, & + hio_burn_flux_elem => this%hvars(ih_burn_flux_elem)%r82d, & hio_m1_si_scls => this%hvars(ih_m1_si_scls)%r82d, & @@ -2404,15 +2899,13 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_mortality_canopy_si_scls => this%hvars(ih_mortality_canopy_si_scls)%r82d, & hio_mortality_understory_si_scls => this%hvars(ih_mortality_understory_si_scls)%r82d, & hio_demotion_rate_si_scls => this%hvars(ih_demotion_rate_si_scls)%r82d, & - hio_demotion_carbonflux_si => this%hvars(ih_demotion_carbonflux_si)%r81d, & + hio_promotion_rate_si_scls => this%hvars(ih_promotion_rate_si_scls)%r82d, & hio_trimming_canopy_si_scls => this%hvars(ih_trimming_canopy_si_scls)%r82d, & hio_trimming_understory_si_scls => this%hvars(ih_trimming_understory_si_scls)%r82d, & hio_crown_area_canopy_si_scls => this%hvars(ih_crown_area_canopy_si_scls)%r82d, & hio_crown_area_understory_si_scls => this%hvars(ih_crown_area_understory_si_scls)%r82d, & - hio_promotion_carbonflux_si => this%hvars(ih_promotion_carbonflux_si)%r81d, & - hio_canopy_mortality_carbonflux_si => this%hvars(ih_canopy_mortality_carbonflux_si)%r81d, & - hio_understory_mortality_carbonflux_si => this%hvars(ih_understory_mortality_carbonflux_si)%r81d, & + hio_leaf_md_canopy_si_scls => this%hvars(ih_leaf_md_canopy_si_scls)%r82d, & hio_root_md_canopy_si_scls => this%hvars(ih_root_md_canopy_si_scls)%r82d, & hio_carbon_balance_canopy_si_scls => this%hvars(ih_carbon_balance_canopy_si_scls)%r82d, & @@ -2447,15 +2940,13 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_yesterdaycanopylevel_understory_si_scls => this%hvars(ih_yesterdaycanopylevel_understory_si_scls)%r82d, & hio_area_si_age => this%hvars(ih_area_si_age)%r82d, & hio_lai_si_age => this%hvars(ih_lai_si_age)%r82d, & - hio_lai_secondary_si => this%hvars(ih_lai_secondary_si)%r81d, & + hio_canopy_area_si_age => this%hvars(ih_canopy_area_si_age)%r82d, & hio_ncl_si_age => this%hvars(ih_ncl_si_age)%r82d, & hio_npatches_si_age => this%hvars(ih_npatches_si_age)%r82d, & hio_zstar_si_age => this%hvars(ih_zstar_si_age)%r82d, & hio_biomass_si_age => this%hvars(ih_biomass_si_age)%r82d, & - hio_fraction_secondary_forest_si => this%hvars(ih_fraction_secondary_forest_si)%r81d, & - hio_biomass_secondary_forest_si => this%hvars(ih_biomass_secondary_forest_si)%r81d, & - hio_woodproduct_si => this%hvars(ih_woodproduct_si)%r81d, & + hio_agesince_anthrodist_si_age => this%hvars(ih_agesince_anthrodist_si_age)%r82d, & hio_secondaryforest_area_si_age => this%hvars(ih_secondaryforest_area_si_age)%r82d, & hio_area_burnt_si_age => this%hvars(ih_area_burnt_si_age)%r82d, & @@ -2485,12 +2976,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d ) ! Split up the associate statement as the nag compiler has a limit on line continuation - associate( hio_gdd_si => this%hvars(ih_gdd_si)%r81d, & - hio_site_ncolddays_si => this%hvars(ih_site_ncolddays_si)%r81d, & - hio_site_nchilldays_si => this%hvars(ih_site_nchilldays_si)%r81d, & - hio_site_cstatus_si => this%hvars(ih_site_cstatus_si)%r81d, & - hio_cleafoff_si => this%hvars(ih_cleafoff_si)%r81d, & - hio_cleafon_si => this%hvars(ih_cleafon_si)%r81d, & + associate( hio_site_dstatus_si_pft => this%hvars(ih_site_dstatus_si_pft)%r82d, & hio_dleafoff_si_pft => this%hvars(ih_dleafoff_si_pft)%r82d, & hio_dleafon_si_pft => this%hvars(ih_dleafon_si_pft)%r82d, & @@ -2500,15 +2986,13 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & hio_tlongterm => this%hvars(ih_tlongterm_si)%r81d, & hio_tgrowth => this%hvars(ih_tgrowth_si)%r81d, & - hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & - hio_err_fates_si => this%hvars(ih_err_fates_si)%r82d, & + hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & 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_lai_si => this%hvars(ih_lai_si)%r81d ) + ) - ! If we don't have dynamics turned on, we just abort these diagnostics - if (hlm_use_ed_st3.eq.itrue) return + model_day_int = nint(hlm_model_day) @@ -2533,23 +3017,12 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) - ! set the fates fraction to one, since it is zero on non-fates columns, & - ! the average is the total gridcell fates fraction - hio_fates_fraction_si(io_si) = 1._r8 - - ! Total carbon model error [kgC/day -> kgC/s] - 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 * & - ha_per_m2 * days_per_sec + do el = 1, num_elements ! Total model error [kg/day -> kg/s] (all elements) - hio_err_fates_si(io_si,el) = sites(s)%mass_balance(el)%err_fates / sec_per_day + hio_err_fates_elem(io_si,el) = sites(s)%mass_balance(el)%err_fates / sec_per_day ! Total element lost to atmosphere from burning (kg/site/day -> kg/m2/s) hio_burn_flux_elem(io_si,el) = & @@ -2558,36 +3031,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end do - ! damage variables - site level - this needs to be OUT of the patch loop - if(hlm_use_tree_damage .eq. itrue) then - - this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) = & - this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) + & - sites(s)%crownarea_canopy_damage * days_per_year * 1 / m2_per_ha - - this%hvars(ih_crownarea_ustory_damage_si)%r81d(io_si) = & - this%hvars(ih_crownarea_ustory_damage_si)%r81d(io_si) + & - sites(s)%crownarea_ustory_damage * days_per_year * 1 / m2_per_ha - - end if - - ! Canopy spread index (0-1) - hio_canopy_spread_si(io_si) = sites(s)%spread - - ! Update the site status for cold deciduous (drought deciduous is now PFT dependent) - hio_site_cstatus_si(io_si) = real(sites(s)%cstatus,r8) - - ! Number of chill days and cold days - hio_site_nchilldays_si(io_si) = real(sites(s)%nchilldays,r8) - hio_site_ncolddays_si(io_si) = real(sites(s)%ncolddays,r8) - - ! Growing degree-days - hio_gdd_si(io_si) = sites(s)%grow_deg_days - - ! Model days elapsed since leaf on/off for cold-deciduous - hio_cleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafoffdate,r8) - hio_cleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafondate,r8) ! Update drought deciduous information (now separated by PFT). @@ -2614,69 +3058,14 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end if end do - ! track total wood product accumulation at the site level - hio_woodproduct_si(io_si) = sites(s)%resources_management%trunk_product_site & - * AREA_INV - - ! site-level fire variables: - - ! Nesterov index (unitless) - hio_nesterov_fire_danger_si(io_si) = sites(s)%acc_NI - - ! number of ignitions [#/km2/day -> #/m2/s] - hio_fire_nignitions_si(io_si) = sites(s)%NF_successful / m2_per_km2 / & - sec_per_day - - ! Fire danger index (FDI) (0-1) - hio_fire_fdi_si(io_si) = sites(s)%FDI - - ! If hydraulics are turned on, track the error terms associated with - ! dynamics [kg/m2] - if(hlm_use_planthydro.eq.itrue)then - this%hvars(ih_h2oveg_dead_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_dead - this%hvars(ih_h2oveg_recruit_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_recruit - this%hvars(ih_h2oveg_growturn_err_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_growturn_err - end if - hio_harvest_debt_si(io_si) = sites(s)%resources_management%harvest_debt - hio_harvest_debt_sec_si(io_si) = sites(s)%resources_management%harvest_debt_sec - - ! error in primary lands from patch fusion [m2 m-2 day-1] -> [m2 m-2 yr-1] - hio_primaryland_fusion_error_si(io_si) = sites(s)%primary_land_patchfusion_error * days_per_year - - ! output site-level disturbance rates [m2 m-2 day-1] -> [m2 m-2 yr-1] - hio_disturbance_rate_p2p_si(io_si) = sum(sites(s)%disturbance_rates_primary_to_primary(1:N_DIST_TYPES)) * days_per_year - hio_disturbance_rate_p2s_si(io_si) = sum(sites(s)%disturbance_rates_primary_to_secondary(1:N_DIST_TYPES)) * days_per_year - hio_disturbance_rate_s2s_si(io_si) = sum(sites(s)%disturbance_rates_secondary_to_secondary(1:N_DIST_TYPES)) * days_per_year - - hio_fire_disturbance_rate_si(io_si) = (sites(s)%disturbance_rates_primary_to_primary(dtype_ifire) + & - sites(s)%disturbance_rates_primary_to_secondary(dtype_ifire) + & - sites(s)%disturbance_rates_secondary_to_secondary(dtype_ifire)) * & - days_per_year - - hio_logging_disturbance_rate_si(io_si) = (sites(s)%disturbance_rates_primary_to_primary(dtype_ilog) + & - sites(s)%disturbance_rates_primary_to_secondary(dtype_ilog) + & - sites(s)%disturbance_rates_secondary_to_secondary(dtype_ilog)) * & - days_per_year - - hio_fall_disturbance_rate_si(io_si) = (sites(s)%disturbance_rates_primary_to_primary(dtype_ifall) + & - sites(s)%disturbance_rates_primary_to_secondary(dtype_ifall) + & - sites(s)%disturbance_rates_secondary_to_secondary(dtype_ifall)) * & - days_per_year - - hio_potential_disturbance_rate_si(io_si) = sum(sites(s)%potential_disturbance_rates(1:N_DIST_TYPES)) * days_per_year - - hio_harvest_carbonflux_si(io_si) = sites(s)%mass_balance(element_pos(carbon12_element))%wood_product * AREA_INV + ! Loop through patches to sum up diagonistics ipa = 0 cpatch => sites(s)%oldest_patch patchloop: do while(associated(cpatch)) - ! Increment the number of patches per site - hio_npatches_si(io_si) = hio_npatches_si(io_si) + 1._r8 - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then - hio_npatches_sec_si(io_si) = hio_npatches_sec_si(io_si) + 1._r8 - end if + cpatch%age_class = get_age_class_index(cpatch%age) @@ -2704,8 +3093,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) + cpatch%ncl_p * cpatch%area hio_npatches_si_age(io_si,cpatch%age_class) = hio_npatches_si_age(io_si,cpatch%age_class) + 1._r8 - hio_lai_si(io_si) = hio_lai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%elai_profile(:,:,:) ) * & - cpatch%total_canopy_area * AREA_INV + if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled hio_zstar_si_age(io_si,cpatch%age_class) = hio_zstar_si_age(io_si,cpatch%age_class) & @@ -2714,8 +3102,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! some diagnostics on secondary forest area and its age distribution if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then - hio_fraction_secondary_forest_si(io_si) = hio_fraction_secondary_forest_si(io_si) + & - cpatch%area * AREA_INV ageclass_since_anthrodist = get_age_class_index(cpatch%age_since_anthro_disturbance) @@ -2728,11 +3114,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) + cpatch%area * AREA_INV endif - ! Secondary forest mean LAI - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then - hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) & - + sum(cpatch%tlai_profile(:,:,:)) * cpatch%total_canopy_area - end if + ! patch-age-resolved fire variables do i_pft = 1,numpft @@ -2773,14 +3155,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_fire_sum_fuel_si_age(io_si, cpatch%age_class) = hio_fire_sum_fuel_si_age(io_si, cpatch%age_class) + & cpatch%sum_fuel * cpatch%area * AREA_INV - ! Canopy trimming - degree to which canopy expansion is limited by leaf economics (0-1) - if(associated(cpatch%tallest))then - hio_trimming_si(io_si) = hio_trimming_si(io_si) + cpatch%tallest%canopy_trim * cpatch%area * AREA_INV - endif - - ! area occupied by plants and trees [m2/m2] - hio_area_plant_si(io_si) = hio_area_plant_si(io_si) + min(cpatch%total_canopy_area,cpatch%area) * AREA_INV - hio_area_trees_si(io_si) = hio_area_trees_si(io_si) + min(cpatch%total_tree_area,cpatch%area) * AREA_INV + ! loop through cohorts on patch ccohort => cpatch%shortest @@ -2796,13 +3171,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) call coagetype_class_index(ccohort%coage, ccohort%pft, & ccohort%coage_class, ccohort%coage_by_pft_class) - ! Increment the number of cohorts per site - hio_ncohorts_si(io_si) = hio_ncohorts_si(io_si) + 1._r8 - - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then - hio_ncohorts_sec_si(io_si) = hio_ncohorts_sec_si(io_si) + 1._r8 - end if - n_perm2 = ccohort%n * AREA_INV hio_canopy_area_si_age(io_si,cpatch%age_class) = hio_canopy_area_si_age(io_si,cpatch%age_class) & @@ -2864,46 +3232,13 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! Zero states, and set the fluxes if( element_list(el).eq.carbon12_element )then - ! mass in different tissues [kg/ha] -> [kg/m2] - this%hvars(ih_storec_si)%r81d(io_si) = & - this%hvars(ih_storec_si)%r81d(io_si) + ccohort%n * & - store_m / m2_per_ha - this%hvars(ih_leafc_si)%r81d(io_si) = & - this%hvars(ih_leafc_si)%r81d(io_si) + ccohort%n * & - leaf_m / m2_per_ha - this%hvars(ih_fnrtc_si)%r81d(io_si) = & - this%hvars(ih_fnrtc_si)%r81d(io_si) + ccohort%n * & - fnrt_m / m2_per_ha - this%hvars(ih_reproc_si)%r81d(io_si) = & - this%hvars(ih_reproc_si)%r81d(io_si)+ ccohort%n * & - repro_m / m2_per_ha - this%hvars(ih_sapwc_si)%r81d(io_si) = & - this%hvars(ih_sapwc_si)%r81d(io_si) + ccohort%n * & - sapw_m / m2_per_ha - this%hvars(ih_totvegc_si)%r81d(io_si) = & - this%hvars(ih_totvegc_si)%r81d(io_si)+ ccohort%n * & - total_m / m2_per_ha - - - call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage,ccohort%canopy_trim, store_max) - this%hvars(ih_storectfrac_si)%r81d(io_si) = & - this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max/m2_per_ha - ! Determine the root carbon biomass in kg/m3 ! [kg/m3] = [kg/plant] * [plant/ha] / [m3/ha] * [fraction] / [m] - do ilyr = 1,sites(s)%nlevsoil this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) = this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) + & fnrt_m * ccohort%n / area * sites(s)%rootfrac_scr(ilyr) / sites(s)%dz_soil(ilyr) end do - - hio_bdead_si(io_si) = hio_bdead_si(io_si) + n_perm2 * struct_m - hio_balive_si(io_si) = hio_balive_si(io_si) + n_perm2 * alive_m - - hio_agb_si(io_si) = hio_agb_si(io_si) + n_perm2 * & - ( leaf_m + (sapw_m + struct_m + store_m) * prt_params%allom_agb_frac(ccohort%pft) ) - ! Update PFT partitioned biomass components hio_leafbiomass_si_pft(io_si,ft) = hio_leafbiomass_si_pft(io_si,ft) + & @@ -2932,12 +3267,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_biomass_si_age(io_si,cpatch%age_class) = hio_biomass_si_age(io_si,cpatch%age_class) & + total_m * ccohort%n * AREA_INV - ! track the total biomass on all secondary lands - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then - hio_biomass_secondary_forest_si(io_si) = hio_biomass_secondary_forest_si(io_si) + & - total_m * ccohort%n * AREA_INV - endif - if (ccohort%canopy_layer .eq. 1) then storec_canopy_scpf(i_scpf) = & storec_canopy_scpf(i_scpf) + ccohort%n * store_m @@ -2957,28 +3286,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) - this%hvars(ih_storen_si)%r81d(io_si) = & - this%hvars(ih_storen_si)%r81d(io_si) + ccohort%n * & - store_m / m2_per_ha - this%hvars(ih_storentfrac_si)%r81d(io_si) = & - this%hvars(ih_storentfrac_si)%r81d(io_si) + ccohort%n * & - store_max / m2_per_ha - this%hvars(ih_leafn_si)%r81d(io_si) = & - this%hvars(ih_leafn_si)%r81d(io_si) + ccohort%n * & - leaf_m / m2_per_ha - this%hvars(ih_fnrtn_si)%r81d(io_si) = & - this%hvars(ih_fnrtn_si)%r81d(io_si) + ccohort%n * & - fnrt_m / m2_per_ha - this%hvars(ih_repron_si)%r81d(io_si) = & - this%hvars(ih_repron_si)%r81d(io_si) + ccohort%n * & - repro_m / m2_per_ha - this%hvars(ih_sapwn_si)%r81d(io_si) = & - this%hvars(ih_sapwn_si)%r81d(io_si) + ccohort%n * & - sapw_m / m2_per_ha - this%hvars(ih_totvegn_si)%r81d(io_si) = & - this%hvars(ih_totvegn_si)%r81d(io_si) + ccohort%n * & - total_m / m2_per_ha - if (ccohort%canopy_layer .eq. 1) then storen_canopy_scpf(i_scpf) = & storen_canopy_scpf(i_scpf) + ccohort%n * store_m @@ -2997,28 +3304,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) - this%hvars(ih_storep_si)%r81d(io_si) = & - this%hvars(ih_storep_si)%r81d(io_si) + ccohort%n * & - store_m / m2_per_ha - this%hvars(ih_storeptfrac_si)%r81d(io_si) = & - this%hvars(ih_storeptfrac_si)%r81d(io_si) + ccohort%n * & - store_max / m2_per_ha - this%hvars(ih_leafp_si)%r81d(io_si) = & - this%hvars(ih_leafp_si)%r81d(io_si) + ccohort%n * & - leaf_m / m2_per_ha - this%hvars(ih_fnrtp_si)%r81d(io_si) = & - this%hvars(ih_fnrtp_si)%r81d(io_si) + ccohort%n * & - fnrt_m / m2_per_ha - this%hvars(ih_reprop_si)%r81d(io_si) = & - this%hvars(ih_reprop_si)%r81d(io_si) + ccohort%n * & - repro_m / m2_per_ha - this%hvars(ih_sapwp_si)%r81d(io_si) = & - this%hvars(ih_sapwp_si)%r81d(io_si) + ccohort%n * & - sapw_m / m2_per_ha - this%hvars(ih_totvegp_si)%r81d(io_si) = & - this%hvars(ih_totvegp_si)%r81d(io_si)+ ccohort%n * & - total_m / m2_per_ha - if (ccohort%canopy_layer .eq. 1) then storep_canopy_scpf(i_scpf) = & storep_canopy_scpf(i_scpf) + ccohort%n * store_m @@ -3085,24 +3370,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) struct_m_net_alloc = ccohort%prt%GetNetAlloc(struct_organ, carbon12_element) * days_per_year repro_m_net_alloc = ccohort%prt%GetNetAlloc(repro_organ, carbon12_element) * days_per_year - ! ecosystem-level, organ-partitioned NPP/allocation fluxes - ! [kgC/yr] -> [kgC/sec] - hio_npp_leaf_si(io_si) = hio_npp_leaf_si(io_si) + & - leaf_m_net_alloc * n_perm2 / days_per_year / sec_per_day - hio_npp_seed_si(io_si) = hio_npp_seed_si(io_si) + & - repro_m_net_alloc * n_perm2 / days_per_year / sec_per_day - hio_npp_stem_si(io_si) = hio_npp_stem_si(io_si) + & - (sapw_m_net_alloc + struct_m_net_alloc) * n_perm2 * & - (prt_params%allom_agb_frac(ccohort%pft)) / & - days_per_year / sec_per_day - hio_npp_froot_si(io_si) = hio_npp_froot_si(io_si) + & - fnrt_m_net_alloc * n_perm2 / days_per_year / sec_per_day - hio_npp_croot_si(io_si) = hio_npp_croot_si(io_si) + & - (sapw_m_net_alloc + struct_m_net_alloc) * n_perm2 * & - (1._r8-prt_params%allom_agb_frac(ccohort%pft)) / & - days_per_year / sec_per_day - hio_npp_stor_si(io_si) = hio_npp_stor_si(io_si) + & - store_m_net_alloc * n_perm2 / days_per_year / sec_per_day + associate( scpf => ccohort%size_by_pft_class, & scls => ccohort%size_class, & @@ -3157,10 +3425,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_ddbh_si_scpf(io_si,scpf) = hio_ddbh_si_scpf(io_si,scpf) + & ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm - hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) + & - ccohort%height * & - 0.25_r8*pi_const*((dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha - end if ! mortality sums [#/m2] @@ -3360,8 +3624,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_lai_canopy_si_scpf(io_si,scpf) = hio_lai_canopy_si_scpf(io_si,scpf) + & ccohort%treelai*ccohort%c_area * AREA_INV - hio_canopy_biomass_si(io_si) = hio_canopy_biomass_si(io_si) + n_perm2 * total_m - !hio_mortality_canopy_si_scpf(io_si,scpf) = hio_mortality_canopy_si_scpf(io_si,scpf)+ & ! (ccohort%bmort + ccohort%hmort + ccohort%cmort + & ! ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n @@ -3405,20 +3667,6 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_m3_mortality_canopy_si_scls(io_si,scls) = hio_m3_mortality_canopy_si_scls(io_si,scls) + & ccohort%cmort * ccohort%n / m2_per_ha - hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & - total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & - ccohort%n * ha_per_m2 - - hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & - ccohort%c_area + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%c_area * sec_per_day * days_per_year - hio_carbon_balance_canopy_si_scls(io_si,scls) = hio_carbon_balance_canopy_si_scls(io_si,scls) + & ccohort%n * ccohort%npp_acc_hold / m2_per_ha / days_per_year / sec_per_day @@ -3485,8 +3733,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_yesterdaycanopylevel_canopy_si_scls(io_si,scls) + & ccohort%canopy_layer_yesterday * ccohort%n / m2_per_ha - hio_ca_weighted_height_si(io_si) = hio_ca_weighted_height_si(io_si) + & - ccohort%height * ccohort%c_area / m2_per_ha + else canlayer hio_nplant_understory_si_scag(io_si,iscag) = hio_nplant_understory_si_scag(io_si,iscag) + ccohort%n / m2_per_ha hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & @@ -3498,8 +3745,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) store_m * ccohort%n / m2_per_ha hio_bleaf_understory_si_scpf(io_si,scpf) = hio_bleaf_understory_si_scpf(io_si,scpf) + & leaf_m * ccohort%n / m2_per_ha - hio_understory_biomass_si(io_si) = hio_understory_biomass_si(io_si) + & - n_perm2 * total_m + hio_lai_understory_si_scpf(io_si,scpf) = hio_lai_understory_si_scpf(io_si,scpf) + & ccohort%treelai*ccohort%c_area * AREA_INV @@ -3519,7 +3765,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then hio_mortality_canopy_secondary_si_scls(io_si,scls) = hio_mortality_canopy_secondary_si_scls(io_si,scls) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n / m2_per_ha + & + ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha end if @@ -3555,19 +3801,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_m3_mortality_understory_si_scls(io_si,scls) = hio_m3_mortality_understory_si_scls(io_si,scls) + & ccohort%cmort * ccohort%n / m2_per_ha - hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & - total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & - ccohort%n * ha_per_m2 - - hio_understory_mortality_crownarea_si(io_si) = hio_understory_mortality_crownarea_si(io_si) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & - ccohort%c_area + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%c_area * sec_per_day * days_per_year + hio_carbon_balance_understory_si_scls(io_si,scls) = hio_carbon_balance_understory_si_scls(io_si,scls) + & ccohort%npp_acc_hold * ccohort%n / m2_per_ha / days_per_year / sec_per_day @@ -3675,21 +3909,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ccohort => ccohort%taller enddo cohortloop ! cohort loop - ! Patch specific variables that are already calculated - ! These things are all duplicated. Should they all be converted to LL or array structures RF? - ! define scalar to counteract the patch albedo scaling logic for conserved quantities - - ! Update Fire Variables - hio_spitfire_ros_si(io_si) = hio_spitfire_ros_si(io_si) + cpatch%ROS_front * cpatch%area * AREA_INV / sec_per_min - hio_effect_wspeed_si(io_si) = hio_effect_wspeed_si(io_si) + cpatch%effect_wspeed * cpatch%area * AREA_INV / sec_per_min - hio_tfc_ros_si(io_si) = hio_tfc_ros_si(io_si) + cpatch%TFC_ROS * cpatch%area * AREA_INV - hio_fire_intensity_si(io_si) = hio_fire_intensity_si(io_si) + cpatch%FI * cpatch%area * AREA_INV * J_per_kJ - hio_fire_area_si(io_si) = hio_fire_area_si(io_si) + cpatch%frac_burnt * cpatch%area * AREA_INV / sec_per_day - hio_fire_fuel_bulkd_si(io_si) = hio_fire_fuel_bulkd_si(io_si) + cpatch%fuel_bulkd * cpatch%area * AREA_INV - hio_fire_fuel_eff_moist_si(io_si) = hio_fire_fuel_eff_moist_si(io_si) + cpatch%fuel_eff_moist * cpatch%area * AREA_INV - hio_fire_fuel_sav_si(io_si) = hio_fire_fuel_sav_si(io_si) + cpatch%fuel_sav * cpatch%area * AREA_INV / m_per_cm - hio_fire_fuel_mef_si(io_si) = hio_fire_fuel_mef_si(io_si) + cpatch%fuel_mef * cpatch%area * AREA_INV - hio_sum_fuel_si(io_si) = hio_sum_fuel_si(io_si) + cpatch%sum_fuel * cpatch%area * AREA_INV + do ilyr = 1,sites(s)%nlevsoil hio_fragmentation_scaler_sl(io_si,ilyr) = hio_fragmentation_scaler_sl(io_si,ilyr) + cpatch%fragmentation_scaler(ilyr) * cpatch%area * AREA_INV @@ -3712,8 +3932,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end do - hio_fire_intensity_area_product_si(io_si) = hio_fire_intensity_area_product_si(io_si) + & - cpatch%FI * cpatch%frac_burnt * cpatch%area * AREA_INV * J_per_kJ + ! Update Litter Flux Variables @@ -3742,12 +3961,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end do patchloop !patch loop - ! divide basal-area-weighted height by basal area to get mean - if ( sum(hio_ba_si_scpf(io_si,:)) .gt. nearzero ) then - hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) / sum(hio_ba_si_scpf(io_si,:)) - else - hio_ba_weighted_height_si(io_si) = 0._r8 - endif + ! divide so-far-just-summed but to-be-averaged patch-age-class ! variables by patch-age-class area to get mean values @@ -4262,10 +4476,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! Normalize storage fractions and L2FR - if( this%hvars(ih_storectfrac_si)%r81d(io_si)>nearzero ) then - this%hvars(ih_storectfrac_si)%r81d(io_si) = this%hvars(ih_storec_si)%r81d(io_si) / & - this%hvars(ih_storectfrac_si)%r81d(io_si) - end if + do i_pft = 1, numpft do i_scls = 1,nlevsclass @@ -4288,10 +4499,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) do el = 1, num_elements if(element_list(el).eq.nitrogen_element)then - if( this%hvars(ih_storentfrac_si)%r81d(io_si)>nearzero ) then - this%hvars(ih_storentfrac_si)%r81d(io_si) = this%hvars(ih_storen_si)%r81d(io_si) / & - this%hvars(ih_storentfrac_si)%r81d(io_si) - end if + do i_pft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls @@ -4310,10 +4518,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end do end do elseif(element_list(el).eq.phosphorus_element)then - if( this%hvars(ih_storeptfrac_si)%r81d(io_si)>nearzero ) then - this%hvars(ih_storeptfrac_si)%r81d(io_si) = this%hvars(ih_storep_si)%r81d(io_si) / & - this%hvars(ih_storeptfrac_si)%r81d(io_si) - end if + do i_pft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (i_pft-1)*nlevsclass + i_scls @@ -4383,6 +4588,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end associate end associate + +end if if_dyn_lev0 + return end subroutine update_history_dyn @@ -8374,7 +8582,7 @@ subroutine define_history_vars(this, initialize_variables) long='total mass-balance error in kg per second by element', & use_default='active', avgflag='A', vtype=site_elem_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_err_fates_si) + index = ih_err_fates_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', & diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index d704ed696d..740fb1c111 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1438,7 +1438,10 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) hlm_use_sp = unset_int hlm_use_inventory_init = unset_int hlm_inventory_ctrl_file = 'unset' + hlm_hist_level_dynam = unset_int + hlm_hist_level_hifrq = unset_int + case('check_allset') if(hlm_numSWb .eq. unset_int) then @@ -1629,6 +1632,16 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if(hlm_hist_level_dynam .eq. unset_int) then + write(fates_log(), *) 'switch defining dynamics history level is unset, hlm_hist_level_dynam, exiting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + if(hlm_hist_level_hifrq .eq. unset_int) then + write(fates_log(), *) 'switch defining high-frequency history level is unset, hlm_hist_level_hifrq, exiting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + if(hlm_use_ch4 .eq. unset_int) then write(fates_log(), *) 'switch for the HLMs CH4 module unset: hlm_use_ch4, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1795,6 +1808,14 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_seeddisp_cadence= ',ival,' to FATES' end if + case('hist_dense_level') + hlm_hist_level_hifrq = ichar(cval(1)) + hlm_hist_level_dynam = ichar(cval(2)) + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_hist_dense_level= ',cval,' to FATES' + end if + + case('spitfire_mode') hlm_spitfire_mode = ival if (fates_global_verbose()) then diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 3b0878e50e..84958a3ecd 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -197,6 +197,19 @@ module FatesInterfaceTypesMod integer, public :: hlm_use_sp ! Flag to use FATES satellite phenology (LAI) mode ! 1 = TRUE, 0 = FALSE + + ! Flag specifying what types of history fields to allocate and prepare + ! The "_dynam" refers to history fields that can be updated on the dynamics (daily) step + ! THe "_hifrq" refers to history fields that can be updated on the model (high-frequency) step + ! 0 = no output + ! 1 = site-level averages only + ! 2 = allow the second dimension, but nothing multi-plexed + ! 3 = allow the second dimension and include everything, including multiplexed + + integer, public :: hlm_hist_level_dynam + + integer, public :: hlm_hist_level_hifrq + ! ------------------------------------------------------------------------------------- ! Parameters that are dictated by FATES and known to be required knowledge ! needed by the HLMs From 401bdd8a4646a3af7ad00d95e969bca2f30e2faa Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Fri, 10 Nov 2023 09:54:10 -0800 Subject: [PATCH 060/300] changing shape of albedo arrays to avoid crash on restart reads --- main/FatesInterfaceMod.F90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 99d7ef56d3..9cc564a8f5 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -611,13 +611,13 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) allocate(bc_out%rssha_pa(maxpatch_total)) ! Canopy Radiation - allocate(bc_out%albd_parb(maxpatch_total,hlm_numSWb)) - allocate(bc_out%albi_parb(maxpatch_total,hlm_numSWb)) - allocate(bc_out%fabd_parb(maxpatch_total,hlm_numSWb)) - allocate(bc_out%fabi_parb(maxpatch_total,hlm_numSWb)) - allocate(bc_out%ftdd_parb(maxpatch_total,hlm_numSWb)) - allocate(bc_out%ftid_parb(maxpatch_total,hlm_numSWb)) - allocate(bc_out%ftii_parb(maxpatch_total,hlm_numSWb)) + allocate(bc_out%albd_parb(fates_maxPatchesPerSite,hlm_numSWb)) + allocate(bc_out%albi_parb(fates_maxPatchesPerSite,hlm_numSWb)) + allocate(bc_out%fabd_parb(fates_maxPatchesPerSite,hlm_numSWb)) + allocate(bc_out%fabi_parb(fates_maxPatchesPerSite,hlm_numSWb)) + allocate(bc_out%ftdd_parb(fates_maxPatchesPerSite,hlm_numSWb)) + allocate(bc_out%ftid_parb(fates_maxPatchesPerSite,hlm_numSWb)) + allocate(bc_out%ftii_parb(fates_maxPatchesPerSite,hlm_numSWb)) ! We allocate the boundary conditions to the BGC From 7045b6a149358b2292578c917847e66a33a9e979 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sat, 11 Nov 2023 13:53:34 -0500 Subject: [PATCH 061/300] incremental progress towards splitting history --- main/FatesHistoryInterfaceMod.F90 | 402 ++++++++++++++++-------------- 1 file changed, 218 insertions(+), 184 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index be94ab7a3d..534044d4d1 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -25,7 +25,6 @@ module FatesHistoryInterfaceMod use EDtypesMod , only : AREA_INV use EDTypesMod , only : numWaterMem use EDTypesMod , only : num_vegtemp_mem - use EDTypesMod , only : site_massbal_type use PRTGenericMod , only : element_list use FatesIOVariableKindMod , only : upfreq_hifr_multi use FatesConstantsMod , only : N_DIST_TYPES @@ -2142,20 +2141,16 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) type(ed_site_type) , intent(inout), target :: sites(nsites) type(bc_in_type) , intent(in) :: bc_in(nsites) ! Locals - type(litter_type), pointer :: litt_c ! Pointer to the carbon12 litter pool - type(litter_type), pointer :: litt ! Generic pointer to any litter pool + + type(site_fluxdiags_type), pointer :: flux_diags type(site_fluxdiags_type), pointer :: flux_diags_c - type(site_massbal_type), pointer :: site_mass integer :: s ! The local site index integer :: io_si ! The site index of the IO array integer :: ilyr ! Soil index for nlevsoil integer :: ipa, ipa2 ! The local "I"ndex of "PA"tches - integer :: lb1,ub1,lb2,ub2 ! IO array bounds for the calling thread - integer :: ivar ! index of IO variable object vector integer :: ft ! functional type index - integer :: cwd integer :: elcwd, elpft ! combined index of element and pft or cwd integer :: i_scpf,i_pft,i_scls ! iterators for scpf, pft, and scls dims integer :: i_cacls, i_capf ! iterators for cohort age and cohort age x pft @@ -2169,7 +2164,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in integer :: i_heightbin ! iterator for height bins integer :: el ! Loop index for elements - integer :: model_day_int ! Integer model day since simulation start + integer :: ageclass_since_anthrodist ! what is the equivalent age class for ! time-since-anthropogenic-disturbance of secondary forest @@ -2193,7 +2188,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8) :: alive_m ! Alive biomass (sap+leaf+fineroot+repro+storage) "" real(r8) :: total_m ! Total vegetation mass real(r8) :: repro_m ! Total reproductive mass (on plant) "" - real(r8) :: sapw_m_turnover + real(r8) :: sapw_m_turnover ! Sapwood turnover rate real(r8) :: store_m_turnover real(r8) :: leaf_m_turnover real(r8) :: fnrt_m_turnover @@ -2207,19 +2202,14 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8) :: area_frac real(r8) :: crown_depth - real(r8) :: storen_canopy_scpf(numpft*nlevsclass) - real(r8) :: storen_understory_scpf(numpft*nlevsclass) - real(r8) :: storep_canopy_scpf(numpft*nlevsclass) - real(r8) :: storep_understory_scpf(numpft*nlevsclass) - real(r8) :: storec_canopy_scpf(numpft*nlevsclass) - real(r8) :: storec_understory_scpf(numpft*nlevsclass) + integer :: return_code type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort - real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) + integer :: tmp @@ -2234,9 +2224,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) call update_history_dyn1(this,nc,nsites,sites,bc_in) if(hlm_hist_level_dynam>1) then call update_history_dyn2(this,nc,nsites,sites,bc_in) - if(hlm_hist_level_dynam>2) then - call update_history_dyn3(this,nc,nsites,sites,bc_in) - end if + !if(hlm_hist_level_dynam>2) then + ! call update_history_dyn3(this,nc,nsites,sites,bc_in) + !end if end if end if return @@ -2252,11 +2242,38 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) integer , intent(in) :: nsites type(ed_site_type) , intent(inout), target :: sites(nsites) type(bc_in_type) , intent(in) :: bc_in(nsites) - - real(r8) :: site_ba ! Site basal area used for weighting - real(r8) :: cohort_ba ! Cohort basal area - real(r8) :: site_ca ! Site crown area used for weighting - real(r8) :: store_max ! Maximum storage capacity for carbon and nutrients + + type(cohort_type), pointer :: ccohort + type(patch_type), pointer :: cpatch + integer :: s ! site counter + integer :: ipa ! patch index matching host model array space + integer :: io_si ! site's index in the history output array space + integer :: el ! element index + integer :: ft ! pft index + real(r8) :: site_ba ! Site basal area used for weighting + real(r8) :: cohort_ba ! Cohort basal area + real(r8) :: site_ca ! Site crown area used for weighting + real(r8) :: store_max ! Maximum storage capacity for carbon and nutrients + real(r8) :: sapw_m ! Sapwood mass (elemental, c,n or p) [kg/plant] + real(r8) :: struct_m ! Structural mass "" + real(r8) :: leaf_m ! Leaf mass "" + real(r8) :: fnrt_m ! Fineroot mass "" + real(r8) :: store_m ! Storage mass "" + real(r8) :: alive_m ! Alive biomass (sap+leaf+fineroot+repro+storage) "" + real(r8) :: total_m ! Total vegetation mass + real(r8) :: repro_m ! Total reproductive mass (on plant) "" + real(r8) :: sapw_m_turnover ! sapwood turnover rate [kg/yr] + real(r8) :: store_m_turnover ! storage turnover rate [kg/yr] + real(r8) :: leaf_m_turnover ! leaf turnover rate [kg/yr] + real(r8) :: fnrt_m_turnover ! fine-root turnover rate [kg/yr] + real(r8) :: struct_m_turnover ! structural turnover rate [kg/yr] + real(r8) :: sapw_m_net_alloc ! mass allocated to sapwood [kg/yr] + real(r8) :: store_m_net_alloc ! mass allocated to storage [kg/yr] + real(r8) :: leaf_m_net_alloc ! mass allocated to leaf [kg/yr] + real(r8) :: fnrt_m_net_alloc ! mass allocated to fine-root [kg/yr] + real(r8) :: struct_m_net_alloc ! mass allocated to structure [kg/yr] + real(r8) :: repro_m_net_alloc ! mass allocated to reproduction [kg/yr] + real(r8) :: n_perm2 ! abundance per m2 associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & @@ -2330,11 +2347,11 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_cleafoff_si => this%hvars(ih_cleafoff_si)%r81d, & hio_cleafon_si => this%hvars(ih_cleafon_si)%r81d, & hio_cbal_err_fates_si => this%hvars(ih_cbal_err_fates_si)%r81d, & - + hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & + hio_tlongterm => this%hvars(ih_tlongterm_si)%r81d, & + hio_tgrowth => this%hvars(ih_tgrowth_si)%r81d, & hio_lai_si => this%hvars(ih_lai_si)%r81d ) - - model_day_int = nint(hlm_model_day) ! --------------------------------------------------------------------------------- ! Loop through the FATES scale hierarchy and fill the history IO arrays @@ -2347,7 +2364,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) site_ba = 0._r8 site_ca = 0._r8 - flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) + ! set the fates fraction to one, since it is zero on non-fates columns, & ! the average is the total gridcell fates fraction hio_fates_fraction_si(io_si) = 1._r8 @@ -2414,6 +2431,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) this%hvars(ih_h2oveg_recruit_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_recruit this%hvars(ih_h2oveg_growturn_err_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_growturn_err end if + hio_harvest_debt_si(io_si) = sites(s)%resources_management%harvest_debt hio_harvest_debt_sec_si(io_si) = sites(s)%resources_management%harvest_debt_sec @@ -2458,6 +2476,18 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_lai_si(io_si) = hio_lai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%elai_profile(:,:,:) ) * & cpatch%total_canopy_area * AREA_INV + ! 24hr veg temperature + hio_tveg24(io_si) = hio_tveg24(io_si) + & + (cpatch%tveg24%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV + + ! long-term veg temperature + hio_tlongterm(io_si) = hio_tlongterm(io_si) + & + (cpatch%tveg_longterm%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV + + ! long-term running mean veg temperature (tgrowth) + hio_tgrowth(io_si) = hio_tgrowth(io_si) + & + (cpatch%tveg_lpa%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV + ! some diagnostics on secondary forest area and its age distribution if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then hio_fraction_secondary_forest_si(io_si) = hio_fraction_secondary_forest_si(io_si) + & @@ -2496,7 +2526,6 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_fire_intensity_area_product_si(io_si) = hio_fire_intensity_area_product_si(io_si) + & cpatch%FI * cpatch%frac_burnt * cpatch%area * AREA_INV * J_per_kJ - ! loop through cohorts on patch ccohort => cpatch%shortest @@ -2753,7 +2782,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) end if end if end do elloop2 - + end do siteloop end associate return @@ -2761,8 +2790,62 @@ end subroutine update_history_dyn1 ! ========================================================================================= - - hio_err_fates_elem => this%hvars(ih_err_fates_elem)%r82d, & + subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) + + ! Arguments + class(fates_history_interface_type) :: this + integer , intent(in) :: nc ! clump index + integer , intent(in) :: nsites + type(ed_site_type) , intent(inout), target :: sites(nsites) + type(bc_in_type) , intent(in) :: bc_in(nsites) + + type(cohort_type), pointer :: ccohort + type(patch_type), pointer :: cpatch + type(litter_type), pointer :: litt_c ! Pointer to the carbon12 litter pool + type(litter_type), pointer :: litt ! Generic pointer to any litter pool + integer :: s ! site counter + integer :: ipa ! patch index matching host model array space + integer :: io_si ! site's index in the history output array space + integer :: el ! element index + integer :: ft ! pft index + real(r8) :: site_ba ! Site basal area used for weighting + integer :: model_day_int ! Integer model day since simulation start + real(r8) :: store_max ! Maximum storage capacity for carbon and nutrients + real(r8) :: sapw_m ! Sapwood mass (elemental, c,n or p) [kg/plant] + real(r8) :: struct_m ! Structural mass "" + real(r8) :: leaf_m ! Leaf mass "" + real(r8) :: fnrt_m ! Fineroot mass "" + real(r8) :: store_m ! Storage mass "" + real(r8) :: alive_m ! Alive biomass (sap+leaf+fineroot+repro+storage) "" + real(r8) :: total_m ! Total vegetation mass + real(r8) :: repro_m ! Total reproductive mass (on plant) "" + real(r8) :: sapw_m_turnover ! sapwood turnover rate [kg/yr] + real(r8) :: store_m_turnover ! storage turnover rate [kg/yr] + real(r8) :: leaf_m_turnover ! leaf turnover rate [kg/yr] + real(r8) :: fnrt_m_turnover ! fine-root turnover rate [kg/yr] + real(r8) :: struct_m_turnover ! structural turnover rate [kg/yr] + real(r8) :: sapw_m_net_alloc ! mass allocated to sapwood [kg/yr] + real(r8) :: store_m_net_alloc ! mass allocated to storage [kg/yr] + real(r8) :: leaf_m_net_alloc ! mass allocated to leaf [kg/yr] + real(r8) :: fnrt_m_net_alloc ! mass allocated to fine-root [kg/yr] + real(r8) :: struct_m_net_alloc ! mass allocated to structure [kg/yr] + real(r8) :: repro_m_net_alloc ! mass allocated to reproduction [kg/yr] + real(r8) :: n_perm2 ! abundance per m2 + + real(r8) :: storen_canopy_scpf(numpft*nlevsclass) + real(r8) :: storen_understory_scpf(numpft*nlevsclass) + real(r8) :: storep_canopy_scpf(numpft*nlevsclass) + real(r8) :: storep_understory_scpf(numpft*nlevsclass) + real(r8) :: storec_canopy_scpf(numpft*nlevsclass) + real(r8) :: storec_understory_scpf(numpft*nlevsclass) + + type(site_fluxdiags_type), pointer :: flux_diags + type(site_fluxdiags_type), pointer :: flux_diags_c + + + real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) + + associate( hio_err_fates_elem => this%hvars(ih_err_fates_elem)%r82d, & hio_biomass_si_pft => this%hvars(ih_biomass_si_pft)%r82d, & hio_biomass_sec_si_pft => this%hvars(ih_biomass_sec_si_pft)%r82d, & hio_leafbiomass_si_pft => this%hvars(ih_leafbiomass_si_pft)%r82d, & @@ -2783,9 +2866,7 @@ end subroutine update_history_dyn1 hio_gpp_sec_si_pft => this%hvars(ih_gpp_sec_si_pft)%r82d, & hio_npp_si_pft => this%hvars(ih_npp_si_pft)%r82d, & hio_npp_sec_si_pft => this%hvars(ih_npp_sec_si_pft)%r82d, & - hio_fragmentation_scaler_sl => this%hvars(ih_fragmentation_scaler_sl)%r82d, & - hio_litter_in_elem => this%hvars(ih_litter_in_elem)%r82d, & hio_litter_out_elem => this%hvars(ih_litter_out_elem)%r82d, & hio_seed_bank_elem => this%hvars(ih_seed_bank_elem)%r82d, & @@ -2793,7 +2874,6 @@ end subroutine update_history_dyn1 hio_seed_in_extern_elem => this%hvars(ih_seeds_in_extern_elem)%r82d, & hio_seed_decay_elem => this%hvars(ih_seed_decay_elem)%r82d, & hio_seed_germ_elem => this%hvars(ih_seed_germ_elem)%r82d, & - hio_gpp_si_scpf => this%hvars(ih_gpp_si_scpf)%r82d, & hio_npp_totl_si_scpf => this%hvars(ih_npp_totl_si_scpf)%r82d, & hio_npp_leaf_si_scpf => this%hvars(ih_npp_leaf_si_scpf)%r82d, & @@ -2804,7 +2884,6 @@ end subroutine update_history_dyn1 hio_npp_agsw_si_scpf => this%hvars(ih_npp_agsw_si_scpf)%r82d, & hio_npp_agdw_si_scpf => this%hvars(ih_npp_agdw_si_scpf)%r82d, & hio_npp_stor_si_scpf => this%hvars(ih_npp_stor_si_scpf)%r82d, & - hio_bstor_canopy_si_scpf => this%hvars(ih_bstor_canopy_si_scpf)%r82d, & hio_bstor_understory_si_scpf => this%hvars(ih_bstor_understory_si_scpf)%r82d, & hio_bleaf_canopy_si_scpf => this%hvars(ih_bleaf_canopy_si_scpf)%r82d, & @@ -2818,7 +2897,6 @@ end subroutine update_history_dyn1 hio_m3_mortality_understory_si_scpf => this%hvars(ih_m3_mortality_understory_si_scpf)%r82d, & hio_m3_mortality_canopy_si_scls => this%hvars(ih_m3_mortality_canopy_si_scls)%r82d, & hio_m3_mortality_understory_si_scls => this%hvars(ih_m3_mortality_understory_si_scls)%r82d, & - hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & hio_nplant_understory_si_scpf => this%hvars(ih_nplant_understory_si_scpf)%r82d, & hio_ddbh_canopy_si_scpf => this%hvars(ih_ddbh_canopy_si_scpf)%r82d, & @@ -2836,7 +2914,6 @@ end subroutine update_history_dyn1 hio_agb_si_scpf => this%hvars(ih_agb_si_scpf)%r82d, & hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & hio_nplant_si_capf => this%hvars(ih_nplant_si_capf)%r82d, & - hio_m1_si_scpf => this%hvars(ih_m1_si_scpf)%r82d, & hio_m2_si_scpf => this%hvars(ih_m2_si_scpf)%r82d, & hio_m3_si_scpf => this%hvars(ih_m3_si_scpf)%r82d, & @@ -2848,16 +2925,11 @@ end subroutine update_history_dyn1 hio_m9_si_scpf => this%hvars(ih_m9_si_scpf)%r82d, & hio_m10_si_scpf => this%hvars(ih_m10_si_scpf)%r82d, & hio_m10_si_capf => this%hvars(ih_m10_si_capf)%r82d, & - hio_crownfiremort_si_scpf => this%hvars(ih_crownfiremort_si_scpf)%r82d, & hio_cambialfiremort_si_scpf => this%hvars(ih_cambialfiremort_si_scpf)%r82d, & - hio_abg_mortality_cflux_si_scpf => this%hvars(ih_abg_mortality_cflux_si_scpf)%r82d, & hio_abg_productivity_cflux_si_scpf => this%hvars(ih_abg_productivity_cflux_si_scpf)%r82d, & - - hio_burn_flux_elem => this%hvars(ih_burn_flux_elem)%r82d, & - hio_m1_si_scls => this%hvars(ih_m1_si_scls)%r82d, & hio_m2_si_scls => this%hvars(ih_m2_si_scls)%r82d, & hio_m3_si_scls => this%hvars(ih_m3_si_scls)%r82d, & @@ -2868,18 +2940,17 @@ end subroutine update_history_dyn1 hio_m8_si_scls => this%hvars(ih_m8_si_scls)%r82d, & hio_m9_si_scls => this%hvars(ih_m9_si_scls)%r82d, & hio_m10_si_scls => this%hvars(ih_m10_si_scls)%r82d, & - hio_m10_si_cacls => this%hvars(ih_m10_si_cacls)%r82d, & + hio_m10_si_cacls => this%hvars(ih_m10_si_cacls)%r82d) - hio_m1_sec_si_scls => this%hvars(ih_m1_sec_si_scls)%r82d, & + ! Break up associates for NAG compilers + associate(hio_m1_sec_si_scls => this%hvars(ih_m1_sec_si_scls)%r82d, & hio_m2_sec_si_scls => this%hvars(ih_m2_sec_si_scls)%r82d, & hio_m3_sec_si_scls => this%hvars(ih_m3_sec_si_scls)%r82d, & hio_m7_sec_si_scls => this%hvars(ih_m7_sec_si_scls)%r82d, & hio_m8_sec_si_scls => this%hvars(ih_m8_sec_si_scls)%r82d, & hio_m9_sec_si_scls => this%hvars(ih_m9_sec_si_scls)%r82d, & hio_m10_sec_si_scls => this%hvars(ih_m10_sec_si_scls)%r82d, & - hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & - hio_cwd_elcwd => this%hvars(ih_cwd_elcwd)%r82d, & hio_cwd_ag_elem => this%hvars(ih_cwd_ag_elem)%r82d, & hio_cwd_bg_elem => this%hvars(ih_cwd_bg_elem)%r82d, & @@ -2899,13 +2970,11 @@ end subroutine update_history_dyn1 hio_mortality_canopy_si_scls => this%hvars(ih_mortality_canopy_si_scls)%r82d, & hio_mortality_understory_si_scls => this%hvars(ih_mortality_understory_si_scls)%r82d, & hio_demotion_rate_si_scls => this%hvars(ih_demotion_rate_si_scls)%r82d, & - hio_promotion_rate_si_scls => this%hvars(ih_promotion_rate_si_scls)%r82d, & hio_trimming_canopy_si_scls => this%hvars(ih_trimming_canopy_si_scls)%r82d, & hio_trimming_understory_si_scls => this%hvars(ih_trimming_understory_si_scls)%r82d, & hio_crown_area_canopy_si_scls => this%hvars(ih_crown_area_canopy_si_scls)%r82d, & hio_crown_area_understory_si_scls => this%hvars(ih_crown_area_understory_si_scls)%r82d, & - hio_leaf_md_canopy_si_scls => this%hvars(ih_leaf_md_canopy_si_scls)%r82d, & hio_root_md_canopy_si_scls => this%hvars(ih_root_md_canopy_si_scls)%r82d, & hio_carbon_balance_canopy_si_scls => this%hvars(ih_carbon_balance_canopy_si_scls)%r82d, & @@ -2940,13 +3009,11 @@ end subroutine update_history_dyn1 hio_yesterdaycanopylevel_understory_si_scls => this%hvars(ih_yesterdaycanopylevel_understory_si_scls)%r82d, & hio_area_si_age => this%hvars(ih_area_si_age)%r82d, & hio_lai_si_age => this%hvars(ih_lai_si_age)%r82d, & - hio_canopy_area_si_age => this%hvars(ih_canopy_area_si_age)%r82d, & hio_ncl_si_age => this%hvars(ih_ncl_si_age)%r82d, & hio_npatches_si_age => this%hvars(ih_npatches_si_age)%r82d, & hio_zstar_si_age => this%hvars(ih_zstar_si_age)%r82d, & hio_biomass_si_age => this%hvars(ih_biomass_si_age)%r82d, & - hio_agesince_anthrodist_si_age => this%hvars(ih_agesince_anthrodist_si_age)%r82d, & hio_secondaryforest_area_si_age => this%hvars(ih_secondaryforest_area_si_age)%r82d, & hio_area_burnt_si_age => this%hvars(ih_area_burnt_si_age)%r82d, & @@ -2975,29 +3042,19 @@ end subroutine update_history_dyn1 hio_mortality_canopy_si_scag => this%hvars(ih_mortality_canopy_si_scag)%r82d, & hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d ) - ! Split up the associate statement as the nag compiler has a limit on line continuation - associate( - hio_site_dstatus_si_pft => this%hvars(ih_site_dstatus_si_pft)%r82d, & + ! Break up associates for NAG compilers + associate( hio_site_dstatus_si_pft => this%hvars(ih_site_dstatus_si_pft)%r82d, & hio_dleafoff_si_pft => this%hvars(ih_dleafoff_si_pft)%r82d, & hio_dleafon_si_pft => this%hvars(ih_dleafon_si_pft)%r82d, & hio_meanliqvol_si_pft => this%hvars(ih_meanliqvol_si_pft)%r82d, & hio_meansmp_si_pft => this%hvars(ih_meansmp_si_pft)%r82d, & hio_elong_factor_si_pft => this%hvars(ih_elong_factor_si_pft)%r82d, & - hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & - hio_tlongterm => this%hvars(ih_tlongterm_si)%r81d, & - hio_tgrowth => this%hvars(ih_tgrowth_si)%r81d, & - hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & 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_nplant_understory_si_scag => this%hvars(ih_nplant_understory_si_scag)%r82d ) model_day_int = nint(hlm_model_day) - - - ! --------------------------------------------------------------------------------- ! Loop through the FATES scale hierarchy and fill the history IO arrays @@ -3015,10 +3072,6 @@ end subroutine update_history_dyn1 storec_canopy_scpf(:) = 0._r8 storec_understory_scpf(:) = 0._r8 - flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) - - - do el = 1, num_elements ! Total model error [kg/day -> kg/s] (all elements) @@ -3031,40 +3084,36 @@ end subroutine update_history_dyn1 end do - - ! Update drought deciduous information (now separated by PFT). - do i_pft = 1,numpft + do ft = 1,numpft ! Update the site-PFT status for drought deciduous - hio_site_dstatus_si_pft(io_si,i_pft) = real(sites(s)%dstatus(i_pft),r8) + hio_site_dstatus_si_pft(io_si,ft) = real(sites(s)%dstatus(ft),r8) ! Model days elapsed since leaf off/on for drought deciduous - hio_dleafoff_si_pft(io_si,i_pft) = real(sites(s)%dndaysleafon (i_pft),r8) - hio_dleafon_si_pft(io_si,i_pft) = real(sites(s)%dndaysleafoff(i_pft),r8) + hio_dleafoff_si_pft(io_si,ft) = real(sites(s)%dndaysleafon (ft),r8) + hio_dleafon_si_pft(io_si,ft) = real(sites(s)%dndaysleafoff(ft),r8) ! Leaf elongation factor (0 means fully abscissed, 1 means fully flushed). - hio_elong_factor_si_pft(io_si,i_pft) = sites(s)%elong_factor(i_pft) + hio_elong_factor_si_pft(io_si,ft) = sites(s)%elong_factor(ft) if(model_day_int>numWaterMem)then ! Mean liquid water content (m3/m3) used for drought phenology - hio_meanliqvol_si_pft(io_si,i_pft) = & - sum(sites(s)%liqvol_memory(1:numWaterMem,i_pft))/real(numWaterMem,r8) + hio_meanliqvol_si_pft(io_si,ft) = & + sum(sites(s)%liqvol_memory(1:numWaterMem,ft))/real(numWaterMem,r8) ! Mean soil matric potential (Pa) used for drought phenology - hio_meansmp_si_pft(io_si,i_pft) = & - sum(sites(s)%smp_memory(1:numWaterMem,i_pft))/real(numWaterMem,r8) & + hio_meansmp_si_pft(io_si,ft) = & + sum(sites(s)%smp_memory(1:numWaterMem,ft))/real(numWaterMem,r8) & * dens_fresh_liquid_water * grav_earth * m_per_mm end if end do - ! Loop through patches to sum up diagonistics ipa = 0 cpatch => sites(s)%oldest_patch patchloop: do while(associated(cpatch)) - cpatch%age_class = get_age_class_index(cpatch%age) @@ -3073,18 +3122,6 @@ end subroutine update_history_dyn1 hio_area_si_age(io_si,cpatch%age_class) = hio_area_si_age(io_si,cpatch%age_class) & + cpatch%area * AREA_INV - ! 24hr veg temperature - hio_tveg24(io_si) = hio_tveg24(io_si) + & - (cpatch%tveg24%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV - - ! long-term veg temperature - hio_tlongterm(io_si) = hio_tlongterm(io_si) + & - (cpatch%tveg_longterm%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV - - ! long-term running mean veg temperature (tgrowth) - hio_tgrowth(io_si) = hio_tgrowth(io_si) + & - (cpatch%tveg_lpa%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV - ! Increment some patch-age-resolved diagnostics hio_lai_si_age(io_si,cpatch%age_class) = hio_lai_si_age(io_si,cpatch%age_class) & + sum(cpatch%tlai_profile(:,:,:)) * cpatch%area @@ -3117,24 +3154,24 @@ end subroutine update_history_dyn1 ! patch-age-resolved fire variables - do i_pft = 1,numpft + do ft = 1,numpft ! for scorch height, weight the value by patch area within any ! given age class - in the event that there is more than one ! patch per age class. - iagepft = cpatch%age_class + (i_pft-1) * nlevage + iagepft = cpatch%age_class + (ft-1) * nlevage hio_scorch_height_si_agepft(io_si,iagepft) = hio_scorch_height_si_agepft(io_si,iagepft) + & - cpatch%Scorch_ht(i_pft) * cpatch%area + cpatch%Scorch_ht(ft) * cpatch%area ! and also pft-labeled patch areas in the event that we are in nocomp mode - if ( hlm_use_nocomp .eq. itrue .and. cpatch%nocomp_pft_label .eq. i_pft) then - this%hvars(ih_nocomp_pftpatchfraction_si_pft)%r82d(io_si,i_pft) = & - this%hvars(ih_nocomp_pftpatchfraction_si_pft)%r82d(io_si,i_pft) + cpatch%area * AREA_INV + if ( hlm_use_nocomp .eq. itrue .and. cpatch%nocomp_pft_label .eq. ft) then + this%hvars(ih_nocomp_pftpatchfraction_si_pft)%r82d(io_si,ft) = & + this%hvars(ih_nocomp_pftpatchfraction_si_pft)%r82d(io_si,ft) + cpatch%area * AREA_INV - this%hvars(ih_nocomp_pftnpatches_si_pft)%r82d(io_si,i_pft) = & - this%hvars(ih_nocomp_pftnpatches_si_pft)%r82d(io_si,i_pft) + 1._r8 + this%hvars(ih_nocomp_pftnpatches_si_pft)%r82d(io_si,ft) = & + this%hvars(ih_nocomp_pftnpatches_si_pft)%r82d(io_si,ft) + 1._r8 - this%hvars(ih_nocomp_pftburnedarea_si_pft)%r82d(io_si,i_pft) = & - this%hvars(ih_nocomp_pftburnedarea_si_pft)%r82d(io_si,i_pft) + & + this%hvars(ih_nocomp_pftburnedarea_si_pft)%r82d(io_si,ft) = & + this%hvars(ih_nocomp_pftburnedarea_si_pft)%r82d(io_si,ft) + & cpatch%frac_burnt * cpatch%area * AREA_INV / sec_per_day endif @@ -3221,7 +3258,6 @@ end subroutine update_history_dyn1 fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) store_m = ccohort%prt%GetState(store_organ, element_list(el)) repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) - alive_m = leaf_m + fnrt_m + sapw_m total_m = alive_m + store_m + struct_m @@ -3335,8 +3371,6 @@ end subroutine update_history_dyn1 ! Site by Size-Class x PFT (SCPF) ! ------------------------------------------------------------------------ - dbh = ccohort%dbh !-0.5*(1./365.25)*ccohort%ddbhdt - ! Flux Variables (cohorts must had experienced a day before any of these values ! have any meaning, otherwise they are just inialization values notnew: if( .not.(ccohort%isnew) ) then @@ -3414,11 +3448,11 @@ end subroutine update_history_dyn1 ! basal area [m2/m2] hio_ba_si_scpf(io_si,scpf) = hio_ba_si_scpf(io_si,scpf) + & - 0.25_r8*pi_const*((dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha + 0.25_r8*pi_const*((ccohort%dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha ! also by size class only hio_ba_si_scls(io_si,scls) = hio_ba_si_scls(io_si,scls) + & - 0.25_r8*pi_const*((dbh/100.0_r8)**2.0_r8)* & + 0.25_r8*pi_const*((ccohort%dbh/100.0_r8)**2.0_r8)* & ccohort%n / m2_per_ha ! growth increment @@ -3969,8 +4003,8 @@ end subroutine update_history_dyn1 if (hio_area_si_age(io_si, ipa2) .gt. nearzero) then hio_lai_si_age(io_si, ipa2) = hio_lai_si_age(io_si, ipa2) / (hio_area_si_age(io_si, ipa2)*AREA) hio_ncl_si_age(io_si, ipa2) = hio_ncl_si_age(io_si, ipa2) / (hio_area_si_age(io_si, ipa2)*AREA) - do i_pft = 1, numpft - iagepft = ipa2 + (i_pft-1) * nlevage + do ft = 1, numpft + iagepft = ipa2 + (ft-1) * nlevage hio_scorch_height_si_agepft(io_si, iagepft) = & hio_scorch_height_si_agepft(io_si, iagepft) / (hio_area_si_age(io_si, ipa2)*AREA) enddo @@ -3989,91 +4023,91 @@ end subroutine update_history_dyn1 ! pass the cohort termination mortality as a flux to the history, and then reset the termination mortality buffer ! note there are various ways of reporting the total mortality, so pass to these as well - do i_pft = 1, numpft + do ft = 1, numpft do i_scls = 1,nlevsclass - i_scpf = (i_pft-1)*nlevsclass + i_scls + i_scpf = (ft-1)*nlevsclass + i_scls ! ! termination mortality. sum of canopy and understory indices - hio_m6_si_scpf(io_si,i_scpf) = (sites(s)%term_nindivs_canopy(i_scls,i_pft) + & - sites(s)%term_nindivs_ustory(i_scls,i_pft)) * & + hio_m6_si_scpf(io_si,i_scpf) = (sites(s)%term_nindivs_canopy(i_scls,ft) + & + sites(s)%term_nindivs_ustory(i_scls,ft)) * & days_per_year / m2_per_ha hio_m6_si_scls(io_si,i_scls) = hio_m6_si_scls(io_si,i_scls) + & - (sites(s)%term_nindivs_canopy(i_scls,i_pft) + & - sites(s)%term_nindivs_ustory(i_scls,i_pft)) * & + (sites(s)%term_nindivs_canopy(i_scls,ft) + & + sites(s)%term_nindivs_ustory(i_scls,ft)) * & days_per_year / m2_per_ha ! ! add termination mortality to canopy and understory mortality hio_mortality_canopy_si_scls(io_si,i_scls) = hio_mortality_canopy_si_scls(io_si,i_scls) + & - sites(s)%term_nindivs_canopy(i_scls,i_pft) * days_per_year / m2_per_ha + sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & - sites(s)%term_nindivs_ustory(i_scls,i_pft) * days_per_year / m2_per_ha + sites(s)%term_nindivs_ustory(i_scls,ft) * days_per_year / m2_per_ha hio_mortality_canopy_si_scpf(io_si,i_scpf) = hio_mortality_canopy_si_scpf(io_si,i_scpf) + & - sites(s)%term_nindivs_canopy(i_scls,i_pft) * days_per_year / m2_per_ha + sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & - sites(s)%term_nindivs_ustory(i_scls,i_pft) * days_per_year / m2_per_ha + sites(s)%term_nindivs_ustory(i_scls,ft) * days_per_year / m2_per_ha ! ! imort on its own - hio_m4_si_scpf(io_si,i_scpf) = sites(s)%imort_rate(i_scls, i_pft) / m2_per_ha - hio_m4_si_scls(io_si,i_scls) = hio_m4_si_scls(io_si,i_scls) + sites(s)%imort_rate(i_scls, i_pft) / m2_per_ha + hio_m4_si_scpf(io_si,i_scpf) = sites(s)%imort_rate(i_scls, ft) / m2_per_ha + hio_m4_si_scls(io_si,i_scls) = hio_m4_si_scls(io_si,i_scls) + sites(s)%imort_rate(i_scls, ft) / m2_per_ha ! ! add imort to other mortality terms. consider imort as understory mortality even if it happens in ! cohorts that may have been promoted as part of the patch creation, and use the pre-calculated site-level ! values to avoid biasing the results by the dramatically-reduced number densities in cohorts that are subject to imort hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & - sites(s)%imort_rate(i_scls, i_pft) / m2_per_ha + sites(s)%imort_rate(i_scls, ft) / m2_per_ha hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & - sites(s)%imort_rate(i_scls, i_pft) / m2_per_ha + sites(s)%imort_rate(i_scls, ft) / m2_per_ha ! iscag = i_scls ! since imort is by definition something that only happens in newly disturbed patches, treat as such hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & - sites(s)%imort_rate(i_scls, i_pft) / m2_per_ha + sites(s)%imort_rate(i_scls, ft) / m2_per_ha ! fire mortality from the site-level diagnostic rates - hio_m5_si_scpf(io_si,i_scpf) = (sites(s)%fmort_rate_canopy(i_scls, i_pft) + & - sites(s)%fmort_rate_ustory(i_scls, i_pft)) / m2_per_ha + hio_m5_si_scpf(io_si,i_scpf) = (sites(s)%fmort_rate_canopy(i_scls, ft) + & + sites(s)%fmort_rate_ustory(i_scls, ft)) / m2_per_ha hio_m5_si_scls(io_si,i_scls) = hio_m5_si_scls(io_si,i_scls) + & - (sites(s)%fmort_rate_canopy(i_scls, i_pft) + & - sites(s)%fmort_rate_ustory(i_scls, i_pft)) / m2_per_ha + (sites(s)%fmort_rate_canopy(i_scls, ft) + & + sites(s)%fmort_rate_ustory(i_scls, ft)) / m2_per_ha ! - hio_crownfiremort_si_scpf(io_si,i_scpf) = sites(s)%fmort_rate_crown(i_scls, i_pft) / m2_per_ha - hio_cambialfiremort_si_scpf(io_si,i_scpf) = sites(s)%fmort_rate_cambial(i_scls, i_pft) / m2_per_ha + hio_crownfiremort_si_scpf(io_si,i_scpf) = sites(s)%fmort_rate_crown(i_scls, ft) / m2_per_ha + hio_cambialfiremort_si_scpf(io_si,i_scpf) = sites(s)%fmort_rate_cambial(i_scls, ft) / m2_per_ha ! ! fire components of overall canopy and understory mortality hio_mortality_canopy_si_scpf(io_si,i_scpf) = hio_mortality_canopy_si_scpf(io_si,i_scpf) + & - sites(s)%fmort_rate_canopy(i_scls, i_pft) / m2_per_ha + sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha hio_mortality_canopy_si_scls(io_si,i_scls) = hio_mortality_canopy_si_scls(io_si,i_scls) + & - sites(s)%fmort_rate_canopy(i_scls, i_pft) / m2_per_ha + sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha ! Shijie: Think about how to add later? !if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then ! hio_mortality_canopy_secondary_si_scls(io_si,i_scls) = hio_mortality_canopy_secondary_si_scls(io_si,i_scls) + & - ! sites(s)%term_nindivs_canopy(i_scls,i_pft) * days_per_year / m2_per_ha + ! sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha !end if ! the fire mortality rates for each layer are total dead, since the usable ! output will then normalize by the counts, we are allowed to sum over layers hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & - sites(s)%fmort_rate_ustory(i_scls, i_pft) / m2_per_ha + sites(s)%fmort_rate_ustory(i_scls, ft) / m2_per_ha hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & - sites(s)%fmort_rate_ustory(i_scls, i_pft) / m2_per_ha + sites(s)%fmort_rate_ustory(i_scls, ft) / m2_per_ha ! ! for scag variables, also treat as happening in the newly-disurbed patch hio_mortality_canopy_si_scag(io_si,iscag) = hio_mortality_canopy_si_scag(io_si,iscag) + & - sites(s)%fmort_rate_canopy(i_scls, i_pft) / m2_per_ha + sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & - sites(s)%fmort_rate_ustory(i_scls, i_pft) / m2_per_ha + sites(s)%fmort_rate_ustory(i_scls, ft) / m2_per_ha ! while in this loop, pass the fusion-induced growth rate flux to history hio_growthflux_fusion_si_scpf(io_si,i_scpf) = hio_growthflux_fusion_si_scpf(io_si,i_scpf) + & - sites(s)%growthflux_fusion(i_scls, i_pft) * days_per_year / m2_per_ha + sites(s)%growthflux_fusion(i_scls, ft) * days_per_year / m2_per_ha end do end do @@ -4090,57 +4124,57 @@ end subroutine update_history_dyn1 hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & sum(sites(s)%imort_carbonflux(:)) - do i_pft = 1, numpft - hio_mortality_carbonflux_si_pft(io_si,i_pft) = hio_mortality_carbonflux_si_pft(io_si,i_pft) + & - (sites(s)%fmort_carbonflux_canopy(i_pft) + & - sites(s)%fmort_carbonflux_ustory(i_pft) ) / g_per_kg + & - sites(s)%imort_carbonflux(i_pft) + & - sites(s)%term_carbonflux_ustory(i_pft) * days_per_sec * ha_per_m2 + & - sites(s)%term_carbonflux_canopy(i_pft) * days_per_sec * ha_per_m2 + do ft = 1, numpft + hio_mortality_carbonflux_si_pft(io_si,ft) = hio_mortality_carbonflux_si_pft(io_si,ft) + & + (sites(s)%fmort_carbonflux_canopy(ft) + & + sites(s)%fmort_carbonflux_ustory(ft) ) / g_per_kg + & + sites(s)%imort_carbonflux(ft) + & + sites(s)%term_carbonflux_ustory(ft) * days_per_sec * ha_per_m2 + & + sites(s)%term_carbonflux_canopy(ft) * days_per_sec * ha_per_m2 - hio_firemortality_carbonflux_si_pft(io_si,i_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) / g_per_kg + hio_firemortality_carbonflux_si_pft(io_si,ft) = sites(s)%fmort_carbonflux_canopy(ft) / g_per_kg end do ! add imort and fmort to aboveground woody mortality - do i_pft = 1, numpft + do ft = 1, numpft do i_scls = 1,nlevsclass - i_scpf = (i_pft-1)*nlevsclass + i_scls + i_scpf = (ft-1)*nlevsclass + i_scls hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) = hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) + & - (sites(s)%fmort_abg_flux(i_scls,i_pft) / g_per_kg ) + & - sites(s)%imort_abg_flux(i_scls,i_pft) + & - (sites(s)%term_abg_flux(i_scls,i_pft) * days_per_sec * ha_per_m2 ) + (sites(s)%fmort_abg_flux(i_scls,ft) / g_per_kg ) + & + sites(s)%imort_abg_flux(i_scls,ft) + & + (sites(s)%term_abg_flux(i_scls,ft) * days_per_sec * ha_per_m2 ) end do end do if(hlm_use_tree_damage .eq. itrue) then - do i_pft = 1, numpft + do ft = 1, numpft do icdam = 1, nlevdamage do i_scls = 1,nlevsclass icdsc = (icdam-1)*nlevsclass + i_scls icdpf = (icdam-1)*nlevsclass + i_scls + & - (i_pft-1) * nlevsclass * nlevdamage + (ft-1) * nlevsclass * nlevdamage this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) = & this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) + & - ( (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, i_pft) * days_per_year) + & - (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, i_pft) * days_per_year) + & - sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) ) / m2_per_ha + ( (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, ft) * days_per_year) + & + (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, ft) * days_per_year) + & + sites(s)%imort_rate_damage(icdam, i_scls, ft) + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, ft) + & + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, ft) ) / m2_per_ha this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) + & - ( sites(s)%term_nindivs_canopy_damage(icdam,i_scls,i_pft) * days_per_year + & - sites(s)%fmort_rate_canopy_damage(icdam, i_scls, i_pft) )/ m2_per_ha + ( sites(s)%term_nindivs_canopy_damage(icdam,i_scls,ft) * days_per_year + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, ft) )/ m2_per_ha this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & - ( sites(s)%term_nindivs_ustory_damage(icdam, i_scls,i_pft) * days_per_year + & - sites(s)%imort_rate_damage(icdam, i_scls, i_pft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, i_pft) )/ m2_per_ha + ( sites(s)%term_nindivs_ustory_damage(icdam, i_scls,ft) * days_per_year + & + sites(s)%imort_rate_damage(icdam, i_scls, ft) + & + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, ft) )/ m2_per_ha end do end do @@ -4176,22 +4210,22 @@ end subroutine update_history_dyn1 sites(s)%crownarea_ustory_damage = 0._r8 ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer - do i_pft = 1, numpft + do ft = 1, numpft ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer - hio_recruitment_si_pft(io_si,i_pft) = sites(s)%recruitment_rate(i_pft) * days_per_year / m2_per_ha + hio_recruitment_si_pft(io_si,ft) = sites(s)%recruitment_rate(ft) * days_per_year / m2_per_ha ! Gridcell output and inputs - hio_seeds_out_gc_si_pft(io_si,i_pft) = sites(s)%seed_out(i_pft) - hio_seeds_in_gc_si_pft(io_si,i_pft) = sites(s)%seed_in(i_pft) + hio_seeds_out_gc_si_pft(io_si,ft) = sites(s)%seed_out(ft) + hio_seeds_in_gc_si_pft(io_si,ft) = sites(s)%seed_in(ft) end do sites(s)%recruitment_rate(:) = 0._r8 ! summarize all of the mortality fluxes by PFT - do i_pft = 1, numpft + do ft = 1, numpft do i_scls = 1,nlevsclass - i_scpf = (i_pft-1)*nlevsclass + i_scls + i_scpf = (ft-1)*nlevsclass + i_scls - hio_mortality_si_pft(io_si,i_pft) = hio_mortality_si_pft(io_si,i_pft) + & + hio_mortality_si_pft(io_si,ft) = hio_mortality_si_pft(io_si,ft) + & hio_m1_si_scpf(io_si,i_scpf) + & hio_m2_si_scpf(io_si,i_scpf) + & hio_m3_si_scpf(io_si,i_scpf) + & @@ -4204,7 +4238,7 @@ end subroutine update_history_dyn1 hio_m10_si_scpf(io_si,i_scpf) if(hlm_use_tree_damage .eq. itrue) then - hio_mortality_si_pft(io_si, i_pft) = hio_mortality_si_pft(io_si,i_pft) + & + hio_mortality_si_pft(io_si, ft) = hio_mortality_si_pft(io_si,ft) + & this%hvars(ih_m11_si_scpf)%r82d(io_si,i_scpf) end if @@ -4215,6 +4249,8 @@ end subroutine update_history_dyn1 ! Some carbon only litter diagnostics (legacy) ! ------------------------------------------------------------------------------ + flux_diags_c => sites(s)%flux_diags(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(:)) + & @@ -4478,9 +4514,9 @@ end subroutine update_history_dyn1 - do i_pft = 1, numpft + do ft = 1, numpft do i_scls = 1,nlevsclass - i_scpf = (i_pft-1)*nlevsclass + i_scls + i_scpf = (ft-1)*nlevsclass + i_scls if( this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) = & @@ -4500,9 +4536,9 @@ end subroutine update_history_dyn1 if(element_list(el).eq.nitrogen_element)then - do i_pft = 1, numpft + do ft = 1, numpft do i_scls = 1,nlevsclass - i_scpf = (i_pft-1)*nlevsclass + i_scls + i_scpf = (ft-1)*nlevsclass + i_scls if( this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & @@ -4519,9 +4555,9 @@ end subroutine update_history_dyn1 end do elseif(element_list(el).eq.phosphorus_element)then - do i_pft = 1, numpft + do ft = 1, numpft do i_scls = 1,nlevsclass - i_scpf = (i_pft-1)*nlevsclass + i_scls + i_scpf = (ft-1)*nlevsclass + i_scls if( this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) = & @@ -4586,13 +4622,11 @@ end subroutine update_history_dyn1 enddo siteloop ! site loop end associate - end associate - + end associate +end associate -end if if_dyn_lev0 - - return - end subroutine update_history_dyn +return +end subroutine update_history_dyn2 ! =============================================================================================== From 807e88abc5710a0f67813d7ace30c747b6777af1 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sun, 12 Nov 2023 12:55:01 -0500 Subject: [PATCH 062/300] incremental progress towards history splitting --- biogeochem/FatesPatchMod.F90 | 3 +- main/FatesHistoryInterfaceMod.F90 | 339 +++++++++++++++------------ main/FatesInterfaceMod.F90 | 13 +- radiation/FatesRadiationDriveMod.F90 | 8 +- 4 files changed, 204 insertions(+), 159 deletions(-) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index eae3e2fa7a..a7bc934173 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -454,7 +454,8 @@ subroutine ZeroValues(this) this%frac_burnt = 0.0_r8 this%tfc_ros = 0.0_r8 this%burnt_frac_litter(:) = 0.0_r8 - + this%solve_err(:) = 0._r8 + this%consv_err(:) = 0._r8 end subroutine ZeroValues !=========================================================================== diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 534044d4d1..d65359e5ec 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -44,6 +44,7 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod , only : hlm_freq_day use FatesInterfaceTypesMod , only : hlm_parteh_mode + use FatesInterfaceTypesMod , only : hio_include_hifr_multi use EDParamsMod , only : ED_val_comp_excln use EDParamsMod , only : ED_val_phen_coldtemp use EDParamsMod , only : nlevleaf @@ -2148,35 +2149,32 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) integer :: s ! The local site index integer :: io_si ! The site index of the IO array - integer :: ilyr ! Soil index for nlevsoil + integer :: ipa, ipa2 ! The local "I"ndex of "PA"tches integer :: ft ! functional type index integer :: elcwd, elpft ! combined index of element and pft or cwd integer :: i_scpf,i_pft,i_scls ! iterators for scpf, pft, and scls dims integer :: i_cacls, i_capf ! iterators for cohort age and cohort age x pft - integer :: i_cwd,i_fuel ! iterators for cwd and fuel dims - integer :: iscag ! size-class x age index - integer :: iscagpft ! size-class x age x pft index - integer :: iagepft ! age x pft index - integer :: i_agefuel ! age x fuel size class index - integer :: ican, ileaf, cnlf_indx ! iterators for leaf and canopy level - integer :: icdpf, icdsc, icdam, cdpf, cdsc ! iterators for the crown damage level - integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in - integer :: i_heightbin ! iterator for height bins + + + + + + + + integer :: el ! Loop index for elements - integer :: ageclass_since_anthrodist ! what is the equivalent age class for - ! time-since-anthropogenic-disturbance of secondary forest + real(r8) :: store_max ! The target nutrient mass for storage element of interest [kg] real(r8) :: n_perm2 ! individuals per m2 for the whole column real(r8) :: dbh ! diameter ("at breast height") real(r8) :: coage ! cohort age real(r8) :: npp_partition_error ! a check that the NPP partitions sum to carbon allocation - real(r8) :: frac_canopy_in_bin ! fraction of a leaf's canopy that is within a given height bin - real(r8) :: binbottom,bintop ! edges of height bins + - real(r8) :: gpp_cached ! variable used to cache gpp value in previous time step; for C13 discrimination + ! The following are all carbon states, turnover and net allocation flux variables ! the organs of relevance should be self explanatory @@ -2199,8 +2197,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) real(r8) :: fnrt_m_net_alloc real(r8) :: struct_m_net_alloc real(r8) :: repro_m_net_alloc - real(r8) :: area_frac - real(r8) :: crown_depth + @@ -2243,8 +2240,11 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) type(ed_site_type) , intent(inout), target :: sites(nsites) type(bc_in_type) , intent(in) :: bc_in(nsites) - type(cohort_type), pointer :: ccohort - type(patch_type), pointer :: cpatch + 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(litter_type), pointer :: litt ! Generic pointer to any litter pool + integer :: s ! site counter integer :: ipa ! patch index matching host model array space integer :: io_si ! site's index in the history output array space @@ -2274,6 +2274,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) real(r8) :: struct_m_net_alloc ! mass allocated to structure [kg/yr] real(r8) :: repro_m_net_alloc ! mass allocated to reproduction [kg/yr] real(r8) :: n_perm2 ! abundance per m2 + real(r8) :: area_frac ! Fraction of area for this patch associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & @@ -2311,7 +2312,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_balive_si => this%hvars(ih_balive_si)%r81d, & hio_agb_si => this%hvars(ih_agb_si)%r81d, & hio_canopy_biomass_si => this%hvars(ih_canopy_biomass_si)%r81d, & - hio_understory_biomass_si => this%hvars(ih_understory_biomass_si)%r81d, & + hio_ustory_biomass_si => this%hvars(ih_understory_biomass_si)%r81d, & hio_primaryland_fusion_error_si => this%hvars(ih_primaryland_fusion_error_si)%r81d, & hio_disturbance_rate_p2p_si => this%hvars(ih_disturbance_rate_p2p_si)%r81d, & hio_disturbance_rate_p2s_si => this%hvars(ih_disturbance_rate_p2s_si)%r81d, & @@ -2330,12 +2331,12 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_npp_croot_si => this%hvars(ih_npp_croot_si)%r81d, & hio_npp_stor_si => this%hvars(ih_npp_stor_si)%r81d, & hio_canopy_mortality_crownarea_si => this%hvars(ih_canopy_mortality_crownarea_si)%r81d, & - hio_understory_mortality_crownarea_si => this%hvars(ih_understory_mortality_crownarea_si)%r81d, & + hio_ustory_mortality_crownarea_si => this%hvars(ih_understory_mortality_crownarea_si)%r81d, & hio_fire_c_to_atm_si => this%hvars(ih_fire_c_to_atm_si)%r81d, & hio_demotion_carbonflux_si => this%hvars(ih_demotion_carbonflux_si)%r81d, & hio_promotion_carbonflux_si => this%hvars(ih_promotion_carbonflux_si)%r81d, & hio_canopy_mortality_carbonflux_si => this%hvars(ih_canopy_mortality_carbonflux_si)%r81d, & - hio_understory_mortality_carbonflux_si => this%hvars(ih_understory_mortality_carbonflux_si)%r81d, & + hio_ustory_mortality_carbonflux_si => this%hvars(ih_understory_mortality_carbonflux_si)%r81d, & hio_lai_secondary_si => this%hvars(ih_lai_secondary_si)%r81d, & hio_fraction_secondary_forest_si => this%hvars(ih_fraction_secondary_forest_si)%r81d, & hio_biomass_secondary_forest_si => this%hvars(ih_biomass_secondary_forest_si)%r81d, & @@ -2462,6 +2463,56 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_harvest_carbonflux_si(io_si) = sites(s)%mass_balance(element_pos(carbon12_element))%wood_product * AREA_INV + + ! carbon flux associated with mortality of trees dying by fire + hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & + sum(sites(s)%fmort_carbonflux_canopy(:)) / g_per_kg + + hio_ustory_mortality_carbonflux_si(io_si) = hio_ustory_mortality_carbonflux_si(io_si) + & + sum(sites(s)%fmort_carbonflux_ustory(:)) / g_per_kg + + ! treat carbon flux from imort the same way + hio_ustory_mortality_carbonflux_si(io_si) = hio_ustory_mortality_carbonflux_si(io_si) + & + sum(sites(s)%imort_carbonflux(:)) + + ! convert kg C / ha / day to kgc / m2 / sec + hio_demotion_carbonflux_si(io_si) = sites(s)%demotion_carbonflux * ha_per_m2 * days_per_sec + hio_promotion_carbonflux_si(io_si) = sites(s)%promotion_carbonflux * ha_per_m2 * days_per_sec + ! + ! mortality-associated carbon fluxes + + hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & + sum(sites(s)%term_carbonflux_canopy(:)) * days_per_sec * ha_per_m2 + + hio_ustory_mortality_carbonflux_si(io_si) = hio_ustory_mortality_carbonflux_si(io_si) + & + sum(sites(s)%term_carbonflux_ustory(:)) * days_per_sec * ha_per_m2 + + ! add site level mortality counting to crownarea diagnostic + hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & + sites(s)%fmort_crownarea_canopy + & + sites(s)%term_crownarea_canopy * days_per_year + + hio_ustory_mortality_crownarea_si(io_si) = hio_ustory_mortality_crownarea_si(io_si) + & + sites(s)%fmort_crownarea_ustory + & + sites(s)%term_crownarea_ustory * days_per_year + & + sites(s)%imort_crownarea + + flux_diags_c => sites(s)%flux_diags(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(:))) * & + AREA_INV * days_per_sec + + hio_litter_out_si(io_si) = 0._r8 + hio_seed_bank_si(io_si) = 0._r8 + hio_ungerm_seed_bank_si(io_si) = 0._r8 + hio_seedling_pool_si(io_si) = 0._r8 + hio_seeds_in_si(io_si) = 0._r8 + hio_seeds_in_local_si(io_si) = 0._r8 + + ! Loop through patches to sum up diagonistics ipa = 0 cpatch => sites(s)%oldest_patch @@ -2526,6 +2577,42 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_fire_intensity_area_product_si(io_si) = hio_fire_intensity_area_product_si(io_si) + & cpatch%FI * cpatch%frac_burnt * cpatch%area * AREA_INV * J_per_kJ + + litt => cpatch%litter(element_pos(carbon12_element)) + + area_frac = cpatch%area * AREA_INV + + ! Sum up all output fluxes (fragmentation) kgC/m2/day -> kgC/m2/s + hio_litter_out_si(io_si) = hio_litter_out_si(io_si) + & + (sum(litt%leaf_fines_frag(:)) + & + sum(litt%root_fines_frag(:,:)) + & + sum(litt%ag_cwd_frag(:)) + & + sum(litt%bg_cwd_frag(:,:)) + & + sum(litt%seed_decay(:)) + & + sum(litt%seed_germ_decay(:))) * & + area_frac * days_per_sec + + ! Sum up total seed bank (germinated and ungerminated) + hio_seed_bank_si(io_si) = hio_seed_bank_si(io_si) + & + (sum(litt%seed(:))+sum(litt%seed_germ(:))) * & + area_frac + + ! Sum up total seed bank (just ungerminated) + hio_ungerm_seed_bank_si(io_si) = hio_ungerm_seed_bank_si(io_si) + & + sum(litt%seed(:)) * area_frac + + ! Sum up total seedling pool + hio_seedling_pool_si(io_si) = hio_seedling_pool_si(io_si) + & + sum(litt%seed_germ(:)) * area_frac + + ! Sum up the input flux into the seed bank (local and external) + hio_seeds_in_si(io_si) = hio_seeds_in_si(io_si) + & + (sum(litt%seed_in_local(:)) + sum(litt%seed_in_extern(:))) * & + area_frac * days_per_sec + + hio_seeds_in_local_si(io_si) = hio_seeds_in_local_si(io_si) + & + sum(litt%seed_in_local(:)) * & + area_frac * days_per_sec ! loop through cohorts on patch ccohort => cpatch%shortest @@ -2756,6 +2843,14 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! Perform any necessary normalizations ! ---------------------------------------------------------------------------------------- + + ! divide secondary plant leaf area by secondary forest area to get the secondary forest LAI + if (hio_fraction_secondary_forest_si(io_si) .gt. nearzero) then + hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) / (hio_fraction_secondary_forest_si(io_si)*AREA) + else + hio_lai_secondary_si(io_si) = 0._r8 + end if + ! divide basal-area-weighted height by basal area to get mean if ( site_ba .gt. nearzero ) then @@ -2782,6 +2877,17 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) end if end if end do elloop2 + + + + + ! zero the site-level termination carbon flux variable + sites(s)%term_carbonflux_canopy(:) = 0._r8 + sites(s)%term_carbonflux_ustory(:) = 0._r8 + + + + end do siteloop end associate @@ -2799,12 +2905,12 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) type(ed_site_type) , intent(inout), target :: sites(nsites) type(bc_in_type) , intent(in) :: bc_in(nsites) - type(cohort_type), pointer :: ccohort - type(patch_type), pointer :: cpatch + type(fates_cohort_type), pointer :: ccohort + type(fates_patch_type), pointer :: cpatch type(litter_type), pointer :: litt_c ! Pointer to the carbon12 litter pool type(litter_type), pointer :: litt ! Generic pointer to any litter pool integer :: s ! site counter - integer :: ipa ! patch index matching host model array space + integer :: ipa,ipa2 ! patch index matching host model array space integer :: io_si ! site's index in the history output array space integer :: el ! element index integer :: ft ! pft index @@ -2831,7 +2937,26 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) real(r8) :: struct_m_net_alloc ! mass allocated to structure [kg/yr] real(r8) :: repro_m_net_alloc ! mass allocated to reproduction [kg/yr] real(r8) :: n_perm2 ! abundance per m2 - + integer :: ageclass_since_anthrodist ! what is the equivalent age class for + ! time-since-anthropogenic-disturbance of secondary forest + real(r8) :: area_frac ! Fraction of area for this patch + real(r8) :: frac_canopy_in_bin ! fraction of a leaf's canopy that is within a given height bin + real(r8) :: binbottom,bintop ! edges of height bins + integer :: height_bin_max, height_bin_min ! which height bin a given cohort's canopy is in + integer :: ican, ileaf, cnlf_indx ! iterators for leaf and canopy level + integer :: elcwd, i_cwd ! combined index of element and pft or cwd + integer :: i_scpf,i_pft,i_scls ! iterators for scpf, pft, and scls dims + integer :: i_cacls, i_capf ! iterators for cohort age and cohort age x pft + integer :: i_fuel ! iterators for fuel dims + integer :: i_heightbin ! iterator for height bins + integer :: iagepft ! age x pft index + integer :: ilyr ! Soil index for nlevsoil + integer :: iscag ! size-class x age index + integer :: iscagpft ! size-class x age x pft index + integer :: icdpf, icdsc, icdam ! iterators for the crown damage level + integer :: i_agefuel ! age x fuel size class index + real(r8) :: gpp_cached ! variable used to cache gpp value in previous time step; for C13 discrimination + real(r8) :: crown_depth ! Depth of the crown [m] real(r8) :: storen_canopy_scpf(numpft*nlevsclass) real(r8) :: storen_understory_scpf(numpft*nlevsclass) real(r8) :: storep_canopy_scpf(numpft*nlevsclass) @@ -3539,32 +3664,32 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! damage variables - cohort level if(hlm_use_tree_damage .eq. itrue) then - cdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) + icdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) - this%hvars(ih_mortality_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_mortality_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_mortality_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_si_cdpf)%r82d(io_si,icdpf) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha ! crown damage by size by pft - this%hvars(ih_nplant_si_cdpf)%r82d(io_si, cdpf) = & - this%hvars(ih_nplant_si_cdpf)%r82d(io_si, cdpf) + ccohort%n / m2_per_ha - this%hvars(ih_m3_si_cdpf)%r82d(io_si, cdpf) = & - this%hvars(ih_m3_si_cdpf)%r82d(io_si, cdpf) + & + this%hvars(ih_nplant_si_cdpf)%r82d(io_si, icdpf) = & + this%hvars(ih_nplant_si_cdpf)%r82d(io_si, icdpf) + ccohort%n / m2_per_ha + this%hvars(ih_m3_si_cdpf)%r82d(io_si, icdpf) = & + this%hvars(ih_m3_si_cdpf)%r82d(io_si, icdpf) + & ccohort%cmort * ccohort%n / m2_per_ha ! mortality this%hvars(ih_m11_si_scpf)%r82d(io_si,scpf) = & this%hvars(ih_m11_si_scpf)%r82d(io_si,scpf) + & ccohort%dgmort*ccohort%n / m2_per_ha - this%hvars(ih_m11_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_m11_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_m11_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m11_si_cdpf)%r82d(io_si,icdpf) + & ccohort%dgmort*ccohort%n / m2_per_ha - this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,icdpf) + & ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm end if @@ -3708,30 +3833,30 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) if(hlm_use_tree_damage .eq. itrue) then ! carbon starvation mortality in the canopy by size x damage x pft - this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,cdpf)+& + this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,icdpf)+& ccohort%cmort * ccohort%n / m2_per_ha ! damage mortality in the canopy by size x damage x pft - this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,cdpf)+& + this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,icdpf)+& ccohort%dgmort * ccohort%n / m2_per_ha - this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,cdpf)+ & + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf)+ & (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + ccohort%smort + & ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha ! nplants by damage - this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,icdpf) + & ccohort%n / m2_per_ha ! growth rate by damage x size x pft in the canopy - this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,icdpf) + & ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm end if ! end if damage @@ -3844,30 +3969,30 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) if(hlm_use_tree_damage .eq. itrue) then ! carbon mortality in the understory by damage x size x pft - this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & ccohort%cmort * ccohort%n / m2_per_ha ! damage in the understory by damage x size x pft - this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & ccohort%dgmort * ccohort%n / m2_per_ha ! total mortality of understory cohorts by damage x size x pft - this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%n * sec_per_day * days_per_year / m2_per_ha - this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,icdpf) + & ccohort%n / m2_per_ha ! growth rate by size x damage x pft - understory - this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,cdpf) = & - this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,cdpf) + & + this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,icdpf) + & ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm end if ! end if damage @@ -4014,12 +4139,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) endif end do - ! divide secondary plant leaf area by secondary forest area to get the secondary forest LAI - if (hio_fraction_secondary_forest_si(io_si) .gt. nearzero) then - hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) / (hio_fraction_secondary_forest_si(io_si)*AREA) - else - hio_lai_secondary_si(io_si) = 0._r8 - end if + ! pass the cohort termination mortality as a flux to the history, and then reset the termination mortality buffer ! note there are various ways of reporting the total mortality, so pass to these as well @@ -4112,17 +4232,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) end do end do - ! - ! carbon flux associated with mortality of trees dying by fire - hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & - sum(sites(s)%fmort_carbonflux_canopy(:)) / g_per_kg - - hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sum(sites(s)%fmort_carbonflux_ustory(:)) / g_per_kg - - ! treat carbon flux from imort the same way - hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sum(sites(s)%imort_carbonflux(:)) + do ft = 1, numpft hio_mortality_carbonflux_si_pft(io_si,ft) = hio_mortality_carbonflux_si_pft(io_si,ft) + & @@ -4250,58 +4360,13 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! ------------------------------------------------------------------------------ flux_diags_c => sites(s)%flux_diags(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(:))) * & - AREA_INV * days_per_sec - - hio_litter_out_si(io_si) = 0._r8 - hio_seed_bank_si(io_si) = 0._r8 - hio_ungerm_seed_bank_si(io_si) = 0._r8 - hio_seedling_pool_si(io_si) = 0._r8 - hio_seeds_in_si(io_si) = 0._r8 - hio_seeds_in_local_si(io_si) = 0._r8 cpatch => sites(s)%oldest_patch do while(associated(cpatch)) - litt => cpatch%litter(element_pos(carbon12_element)) - - area_frac = cpatch%area * AREA_INV - - ! Sum up all output fluxes (fragmentation) kgC/m2/day -> kgC/m2/s - hio_litter_out_si(io_si) = hio_litter_out_si(io_si) + & - (sum(litt%leaf_fines_frag(:)) + & - sum(litt%root_fines_frag(:,:)) + & - sum(litt%ag_cwd_frag(:)) + & - sum(litt%bg_cwd_frag(:,:)) + & - sum(litt%seed_decay(:)) + & - sum(litt%seed_germ_decay(:))) * & - area_frac * days_per_sec - - ! Sum up total seed bank (germinated and ungerminated) - hio_seed_bank_si(io_si) = hio_seed_bank_si(io_si) + & - (sum(litt%seed(:))+sum(litt%seed_germ(:))) * & - area_frac - - ! Sum up total seed bank (just ungerminated) - hio_ungerm_seed_bank_si(io_si) = hio_ungerm_seed_bank_si(io_si) + & - sum(litt%seed(:)) * area_frac - - ! Sum up total seedling pool - hio_seedling_pool_si(io_si) = hio_seedling_pool_si(io_si) + & - sum(litt%seed_germ(:)) * area_frac - - ! Sum up the input flux into the seed bank (local and external) - hio_seeds_in_si(io_si) = hio_seeds_in_si(io_si) + & - (sum(litt%seed_in_local(:)) + sum(litt%seed_in_extern(:))) * & - area_frac * days_per_sec - - hio_seeds_in_local_si(io_si) = hio_seeds_in_local_si(io_si) + & - sum(litt%seed_in_local(:)) * & - area_frac * days_per_sec + @@ -4411,10 +4476,10 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_fines_bg_elem(io_si,el) = hio_fines_bg_elem(io_si,el) + & sum(litt%root_fines(:,:)) * cpatch%area / m2_per_ha - do cwd=1,ncwd - elcwd = (el-1)*ncwd+cwd + do i_cwd=1,ncwd + elcwd = (el-1)*ncwd+i_cwd hio_cwd_elcwd(io_si,elcwd) = hio_cwd_elcwd(io_si,elcwd) + & - (litt%ag_cwd(cwd) + sum(litt%bg_cwd(cwd,:))) * & + (litt%ag_cwd(i_cwd) + sum(litt%bg_cwd(i_cwd,:))) * & cpatch%area / m2_per_ha end do @@ -4581,31 +4646,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_promotion_rate_si_scls(io_si,i_scls) = sites(s)%promotion_rate(i_scls) * days_per_year / m2_per_ha end do ! - ! convert kg C / ha / day to kgc / m2 / sec - hio_demotion_carbonflux_si(io_si) = sites(s)%demotion_carbonflux * ha_per_m2 * days_per_sec - hio_promotion_carbonflux_si(io_si) = sites(s)%promotion_carbonflux * ha_per_m2 * days_per_sec - ! - ! mortality-associated carbon fluxes - - hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & - sum(sites(s)%term_carbonflux_canopy(:)) * days_per_sec * ha_per_m2 - - hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sum(sites(s)%term_carbonflux_ustory(:)) * days_per_sec * ha_per_m2 - - ! add site level mortality counting to crownarea diagnostic - hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & - sites(s)%fmort_crownarea_canopy + & - sites(s)%term_crownarea_canopy * days_per_year - - hio_understory_mortality_crownarea_si(io_si) = hio_understory_mortality_crownarea_si(io_si) + & - sites(s)%fmort_crownarea_ustory + & - sites(s)%term_crownarea_ustory * days_per_year + & - sites(s)%imort_crownarea - - ! and zero the site-level termination carbon flux variable - sites(s)%term_carbonflux_canopy(:) = 0._r8 - sites(s)%term_carbonflux_ustory(:) = 0._r8 + ! ! add the site-level disturbance-associated cwd and litter input fluxes to thir respective flux fields diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 740fb1c111..d5a51fe9a0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1808,12 +1808,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_seeddisp_cadence= ',ival,' to FATES' end if - case('hist_dense_level') - hlm_hist_level_hifrq = ichar(cval(1)) - hlm_hist_level_dynam = ichar(cval(2)) - if (fates_global_verbose()) then - write(fates_log(),*) 'Transfering hlm_hist_dense_level= ',cval,' to FATES' - end if + case('spitfire_mode') @@ -1935,6 +1930,12 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) if(present(cval))then select case (trim(tag)) + + case('hist_dense_level') + read(cval,'(I1,I1)') hlm_hist_level_hifrq,hlm_hist_level_dynam + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_hist_dense_level= ',trim(cval) + end if case('hlm_name') hlm_name = trim(cval) diff --git a/radiation/FatesRadiationDriveMod.F90 b/radiation/FatesRadiationDriveMod.F90 index bfe76a3221..6c71e493a5 100644 --- a/radiation/FatesRadiationDriveMod.F90 +++ b/radiation/FatesRadiationDriveMod.F90 @@ -1206,9 +1206,7 @@ subroutine FatesSunShadeFracs(nsites, sites,bc_in,bc_out) cpatch%ed_parsha_z(:,:,:) = 0._r8 cpatch%parprof_pft_dir_z(:,:,:) = 0._r8 cpatch%parprof_pft_dif_z(:,:,:) = 0._r8 - bc_out(s)%fsun_pa(ifp) = 0._r8 - bc_out(s)%laisun_pa(ifp) = 0._r8 - bc_out(s)%laisha_pa(ifp) = calc_areaindex(cpatch,'elai') + if_notbareground:if(cpatch%nocomp_pft_label.ne.nocomp_bareground)then !only for veg patches ! do not do albedo calculations for bare ground patch in SP mode @@ -1216,6 +1214,10 @@ subroutine FatesSunShadeFracs(nsites, sites,bc_in,bc_out) ! ifp=1 is the first vegetated patch. ifp=ifp+1 + bc_out(s)%fsun_pa(ifp) = 0._r8 + bc_out(s)%laisun_pa(ifp) = 0._r8 + bc_out(s)%laisha_pa(ifp) = calc_areaindex(cpatch,'elai') + ! If there is no sun out, we have a trivial solution if_zenithflag: if(cpatch%solar_zenith_flag ) then From 007380a824e6e6874ec448d5ec87fdd9abfdf5d4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 13 Nov 2023 10:20:45 -0500 Subject: [PATCH 063/300] incremental progress towards split history --- main/FatesHistoryInterfaceMod.F90 | 4705 +++++++++++++++-------------- 1 file changed, 2365 insertions(+), 2340 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index d65359e5ec..bb661ddd3e 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5492,68 +5492,75 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) if(hlm_use_planthydro.eq.ifalse) return + ! Flush the relevant history variables + call this%flush_hvars(nc,upfreq_in=4) + + per_dt_tstep = 1._r8 / dt_tstep + + if(hlm_hist_level_hifrq>0) then - associate( hio_errh2o_scpf => this%hvars(ih_errh2o_scpf)%r82d, & - hio_tran_scpf => this%hvars(ih_tran_scpf)%r82d, & - hio_sapflow_scpf => this%hvars(ih_sapflow_scpf)%r82d, & - hio_sapflow_si => this%hvars(ih_sapflow_si)%r81d, & - hio_iterh1_scpf => this%hvars(ih_iterh1_scpf)%r82d, & - hio_iterh2_scpf => this%hvars(ih_iterh2_scpf)%r82d, & - hio_ath_scpf => this%hvars(ih_ath_scpf)%r82d, & - hio_tth_scpf => this%hvars(ih_tth_scpf)%r82d, & - hio_sth_scpf => this%hvars(ih_sth_scpf)%r82d, & - hio_lth_scpf => this%hvars(ih_lth_scpf)%r82d, & - hio_awp_scpf => this%hvars(ih_awp_scpf)%r82d, & - hio_twp_scpf => this%hvars(ih_twp_scpf)%r82d, & - hio_swp_scpf => this%hvars(ih_swp_scpf)%r82d, & - hio_lwp_scpf => this%hvars(ih_lwp_scpf)%r82d, & - hio_aflc_scpf => this%hvars(ih_aflc_scpf)%r82d, & - hio_tflc_scpf => this%hvars(ih_tflc_scpf)%r82d, & - hio_sflc_scpf => this%hvars(ih_sflc_scpf)%r82d, & - hio_lflc_scpf => this%hvars(ih_lflc_scpf)%r82d, & - hio_btran_scpf => this%hvars(ih_btran_scpf)%r82d, & - hio_h2oveg_si => this%hvars(ih_h2oveg_si)%r81d, & - hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & - hio_nplant_si_capf => this%hvars(ih_nplant_si_capf)%r82d, & - hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d, & - hio_rootwgt_soilvwc_si => this%hvars(ih_rootwgt_soilvwc_si)%r81d, & - hio_rootwgt_soilvwcsat_si => this%hvars(ih_rootwgt_soilvwcsat_si)%r81d, & - hio_rootwgt_soilmatpot_si => this%hvars(ih_rootwgt_soilmatpot_si)%r81d, & - hio_soilmatpot_sl => this%hvars(ih_soilmatpot_sl)%r82d, & - hio_soilvwc_sl => this%hvars(ih_soilvwc_sl)%r82d, & - hio_soilvwcsat_sl => this%hvars(ih_soilvwcsat_sl)%r82d, & - hio_rootuptake_si => this%hvars(ih_rootuptake_si)%r81d, & - hio_rootuptake_sl => this%hvars(ih_rootuptake_sl)%r82d, & - hio_rootuptake0_scpf => this%hvars(ih_rootuptake0_scpf)%r82d, & - hio_rootuptake10_scpf => this%hvars(ih_rootuptake10_scpf)%r82d, & - hio_rootuptake50_scpf => this%hvars(ih_rootuptake50_scpf)%r82d, & - hio_rootuptake100_scpf => this%hvars(ih_rootuptake100_scpf)%r82d ) - - ! Flush the relevant history variables - call this%flush_hvars(nc,upfreq_in=4) + + associate( hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d, & + hio_rootwgt_soilvwc_si => this%hvars(ih_rootwgt_soilvwc_si)%r81d, & + hio_rootwgt_soilvwcsat_si => this%hvars(ih_rootwgt_soilvwcsat_si)%r81d, & + hio_rootwgt_soilmatpot_si => this%hvars(ih_rootwgt_soilmatpot_si)%r81d, & + hio_sapflow_si => this%hvars(ih_sapflow_si)%r81d, & + hio_rootuptake_si => this%hvars(ih_rootuptake_si)%r81d ) + + associate( hio_errh2o_scpf => this%hvars(ih_errh2o_scpf)%r82d, & + hio_tran_scpf => this%hvars(ih_tran_scpf)%r82d, & + hio_sapflow_scpf => this%hvars(ih_sapflow_scpf)%r82d, & + hio_iterh1_scpf => this%hvars(ih_iterh1_scpf)%r82d, & + hio_iterh2_scpf => this%hvars(ih_iterh2_scpf)%r82d, & + hio_ath_scpf => this%hvars(ih_ath_scpf)%r82d, & + hio_tth_scpf => this%hvars(ih_tth_scpf)%r82d, & + hio_sth_scpf => this%hvars(ih_sth_scpf)%r82d, & + hio_lth_scpf => this%hvars(ih_lth_scpf)%r82d, & + hio_awp_scpf => this%hvars(ih_awp_scpf)%r82d, & + hio_twp_scpf => this%hvars(ih_twp_scpf)%r82d, & + hio_swp_scpf => this%hvars(ih_swp_scpf)%r82d, & + hio_lwp_scpf => this%hvars(ih_lwp_scpf)%r82d, & + hio_aflc_scpf => this%hvars(ih_aflc_scpf)%r82d, & + hio_tflc_scpf => this%hvars(ih_tflc_scpf)%r82d, & + hio_sflc_scpf => this%hvars(ih_sflc_scpf)%r82d, & + hio_lflc_scpf => this%hvars(ih_lflc_scpf)%r82d, & + hio_btran_scpf => this%hvars(ih_btran_scpf)%r82d, & + hio_h2oveg_si => this%hvars(ih_h2oveg_si)%r81d, & + hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & + hio_nplant_si_capf => this%hvars(ih_nplant_si_capf)%r82d, & + hio_soilmatpot_sl => this%hvars(ih_soilmatpot_sl)%r82d, & + hio_soilvwc_sl => this%hvars(ih_soilvwc_sl)%r82d, & + hio_soilvwcsat_sl => this%hvars(ih_soilvwcsat_sl)%r82d, & + hio_rootuptake_sl => this%hvars(ih_rootuptake_sl)%r82d, & + hio_rootuptake0_scpf => this%hvars(ih_rootuptake0_scpf)%r82d, & + hio_rootuptake10_scpf => this%hvars(ih_rootuptake10_scpf)%r82d, & + hio_rootuptake50_scpf => this%hvars(ih_rootuptake50_scpf)%r82d, & + hio_rootuptake100_scpf => this%hvars(ih_rootuptake100_scpf)%r82d ) + + if(print_iterations) then + do iscpf = 1,iterh2_nhist + iterh2_histx(iscpf) = iterh2_dx*real(iscpf-1,r8) + end do + end if + + do s = 1,nsites - per_dt_tstep = 1._r8 / dt_tstep - - if(print_iterations) then - do iscpf = 1,iterh2_nhist - iterh2_histx(iscpf) = iterh2_dx*real(iscpf-1,r8) - end do - end if - do s = 1,nsites + call this%zero_site_hvars(sites(s),upfreq_in=4) + + site_hydr => sites(s)%si_hydr + nlevrhiz = site_hydr%nlevrhiz + nlevsoil = bc_in(s)%nlevsoil + io_si = sites(s)%h_gid - call this%zero_site_hvars(sites(s),upfreq_in=4) + hio_h2oveg_si(io_si) = site_hydr%h2oveg + hio_h2oveg_hydro_err_si(io_si) = site_hydr%h2oveg_hydro_err + hio_rootuptake_si(io_si) = sum(site_hydr%rootuptake_sl,dim=1) - site_hydr => sites(s)%si_hydr - nlevrhiz = site_hydr%nlevrhiz - nlevsoil = bc_in(s)%nlevsoil - io_si = sites(s)%h_gid - hio_h2oveg_si(io_si) = site_hydr%h2oveg - hio_h2oveg_hydro_err_si(io_si) = site_hydr%h2oveg_hydro_err + if(hlm_hist_level_hifrq>1) then + hio_rootuptake_sl(io_si,1:nlevsoil) = site_hydr%rootuptake_sl(1:nlevsoil) + end if - hio_rootuptake_sl(io_si,1:nlevsoil) = site_hydr%rootuptake_sl(1:nlevsoil) - hio_rootuptake_si(io_si) = sum(site_hydr%rootuptake_sl,dim=1) - ! Get column means of some soil diagnostics, these are weighted ! by the amount of fine-root surface area in each layer ! -------------------------------------------------------------------- @@ -5593,14 +5600,16 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) mean_soil_vwc = mean_soil_vwc + vwc*layer_areaweight mean_soil_vwcsat = mean_soil_vwcsat + vwc_sat*layer_areaweight mean_soil_matpot = mean_soil_matpot + psi*layer_areaweight - - hio_soilmatpot_sl(io_si,j_bc) = psi * pa_per_mpa - hio_soilvwc_sl(io_si,j_bc) = vwc - hio_soilvwcsat_sl(io_si,j_bc) = vwc_sat - + + if(hlm_hist_level_hifrq>1) then + hio_soilmatpot_sl(io_si,j_bc) = psi * pa_per_mpa + hio_soilvwc_sl(io_si,j_bc) = vwc + hio_soilvwcsat_sl(io_si,j_bc) = vwc_sat + end if end do end do + hio_rootwgt_soilvwc_si(io_si) = mean_soil_vwc/areaweight hio_rootwgt_soilvwcsat_si(io_si) = mean_soil_vwcsat/areaweight hio_rootwgt_soilmatpot_si(io_si) = mean_soil_matpot/areaweight * pa_per_mpa @@ -5641,20 +5650,20 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) end do !patch loop end if - - do ipft = 1, numpft - do iscls = 1,nlevsclass - iscpf = (ipft-1)*nlevsclass + iscls - hio_sapflow_scpf(io_si,iscpf) = site_hydr%sapflow_scpf(iscls, ipft) * ha_per_m2 - hio_rootuptake0_scpf(io_si,iscpf) = site_hydr%rootuptake0_scpf(iscls,ipft) * ha_per_m2 - hio_rootuptake10_scpf(io_si,iscpf) = site_hydr%rootuptake10_scpf(iscls,ipft) * ha_per_m2 - hio_rootuptake50_scpf(io_si,iscpf) = site_hydr%rootuptake50_scpf(iscls,ipft) * ha_per_m2 - hio_rootuptake100_scpf(io_si,iscpf) = site_hydr%rootuptake100_scpf(iscls,ipft) * ha_per_m2 - hio_iterh1_scpf(io_si,iscpf) = 0._r8 - hio_iterh2_scpf(io_si,iscpf) = 0._r8 + if(hlm_hist_level_hifrq>1) then + do ipft = 1, numpft + do iscls = 1,nlevsclass + iscpf = (ipft-1)*nlevsclass + iscls + hio_sapflow_scpf(io_si,iscpf) = site_hydr%sapflow_scpf(iscls, ipft) * ha_per_m2 + hio_rootuptake0_scpf(io_si,iscpf) = site_hydr%rootuptake0_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake10_scpf(io_si,iscpf) = site_hydr%rootuptake10_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake50_scpf(io_si,iscpf) = site_hydr%rootuptake50_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake100_scpf(io_si,iscpf) = site_hydr%rootuptake100_scpf(iscls,ipft) * ha_per_m2 + hio_iterh1_scpf(io_si,iscpf) = 0._r8 + hio_iterh2_scpf(io_si,iscpf) = 0._r8 + end do end do - end do - + ipa = 0 cpatch => sites(s)%oldest_patch do while(associated(cpatch)) @@ -5741,8 +5750,9 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) ipa = ipa + 1 cpatch => cpatch%younger end do !patch loop - - if(hlm_use_ed_st3.eq.ifalse) then + end if + + if((hlm_use_ed_st3.eq.ifalse) .and. (hlm_hist_level_hifrq>1)) then do iscpf=1,nlevsclass*numpft if ((abs(hio_nplant_si_scpf(io_si, iscpf)-(nplant_scpf(iscpf)*ha_per_m2)) > 1.0E-8_r8) .and. & (hio_nplant_si_scpf(io_si, iscpf) .ne. hlm_hio_ignore_val)) then @@ -5757,11 +5767,12 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) end if end do end if + end do - if(print_iterations) then - write(fmt_char,'(I2)') iterh2_nhist - write(fates_log(),fmt='(A,'//fmt_char//'I5)') 'Solves: ',int(iterh2_histy(:)) - end if + if(print_iterations) then + write(fmt_char,'(I2)') iterh2_nhist + write(fates_log(),fmt='(A,'//fmt_char//'I5)') 'Solves: ',int(iterh2_histy(:)) + end if @@ -5887,24 +5898,28 @@ subroutine define_history_vars(this, initialize_variables) ! cohort size x crown damage (site_cdsc_r8) : SZCD ! cohort size x crown damage x pft (site_cdpf_r8) : CDPF - ! Site level counting variables - call this%set_history_var(vname='FATES_NPATCHES', units='', & - long='total number of patches per site', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_npatches_si) - call this%set_history_var(vname='FATES_NCOHORTS', units='', & - long='total number of cohorts per site', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_ncohorts_si) + if(hlm_hist_level_dynam>0) then - call this%set_history_var(vname='FATES_NPATCHES_SECONDARY', units='', & + + ! Site level counting variables + call this%set_history_var(vname='FATES_NPATCHES', units='', & long='total number of patches per site', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_npatches_sec_si) + index=ih_npatches_si) + + call this%set_history_var(vname='FATES_NCOHORTS', units='', & + long='total number of cohorts per site', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_ncohorts_si) + + call this%set_history_var(vname='FATES_NPATCHES_SECONDARY', units='', & + long='total number of patches per site', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_npatches_sec_si) call this%set_history_var(vname='FATES_NCOHORTS_SECONDARY', units='', & long='total number of cohorts per site', use_default='active', & @@ -5999,2406 +6014,2428 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_lai_si) - call this%set_history_var(vname='FATES_VEGC_PF', units='kg m-2', & - long='total PFT-level biomass in kg of carbon per land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_LAI_SECONDARY', units='m2 m-2', & + long='leaf area index per m2 land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_biomass_si_pft) + index=ih_lai_secondary_si) - call this%set_history_var(vname='FATES_VEGC_SE_PF', units='kg m-2', & - long='total PFT-level biomass in kg of carbon per land area, secondary patches', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_biomass_sec_si_pft) + ! Secondary forest area and age diagnostics - call this%set_history_var(vname='FATES_LEAFC_PF', units='kg m-2', & - long='total PFT-level leaf biomass in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_SECONDARY_FOREST_FRACTION', & + units='m2 m-2', long='secondary forest fraction', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_leafbiomass_si_pft) + index=ih_fraction_secondary_forest_si) - call this%set_history_var(vname='FATES_STOREC_PF', units='kg m-2', & - long='total PFT-level stored biomass in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_WOOD_PRODUCT', units='kg m-2', & + long='total wood product from logging in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_storebiomass_si_pft) + index=ih_woodproduct_si) - call this%set_history_var(vname='FATES_CROWNAREA_PF', units='m2 m-2', & - long='total PFT-level crown area per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, & + call this%set_history_var(vname='FATES_SECONDARY_FOREST_VEGC', & + units='kg m-2', & + long='biomass on secondary lands in kg carbon per m2 land area (mult by FATES_SECONDARY_FOREST_FRACTION to get per secondary forest area)', & + use_default='active', avgflag='A', vtype=site_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_crownarea_si_pft) + index=ih_biomass_secondary_forest_si) + ! Fire Variables - call this%set_history_var(vname='FATES_CANOPYCROWNAREA_PF', & - units='m2 m-2', long='total PFT-level canopy-layer crown area per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_canopycrownarea_si_pft) + call this%set_history_var(vname='FATES_NESTEROV_INDEX', units='', & + long='nesterov fire danger index', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_nesterov_fire_danger_si) - call this%set_history_var(vname='FATES_GPP_PF', units='kg m-2 s-1', & - long='total PFT-level GPP in kg carbon per m2 land area per second', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_IGNITIONS', & + units='m-2 s-1', & + long='number of successful fire ignitions per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_gpp_si_pft) + index=ih_fire_nignitions_si) - call this%set_history_var(vname='FATES_NPP_PF', units='kg m-2 s-1', & - long='total PFT-level NPP in kg carbon per m2 land area per second', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_FDI', units='1', & + long='Fire Danger Index (probability that an ignition will lead to a fire)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_npp_si_pft) + index=ih_fire_fdi_si) - call this%set_history_var(vname='FATES_GPP_SE_PF', units='kg m-2 s-1', & - long='total PFT-level GPP in kg carbon per m2 land area per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_ROS', units='m s-1', & + long='fire rate of spread in meters per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_gpp_sec_si_pft) + index=ih_spitfire_ros_si) - call this%set_history_var(vname='FATES_NPP_SE_PF', units='kg m-2 s-1', & - long='total PFT-level NPP in kg carbon per m2 land area per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_EFFECT_WSPEED', units='m s-1', & + long ='effective wind speed for fire spread in meters per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_npp_sec_si_pft) + index=ih_effect_wspeed_si) - call this%set_history_var(vname='FATES_NPLANT_PF', units='m-2', & - long='total PFT-level number of individuals per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_FUELCONSUMED', units='kg m-2', & + long ='total fuel consumed in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nindivs_si_pft) + index=ih_tfc_ros_si) - call this%set_history_var(vname='FATES_NPLANT_SEC_PF', units='m-2', & - long='total PFT-level number of individuals per m2 land area, secondary patches', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_FIRE_INTENSITY', & + units='J m-1 s-1', & + long='spitfire surface fireline intensity in J per m per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nindivs_sec_si_pft) + index=ih_fire_intensity_si) - call this%set_history_var(vname='FATES_RECRUITMENT_PF', & - units='m-2 yr-1', & - long='PFT-level recruitment rate in number of individuals per m2 land area per year', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_FIRE_INTENSITY_BURNFRAC', & + units='J m-1 s-1', & + long='product of surface fire intensity and burned area fraction -- divide by FATES_BURNFRAC to get area-weighted mean intensity', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_recruitment_si_pft) - - call this%set_history_var(vname='FATES_SEEDS_IN_GRIDCELL_PF', & - units='kg', & - long='Site-level seed mass input from neighboring gridcells per pft', & - use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + index=ih_fire_intensity_area_product_si) + + call this%set_history_var(vname='FATES_BURNFRAC', units='s-1', & + long='burned area fraction per second', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_seeds_in_gc_si_pft) + index=ih_fire_area_si) - call this%set_history_var(vname='FATES_SEEDS_OUT_GRIDCELL_PF', & - units='kg', & - long='Site-level seed mass output to neighboring gridcells per pft', & - use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + call this%set_history_var(vname='FATES_FUEL_MEF', units='m3 m-3', & + long='fuel moisture of extinction (volumetric)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_seeds_out_gc_si_pft) - - call this%set_history_var(vname='FATES_MORTALITY_PF', units='m-2 yr-1', & - long='PFT-level mortality rate in number of individuals per m2 land area per year', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + index=ih_fire_fuel_mef_si) + + call this%set_history_var(vname='FATES_FUEL_BULKD', & + units='kg m-3', long='fuel bulk density in kg per m3', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_mortality_si_pft) + index = ih_fire_fuel_bulkd_si ) - !MLO - Drought-deciduous phenology variables are now defined for each PFT. - call this%set_history_var(vname='FATES_DROUGHT_STATUS_PF', & - units='', & - long='PFT-level drought status, <2 too dry for leaves, >=2 not too dry', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_site_dstatus_si_pft) + call this%set_history_var(vname='FATES_FUEL_EFF_MOIST', units='m3 m-3', & + long='spitfire fuel moisture (volumetric)', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_fire_fuel_eff_moist_si) - call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFOFF_PF', & - units='days', long='PFT-level days elapsed since drought leaf drop', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_dleafoff_si_pft) + call this%set_history_var(vname='FATES_FUEL_SAV', units='m-1', & + long='spitfire fuel surface area to volume ratio', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_fuel_sav_si) - call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFON_PF', & - units='days', & - long='PFT-level days elapsed since drought leaf flush', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_dleafon_si_pft) + call this%set_history_var(vname='FATES_FUEL_AMOUNT', units='kg m-2', & + long='total ground fuel related to FATES_ROS (omits 1000hr fuels) in kg C per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_sum_fuel_si) + ! Litter Variables - call this%set_history_var(vname='FATES_MEANLIQVOL_DROUGHTPHEN_PF', & - units='m3 m-3', & - long='PFT-level mean liquid water volume for drought phenolgy', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_meanliqvol_si_pft) + call this%set_history_var(vname='FATES_LITTER_IN', units='kg m-2 s-1', & + long='litter flux in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_in_si) - call this%set_history_var(vname='FATES_MEANSMP_DROUGHTPHEN_PF', & - units='Pa', & - long='PFT-level mean soil matric potential for drought phenology', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_meansmp_si_pft) + call this%set_history_var(vname='FATES_LITTER_OUT', units='kg m-2 s-1', & + long='litter flux out in kg carbon (exudation, fragmentation, seed decay)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_out_si) - call this%set_history_var(vname='FATES_ELONG_FACTOR_PF', & - units='1', & - long='PFT-level mean elongation factor (partial flushing/abscission)', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_elong_factor_si_pft) + call this%set_history_var(vname='FATES_SEED_BANK', units='kg m-2', & + long='total seed mass of all PFTs in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_seed_bank_si) + + call this%set_history_var(vname='FATES_UNGERM_SEED_BANK', units='kg m-2', & + long='ungerminated seed mass of all PFTs in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_ungerm_seed_bank_si) - nocomp_if: if (hlm_use_nocomp .eq. itrue) then - call this%set_history_var(vname='FATES_NOCOMP_NPATCHES_PF', units='', & - long='number of patches per PFT (nocomp-mode-only)', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nocomp_pftnpatches_si_pft) - - call this%set_history_var(vname='FATES_NOCOMP_PATCHAREA_PF', units='m2 m-2',& - long='total patch area allowed per PFT (nocomp-mode-only)', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nocomp_pftpatchfraction_si_pft) - - call this%set_history_var(vname='FATES_NOCOMP_BURNEDAREA_PF', units='s-1', & - long='total burned area of PFT-labeled patch area (nocomp-mode-only)',& - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nocomp_pftburnedarea_si_pft) - endif nocomp_if - - ! patch age class variables - call this%set_history_var(vname='FATES_PATCHAREA_AP', units='m2 m-2', & - long='patch area by age bin per m2 land area', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index=ih_area_si_age) - - call this%set_history_var(vname='FATES_LAI_AP', units='m2 m-2', & - long='leaf area index by age bin per m2 land area', & - use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_lai_si_age) - - call this%set_history_var(vname='FATES_LAI_SECONDARY', units='m2 m-2', & - long='leaf area index per m2 land area, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_lai_secondary_si) - - call this%set_history_var(vname='FATES_CANOPYAREA_AP', units='m2 m-2', & - long='canopy area by age bin per m2 land area', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index=ih_canopy_area_si_age) - - call this%set_history_var(vname='FATES_NCL_AP', units='', & - long='number of canopy levels by age bin', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_ncl_si_age) - - call this%set_history_var(vname='FATES_NPATCH_AP', units='', & - long='number of patches by age bin', use_default='inactive', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_npatches_si_age) - - if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled - tempstring = 'active' - else - tempstring = 'inactive' - endif - - call this%set_history_var(vname='FATES_ZSTAR_AP', units='m', & - long='product of zstar and patch area by age bin (divide by FATES_PATCHAREA_AP to get mean zstar)', & - use_default=trim(tempstring), avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_zstar_si_age) - - call this%set_history_var(vname='FATES_CANOPYAREA_HT', units='m2 m-2', & - long='canopy area height distribution', & - use_default='active', avgflag='A', vtype=site_height_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_canopy_height_dist_si_height) - - call this%set_history_var(vname='FATES_LEAFAREA_HT', units='m2 m-2', & - long='leaf area height distribution', use_default='active', & - avgflag='A', vtype=site_height_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_leaf_height_dist_si_height) - - call this%set_history_var(vname='FATES_VEGC_AP', units='kg m-2', & - long='total biomass within a given patch age bin in kg carbon per m2 land area', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_biomass_si_age) - - ! Secondary forest area and age diagnostics - - call this%set_history_var(vname='FATES_SECONDARY_FOREST_FRACTION', & - units='m2 m-2', long='secondary forest fraction', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fraction_secondary_forest_si) - - call this%set_history_var(vname='FATES_WOOD_PRODUCT', units='kg m-2', & - long='total wood product from logging in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_woodproduct_si) - - call this%set_history_var(vname='FATES_SECONDARY_FOREST_VEGC', & - units='kg m-2', & - long='biomass on secondary lands in kg carbon per m2 land area (mult by FATES_SECONDARY_FOREST_FRACTION to get per secondary forest area)', & - use_default='active', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_biomass_secondary_forest_si) - - call this%set_history_var(vname='FATES_SECONDAREA_ANTHRODIST_AP', & - units='m2 m-2', & - long='secondary forest patch area age distribution since anthropgenic disturbance', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_agesince_anthrodist_si_age) - - call this%set_history_var(vname='FATES_SECONDAREA_DIST_AP', & - units='m2 m-2', & - long='secondary forest patch area age distribution since any kind of disturbance', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_secondaryforest_area_si_age) - - ! Fire Variables - - call this%set_history_var(vname='FATES_NESTEROV_INDEX', units='', & - long='nesterov fire danger index', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nesterov_fire_danger_si) - - call this%set_history_var(vname='FATES_IGNITIONS', & - units='m-2 s-1', & - long='number of successful fire ignitions per m2 land area per second', & + call this%set_history_var(vname='FATES_SEEDLING_POOL', units='kg m-2', & + long='total seedling (ie germinated seeds) mass of all PFTs in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_nignitions_si) + index = ih_seedling_pool_si) - call this%set_history_var(vname='FATES_FDI', units='1', & - long='Fire Danger Index (probability that an ignition will lead to a fire)', & + call this%set_history_var(vname='FATES_SEEDS_IN', units='kg m-2 s-1', & + long='seed production rate in kg carbon per m2 second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_fdi_si) + index = ih_seeds_in_si) - call this%set_history_var(vname='FATES_ROS', units='m s-1', & - long='fire rate of spread in meters per second', & + call this%set_history_var(vname='FATES_SEEDS_IN_LOCAL', units='kg m-2 s-1', & + long='local seed production rate in kg carbon per m2 second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_spitfire_ros_si) + index = ih_seeds_in_local_si) - call this%set_history_var(vname='FATES_EFFECT_WSPEED', units='m s-1', & - long ='effective wind speed for fire spread in meters per second', & + call this%set_history_var(vname='FATES_STOREC', units='kg m-2', & + long='total biomass in live plant storage in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_effect_wspeed_si) + index = ih_storec_si) - call this%set_history_var(vname='FATES_FUELCONSUMED', units='kg m-2', & - long ='total fuel consumed in kg carbon per m2 land area', & + call this%set_history_var(vname='FATES_STOREC_TF', units='kg kg-1', & + long='Storage C fraction of target', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_si ) + + call this%set_history_var(vname='FATES_VEGC', units='kg m-2', & + long='total biomass in live plants in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_tfc_ros_si) + index = ih_totvegc_si) - call this%set_history_var(vname='FATES_FIRE_INTENSITY', & - units='J m-1 s-1', & - long='spitfire surface fireline intensity in J per m per second', & + call this%set_history_var(vname='FATES_SAPWOODC', units='kg m-2', & + long='total biomass in live plant sapwood in kg carbon per m2', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_intensity_si) + index = ih_sapwc_si) - call this%set_history_var(vname='FATES_FIRE_INTENSITY_BURNFRAC', & - units='J m-1 s-1', & - long='product of surface fire intensity and burned area fraction -- divide by FATES_BURNFRAC to get area-weighted mean intensity', & + call this%set_history_var(vname='FATES_LEAFC', units='kg m-2', & + long='total biomass in live plant leaves in kg carbon per m2', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_intensity_area_product_si) - - call this%set_history_var(vname='FATES_BURNFRAC', units='s-1', & - long='burned area fraction per second', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_area_si) + index = ih_leafc_si) - call this%set_history_var(vname='FATES_FUEL_MEF', units='m3 m-3', & - long='fuel moisture of extinction (volumetric)', & + call this%set_history_var(vname='FATES_FROOTC', units='kg m-2', & + long='total biomass in live plant fine roots in kg carbon per m2', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_fuel_mef_si) - - call this%set_history_var(vname='FATES_FUEL_BULKD', & - units='kg m-3', long='fuel bulk density in kg per m3', & + index = ih_fnrtc_si) + + call this%set_history_var(vname='FATES_REPROC', units='kg m-2', & + long='total biomass in live plant reproductive tissues in kg carbon per m2', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_fuel_bulkd_si ) + index = ih_reproc_si) - call this%set_history_var(vname='FATES_FUEL_EFF_MOIST', units='m3 m-3', & - long='spitfire fuel moisture (volumetric)', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fire_fuel_eff_moist_si) + ! Output specific to the chemical species dynamics used (parteh) + select case(hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) - call this%set_history_var(vname='FATES_FUEL_SAV', units='m-1', & - long='spitfire fuel surface area to volume ratio', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_fuel_sav_si) + call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for target allometry', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) - call this%set_history_var(vname='FATES_FUEL_AMOUNT', units='kg m-2', & - long='total ground fuel related to FATES_ROS (omits 1000hr fuels) in kg C per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_sum_fuel_si) + call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & + long='ammonium uptake rate by plants in kg NH4 per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_nh4uptake_si) - call this%set_history_var(vname='FATES_FRAGMENTATION_SCALER_SL', units='', & - long='factor (0-1) by which litter/cwd fragmentation proceeds relative to max rate by soil layer', & - use_default='active', avgflag='A', vtype=site_soil_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fragmentation_scaler_sl) + call this%set_history_var(vname='FATES_NO3UPTAKE', units='kg m-2 s-1', & + long='nitrate uptake rate by plants in kg NO3 per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_no3uptake_si) - call this%set_history_var(vname='FATES_FUEL_MOISTURE_FC', units='m3 m-3', & - long='spitfire fuel class-level fuel moisture (volumetric)', & - use_default='active', avgflag='A', vtype=site_fuel_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_moisture_si_fuel) + call this%set_history_var(vname='FATES_NEFFLUX', units='kg m-2 s-1', & + long='nitrogen effluxed from plant in kg N per m2 per second (unused)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_nefflux_si) - call this%set_history_var(vname='FATES_FUEL_AMOUNT_FC', units='kg m-2', & - long='spitfire fuel-class level fuel amount in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_fuel_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fuel_amount_si_fuel) + 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=5, ivar=ivar, initialize=initialize_variables, & + index = ih_ndemand_si) - call this%set_history_var(vname='FATES_FUEL_AMOUNT_APFC', units='kg m-2', & - long='spitfire fuel quantity in each age x fuel class in kg carbon per m2 land area', & - use_default='inactive', avgflag='A', vtype=site_agefuel_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fuel_amount_age_fuel) + 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', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_nfix_si) - call this%set_history_var(vname='FATES_BURNFRAC_AP', units='s-1', & - long='spitfire fraction area burnt (per second) by patch age', & - use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_area_burnt_si_age) + end select + nitrogen_active_if: if(any(element_list(:)==nitrogen_element)) then + call this%set_history_var(vname='FATES_STOREN', units='kg m-2', & + long='total nitrogen in live plant storage', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_storen_si) - call this%set_history_var(vname='FATES_FIRE_INTENSITY_BURNFRAC_AP', & - units='J m-1 s-1', & - long='product of fire intensity and burned fraction, resolved by patch age (so divide by FATES_BURNFRAC_AP to get burned-area-weighted-average intensity)', & - use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_intensity_si_age) + call this%set_history_var(vname='FATES_STOREN_TF', units='1', & + long='storage N fraction of target', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storentfrac_si) - call this%set_history_var(vname='FATES_FUEL_AMOUNT_AP', units='kg m-2', & - long='spitfire ground fuel (kg carbon per m2) related to FATES_ROS (omits 1000hr fuels) within each patch age bin (divide by FATES_PATCHAREA_AP to get fuel per unit area of that-age patch)', & - use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_sum_fuel_si_age) + call this%set_history_var(vname='FATES_VEGN', units='kg m-2', & + long='total nitrogen in live plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_totvegn_si) - call this%set_history_var(vname='FATES_FUEL_BURNT_BURNFRAC_FC', units='1', & - long='product of fraction (0-1) of fuel burnt and burnt fraction (divide by FATES_BURNFRAC to get burned-area-weighted mean fraction fuel burnt)', & - use_default='active', avgflag='A', vtype=site_fuel_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_burnt_frac_litter_si_fuel) + call this%set_history_var(vname='FATES_SAPWOODN', units='kg m-2', & + long='total nitrogen in live plant sapwood', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_sapwn_si) - ! Litter Variables + call this%set_history_var(vname='FATES_LEAFN', units='kg m-2', & + long='total nitrogen in live plant leaves', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_leafn_si) - call this%set_history_var(vname='FATES_LITTER_IN', units='kg m-2 s-1', & - long='litter flux in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_in_si) + call this%set_history_var(vname='FATES_FROOTN', units='kg m-2', & + long='total nitrogen in live plant fine-roots', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fnrtn_si) - call this%set_history_var(vname='FATES_LITTER_OUT', units='kg m-2 s-1', & - long='litter flux out in kg carbon (exudation, fragmentation, seed decay)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_out_si) + call this%set_history_var(vname='FATES_REPRON', units='kg m-2', & + long='total nitrogen in live plant reproductive tissues', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_repron_si) + end if nitrogen_active_if - call this%set_history_var(vname='FATES_SEED_BANK', units='kg m-2', & - long='total seed mass of all PFTs in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seed_bank_si) - - call this%set_history_var(vname='FATES_UNGERM_SEED_BANK', units='kg m-2', & - long='ungerminated seed mass of all PFTs in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_ungerm_seed_bank_si) + phosphorus_active_if: if(any(element_list(:)==phosphorus_element)) then + call this%set_history_var(vname='FATES_STOREP', units='kg m-2', & + long='total phosphorus in live plant storage', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_storep_si) - call this%set_history_var(vname='FATES_SEEDLING_POOL', units='kg m-2', & - long='total seedling (ie germinated seeds) mass of all PFTs in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seedling_pool_si) + call this%set_history_var(vname='FATES_STOREP_TF', units='1', & + long='storage P fraction of target', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, & + index = ih_storeptfrac_si) - call this%set_history_var(vname='FATES_SEEDS_IN', units='kg m-2 s-1', & - long='seed production rate in kg carbon per m2 second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seeds_in_si) + call this%set_history_var(vname='FATES_VEGP', units='kg m-2', & + long='total phosphorus in live plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_totvegp_si) - call this%set_history_var(vname='FATES_SEEDS_IN_LOCAL', units='kg m-2 s-1', & - long='local seed production rate in kg carbon per m2 second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seeds_in_local_si) + call this%set_history_var(vname='FATES_SAPWOODP', units='kg m-2', & + long='Total phosphorus in live plant sapwood', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_sapwp_si) - call this%set_history_var(vname='FATES_LITTER_IN_EL', units='kg m-2 s-1', & - long='litter flux in in kg element per m2 per second', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_in_elem) + call this%set_history_var(vname='FATES_LEAFP', units='kg m-2', & + long='total phosphorus in live plant leaves', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_leafp_si) - call this%set_history_var(vname='FATES_LITTER_OUT_EL', units='kg m-2 s-1', & - long='litter flux out (exudation, fragmentation and seed decay) in kg element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_out_elem) + call this%set_history_var(vname='FATES_FROOTP', units='kg m-2', & + long='total phosphorus in live plant fine roots', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fnrtp_si) - call this%set_history_var(vname='FATES_SEED_BANK_EL', units='kg m-2', & - long='element-level total seed mass of all PFTs in kg element per m2', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seed_bank_elem) + call this%set_history_var(vname='FATES_REPROP', units='kg m-2', & + long='total phosphorus in live plant reproductive tissues', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_reprop_si) - call this%set_history_var(vname='FATES_SEEDS_IN_LOCAL_EL', & - units='kg m-2 s-1', & - long='within-site, element-level seed production rate in kg element per m2 per second', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seeds_in_local_elem) + call this%set_history_var(vname='FATES_PUPTAKE', units='kg m-2 s-1', & + long='mineralized phosphorus uptake rate of plants in kg P per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_puptake_si) - call this%set_history_var(vname='FATES_SEEDS_IN_EXTERN_EL', & - units='kg m-2 s-1', long='external seed influx rate in kg element per m2 per second', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seeds_in_extern_elem) + call this%set_history_var(vname='FATES_PEFFLUX', units='kg m-2 s-1', & + long='phosphorus effluxed from plant in kg P per m2 per second (unused)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_pefflux_si) - call this%set_history_var(vname='FATES_SEED_GERM_EL', units='kg m-2', & - long='element-level total germinated seed mass of all PFTs in kg element per m2', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seed_germ_elem) + 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=5, ivar=ivar, initialize=initialize_variables, & + index = ih_pdemand_si) + end if phosphorus_active_if + call this%set_history_var(vname='FATES_STRUCTC', units='kg m-2', & + long='structural biomass in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_bdead_si) - call this%set_history_var(vname='FATES_SEED_DECAY_EL', units='kg m-2 s-1', & - long='seed mass decay (germinated and un-germinated) in kg element per m2 per second', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seed_decay_elem) + call this%set_history_var(vname='FATES_NONSTRUCTC', units='kg m-2', & + long='non-structural biomass (sapwood + leaf + fineroot) in kg carbon per m2', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_balive_si) - ! SITE LEVEL CARBON STATE VARIABLES + call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND', units='kg m-2', & + long='aboveground biomass in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_agb_si) - call this%set_history_var(vname='FATES_STOREC', units='kg m-2', & - long='total biomass in live plant storage in kg carbon per m2 land area', & + call this%set_history_var(vname='FATES_CANOPY_VEGC', units='kg m-2', & + long='biomass of canopy plants in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_storec_si) + index = ih_canopy_biomass_si) - call this%set_history_var(vname='FATES_STOREC_TF', units='kg kg-1', & - long='Storage C fraction of target', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_si ) + call this%set_history_var(vname='FATES_USTORY_VEGC', units='kg m-2', & + long='biomass of understory plants in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_understory_biomass_si) - call this%set_history_var(vname='FATES_STOREC_TF_USTORY_SZPF', units='kg kg-1', & - long='Storage C fraction of target by size x pft, in the understory', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_ustory_scpf ) + ! disturbance rates + call this%set_history_var(vname='FATES_PRIMARY_PATCHFUSION_ERR', & + units='m2 m-2 yr-1', & + long='error in total primary lands associated with patch fusion', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_primaryland_fusion_error_si) - call this%set_history_var(vname='FATES_STOREC_TF_CANOPY_SZPF', units='kg kg-1', & - long='Storage C fraction of target by size x pft, in the canopy', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_canopy_scpf ) - - - - call this%set_history_var(vname='FATES_VEGC', units='kg m-2', & - long='total biomass in live plants in kg carbon per m2 land area', & + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_P2P', & + units='m2 m-2 yr-1', & + long='disturbance rate from primary to primary lands', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_totvegc_si) + index = ih_disturbance_rate_p2p_si) - call this%set_history_var(vname='FATES_SAPWOODC', units='kg m-2', & - long='total biomass in live plant sapwood in kg carbon per m2', & + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_P2S', & + units='m2 m-2 yr-1', & + long='disturbance rate from primary to secondary lands', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_sapwc_si) + index = ih_disturbance_rate_p2s_si ) - call this%set_history_var(vname='FATES_LEAFC', units='kg m-2', & - long='total biomass in live plant leaves in kg carbon per m2', & + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_S2S', & + units='m2 m-2 yr-1', & + long='disturbance rate from secondary to secondary lands', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_leafc_si) + index = ih_disturbance_rate_s2s_si) - call this%set_history_var(vname='FATES_FROOTC', units='kg m-2', & - long='total biomass in live plant fine roots in kg carbon per m2', & + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_FIRE', & + units='m2 m-2 yr-1', long='disturbance rate from fire', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fnrtc_si) + index = ih_fire_disturbance_rate_si) - call this%set_history_var(vname='FATES_FROOTC_SL', units='kg m-3', & - long='Total carbon in live plant fine-roots over depth', use_default='active', & - avgflag='A', vtype=site_soil_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_sl ) - - call this%set_history_var(vname='FATES_REPROC', units='kg m-2', & - long='total biomass in live plant reproductive tissues in kg carbon per m2', & + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_LOGGING', & + units='m2 m-2 yr-1', long='disturbance rate from logging', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_reproc_si) + index = ih_logging_disturbance_rate_si) + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_TREEFALL', & + units='m2 m-2 yr-1', long='disturbance rate from treefall', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fall_disturbance_rate_si) - ! Output specific to the chemical species dynamics used (parteh) - select case(hlm_parteh_mode) - case (prt_cnp_flex_allom_hyp) + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_POTENTIAL', & + units='m2 m-2 yr-1', & + long='potential (i.e., including unresolved) disturbance rate', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_potential_disturbance_rate_si) - call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for target allometry', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) - - call this%set_history_var(vname='FATES_L2FR_CANOPY_REC_PF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for recruits (canopy)', & - use_default='active', & - avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) + call this%set_history_var(vname='FATES_HARVEST_CARBON_FLUX', & + units='kg m-2 yr-1', & + long='harvest carbon flux in kg carbon per m2 per year', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_harvest_carbonflux_si) - call this%set_history_var(vname='FATES_L2FR_USTORY_REC_PF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for recruits (understory)', & - use_default='active', & - avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) + call this%set_history_var(vname='FATES_TVEG24', units='degree_Celsius', & + long='fates 24-hr running mean vegetation temperature by site', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) - !call this%set_history_var(vname='FATES_L2FR_CLSZPF', units='kg kg-1', & - ! long='The leaf to fineroot biomass multiplier for target allometry', & - ! use_default='inactive', & - ! avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & - ! ivar=ivar, initialize=initialize_variables, index = ih_l2fr_clscpf) + call this%set_history_var(vname='FATES_TLONGTERM', units='degree_Celsius', & + long='fates 30-year running mean vegetation temperature by site', & + use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_tlongterm_si ) - call this%set_history_var(vname='FATES_NH4UPTAKE_SZPF', & - units='kg m-2 s-1', & - long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_nh4uptake_scpf) + call this%set_history_var(vname='FATES_TGROWTH', units='degree_Celsius', & + long='fates long-term running mean vegetation temperature by site', & + use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_tgrowth_si ) - call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & - units='kg m-2 s-1', & - long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_no3uptake_scpf) + call this%set_history_var(vname='FATES_HARVEST_DEBT', units='kg C', & + long='Accumulated carbon failed to be harvested', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) - call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & - long='nitrogen efflux, root to soil, 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=5, ivar=ivar, & - initialize=initialize_variables, index = ih_nefflux_scpf) + call this%set_history_var(vname='FATES_HARVEST_DEBT_SEC', units='kg C', & + long='Accumulated carbon failed to be harvested from secondary patches', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) - 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=5, ivar=ivar, & - initialize=initialize_variables, index = ih_ndemand_scpf) + call this%set_history_var(vname='FATES_EXCESS_RESP', units='kg m-2 s-1', & + long='respiration of un-allocatable carbon gain', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_excess_resp_si) + ! slow carbon fluxes associated with mortality from or transfer betweeen canopy and understory - 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, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_nfix_scpf) - + call this%set_history_var(vname='FATES_DEMOTION_CARBONFLUX', & + units = 'kg m-2 s-1', & + long='demotion-associated biomass carbon flux from canopy to understory in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_demotion_carbonflux_si) - call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & - long='ammonium uptake rate by plants in kg NH4 per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_nh4uptake_si) + call this%set_history_var(vname='FATES_PROMOTION_CARBONFLUX', & + units = 'kg m-2 s-1', & + long='promotion-associated biomass carbon flux from understory to canopy in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_promotion_carbonflux_si) - call this%set_history_var(vname='FATES_NO3UPTAKE', units='kg m-2 s-1', & - long='nitrate uptake rate by plants in kg NO3 per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_no3uptake_si) + call this%set_history_var(vname='FATES_MORTALITY_CFLUX_CANOPY', & + units = 'kg m-2 s-1', & + long='flux of biomass carbon from live to dead pools from mortality of canopy plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_canopy_mortality_carbonflux_si) - call this%set_history_var(vname='FATES_NEFFLUX', units='kg m-2 s-1', & - long='nitrogen effluxed from plant in kg N per m2 per second (unused)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_nefflux_si) + call this%set_history_var(vname='FATES_MORTALITY_CFLUX_USTORY', & + units = 'kg m-2 s-1', & + long='flux of biomass carbon from live to dead pools from mortality of understory plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_understory_mortality_carbonflux_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=5, ivar=ivar, initialize=initialize_variables, & - index = ih_ndemand_si) + call this%set_history_var(vname='MORTALITY_CROWNAREA_CANOPY', & + units = 'm2/ha/year', & + long='Crown area of canopy trees that died', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_canopy_mortality_crownarea_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', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_nfix_si) - - end select + call this%set_history_var(vname='MORTALITY_CROWNAREA_UNDERSTORY', & + units = 'm2/ha/year', & + long='Crown aera of understory trees that died', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_understory_mortality_crownarea_si ) - nitrogen_active_if: if(any(element_list(:)==nitrogen_element)) then - call this%set_history_var(vname='FATES_STOREN', units='kg m-2', & - long='total nitrogen in live plant storage', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_storen_si) - - call this%set_history_var(vname='FATES_STOREN_TF', units='1', & - long='storage N fraction of target', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storentfrac_si) - - call this%set_history_var(vname='FATES_VEGN', units='kg m-2', & - long='total nitrogen in live plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_totvegn_si) - - call this%set_history_var(vname='FATES_SAPWOODN', units='kg m-2', & - long='total nitrogen in live plant sapwood', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_sapwn_si) + call this%set_history_var(vname='FATES_FIRE_CLOSS', units='kg m-2 s-1', & + long='carbon loss to atmosphere from fire in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_c_to_atm_si) - call this%set_history_var(vname='FATES_LEAFN', units='kg m-2', & - long='total nitrogen in live plant leaves', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_leafn_si) + call this%set_history_var(vname='FATES_CBALANCE_ERROR', & + units='kg s-1', & + long='total carbon error in kg carbon per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_cbal_err_fates_si) - call this%set_history_var(vname='FATES_FROOTN', units='kg m-2', & - long='total nitrogen in live plant fine-roots', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fnrtn_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', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_leaf_si) - call this%set_history_var(vname='FATES_REPRON', units='kg m-2', & - long='total nitrogen in live plant reproductive tissues', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_repron_si) + call this%set_history_var(vname='FATES_SEED_ALLOC', units='kg m-2 s-1', & + long='allocation to seeds in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_seed_si) - call this%set_history_var(vname='FATES_VEGN_SZPF', units='kg m-2', & - long='total (live) vegetation nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_totvegn_scpf) + call this%set_history_var(vname='FATES_STEM_ALLOC', units='kg m-2 s-1', & + long='allocation to stem in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stem_si) - call this%set_history_var(vname='FATES_LEAFN_SZPF', units='kg m-2', & - long='leaf nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_leafn_scpf) + call this%set_history_var(vname='FATES_FROOT_ALLOC', units='kg m-2 s-1', & + long='allocation to fine roots in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_froot_si) - call this%set_history_var(vname='FATES_FROOTN_SZPF', units='kg m-2', & - long='fine-root nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fnrtn_scpf) + call this%set_history_var(vname='FATES_CROOT_ALLOC', units='kg m-2 s-1', & + long='allocation to coarse roots in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_croot_si) - call this%set_history_var(vname='FATES_SAPWOODN_SZPF', units='kg m-2', & - long='sapwood nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sapwn_scpf) + call this%set_history_var(vname='FATES_STORE_ALLOC', units='kg m-2 s-1', & + long='allocation to storage tissues in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stor_si) + + HERE + + if(hlm_hist_level_dynam>1) then + + call this%set_history_var(vname='FATES_VEGC_PF', units='kg m-2', & + long='total PFT-level biomass in kg of carbon per land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_biomass_si_pft) + + call this%set_history_var(vname='FATES_VEGC_SE_PF', units='kg m-2', & + long='total PFT-level biomass in kg of carbon per land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_biomass_sec_si_pft) - call this%set_history_var(vname='FATES_STOREN_SZPF', units='kg m-2', & - long='storage nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storen_scpf) + call this%set_history_var(vname='FATES_LEAFC_PF', units='kg m-2', & + long='total PFT-level leaf biomass in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_leafbiomass_si_pft) - call this%set_history_var(vname='FATES_STOREN_TF_CANOPY_SZPF', & - units='1', & - long='storage nitrogen fraction (0-1) of target, in canopy, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storentfrac_canopy_scpf) + call this%set_history_var(vname='FATES_STOREC_PF', units='kg m-2', & + long='total PFT-level stored biomass in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_storebiomass_si_pft) - call this%set_history_var(vname='FATES_STOREN_TF_USTORY_SZPF', & - units='1', & - long='storage nitrogen fraction (0-1) of target, in understory, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_storentfrac_understory_scpf) + call this%set_history_var(vname='FATES_CROWNAREA_PF', units='m2 m-2', & + long='total PFT-level crown area per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_crownarea_si_pft) - call this%set_history_var(vname='FATES_REPRON_SZPF', units='kg m-2', & - long='reproductive nitrogen mass (on plant) by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_repron_scpf) + call this%set_history_var(vname='FATES_CANOPYCROWNAREA_PF', & + units='m2 m-2', long='total PFT-level canopy-layer crown area per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_canopycrownarea_si_pft) - end if nitrogen_active_if + call this%set_history_var(vname='FATES_GPP_PF', units='kg m-2 s-1', & + long='total PFT-level GPP in kg carbon per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_gpp_si_pft) + call this%set_history_var(vname='FATES_NPP_PF', units='kg m-2 s-1', & + long='total PFT-level NPP in kg carbon per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_npp_si_pft) - phosphorus_active_if: if(any(element_list(:)==phosphorus_element)) then - call this%set_history_var(vname='FATES_STOREP', units='kg m-2', & - long='total phosphorus in live plant storage', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_storep_si) + call this%set_history_var(vname='FATES_GPP_SE_PF', units='kg m-2 s-1', & + long='total PFT-level GPP in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_gpp_sec_si_pft) - call this%set_history_var(vname='FATES_STOREP_TF', units='1', & - long='storage P fraction of target', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, & - index = ih_storeptfrac_si) + call this%set_history_var(vname='FATES_NPP_SE_PF', units='kg m-2 s-1', & + long='total PFT-level NPP in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_npp_sec_si_pft) - call this%set_history_var(vname='FATES_VEGP', units='kg m-2', & - long='total phosphorus in live plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_totvegp_si) + call this%set_history_var(vname='FATES_NPLANT_PF', units='m-2', & + long='total PFT-level number of individuals per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_nindivs_si_pft) - call this%set_history_var(vname='FATES_SAPWOODP', units='kg m-2', & - long='Total phosphorus in live plant sapwood', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sapwp_si) + call this%set_history_var(vname='FATES_NPLANT_SEC_PF', units='m-2', & + long='total PFT-level number of individuals per m2 land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_nindivs_sec_si_pft) - call this%set_history_var(vname='FATES_LEAFP', units='kg m-2', & - long='total phosphorus in live plant leaves', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_leafp_si) + call this%set_history_var(vname='FATES_RECRUITMENT_PF', & + units='m-2 yr-1', & + long='PFT-level recruitment rate in number of individuals per m2 land area per year', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_recruitment_si_pft) + + call this%set_history_var(vname='FATES_SEEDS_IN_GRIDCELL_PF', & + units='kg', & + long='Site-level seed mass input from neighboring gridcells per pft', & + use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_seeds_in_gc_si_pft) - call this%set_history_var(vname='FATES_FROOTP', units='kg m-2', & - long='total phosphorus in live plant fine roots', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fnrtp_si) + call this%set_history_var(vname='FATES_SEEDS_OUT_GRIDCELL_PF', & + units='kg', & + long='Site-level seed mass output to neighboring gridcells per pft', & + use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_seeds_out_gc_si_pft) + + call this%set_history_var(vname='FATES_MORTALITY_PF', units='m-2 yr-1', & + long='PFT-level mortality rate in number of individuals per m2 land area per year', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_mortality_si_pft) - call this%set_history_var(vname='FATES_REPROP', units='kg m-2', & - long='total phosphorus in live plant reproductive tissues', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_reprop_si) + !MLO - Drought-deciduous phenology variables are now defined for each PFT. + call this%set_history_var(vname='FATES_DROUGHT_STATUS_PF', & + units='', & + long='PFT-level drought status, <2 too dry for leaves, >=2 not too dry', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_site_dstatus_si_pft) - call this%set_history_var(vname='FATES_PUPTAKE', units='kg m-2 s-1', & - long='mineralized phosphorus uptake rate of plants in kg P per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_puptake_si) + call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFOFF_PF', & + units='days', long='PFT-level days elapsed since drought leaf drop', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_dleafoff_si_pft) - call this%set_history_var(vname='FATES_PEFFLUX', units='kg m-2 s-1', & - long='phosphorus effluxed from plant in kg P per m2 per second (unused)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_pefflux_si) + call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFON_PF', & + units='days', & + long='PFT-level days elapsed since drought leaf flush', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_dleafon_si_pft) - 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=5, ivar=ivar, initialize=initialize_variables, & - index = ih_pdemand_si) + call this%set_history_var(vname='FATES_MEANLIQVOL_DROUGHTPHEN_PF', & + units='m3 m-3', & + long='PFT-level mean liquid water volume for drought phenolgy', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_meanliqvol_si_pft) + + call this%set_history_var(vname='FATES_MEANSMP_DROUGHTPHEN_PF', & + units='Pa', & + long='PFT-level mean soil matric potential for drought phenology', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_meansmp_si_pft) + + call this%set_history_var(vname='FATES_ELONG_FACTOR_PF', & + units='1', & + long='PFT-level mean elongation factor (partial flushing/abscission)', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_elong_factor_si_pft) + + nocomp_if: if (hlm_use_nocomp .eq. itrue) then + call this%set_history_var(vname='FATES_NOCOMP_NPATCHES_PF', units='', & + long='number of patches per PFT (nocomp-mode-only)', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_nocomp_pftnpatches_si_pft) + + call this%set_history_var(vname='FATES_NOCOMP_PATCHAREA_PF', units='m2 m-2',& + long='total patch area allowed per PFT (nocomp-mode-only)', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_nocomp_pftpatchfraction_si_pft) + + call this%set_history_var(vname='FATES_NOCOMP_BURNEDAREA_PF', units='s-1', & + long='total burned area of PFT-labeled patch area (nocomp-mode-only)',& + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_nocomp_pftburnedarea_si_pft) + endif nocomp_if + + ! patch age class variables + call this%set_history_var(vname='FATES_PATCHAREA_AP', units='m2 m-2', & + long='patch area by age bin per m2 land area', use_default='active', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index=ih_area_si_age) + + call this%set_history_var(vname='FATES_LAI_AP', units='m2 m-2', & + long='leaf area index by age bin per m2 land area', & + use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_lai_si_age) + + + + call this%set_history_var(vname='FATES_CANOPYAREA_AP', units='m2 m-2', & + long='canopy area by age bin per m2 land area', use_default='active', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index=ih_canopy_area_si_age) + + call this%set_history_var(vname='FATES_NCL_AP', units='', & + long='number of canopy levels by age bin', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_ncl_si_age) + + call this%set_history_var(vname='FATES_NPATCH_AP', units='', & + long='number of patches by age bin', use_default='inactive', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_npatches_si_age) + + if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled + tempstring = 'active' + else + tempstring = 'inactive' + endif + + call this%set_history_var(vname='FATES_ZSTAR_AP', units='m', & + long='product of zstar and patch area by age bin (divide by FATES_PATCHAREA_AP to get mean zstar)', & + use_default=trim(tempstring), avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_zstar_si_age) + + call this%set_history_var(vname='FATES_CANOPYAREA_HT', units='m2 m-2', & + long='canopy area height distribution', & + use_default='active', avgflag='A', vtype=site_height_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_canopy_height_dist_si_height) + + call this%set_history_var(vname='FATES_LEAFAREA_HT', units='m2 m-2', & + long='leaf area height distribution', use_default='active', & + avgflag='A', vtype=site_height_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_leaf_height_dist_si_height) + + call this%set_history_var(vname='FATES_VEGC_AP', units='kg m-2', & + long='total biomass within a given patch age bin in kg carbon per m2 land area', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_biomass_si_age) + + call this%set_history_var(vname='FATES_SECONDAREA_ANTHRODIST_AP', & + units='m2 m-2', & + long='secondary forest patch area age distribution since anthropgenic disturbance', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_agesince_anthrodist_si_age) + + call this%set_history_var(vname='FATES_SECONDAREA_DIST_AP', & + units='m2 m-2', & + long='secondary forest patch area age distribution since any kind of disturbance', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_secondaryforest_area_si_age) + + call this%set_history_var(vname='FATES_FRAGMENTATION_SCALER_SL', units='', & + long='factor (0-1) by which litter/cwd fragmentation proceeds relative to max rate by soil layer', & + use_default='active', avgflag='A', vtype=site_soil_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fragmentation_scaler_sl) + + call this%set_history_var(vname='FATES_FUEL_MOISTURE_FC', units='m3 m-3', & + long='spitfire fuel class-level fuel moisture (volumetric)', & + use_default='active', avgflag='A', vtype=site_fuel_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_moisture_si_fuel) + + call this%set_history_var(vname='FATES_FUEL_AMOUNT_FC', units='kg m-2', & + long='spitfire fuel-class level fuel amount in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_fuel_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fuel_amount_si_fuel) + + call this%set_history_var(vname='FATES_FUEL_AMOUNT_APFC', units='kg m-2', & + long='spitfire fuel quantity in each age x fuel class in kg carbon per m2 land area', & + use_default='inactive', avgflag='A', vtype=site_agefuel_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fuel_amount_age_fuel) + + call this%set_history_var(vname='FATES_BURNFRAC_AP', units='s-1', & + long='spitfire fraction area burnt (per second) by patch age', & + use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_area_burnt_si_age) + + call this%set_history_var(vname='FATES_FIRE_INTENSITY_BURNFRAC_AP', & + units='J m-1 s-1', & + long='product of fire intensity and burned fraction, resolved by patch age (so divide by FATES_BURNFRAC_AP to get burned-area-weighted-average intensity)', & + use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_intensity_si_age) + + call this%set_history_var(vname='FATES_FUEL_AMOUNT_AP', units='kg m-2', & + long='spitfire ground fuel (kg carbon per m2) related to FATES_ROS (omits 1000hr fuels) within each patch age bin (divide by FATES_PATCHAREA_AP to get fuel per unit area of that-age patch)', & + use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_sum_fuel_si_age) + + call this%set_history_var(vname='FATES_FUEL_BURNT_BURNFRAC_FC', units='1', & + long='product of fraction (0-1) of fuel burnt and burnt fraction (divide by FATES_BURNFRAC to get burned-area-weighted mean fraction fuel burnt)', & + use_default='active', avgflag='A', vtype=site_fuel_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_burnt_frac_litter_si_fuel) + + call this%set_history_var(vname='FATES_LITTER_IN_EL', units='kg m-2 s-1', & + long='litter flux in in kg element per m2 per second', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_in_elem) + + call this%set_history_var(vname='FATES_LITTER_OUT_EL', units='kg m-2 s-1', & + long='litter flux out (exudation, fragmentation and seed decay) in kg element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_out_elem) + + call this%set_history_var(vname='FATES_SEED_BANK_EL', units='kg m-2', & + long='element-level total seed mass of all PFTs in kg element per m2', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_seed_bank_elem) + + call this%set_history_var(vname='FATES_SEEDS_IN_LOCAL_EL', & + units='kg m-2 s-1', & + long='within-site, element-level seed production rate in kg element per m2 per second', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_seeds_in_local_elem) + + call this%set_history_var(vname='FATES_SEEDS_IN_EXTERN_EL', & + units='kg m-2 s-1', long='external seed influx rate in kg element per m2 per second', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_seeds_in_extern_elem) + + call this%set_history_var(vname='FATES_SEED_GERM_EL', units='kg m-2', & + long='element-level total germinated seed mass of all PFTs in kg element per m2', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_seed_germ_elem) + + call this%set_history_var(vname='FATES_SEED_DECAY_EL', units='kg m-2 s-1', & + long='seed mass decay (germinated and un-germinated) in kg element per m2 per second', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_seed_decay_elem) + + ! SITE LEVEL CARBON STATE VARIABLES + + call this%set_history_var(vname='FATES_STOREC_TF_USTORY_SZPF', units='kg kg-1', & + long='Storage C fraction of target by size x pft, in the understory', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_ustory_scpf ) - call this%set_history_var(vname='FATES_VEGP_SZPF', units='kg m-2', & - long='total (live) vegetation phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_totvegp_scpf) - call this%set_history_var(vname='FATES_LEAFP_SZPF', units='kg m-2', & - long='leaf phosphorus mass by size-class x pft', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_leafp_scpf ) + call this%set_history_var(vname='FATES_STOREC_TF_CANOPY_SZPF', units='kg kg-1', & + long='Storage C fraction of target by size x pft, in the canopy', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_canopy_scpf ) + + - call this%set_history_var(vname='FATES_FROOTP_SZPF', units='kg m-2', & - long='fine-root phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fnrtp_scpf) + + call this%set_history_var(vname='FATES_FROOTC_SL', units='kg m-3', & + long='Total carbon in live plant fine-roots over depth', use_default='active', & + avgflag='A', vtype=site_soil_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_sl ) - call this%set_history_var(vname='FATES_SAPWOODP_SZPF', units='kg m-2', & - long='sapwood phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sapwp_scpf) + - call this%set_history_var(vname='FATES_STOREP_SZPF', units='kg m-2', & - long='storage phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storep_scpf) - call this%set_history_var(vname='FATES_STOREP_TF_CANOPY_SZPF', & - units='1', & - long='storage phosphorus fraction (0-1) of target, in canopy, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storeptfrac_canopy_scpf) + + ! Output specific to the chemical species dynamics used (parteh) + select case(hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) + + call this%set_history_var(vname='FATES_L2FR_CANOPY_REC_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (canopy)', & + use_default='active', & + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) - call this%set_history_var(vname='FATES_STOREP_TF_USTORY_SZPF', & - units='1', & - long='storage phosphorus fraction (0-1) of target, in understory, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_storeptfrac_understory_scpf) + call this%set_history_var(vname='FATES_L2FR_USTORY_REC_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (understory)', & + use_default='active', & + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) - call this%set_history_var(vname='FATES_REPROP_SZPF', units='kg m-2', & - long='reproductive phosphorus mass (on plant) by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_reprop_scpf) + !call this%set_history_var(vname='FATES_L2FR_CLSZPF', units='kg kg-1', & + ! long='The leaf to fineroot biomass multiplier for target allometry', & + ! use_default='inactive', & + ! avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & + ! ivar=ivar, initialize=initialize_variables, index = ih_l2fr_clscpf) - call this%set_history_var(vname='FATES_PUPTAKE_SZPF', & + call this%set_history_var(vname='FATES_NH4UPTAKE_SZPF', & units='kg m-2 s-1', & - long='phosphorus uptake rate by plants, by size-class x pft in kg P per m2 per second', & + long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_puptake_scpf) + initialize=initialize_variables, index = ih_nh4uptake_scpf) - call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & + call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & units='kg m-2 s-1', & - long='phosphorus efflux, root to soil, by size-class x pft in kg P per m2 per second', & + long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_pefflux_scpf) + initialize=initialize_variables, index = ih_no3uptake_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', & + call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & + long='nitrogen efflux, root to soil, 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=5, ivar=ivar, & - initialize=initialize_variables, index = ih_pdemand_scpf) - - end if phosphorus_active_if - - call this%set_history_var(vname='FATES_STRUCTC', units='kg m-2', & - long='structural biomass in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_bdead_si) - - call this%set_history_var(vname='FATES_NONSTRUCTC', units='kg m-2', & - long='non-structural biomass (sapwood + leaf + fineroot) in kg carbon per m2', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_balive_si) - - call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND', units='kg m-2', & - long='aboveground biomass in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_agb_si) - - call this%set_history_var(vname='FATES_CANOPY_VEGC', units='kg m-2', & - long='biomass of canopy plants in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_canopy_biomass_si) - - call this%set_history_var(vname='FATES_USTORY_VEGC', units='kg m-2', & - long='biomass of understory plants in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_understory_biomass_si) - - ! disturbance rates - - call this%set_history_var(vname='FATES_PRIMARY_PATCHFUSION_ERR', & - units='m2 m-2 yr-1', & - long='error in total primary lands associated with patch fusion', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_primaryland_fusion_error_si) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_P2P', & - units='m2 m-2 yr-1', & - long='disturbance rate from primary to primary lands', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_disturbance_rate_p2p_si) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_P2S', & - units='m2 m-2 yr-1', & - long='disturbance rate from primary to secondary lands', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_disturbance_rate_p2s_si ) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_S2S', & - units='m2 m-2 yr-1', & - long='disturbance rate from secondary to secondary lands', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_disturbance_rate_s2s_si) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_FIRE', & - units='m2 m-2 yr-1', long='disturbance rate from fire', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_disturbance_rate_si) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_LOGGING', & - units='m2 m-2 yr-1', long='disturbance rate from logging', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_logging_disturbance_rate_si) + initialize=initialize_variables, index = ih_nefflux_scpf) - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_TREEFALL', & - units='m2 m-2 yr-1', long='disturbance rate from treefall', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fall_disturbance_rate_si) + 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=5, ivar=ivar, & + initialize=initialize_variables, index = ih_ndemand_scpf) - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_POTENTIAL', & - units='m2 m-2 yr-1', & - long='potential (i.e., including unresolved) disturbance rate', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_potential_disturbance_rate_si) + 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, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_nfix_scpf) + + end select - call this%set_history_var(vname='FATES_HARVEST_CARBON_FLUX', & - units='kg m-2 yr-1', & - long='harvest carbon flux in kg carbon per m2 per year', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_harvest_carbonflux_si) + nitrogen_active_if: if(any(element_list(:)==nitrogen_element)) then - ! Canopy Resistance + call this%set_history_var(vname='FATES_VEGN_SZPF', units='kg m-2', & + long='total (live) vegetation nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_totvegn_scpf) - call this%set_history_var(vname='FATES_STOMATAL_COND', & - units='mol m-2 s-1', long='mean stomatal conductance', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_c_stomata_si) + call this%set_history_var(vname='FATES_LEAFN_SZPF', units='kg m-2', & + long='leaf nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_leafn_scpf) - call this%set_history_var(vname='FATES_LBLAYER_COND', units='mol m-2 s-1', & - long='mean leaf boundary layer conductance', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_c_lblayer_si) + call this%set_history_var(vname='FATES_FROOTN_SZPF', units='kg m-2', & + long='fine-root nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_fnrtn_scpf) - ! Temperature + call this%set_history_var(vname='FATES_SAPWOODN_SZPF', units='kg m-2', & + long='sapwood nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_sapwn_scpf) - call this%set_history_var(vname='FATES_TVEG24', units='degree_Celsius', & - long='fates 24-hr running mean vegetation temperature by site', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) + call this%set_history_var(vname='FATES_STOREN_SZPF', units='kg m-2', & + long='storage nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storen_scpf) - call this%set_history_var(vname='FATES_TLONGTERM', units='degree_Celsius', & - long='fates 30-year running mean vegetation temperature by site', & - use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_tlongterm_si ) + call this%set_history_var(vname='FATES_STOREN_TF_CANOPY_SZPF', & + units='1', & + long='storage nitrogen fraction (0-1) of target, in canopy, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storentfrac_canopy_scpf) - call this%set_history_var(vname='FATES_TGROWTH', units='degree_Celsius', & - long='fates long-term running mean vegetation temperature by site', & - use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_tgrowth_si ) + call this%set_history_var(vname='FATES_STOREN_TF_USTORY_SZPF', & + units='1', & + long='storage nitrogen fraction (0-1) of target, in understory, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, & + index = ih_storentfrac_understory_scpf) - call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & - long='fates instantaneous mean vegetation temperature by site', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) + call this%set_history_var(vname='FATES_REPRON_SZPF', units='kg m-2', & + long='reproductive nitrogen mass (on plant) by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_repron_scpf) - ! radiation error - call this%set_history_var(vname='FATES_RAD_ERROR', units='W m-2 ', & - long='radiation error in FATES RTM', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_rad_error_si) + end if nitrogen_active_if - call this%set_history_var(vname='FATES_VIS_SOLVE_ERROR', units='-', & - long='mean two-stream solver error for VIS', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_vis_solve_err_si) - - call this%set_history_var(vname='FATES_NIR_SOLVE_ERROR', units='-', & - long='mean two-stream solver error for NIR', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_nir_solve_err_si) - - call this%set_history_var(vname='FATES_VIS_CONSV_ERROR', units='-', & - long='mean two-stream conservation error for VIS', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_vis_consv_err_si) + phosphorus_active_if: if(any(element_list(:)==phosphorus_element)) then + + call this%set_history_var(vname='FATES_VEGP_SZPF', units='kg m-2', & + long='total (live) vegetation phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_totvegp_scpf) - call this%set_history_var(vname='FATES_NIR_CONSV_ERROR', units='-', & - long='mean two-stream conservation error for NIR', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_nir_consv_err_si) + call this%set_history_var(vname='FATES_LEAFP_SZPF', units='kg m-2', & + long='leaf phosphorus mass by size-class x pft', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_leafp_scpf ) - call this%set_history_var(vname='FATES_VIS_SOLVE_ERROR_AGE', units='-', & - long='mean two-stream solver error for VIS by patch age', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_vis_solve_err_age_si) + call this%set_history_var(vname='FATES_FROOTP_SZPF', units='kg m-2', & + long='fine-root phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_fnrtp_scpf) - call this%set_history_var(vname='FATES_NIR_SOLVE_ERROR_AGE', units='-', & - long='mean two-stream solver error for NIR by patch age', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_nir_solve_err_age_si) + call this%set_history_var(vname='FATES_SAPWOODP_SZPF', units='kg m-2', & + long='sapwood phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_sapwp_scpf) - call this%set_history_var(vname='FATES_VIS_CONSV_ERROR_AGE', units='-', & - long='mean two-stream conservation error for VIS by patch age', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_vis_consv_err_age_si) - - call this%set_history_var(vname='FATES_NIR_CONSV_ERROR_AGE', units='-', & - long='mean two-stream conservation error for NIR by patch age', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_nir_consv_err_age_si) - - call this%set_history_var(vname='FATES_AR', units='gC/m^2/s', & - long='autotrophic respiration', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_aresp_si ) + call this%set_history_var(vname='FATES_STOREP_SZPF', units='kg m-2', & + long='storage phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storep_scpf) - call this%set_history_var(vname='FATES_HARVEST_DEBT', units='kg C', & - long='Accumulated carbon failed to be harvested', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) + call this%set_history_var(vname='FATES_STOREP_TF_CANOPY_SZPF', & + units='1', & + long='storage phosphorus fraction (0-1) of target, in canopy, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storeptfrac_canopy_scpf) - call this%set_history_var(vname='FATES_HARVEST_DEBT_SEC', units='kg C', & - long='Accumulated carbon failed to be harvested from secondary patches', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) + call this%set_history_var(vname='FATES_STOREP_TF_USTORY_SZPF', & + units='1', & + long='storage phosphorus fraction (0-1) of target, in understory, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, & + index = ih_storeptfrac_understory_scpf) + call this%set_history_var(vname='FATES_REPROP_SZPF', units='kg m-2', & + long='reproductive phosphorus mass (on plant) by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_reprop_scpf) + call this%set_history_var(vname='FATES_PUPTAKE_SZPF', & + units='kg m-2 s-1', & + long='phosphorus uptake rate by plants, 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=5, ivar=ivar, & + initialize=initialize_variables, index = ih_puptake_scpf) - ! Ecosystem Carbon Fluxes (updated rapidly, upfreq=2) + call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & + units='kg m-2 s-1', & + long='phosphorus efflux, root to soil, 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=5, ivar=ivar, & + initialize=initialize_variables, index = ih_pefflux_scpf) - call this%set_history_var(vname='FATES_NPP', units='kg m-2 s-1', & - long='net primary production in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_si) + 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=5, ivar=ivar, & + initialize=initialize_variables, index = ih_pdemand_scpf) - call this%set_history_var(vname='FATES_NPP_SECONDARY', units='kg m-2 s-1', & - long='net primary production in kg carbon per m2 per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_secondary_si) + end if phosphorus_active_if - call this%set_history_var(vname='FATES_GPP', units='kg m-2 s-1', & - long='gross primary production in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_si) + call this%set_history_var(vname='FATES_CROWNAREA_CLLL', units='m2 m-2', & + long='area fraction of the total ground occupied by each canopy-leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_crownarea_si_cnlf) + + call this%set_history_var(vname='FATES_CROWNAREA_CL', units='m2 m-2', & + long='area fraction of the canopy footprint occupied by each canopy-leaf layer', use_default='active', & + avgflag='A', vtype=site_can_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_crownarea_cl) - call this%set_history_var(vname='FATES_GPP_SECONDARY', units='kg m-2 s-1', & - long='gross primary production in kg carbon per m2 per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_secondary_si) + + call this%set_history_var(vname='FATES_MORTALITY_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_mortality_carbonflux_si_pft) - call this%set_history_var(vname='FATES_AUTORESP', units='kg m-2 s-1', & - long='autotrophic respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_si) + call this%set_history_var(vname='FATES_MORTALITY_FIRE_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from fire mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_firemortality_carbonflux_si_pft) - call this%set_history_var(vname='FATES_AUTORESP_SECONDARY', units='kg m-2 s-1', & - long='autotrophic respiration in kg carbon per m2 per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_secondary_si) + call this%set_history_var(vname='FATES_MORTALITY_HYDRO_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from hydraulic failure mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_hydraulicmortality_carbonflux_si_pft) - call this%set_history_var(vname='FATES_GROWTH_RESP', units='kg m-2 s-1', & - long='growth respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_growth_resp_si) + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_cstarvmortality_carbonflux_si_pft) - call this%set_history_var(vname='FATES_GROWTH_RESP_SECONDARY', units='kg m-2 s-1', & - long='growth respiration in kg carbon per m2 per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_growth_resp_secondary_si) + call this%set_history_var(vname='FATES_ABOVEGROUND_MORT_SZPF', units='kg m-2 s-1', & + long='Aboveground flux of carbon from AGB to necromass due to mortality', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_abg_mortality_cflux_si_scpf) - call this%set_history_var(vname='FATES_MAINT_RESP', units='kg m-2 s-1', & - long='maintenance respiration in kg carbon per m2 land area per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_maint_resp_si) + call this%set_history_var(vname='FATES_ABOVEGROUND_PROD_SZPF', units='kg m-2 s-1', & + long='Aboveground carbon productivity', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_abg_productivity_cflux_si_scpf) + ! size class by age dimensioned variables - call this%set_history_var(vname='FATES_MAINT_RESP_UNREDUCED', units='kg m-2 s-1', & - long='diagnostic maintenance respiration if the low-carbon-storage reduction is ignored', & - use_default='unactive', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_maint_resp_unreduced_si) + call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & + long='number of plants per m2 in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_si_scag) - call this%set_history_var(vname='FATES_MAINT_RESP_SECONDARY', units='kg m-2 s-1', & - long='maintenance respiration in kg carbon per m2 land area per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_maint_resp_secondary_si) + call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZAP', units = 'm-2', & + long='number of plants per m2 in canopy in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_canopy_si_scag) - call this%set_history_var(vname='FATES_EXCESS_RESP', units='kg m-2 s-1', & - long='respiration of un-allocatable carbon gain', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_excess_resp_si) - + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZAP', & + units = 'm-2', & + long='number of plants per m2 in understory in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_understory_si_scag) + call this%set_history_var(vname='FATES_DDBH_CANOPY_SZAP', & + units = 'm m-2 yr-1', & + long='growth rate of canopy plants in meters DBH per m2 per year in canopy in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_canopy_si_scag) - call this%set_history_var(vname='FATES_AR_CANOPY', units='gC/m^2/s', & - long='autotrophic respiration of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ar_canopy_si ) + call this%set_history_var(vname='FATES_DDBH_USTORY_SZAP', & + units = 'm m-2 yr-1', & + long='growth rate of understory plants in meters DBH per m2 per year in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_understory_si_scag) + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZAP', & + units = 'm-2 yr-1', & + long='mortality rate of canopy plants in number of plants per m2 per year in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_canopy_si_scag) + call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZAP', & + units = 'm-2 yr-1', & + long='mortality rate of understory plants in number of plants per m2 per year in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_understory_si_scag) - ! fast fluxes by age bin + ! size x age x pft dimensioned + call this%set_history_var(vname='FATES_NPLANT_SZAPPF',units = 'm-2', & + long='number of plants per m2 in each size x age x pft class', & + use_default='inactive', avgflag='A', vtype=site_scagpft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_si_scagpft) - call this%set_history_var(vname='FATES_AR_UNDERSTORY', units='gC/m^2/s', & - long='autotrophic respiration of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ar_understory_si ) + ! age x pft dimensioned + call this%set_history_var(vname='FATES_NPP_APPF',units = 'kg m-2 s-1', & + long='NPP per PFT in each age bin in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_agepft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_si_agepft) - ! fast fluxes separated canopy/understory - call this%set_history_var(vname='FATES_GPP_CANOPY', units='kg m-2 s-1', & - long='gross primary production of canopy plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_gpp_canopy_si) + call this%set_history_var(vname='FATES_VEGC_APPF',units = 'kg m-2', & + long='biomass per PFT in each age bin in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_agepft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_biomass_si_agepft) - call this%set_history_var(vname='FATES_AUTORESP_CANOPY', & - units='kg m-2 s-1', & - long='autotrophic respiration of canopy plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_ar_canopy_si) + call this%set_history_var(vname='FATES_SCORCH_HEIGHT_APPF',units = 'm', & + long='SPITFIRE flame Scorch Height (calculated per PFT in each patch age bin)', & + use_default='inactive', avgflag='A', vtype=site_agepft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_scorch_height_si_agepft) - call this%set_history_var(vname='FATES_GPP_USTORY', & - units='kg m-2 s-1', & - long='gross primary production of understory plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_gpp_understory_si) - call this%set_history_var(vname='FATES_AUTORESP_USTORY', & - units='kg m-2 s-1', & - long='autotrophic respiration of understory plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_ar_understory_si) + ! Carbon Flux (grid dimension x scpf) (THESE ARE DEFAULT INACTIVE!!! + ! (BECAUSE THEY TAKE UP SPACE!!! + ! =================================================================================== + call this%set_history_var(vname='FATES_GPP_SZPF', units='kg m-2 s-1', & + long='gross primary production by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_gpp_si_scpf) - ! This next group are multidimensional variables that are updated - ! over the short timestep. We turn off these variables when we want - ! to save time (and some space) - - if_include_hifr_multi: if (hio_include_hifr_multi) then + call this%set_history_var(vname='FATES_GPP_CANOPY_SZPF', & + units='kg m-2 s-1', & + long='gross primary production of canopy plants by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_gpp_canopy_si_scpf) - call this%set_history_var(vname='FATES_NPP_AP', units='kg m-2 s-1', & - long='net primary productivity by age bin in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_si_age) + call this%set_history_var(vname='FATES_AUTORESP_CANOPY_SZPF', & + units='kg m-2 s-1', & + long='autotrophic respiration of canopy plants by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_canopy_si_scpf) - call this%set_history_var(vname='FATES_GPP_AP', units='kg m-2 s-1', & - long='gross primary productivity by age bin in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_gpp_si_age) + call this%set_history_var(vname='FATES_GPP_USTORY_SZPF', & + units='kg m-2 s-1', & + long='gross primary production of understory plants by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_gpp_understory_si_scpf) - call this%set_history_var(vname='FATES_RDARK_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='dark respiration for understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_rdark_understory_si_scls) + call this%set_history_var(vname='FATES_AUTORESP_USTORY_SZPF', & + units='kg m-2 s-1', & + long='autotrophic respiration of understory plants by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_understory_si_scpf) - call this%set_history_var(vname='FATES_LSTEMMAINTAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='live stem maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_livestem_mr_understory_si_scls) + call this%set_history_var(vname='FATES_NPP_SZPF', units='kg m-2 s-1', & + long='total net primary production by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_totl_si_scpf) - call this%set_history_var(vname='FATES_CROOTMAINTAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='live coarse root maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_livecroot_mr_understory_si_scls) + call this%set_history_var(vname='FATES_LEAF_ALLOC_SZPF', units='kg m-2 s-1', & + long='allocation to leaves by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_leaf_si_scpf) - call this%set_history_var(vname='FATES_FROOTMAINTAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='fine root maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_froot_mr_understory_si_scls) + call this%set_history_var(vname='FATES_SEED_ALLOC_SZPF', units='kg m-2 s-1', & + long='allocation to seeds by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_seed_si_scpf) - call this%set_history_var(vname='FATES_GROWAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='growth autotrophic respiration of understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_resp_g_understory_si_scls) + call this%set_history_var(vname='FATES_FROOT_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to fine roots by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_fnrt_si_scpf) - call this%set_history_var(vname='FATES_MAINTAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='maintenance autotrophic respiration of understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', & - upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_resp_m_understory_si_scls) + call this%set_history_var(vname='FATES_BGSAPWOOD_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to below-ground sapwood by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_bgsw_si_scpf) - call this%set_history_var(vname='FATES_RDARK_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='dark respiration for canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_rdark_canopy_si_scls) + call this%set_history_var(vname='FATES_BGSTRUCT_ALLOC_SZPF', units='kg m-2 s-1', & + long='allocation to below-ground structural (deadwood) by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_bgdw_si_scpf) - call this%set_history_var(vname='FATES_CROOTMAINTAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_livecroot_mr_canopy_si_scls) + call this%set_history_var(vname='FATES_AGSAPWOOD_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to above-ground sapwood by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_agsw_si_scpf) - call this%set_history_var(vname='FATES_FROOTMAINTAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_froot_mr_canopy_si_scls) + call this%set_history_var(vname = 'FATES_AGSTRUCT_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to above-ground structural (deadwood) by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_agdw_si_scpf) - call this%set_history_var(vname='FATES_GROWAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='growth autotrophic respiration of canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_resp_g_canopy_si_scls) + call this%set_history_var(vname = 'FATES_STORE_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to storage C by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stor_si_scpf) - call this%set_history_var(vname='FATES_MAINTAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='maintenance autotrophic respiration of canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_resp_m_canopy_si_scls) + call this%set_history_var(vname='FATES_DDBH_SZPF', units = 'm m-2 yr-1', & + long='diameter growth increment by pft/size', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_ddbh_si_scpf) - call this%set_history_var(vname='FATES_LSTEMMAINTAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='live stem maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_livestem_mr_canopy_si_scls) + call this%set_history_var(vname='FATES_GROWTHFLUX_SZPF', & + units = 'm-2 yr-1', & + long='flux of individuals into a given size class bin via growth and recruitment', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_growthflux_si_scpf) - call this%set_history_var(vname='FATES_AUTORESP_SZPF', & - units = 'kg m-2 s-1', & - long='total autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_si_scpf) + call this%set_history_var(vname='FATES_GROWTHFLUX_FUSION_SZPF', & + units = 'm-2 yr-1', & + long='flux of individuals into a given size class bin via fusion', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_growthflux_fusion_si_scpf) - call this%set_history_var(vname='FATES_GROWAR_SZPF', & - units = 'kg m-2 s-1', & - long='growth autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_grow_si_scpf) + call this%set_history_var(vname='FATES_DDBH_CANOPY_SZPF', & + units = 'm m-2 yr-1', & + long='diameter growth increment by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_canopy_si_scpf) - call this%set_history_var(vname='FATES_MAINTAR_SZPF', & - units = 'kg m-2 s-1', & - long='maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_maint_si_scpf) + call this%set_history_var(vname='FATES_DDBH_USTORY_SZPF', & + units = 'm m-2 yr-1', & + long='diameter growth increment by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_understory_si_scpf) - call this%set_history_var(vname='FATES_RDARK_SZPF', & - units = 'kg m-2 s-1', & - long='dark portion of maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_darkm_si_scpf) + call this%set_history_var(vname='FATES_BASALAREA_SZPF', units = 'm2 m-2', & + long='basal area by pft/size', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_ba_si_scpf) - call this%set_history_var(vname='FATES_AGSAPMAINTAR_SZPF', & - units = 'kg m-2 s-1', & - long='above-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_agsapm_si_scpf) + call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND_SZPF', & + units = 'kg m-2', & + long='aboveground biomass by pft/size in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_agb_si_scpf) - call this%set_history_var(vname='FATES_BGSAPMAINTAR_SZPF', & - units = 'kg m-2 s-1', & - long='below-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_crootm_si_scpf) + call this%set_history_var(vname='FATES_NPLANT_SZPF', units = 'm-2', & + long='stem number density by pft/size', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_nplant_si_scpf) - call this%set_history_var(vname='FATES_FROOTMAINTAR_SZPF', & - units = 'kg m-2 s-1', & - long='fine root maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_frootm_si_scpf) + call this%set_history_var(vname='FATES_NPLANT_ACPF', units = 'm-2', & + long='stem number density by pft and age class', & + use_default='inactive', avgflag='A', vtype=site_coage_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_nplant_si_capf) - call this%set_history_var(vname='FATES_PARSUN_CLLL', units='W m-2', & - long='PAR absorbed in the sun by each canopy and leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_parsun_z_si_cnlf) + call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SZPF', & + units = 'm-2 yr-1', & + long='background mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m1_si_scpf) - call this%set_history_var(vname='FATES_PARSHA_CLLL', units='W m-2', & - long='PAR absorbed in the shade by each canopy and leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_parsha_z_si_cnlf) + call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SZPF', & + units = 'm-2 yr-1', & + long='hydraulic mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m2_si_scpf) - call this%set_history_var(vname='FATES_PARSUN_CLLLPF', units='W m-2', & - long='PAR absorbed in the sun by each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parsun_z_si_cnlfpft) + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZPF', & + units = 'm-2 yr-1', & + long='carbon starvation mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_si_scpf) - call this%set_history_var(vname='FATES_PARSHA_CLLLPF', units='W m-2', & - long='PAR absorbed in the shade by each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parsha_z_si_cnlfpft) + call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZPF', & + units = 'm-2 yr-1', & + long='impact mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m4_si_scpf) - call this%set_history_var(vname='FATES_PARSUN_CL', units='W m-2', & - long='PAR absorbed by sunlit leaves in each canopy layer', & - use_default='inactive', avgflag='A', vtype=site_can_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parsun_si_can ) + call this%set_history_var(vname='FATES_MORTALITY_FIRE_SZPF', & + units = 'm-2 yr-1', & + long='fire mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m5_si_scpf) - call this%set_history_var(vname='FATES_PARSHA_CL', units='W m-2', & - long='PAR absorbed by shaded leaves in each canopy layer', & - use_default='inactive', avgflag='A', vtype=site_can_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parsha_si_can) + call this%set_history_var(vname='FATES_MORTALITY_CROWNSCORCH_SZPF', & + units = 'm-2 yr-1', & + long='fire mortality from crown scorch by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_crownfiremort_si_scpf) - call this%set_history_var(vname='FATES_LAISUN_CLLL', units='m2 m-2', & - long='LAI in the sun by each canopy and leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisun_z_si_cnlf) + call this%set_history_var(vname='FATES_MORTALITY_CAMBIALBURN_SZPF', & + units = 'm-2 yr-1', & + long='fire mortality from cambial burn by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_cambialfiremort_si_scpf) - call this%set_history_var(vname='FATES_LAISHA_CLLL', units='m2 m-2', & - long='LAI in the shade by each canopy and leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisha_z_si_cnlf) + call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZPF', & + units = 'm-2 yr-1', & + long='termination mortality by pft/size in number pf plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m6_si_scpf) - call this%set_history_var(vname='FATES_LAISUN_CLLLPF', units='m2 m-2', & - long='Sunlit leaf area by each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisun_clllpf) + call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZPF', & + units = 'm-2 yr-1', & + long='logging mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_m7_si_scpf) - call this%set_history_var(vname='FATES_LAISHA_CLLLPF', units='m2 m-2', & - long='Shaded leaf area by each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisha_clllpf) + call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SZPF', & + units = 'm-2 yr-1', & + long='freezing mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m8_si_scpf) - call this%set_history_var(vname='FATES_PARPROF_DIR_CLLLPF', units='W m-2', & - long='radiative profile of direct PAR through each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parprof_dir_si_cnlfpft) + call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SZPF', & + units = 'm-2 yr-1', & + long='senescence mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m9_si_scpf) - call this%set_history_var(vname='FATES_PARPROF_DIF_CLLLPF', units='W m-2', & - long='radiative profile of diffuse PAR through each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parprof_dif_si_cnlfpft) + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SZPF', & + units = 'm-2 yr-1', & + long='age senescence mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype =site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_m10_si_scpf) - call this%set_history_var(vname='FATES_LAISUN_CL', units='m2 m-2', & - long='LAI of sunlit leaves by canopy layer', & - use_default='inactive', avgflag='A', vtype=site_can_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisun_si_can) + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_ACPF', & + units='m-2 yr-1', & + long='age senescence mortality by pft/cohort age in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype =site_coage_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index =ih_m10_si_capf) - call this%set_history_var(vname='FATES_LAISHA_CL', units='m2 m-2', & - long='LAI of shaded leaves by canopy layer', & - use_default='inactive', avgflag='A', vtype=site_can_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisha_si_can) + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZPF', & + units = 'm-2 yr-1', & + long='total mortality of canopy plants by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_canopy_si_scpf) - call this%set_history_var(vname='FATES_PARPROF_DIR_CLLL', units='W m-2', & - long='radiative profile of direct PAR through each canopy and leaf layer (averaged across PFTs)', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parprof_dir_si_cnlf) + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZPF', & + units = 'N/ha/yr', & + long='C starvation mortality of canopy plants by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scpf ) - call this%set_history_var(vname='FATES_PARPROF_DIF_CLLL', units='W m-2', & - long='radiative profile of diffuse PAR through each canopy and leaf layer (averaged across PFTs)', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parprof_dif_si_cnlf) + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZPF', & + units = 'N/ha/yr', & + long='C starvation mortality of understory plants by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_understory_si_scpf ) - ! canopy-resolved fluxes and structure + + call this%set_history_var(vname='FATES_C13DISC_SZPF', units = 'per mil', & + long='C13 discrimination by pft/size',use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_c13disc_si_scpf) - call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLL', & - units='kg m-2 s-1', & - long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_ts_net_uptake_si_cnlf) + call this%set_history_var(vname='FATES_STOREC_CANOPY_SZPF', units = 'kg m-2', & + long='biomass in storage pools of canopy plants by pft/size in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_bstor_canopy_si_scpf) - call this%set_history_var(vname='FATES_CROWNFRAC_CLLLPF', units='m2 m-2', & - long='area fraction of the canopy footprint occupied by each canopy-leaf-pft layer', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_crownfrac_clllpf) + call this%set_history_var(vname='FATES_LEAFC_CANOPY_SZPF', & + units = 'kg m-2', & + long='biomass in leaves of canopy plants by pft/size in kg carbon per m2', & + use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, & + index = ih_bleaf_canopy_si_scpf) - call this%set_history_var(vname='FATES_LBLAYER_COND_AP', & - units='mol m-2 s-1', & - long='mean leaf boundary layer conductance - by patch age', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_c_lblayer_si_age) + call this%set_history_var(vname='FATES_LAI_CANOPY_SZPF', & + units = 'm2 m-2', & + long='Leaf area index (LAI) of canopy plants by pft/size', & + use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, & + index = ih_lai_canopy_si_scpf ) - ! Canopy resistance - call this%set_history_var(vname='FATES_STOMATAL_COND_AP', & - units='mol m-2 s-1', long='mean stomatal conductance - by patch age', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_c_stomata_si_age) + call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZPF', units = 'm-2', & + long='number of canopy plants by size/pft per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_canopy_si_scpf) - end if if_include_hifr_multi - - call this%set_history_var(vname='FATES_CROWNAREA_CLLL', units='m2 m-2', & - long='area fraction of the total ground occupied by each canopy-leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_crownarea_si_cnlf) - - call this%set_history_var(vname='FATES_CROWNAREA_CL', units='m2 m-2', & - long='area fraction of the canopy footprint occupied by each canopy-leaf layer', use_default='active', & - avgflag='A', vtype=site_can_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_crownarea_cl) - - ! slow carbon fluxes associated with mortality from or transfer betweeen canopy and understory + call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZPF', & + units = 'm-2 yr-1', & + long='total mortality of understory plants by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, & + index = ih_mortality_understory_si_scpf) - call this%set_history_var(vname='FATES_DEMOTION_CARBONFLUX', & - units = 'kg m-2 s-1', & - long='demotion-associated biomass carbon flux from canopy to understory in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_demotion_carbonflux_si) + call this%set_history_var(vname='FATES_STOREC_USTORY_SZPF', & + units = 'kg m-2', & + long='biomass in storage pools of understory plants by pft/size in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_bstor_understory_si_scpf) - call this%set_history_var(vname='FATES_PROMOTION_CARBONFLUX', & - units = 'kg m-2 s-1', & - long='promotion-associated biomass carbon flux from understory to canopy in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_promotion_carbonflux_si) + call this%set_history_var(vname='FATES_LEAFC_USTORY_SZPF', & + units = 'kg m-2', & + long='biomass in leaves of understory plants by pft/size in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_bleaf_understory_si_scpf) - call this%set_history_var(vname='FATES_MORTALITY_CFLUX_CANOPY', & - units = 'kg m-2 s-1', & - long='flux of biomass carbon from live to dead pools from mortality of canopy plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_canopy_mortality_carbonflux_si) + call this%set_history_var(vname='FATES_LAI_USTORY_SZPF', & + units = 'm2 m-2', & + long='Leaf area index (LAI) of understory plants by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_lai_understory_si_scpf ) - call this%set_history_var(vname='FATES_MORTALITY_CFLUX_USTORY', & - units = 'kg m-2 s-1', & - long='flux of biomass carbon from live to dead pools from mortality of understory plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_understory_mortality_carbonflux_si) + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZPF', & + units = 'm-2', & + long='density of understory plants by pft/size in number of plants per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_understory_si_scpf) - call this%set_history_var(vname='FATES_MORTALITY_CFLUX_PF', units='kg m-2 s-1', & - long='PFT-level flux of biomass carbon from live to dead pool from mortality', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_mortality_carbonflux_si_pft) + call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_DC', units='kg m-2', & + long='debris class-level aboveground coarse woody debris stocks in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_ag_si_cwdsc) - call this%set_history_var(vname='FATES_MORTALITY_FIRE_CFLUX_PF', units='kg m-2 s-1', & - long='PFT-level flux of biomass carbon from live to dead pool from fire mortality', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_firemortality_carbonflux_si_pft) + call this%set_history_var(vname='FATES_CWD_BELOWGROUND_DC', units='kg m-2', & + long='debris class-level belowground coarse woody debris stocks in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_bg_si_cwdsc) - call this%set_history_var(vname='FATES_MORTALITY_HYDRO_CFLUX_PF', units='kg m-2 s-1', & - long='PFT-level flux of biomass carbon from live to dead pool from hydraulic failure mortality', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_hydraulicmortality_carbonflux_si_pft) + call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_IN_DC', & + units='kg m-2 s-1', & + long='debris class-level aboveground coarse woody debris input in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_ag_in_si_cwdsc) - call this%set_history_var(vname='FATES_MORTALITY_CSTARV_CFLUX_PF', units='kg m-2 s-1', & - long='PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_cstarvmortality_carbonflux_si_pft) + call this%set_history_var(vname='FATES_CWD_BELOWGROUND_IN_DC', & + units='kg m-2 s-1', & + long='debris class-level belowground coarse woody debris input in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_bg_in_si_cwdsc) - call this%set_history_var(vname='FATES_ABOVEGROUND_MORT_SZPF', units='kg m-2 s-1', & - long='Aboveground flux of carbon from AGB to necromass due to mortality', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_abg_mortality_cflux_si_scpf) + call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_OUT_DC', & + units='kg m-2 s-1', & + long='debris class-level aboveground coarse woody debris output in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_ag_out_si_cwdsc) - call this%set_history_var(vname='FATES_ABOVEGROUND_PROD_SZPF', units='kg m-2 s-1', & - long='Aboveground carbon productivity', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_abg_productivity_cflux_si_scpf) + call this%set_history_var(vname='FATES_CWD_BELOWGROUND_OUT_DC', & + units='kg m-2 s-1', & + long='debris class-level belowground coarse woody debris output in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_bg_out_si_cwdsc) - call this%set_history_var(vname='MORTALITY_CROWNAREA_CANOPY', & - units = 'm2/ha/year', & - long='Crown area of canopy trees that died', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_canopy_mortality_crownarea_si ) - call this%set_history_var(vname='MORTALITY_CROWNAREA_UNDERSTORY', & - units = 'm2/ha/year', & - long='Crown aera of understory trees that died', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_understory_mortality_crownarea_si ) - - ! size class by age dimensioned variables + ! size-class only variables - call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & - long='number of plants per m2 in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & + call this%set_history_var(vname='FATES_DDBH_CANOPY_SZ', & + units = 'm m-2 yr-1', long='diameter growth increment by size of canopy plants', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_si_scag) + initialize=initialize_variables, index = ih_ddbh_canopy_si_scls) - call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZAP', units = 'm-2', & - long='number of plants per m2 in canopy in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & + call this%set_history_var(vname='FATES_DDBH_USTORY_SZ', & + units = 'm m-2 yr-1', long='diameter growth increment by size of understory plants', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_canopy_si_scag) + initialize=initialize_variables, index = ih_ddbh_understory_si_scls) - call this%set_history_var(vname='FATES_NPLANT_USTORY_SZAP', & + call this%set_history_var(vname='FATES_YESTCANLEV_CANOPY_SZ', & units = 'm-2', & - long='number of plants per m2 in understory in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & + long='yesterdays canopy level for canopy plants by size class in number of plants per m2', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_understory_si_scag) + initialize=initialize_variables, & + index = ih_yesterdaycanopylevel_canopy_si_scls) - call this%set_history_var(vname='FATES_DDBH_CANOPY_SZAP', & - units = 'm m-2 yr-1', & - long='growth rate of canopy plants in meters DBH per m2 per year in canopy in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & + call this%set_history_var(vname='FATES_YESTCANLEV_USTORY_SZ', & + units = 'm-2', & + long='yesterdays canopy level for understory plants by size class in number of plants per m2', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_canopy_si_scag) + initialize=initialize_variables, & + index = ih_yesterdaycanopylevel_understory_si_scls) - call this%set_history_var(vname='FATES_DDBH_USTORY_SZAP', & - units = 'm m-2 yr-1', & - long='growth rate of understory plants in meters DBH per m2 per year in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_understory_si_scag) + call this%set_history_var(vname='FATES_BASALAREA_SZ', units = 'm2 m-2', & + long='basal area by size class', use_default='active', & + avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_ba_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZAP', & - units = 'm-2 yr-1', & - long='mortality rate of canopy plants in number of plants per m2 per year in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & + call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND_SZ', & + units = 'kg m-2', & + long='aboveground biomass by size class in kg carbon per m2', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_canopy_si_scag) + initialize=initialize_variables, index = ih_agb_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZAP', & - units = 'm-2 yr-1', & - long='mortality rate of understory plants in number of plants per m2 per year in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & + call this%set_history_var(vname='FATES_VEGC_SZ', units = 'kg m-2', & + long='total biomass by size class in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_understory_si_scag) - - ! size x age x pft dimensioned + initialize=initialize_variables, index = ih_biomass_si_scls) - call this%set_history_var(vname='FATES_NPLANT_SZAPPF',units = 'm-2', & - long='number of plants per m2 in each size x age x pft class', & - use_default='inactive', avgflag='A', vtype=site_scagpft_r8, & + call this%set_history_var(vname='FATES_DEMOTION_RATE_SZ', & + units = 'm-2 yr-1', & + long='demotion rate from canopy to understory by size class in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_si_scagpft) + initialize=initialize_variables, index = ih_demotion_rate_si_scls) - ! age x pft dimensioned - call this%set_history_var(vname='FATES_NPP_APPF',units = 'kg m-2 s-1', & - long='NPP per PFT in each age bin in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_agepft_r8, & + call this%set_history_var(vname='FATES_PROMOTION_RATE_SZ', & + units = 'm-2 yr-1', & + long='promotion rate from understory to canopy by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_si_agepft) + initialize=initialize_variables, index = ih_promotion_rate_si_scls) - call this%set_history_var(vname='FATES_VEGC_APPF',units = 'kg m-2', & - long='biomass per PFT in each age bin in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_agepft_r8, & + call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZ', & + units = 'm-2', & + long='number of canopy plants per m2 by size class', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_biomass_si_agepft) + initialize=initialize_variables, index = ih_nplant_canopy_si_scls) - call this%set_history_var(vname='FATES_SCORCH_HEIGHT_APPF',units = 'm', & - long='SPITFIRE flame Scorch Height (calculated per PFT in each patch age bin)', & - use_default='inactive', avgflag='A', vtype=site_agepft_r8, & + call this%set_history_var(vname='FATES_LAI_CANOPY_SZ', units = 'm2 m-2', & + long='leaf area index (LAI) of canopy plants by size class', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_scorch_height_si_agepft) - - - ! Carbon Flux (grid dimension x scpf) (THESE ARE DEFAULT INACTIVE!!! - ! (BECAUSE THEY TAKE UP SPACE!!! - ! =================================================================================== + initialize=initialize_variables, index = ih_lai_canopy_si_scls) - call this%set_history_var(vname='FATES_GPP_SZPF', units='kg m-2 s-1', & - long='gross primary production by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_SAI_CANOPY_SZ', units = 'm2 m-2', & + long='stem area index (SAI) of canopy plants by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_gpp_si_scpf) + initialize=initialize_variables, index = ih_sai_canopy_si_scls) - call this%set_history_var(vname='FATES_GPP_CANOPY_SZPF', & - units='kg m-2 s-1', & - long='gross primary production of canopy plants by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZ', & + units = 'm-2 yr-1', & + long='total mortality of canopy trees by size class in number of plants per m2', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_gpp_canopy_si_scpf) + initialize=initialize_variables, index = ih_mortality_canopy_si_scls) - call this%set_history_var(vname='FATES_AUTORESP_CANOPY_SZPF', & - units='kg m-2 s-1', & - long='autotrophic respiration of canopy plants by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SE_SZ', & + units = 'm-2 yr-1', & + long='total mortality of canopy trees by size class in number of plants per m2, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_canopy_si_scpf) + initialize=initialize_variables, index = ih_mortality_canopy_secondary_si_scls) - call this%set_history_var(vname='FATES_GPP_USTORY_SZPF', & - units='kg m-2 s-1', & - long='gross primary production of understory plants by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZ', & + units = 'm-2', & + long='number of understory plants per m2 by size class', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_gpp_understory_si_scpf) + initialize=initialize_variables, index = ih_nplant_understory_si_scls) - call this%set_history_var(vname='FATES_AUTORESP_USTORY_SZPF', & - units='kg m-2 s-1', & - long='autotrophic respiration of understory plants by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZ', & + units = 'N/ha/yr', & + long='C starvation mortality of canopy plants by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_understory_si_scpf) + initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scls ) - call this%set_history_var(vname='FATES_NPP_SZPF', units='kg m-2 s-1', & - long='total net primary production by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZ', & + units = 'N/ha/yr', & + long='C starvation mortality of understory plants by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_totl_si_scpf) + initialize=initialize_variables, index = ih_m3_mortality_understory_si_scls ) + + call this%set_history_var(vname='FATES_LAI_USTORY_SZ', & + units = 'm2 m-2', & + long='leaf area index (LAI) of understory plants by size class', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_lai_understory_si_scls) - call this%set_history_var(vname='FATES_LEAF_ALLOC_SZPF', units='kg m-2 s-1', & - long='allocation to leaves by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_SAI_USTORY_SZ', & + units = 'm2 m-2', & + long='stem area index (SAI) of understory plants by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_leaf_si_scpf) + initialize=initialize_variables, index = ih_sai_understory_si_scls) - call this%set_history_var(vname='FATES_SEED_ALLOC_SZPF', units='kg m-2 s-1', & - long='allocation to seeds by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_seed_si_scpf) + call this%set_history_var(vname='FATES_NPLANT_SZ', units = 'm-2', & + long='number of plants per m2 by size class', use_default='active', & + avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_scls) - call this%set_history_var(vname='FATES_FROOT_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to fine roots by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_NPLANT_AC', units = 'm-2', & + long='number of plants per m2 by cohort age class', & + use_default='active', avgflag='A', vtype=site_coage_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_fnrt_si_scpf) - - call this%set_history_var(vname='FATES_BGSAPWOOD_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to below-ground sapwood by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_bgsw_si_scpf) - - call this%set_history_var(vname='FATES_BGSTRUCT_ALLOC_SZPF', units='kg m-2 s-1', & - long='allocation to below-ground structural (deadwood) by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_bgdw_si_scpf) - - call this%set_history_var(vname='FATES_AGSAPWOOD_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to above-ground sapwood by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_agsw_si_scpf) + initialize=initialize_variables, index = ih_nplant_si_cacls) - call this%set_history_var(vname = 'FATES_AGSTRUCT_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to above-ground structural (deadwood) by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_agdw_si_scpf) + call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SZ', & + units = 'm-2 yr-1', & + long='background mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m1_si_scls) - call this%set_history_var(vname = 'FATES_STORE_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to storage C by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stor_si_scpf) + call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SZ', & + units = 'm-2 yr-1', & + long='hydraulic mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m2_si_scls) - call this%set_history_var(vname='FATES_DDBH_SZPF', units = 'm m-2 yr-1', & - long='diameter growth increment by pft/size', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_ddbh_si_scpf) + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZ', & + units = 'm-2 yr-1', & + long='carbon starvation mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_si_scls) - call this%set_history_var(vname='FATES_GROWTHFLUX_SZPF', & + call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SE_SZ', & units = 'm-2 yr-1', & - long='flux of individuals into a given size class bin via growth and recruitment', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + long='background mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_growthflux_si_scpf) + initialize=initialize_variables, index = ih_m1_sec_si_scls) - call this%set_history_var(vname='FATES_GROWTHFLUX_FUSION_SZPF', & + call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SE_SZ', & units = 'm-2 yr-1', & - long='flux of individuals into a given size class bin via fusion', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + long='hydraulic mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_growthflux_fusion_si_scpf) + initialize=initialize_variables, index = ih_m2_sec_si_scls) - call this%set_history_var(vname='FATES_DDBH_CANOPY_SZPF', & - units = 'm m-2 yr-1', & - long='diameter growth increment by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SE_SZ', & + units = 'm-2 yr-1', & + long='carbon starvation mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_canopy_si_scpf) + initialize=initialize_variables, index = ih_m3_sec_si_scls) - call this%set_history_var(vname='FATES_DDBH_USTORY_SZPF', & - units = 'm m-2 yr-1', & - long='diameter growth increment by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZ', & + units = 'm-2 yr-1', & + long='impact mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_understory_si_scpf) + initialize=initialize_variables, index = ih_m4_si_scls) - call this%set_history_var(vname='FATES_BASALAREA_SZPF', units = 'm2 m-2', & - long='basal area by pft/size', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_ba_si_scpf) + call this%set_history_var(vname='FATES_MORTALITY_FIRE_SZ', & + units = 'm-2 yr-1', & + long='fire mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m5_si_scls) - call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND_SZPF', & - units = 'kg m-2', & - long='aboveground biomass by pft/size in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_agb_si_scpf) + call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZ', & + units = 'm-2 yr-1', & + long='termination mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m6_si_scls) - call this%set_history_var(vname='FATES_NPLANT_SZPF', units = 'm-2', & - long='stem number density by pft/size', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_nplant_si_scpf) + call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZ', & + units = 'm-2 yr-1', & + long='logging mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m7_si_scls) - call this%set_history_var(vname='FATES_NPLANT_ACPF', units = 'm-2', & - long='stem number density by pft and age class', & - use_default='inactive', avgflag='A', vtype=site_coage_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_nplant_si_capf) + call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SZ', & + units = 'm-2 yr-1', & + long='freezing mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_m8_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SZPF', & + call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SZ', & units = 'm-2 yr-1', & - long='background mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + long='senescence mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m1_si_scpf) + initialize=initialize_variables, index = ih_m9_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SZPF', & + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SZ', & units = 'm-2 yr-1', & - long='hydraulic mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + long='age senescence mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m2_si_scpf) + initialize=initialize_variables, index = ih_m10_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZPF', & + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_AC', & units = 'm-2 yr-1', & - long='carbon starvation mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + long='age senescence mortality by cohort age in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_coage_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_si_scpf) + initialize=initialize_variables, index = ih_m10_si_cacls) - call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZPF', & + call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SE_SZ', & units = 'm-2 yr-1', & - long='impact mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + long='logging mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m4_si_scpf) + initialize=initialize_variables, index = ih_m7_sec_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_FIRE_SZPF', & - units = 'm-2 yr-1', & - long='fire mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SE_SZ', & + units = 'm-2 event-1', & + long='freezing mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m5_si_scpf) + initialize=initialize_variables, index = ih_m8_sec_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_CROWNSCORCH_SZPF', & + call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SE_SZ', & units = 'm-2 yr-1', & - long='fire mortality from crown scorch by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + long='senescence mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_crownfiremort_si_scpf) + initialize=initialize_variables, index = ih_m9_sec_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_CAMBIALBURN_SZPF', & + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SE_SZ', & units = 'm-2 yr-1', & - long='fire mortality from cambial burn by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + long='age senescence mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cambialfiremort_si_scpf) + initialize=initialize_variables, index = ih_m10_sec_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZPF', & - units = 'm-2 yr-1', & - long='termination mortality by pft/size in number pf plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_NPP_CANOPY_SZ', units = 'kg m-2 s-1', & + long='NPP of canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m6_si_scpf) + initialize=initialize_variables, & + index = ih_carbon_balance_canopy_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZPF', & - units = 'm-2 yr-1', & - long='logging mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_m7_si_scpf) + call this%set_history_var(vname='FATES_NPP_USTORY_SZ', units = 'kg m-2 s-1', & + long='NPP of understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, & + index = ih_carbon_balance_understory_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SZPF', & + call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZ', & units = 'm-2 yr-1', & - long='freezing mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + long='total mortality of understory trees by size class in individuals per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m8_si_scpf) + initialize=initialize_variables, & + index = ih_mortality_understory_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SZPF', & - units = 'm-2 yr-1', & - long='senescence mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_TRIMMING_CANOPY_SZ', units = 'm-2', & + long='trimming term of canopy plants weighted by plant density, by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m9_si_scpf) + initialize=initialize_variables, index = ih_trimming_canopy_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SZPF', & - units = 'm-2 yr-1', & - long='age senescence mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype =site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_m10_si_scpf) + call this%set_history_var(vname='FATES_TRIMMING_USTORY_SZ', & + units = 'm-2', & + long='trimming term of understory plants weighted by plant density, by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, & + index = ih_trimming_understory_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_ACPF', & - units='m-2 yr-1', & - long='age senescence mortality by pft/cohort age in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype =site_coage_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index =ih_m10_si_capf) + call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_SZ', units = 'm2 m-2', & + long='total crown area of canopy plants by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_crown_area_canopy_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZPF', & - units = 'm-2 yr-1', & - long='total mortality of canopy plants by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_CROWNAREA_USTORY_SZ', units = 'm2 m-2', & + long='total crown area of understory plants by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_canopy_si_scpf) + initialize=initialize_variables, index = ih_crown_area_understory_si_scls) - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZPF', & - units = 'N/ha/yr', & - long='C starvation mortality of canopy plants by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_LEAFCTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='leaf turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scpf ) + initialize=initialize_variables, index = ih_leaf_md_canopy_si_scls) - call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZPF', & - units = 'N/ha/yr', & - long='C starvation mortality of understory plants by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_FROOTCTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='fine root turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_mortality_understory_si_scpf ) + initialize=initialize_variables, index = ih_root_md_canopy_si_scls) - - call this%set_history_var(vname='FATES_C13DISC_SZPF', units = 'per mil', & - long='C13 discrimination by pft/size',use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_c13disc_si_scpf) + call this%set_history_var(vname='FATES_STORECTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='storage turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_bstore_md_canopy_si_scls) - call this%set_history_var(vname='FATES_STOREC_CANOPY_SZPF', units = 'kg m-2', & - long='biomass in storage pools of canopy plants by pft/size in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_STRUCTCTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='structural C turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bstor_canopy_si_scpf) + initialize=initialize_variables, index = ih_bdead_md_canopy_si_scls) - call this%set_history_var(vname='FATES_LEAFC_CANOPY_SZPF', & - units = 'kg m-2', & - long='biomass in leaves of canopy plants by pft/size in kg carbon per m2', & - use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, & - index = ih_bleaf_canopy_si_scpf) + call this%set_history_var(vname='FATES_SAPWOODCTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='sapwood turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_bsw_md_canopy_si_scls) - call this%set_history_var(vname='FATES_LAI_CANOPY_SZPF', & - units = 'm2 m-2', & - long='Leaf area index (LAI) of canopy plants by pft/size', & - use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, & - index = ih_lai_canopy_si_scpf ) + call this%set_history_var(vname='FATES_SEED_PROD_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='seed production of canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_seed_prod_canopy_si_scls) - call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZPF', units = 'm-2', & - long='number of canopy plants by size/pft per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_LEAF_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to leaves for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_leaf_canopy_si_scls) + + call this%set_history_var(vname='FATES_FROOT_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to fine root C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_fnrt_canopy_si_scls) + + call this%set_history_var(vname='FATES_SAPWOOD_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to sapwood C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_sapw_canopy_si_scls) + + call this%set_history_var(vname='FATES_STRUCT_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to structural C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_dead_canopy_si_scls) + + call this%set_history_var(vname='FATES_SEED_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to reproductive C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_seed_canopy_si_scls) + + call this%set_history_var(vname='FATES_STORE_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to storage C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stor_canopy_si_scls) + + call this%set_history_var(vname='FATES_LEAFCTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='leaf turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_canopy_si_scpf) + initialize=initialize_variables, & + index = ih_leaf_md_understory_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZPF', & - units = 'm-2 yr-1', & - long='total mortality of understory plants by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_FROOTCTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='fine root turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, & + index = ih_root_md_understory_si_scls) + + call this%set_history_var(vname='FATES_STORECTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='storage C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, & - index = ih_mortality_understory_si_scpf) + index = ih_bstore_md_understory_si_scls) - call this%set_history_var(vname='FATES_STOREC_USTORY_SZPF', & - units = 'kg m-2', & - long='biomass in storage pools of understory plants by pft/size in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_STRUCTCTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='structural C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bstor_understory_si_scpf) + initialize=initialize_variables, & + index = ih_bdead_md_understory_si_scls) - call this%set_history_var(vname='FATES_LEAFC_USTORY_SZPF', & - units = 'kg m-2', & - long='biomass in leaves of understory plants by pft/size in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_SAPWOODCTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='sapwood C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bleaf_understory_si_scpf) + initialize=initialize_variables, index = ih_bsw_md_understory_si_scls) - call this%set_history_var(vname='FATES_LAI_USTORY_SZPF', & - units = 'm2 m-2', & - long='Leaf area index (LAI) of understory plants by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + call this%set_history_var(vname='FATES_SEED_PROD_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='seed production of understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_lai_understory_si_scpf ) + initialize=initialize_variables, & + index = ih_seed_prod_understory_si_scls) - call this%set_history_var(vname='FATES_NPLANT_USTORY_SZPF', & - units = 'm-2', & - long='density of understory plants by pft/size in number of plants per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_understory_si_scpf) + call this%set_history_var(vname='FATES_LEAF_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to leaves for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_leaf_understory_si_scls) - call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_DC', units='kg m-2', & - long='debris class-level aboveground coarse woody debris stocks in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_ag_si_cwdsc) + call this%set_history_var(vname='FATES_FROOT_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to fine roots for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_fnrt_understory_si_scls) - call this%set_history_var(vname='FATES_CWD_BELOWGROUND_DC', units='kg m-2', & - long='debris class-level belowground coarse woody debris stocks in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_bg_si_cwdsc) + call this%set_history_var(vname='FATES_SAPWOOD_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to sapwood C for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_sapw_understory_si_scls) - call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_IN_DC', & - units='kg m-2 s-1', & - long='debris class-level aboveground coarse woody debris input in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_ag_in_si_cwdsc) + call this%set_history_var(vname='FATES_STRUCT_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to structural C for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_dead_understory_si_scls) - call this%set_history_var(vname='FATES_CWD_BELOWGROUND_IN_DC', & - units='kg m-2 s-1', & - long='debris class-level belowground coarse woody debris input in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_bg_in_si_cwdsc) + call this%set_history_var(vname='FATES_SEED_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to reproductive C for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_seed_understory_si_scls) - call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_OUT_DC', & - units='kg m-2 s-1', & - long='debris class-level aboveground coarse woody debris output in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_ag_out_si_cwdsc) + call this%set_history_var(vname='FATES_STORE_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to storage C for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stor_understory_si_scls) - call this%set_history_var(vname='FATES_CWD_BELOWGROUND_OUT_DC', & - units='kg m-2 s-1', & - long='debris class-level belowground coarse woody debris output in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_bg_out_si_cwdsc) + ! CROWN DAMAGE VARIABLES + if_crowndamage: if(hlm_use_tree_damage .eq. itrue) then + + call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 m-2 yr-1', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) + call this%set_history_var(vname='FATES_CROWNAREA_USTORY_CD', units = 'm2 m-2 yr-1', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) - ! size-class only variables + call this%set_history_var(vname='FATES_NPLANT_CDPF', units = 'm-2', & + long='N. plants per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdpf ) - call this%set_history_var(vname='FATES_DDBH_CANOPY_SZ', & - units = 'm m-2 yr-1', long='diameter growth increment by size of canopy plants', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_canopy_si_scls) + call this%set_history_var(vname='FATES_NPLANT_CANOPY_CDPF', units = 'm-2', & + long='N. plants per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_DDBH_USTORY_SZ', & - units = 'm m-2 yr-1', long='diameter growth increment by size of understory plants', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_understory_si_scls) + call this%set_history_var(vname='FATES_NPLANT_USTORY_CDPF', units = 'm-2', & + long='N. plants in the understory per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdpf ) - call this%set_history_var(vname='FATES_YESTCANLEV_CANOPY_SZ', & - units = 'm-2', & - long='yesterdays canopy level for canopy plants by size class in number of plants per m2', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_yesterdaycanopylevel_canopy_si_scls) + call this%set_history_var(vname='FATES_M3_CDPF', units = 'm-2 yr-1', & + long='carbon starvation mortality by damaage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdpf ) - call this%set_history_var(vname='FATES_YESTCANLEV_USTORY_SZ', & - units = 'm-2', & - long='yesterdays canopy level for understory plants by size class in number of plants per m2', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_yesterdaycanopylevel_understory_si_scls) + call this%set_history_var(vname='FATES_M11_SZPF', units = 'm-2 yr-1', & + long='damage mortality by pft/size',use_default='inactive', & + avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scpf ) - call this%set_history_var(vname='FATES_BASALAREA_SZ', units = 'm2 m-2', & - long='basal area by size class', use_default='active', & - avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_ba_si_scls) + call this%set_history_var(vname='FATES_M11_CDPF', units = 'm-2 yr-1', & + long='damage mortality by damaage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdpf ) - call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND_SZ', & - units = 'kg m-2', & - long='aboveground biomass by size class in kg carbon per m2', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_agb_si_scls) + call this%set_history_var(vname='FATES_MORTALITY_CDPF', units = 'm-2 yr-1', & + long='mortality by damage class by size by pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdpf ) - call this%set_history_var(vname='FATES_VEGC_SZ', units = 'kg m-2', & - long='total biomass by size class in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_biomass_si_scls) + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & + long='C starvation mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_DEMOTION_RATE_SZ', & - units = 'm-2 yr-1', & - long='demotion rate from canopy to understory by size class in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_demotion_rate_si_scls) + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & + long='C starvation mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdpf ) - call this%set_history_var(vname='FATES_PROMOTION_RATE_SZ', & - units = 'm-2 yr-1', & - long='promotion rate from understory to canopy by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_promotion_rate_si_scls) + call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & + long='damage mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZ', & - units = 'm-2', & - long='number of canopy plants per m2 by size class', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_canopy_si_scls) + call this%set_history_var(vname='FATES_M11_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & + long='damage mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdpf ) - call this%set_history_var(vname='FATES_LAI_CANOPY_SZ', units = 'm2 m-2', & - long='leaf area index (LAI) of canopy plants by size class', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_lai_canopy_si_scls) + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & + long='mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_cdpf ) - call this%set_history_var(vname='FATES_SAI_CANOPY_SZ', units = 'm2 m-2', & - long='stem area index (SAI) of canopy plants by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sai_canopy_si_scls) + call this%set_history_var(vname='FATES_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & + long='mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='FATES_DDBH_CDPF', units = 'm m-2 yr-1', & + long='ddbh annual increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdpf ) + + call this%set_history_var(vname='FATES_DDBH_CANOPY_CDPF', units = 'm m-2 yr-1', & + long='ddbh annual canopy increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_canopy_si_cdpf ) + + call this%set_history_var(vname='FATES_DDBH_USTORY_CDPF', units = 'm m-2 yr-1', & + long='ddbh annual understory increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_understory_si_cdpf ) - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZ', & - units = 'm-2 yr-1', & - long='total mortality of canopy trees by size class in number of plants per m2', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_canopy_si_scls) + end if if_crowndamage + - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SE_SZ', & - units = 'm-2 yr-1', & - long='total mortality of canopy trees by size class in number of plants per m2, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & + call this%set_history_var(vname='FATES_FIRE_FLUX_EL', units='kg m-2 s-1', & + long='loss to atmosphere from fire by element in kg element per m2 per s', & + use_default='active', avgflag='A', vtype=site_elem_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_canopy_secondary_si_scls) + initialize=initialize_variables, index = ih_burn_flux_elem) + - call this%set_history_var(vname='FATES_NPLANT_USTORY_SZ', & - units = 'm-2', & - long='number of understory plants per m2 by size class', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_understory_si_scls) + call this%set_history_var(vname='FATES_ERROR_EL', units='kg s-1', & + long='total mass-balance error in kg per second by element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_err_fates_elem) - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZ', & - units = 'N/ha/yr', & - long='C starvation mortality of canopy plants by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & + 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, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scls ) + initialize=initialize_variables, index = ih_fines_ag_elem) - call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZ', & - units = 'N/ha/yr', & - long='C starvation mortality of understory plants by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_mortality_understory_si_scls ) - - call this%set_history_var(vname='FATES_LAI_USTORY_SZ', & - units = 'm2 m-2', & - long='leaf area index (LAI) of understory plants by size class', & - use_default='active', avgflag='A', vtype=site_size_r8, & + call this%set_history_var(vname='FATES_LITTER_BG_FINE_EL', units='kg m-2', & + long='mass of belowground litter in fines (fineroots) by element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_lai_understory_si_scls) + initialize=initialize_variables, index = ih_fines_bg_elem) - call this%set_history_var(vname='FATES_SAI_USTORY_SZ', & - units = 'm2 m-2', & - long='stem area index (SAI) of understory plants by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & + call this%set_history_var(vname='FATES_LITTER_BG_CWD_EL', units='kg m-2', & + long='mass of belowground litter in coarse woody debris (coarse roots) by element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sai_understory_si_scls) - - call this%set_history_var(vname='FATES_NPLANT_SZ', units = 'm-2', & - long='number of plants per m2 by size class', use_default='active', & - avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_scls) - - call this%set_history_var(vname='FATES_NPLANT_AC', units = 'm-2', & - long='number of plants per m2 by cohort age class', & - use_default='active', avgflag='A', vtype=site_coage_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_si_cacls) + initialize=initialize_variables, index = ih_cwd_bg_elem) - call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SZ', & - units = 'm-2 yr-1', & - long='background mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & + call this%set_history_var(vname='FATES_LITTER_AG_CWD_EL', units='kg m-2', & + long='mass of aboveground litter in coarse woody debris (trunks/branches/twigs) by element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m1_si_scls) + initialize=initialize_variables, index = ih_cwd_ag_elem) - call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SZ', & - units = 'm-2 yr-1', & - long='hydraulic mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & + call this%set_history_var(vname='FATES_LITTER_CWD_ELDC', units='kg m-2', & + long='total mass of litter in coarse woody debris by element and coarse woody debris size', & + use_default='active', avgflag='A', vtype=site_elcwd_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m2_si_scls) + initialize=initialize_variables, index = ih_cwd_elcwd) - call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZ', & - units = 'm-2 yr-1', & - long='carbon starvation mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_si_scls) + ! Mass states C/N/P SCPF dimensions + ! CARBON + call this%set_history_var(vname='FATES_VEGC_SZPF', units='kg m-2', & + long='total vegetation biomass in live plants by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_totvegc_scpf) - call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SE_SZ', & - units = 'm-2 yr-1', & - long='background mortality by size in number of plants per m2 per year, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m1_sec_si_scls) + call this%set_history_var(vname='FATES_LEAFC_SZPF', units='kg m-2', & + long='leaf carbon mass by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_leafc_scpf) - call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SE_SZ', & - units = 'm-2 yr-1', & - long='hydraulic mortality by size in number of plants per m2 per year, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m2_sec_si_scls) + call this%set_history_var(vname='FATES_FROOTC_SZPF', units='kg m-2', & + long='fine-root carbon mass by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fnrtc_scpf) - call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SE_SZ', & - units = 'm-2 yr-1', & - long='carbon starvation mortality by size in number of plants per m2 per year, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_sec_si_scls) + call this%set_history_var(vname='FATES_SAPWOODC_SZPF', units='kg m-2', & + long='sapwood carbon mass by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_sapwc_scpf) - call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZ', & - units = 'm-2 yr-1', & - long='impact mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m4_si_scls) + call this%set_history_var(vname='FATES_STOREC_SZPF', units='kg m-2', & + long='storage carbon mass by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_storec_scpf) - call this%set_history_var(vname='FATES_MORTALITY_FIRE_SZ', & - units = 'm-2 yr-1', & - long='fire mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m5_si_scls) + call this%set_history_var(vname='FATES_REPROC_SZPF', units='kg m-2', & + long='reproductive carbon mass (on plant) by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_reproc_scpf) + + HERE + - call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZ', & - units = 'm-2 yr-1', & - long='termination mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m6_si_scls) + if(hlm_hist_level_hifrq>0) then - call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZ', & - units = 'm-2 yr-1', & - long='logging mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m7_si_scls) + ! Canopy Resistance - call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SZ', & - units = 'm-2 yr-1', & - long='freezing mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m8_si_scls) + call this%set_history_var(vname='FATES_STOMATAL_COND', & + units='mol m-2 s-1', long='mean stomatal conductance', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_c_stomata_si) - call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SZ', & - units = 'm-2 yr-1', & - long='senescence mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m9_si_scls) + call this%set_history_var(vname='FATES_LBLAYER_COND', units='mol m-2 s-1', & + long='mean leaf boundary layer conductance', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_c_lblayer_si) - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SZ', & - units = 'm-2 yr-1', & - long='age senescence mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m10_si_scls) + ! Temperature - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_AC', & - units = 'm-2 yr-1', & - long='age senescence mortality by cohort age in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_coage_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m10_si_cacls) + call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & + long='fates instantaneous mean vegetation temperature by site', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) - call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SE_SZ', & - units = 'm-2 yr-1', & - long='logging mortality by size in number of plants per m2 per event, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m7_sec_si_scls) + ! radiation error + call this%set_history_var(vname='FATES_RAD_ERROR', units='W m-2 ', & + long='radiation error in FATES RTM', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_rad_error_si) - call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SE_SZ', & - units = 'm-2 event-1', & - long='freezing mortality by size in number of plants per m2 per event, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m8_sec_si_scls) + call this%set_history_var(vname='FATES_VIS_SOLVE_ERROR', units='-', & + long='mean two-stream solver error for VIS', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_vis_solve_err_si) + + call this%set_history_var(vname='FATES_NIR_SOLVE_ERROR', units='-', & + long='mean two-stream solver error for NIR', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_nir_solve_err_si) + + call this%set_history_var(vname='FATES_VIS_CONSV_ERROR', units='-', & + long='mean two-stream conservation error for VIS', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_vis_consv_err_si) - call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SE_SZ', & - units = 'm-2 yr-1', & - long='senescence mortality by size in number of plants per m2 per event, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m9_sec_si_scls) + call this%set_history_var(vname='FATES_NIR_CONSV_ERROR', units='-', & + long='mean two-stream conservation error for NIR', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_nir_consv_err_si) - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SE_SZ', & - units = 'm-2 yr-1', & - long='age senescence mortality by size in number of plants per m2 per year, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m10_sec_si_scls) + call this%set_history_var(vname='FATES_AR', units='gC/m^2/s', & + long='autotrophic respiration', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_aresp_si ) + ! Ecosystem Carbon Fluxes (updated rapidly, upfreq=2) - call this%set_history_var(vname='FATES_NPP_CANOPY_SZ', units = 'kg m-2 s-1', & - long='NPP of canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_carbon_balance_canopy_si_scls) + call this%set_history_var(vname='FATES_NPP', units='kg m-2 s-1', & + long='net primary production in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_si) - call this%set_history_var(vname='FATES_NPP_USTORY_SZ', units = 'kg m-2 s-1', & - long='NPP of understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_carbon_balance_understory_si_scls) + call this%set_history_var(vname='FATES_NPP_SECONDARY', units='kg m-2 s-1', & + long='net primary production in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_secondary_si) - call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZ', & - units = 'm-2 yr-1', & - long='total mortality of understory trees by size class in individuals per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_mortality_understory_si_scls) + call this%set_history_var(vname='FATES_GPP', units='kg m-2 s-1', & + long='gross primary production in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_si) - call this%set_history_var(vname='FATES_TRIMMING_CANOPY_SZ', units = 'm-2', & - long='trimming term of canopy plants weighted by plant density, by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_trimming_canopy_si_scls) + call this%set_history_var(vname='FATES_GPP_SECONDARY', units='kg m-2 s-1', & + long='gross primary production in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_secondary_si) - call this%set_history_var(vname='FATES_TRIMMING_USTORY_SZ', & - units = 'm-2', & - long='trimming term of understory plants weighted by plant density, by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_trimming_understory_si_scls) + call this%set_history_var(vname='FATES_AUTORESP', units='kg m-2 s-1', & + long='autotrophic respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_si) - call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_SZ', units = 'm2 m-2', & - long='total crown area of canopy plants by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_crown_area_canopy_si_scls) + call this%set_history_var(vname='FATES_AUTORESP_SECONDARY', units='kg m-2 s-1', & + long='autotrophic respiration in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_secondary_si) - call this%set_history_var(vname='FATES_CROWNAREA_USTORY_SZ', units = 'm2 m-2', & - long='total crown area of understory plants by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_crown_area_understory_si_scls) + call this%set_history_var(vname='FATES_GROWTH_RESP', units='kg m-2 s-1', & + long='growth respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_growth_resp_si) - call this%set_history_var(vname='FATES_LEAFCTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='leaf turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_leaf_md_canopy_si_scls) + call this%set_history_var(vname='FATES_GROWTH_RESP_SECONDARY', units='kg m-2 s-1', & + long='growth respiration in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_growth_resp_secondary_si) - call this%set_history_var(vname='FATES_FROOTCTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='fine root turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_root_md_canopy_si_scls) + call this%set_history_var(vname='FATES_MAINT_RESP', units='kg m-2 s-1', & + long='maintenance respiration in kg carbon per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_maint_resp_si) - call this%set_history_var(vname='FATES_STORECTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='storage turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bstore_md_canopy_si_scls) + call this%set_history_var(vname='FATES_MAINT_RESP_UNREDUCED', units='kg m-2 s-1', & + long='diagnostic maintenance respiration if the low-carbon-storage reduction is ignored', & + use_default='unactive', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_maint_resp_unreduced_si) - call this%set_history_var(vname='FATES_STRUCTCTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='structural C turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bdead_md_canopy_si_scls) + call this%set_history_var(vname='FATES_MAINT_RESP_SECONDARY', units='kg m-2 s-1', & + long='maintenance respiration in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_maint_resp_secondary_si) - call this%set_history_var(vname='FATES_SAPWOODCTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='sapwood turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bsw_md_canopy_si_scls) + call this%set_history_var(vname='FATES_AR_CANOPY', units='gC/m^2/s', & + long='autotrophic respiration of canopy plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_ar_canopy_si ) - call this%set_history_var(vname='FATES_SEED_PROD_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='seed production of canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_seed_prod_canopy_si_scls) + call this%set_history_var(vname='FATES_AR_UNDERSTORY', units='gC/m^2/s', & + long='autotrophic respiration of understory plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_ar_understory_si ) - call this%set_history_var(vname='FATES_LEAF_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to leaves for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_leaf_canopy_si_scls) + ! fast fluxes separated canopy/understory + call this%set_history_var(vname='FATES_GPP_CANOPY', units='kg m-2 s-1', & + long='gross primary production of canopy plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_gpp_canopy_si) - call this%set_history_var(vname='FATES_FROOT_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to fine root C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_fnrt_canopy_si_scls) + call this%set_history_var(vname='FATES_AUTORESP_CANOPY', & + units='kg m-2 s-1', & + long='autotrophic respiration of canopy plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_ar_canopy_si) - call this%set_history_var(vname='FATES_SAPWOOD_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to sapwood C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_sapw_canopy_si_scls) + call this%set_history_var(vname='FATES_GPP_USTORY', & + units='kg m-2 s-1', & + long='gross primary production of understory plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_gpp_understory_si) - call this%set_history_var(vname='FATES_STRUCT_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to structural C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_dead_canopy_si_scls) + call this%set_history_var(vname='FATES_AUTORESP_USTORY', & + units='kg m-2 s-1', & + long='autotrophic respiration of understory plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_ar_understory_si) - call this%set_history_var(vname='FATES_SEED_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to reproductive C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_seed_canopy_si_scls) - call this%set_history_var(vname='FATES_STORE_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to storage C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stor_canopy_si_scls) call this%set_history_var(vname='FATES_LEAFMAINTAR', & units = 'kg m-2 s-1', & @@ -8419,351 +8456,339 @@ subroutine define_history_vars(this, initialize_variables) long='live coarse root maintenance autotrophic respiration in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_livecroot_mr_si) - - call this%set_history_var(vname='FATES_LSTEMMAINTAR', & - units = 'kg m-2 s-1', & - long='live stem maintenance autotrophic respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_livestem_mr_si) - - - - - - - - call this%set_history_var(vname='FATES_LEAFCTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='leaf turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_leaf_md_understory_si_scls) - - call this%set_history_var(vname='FATES_FROOTCTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='fine root turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_root_md_understory_si_scls) - - call this%set_history_var(vname='FATES_STORECTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='storage C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_bstore_md_understory_si_scls) - - call this%set_history_var(vname='FATES_STRUCTCTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='structural C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_bdead_md_understory_si_scls) - - call this%set_history_var(vname='FATES_SAPWOODCTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='sapwood C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bsw_md_understory_si_scls) + index = ih_livecroot_mr_si) - call this%set_history_var(vname='FATES_SEED_PROD_USTORY_SZ', & + call this%set_history_var(vname='FATES_LSTEMMAINTAR', & units = 'kg m-2 s-1', & - long='seed production of understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_seed_prod_understory_si_scls) + long='live stem maintenance autotrophic respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_livestem_mr_si) - call this%set_history_var(vname='FATES_LEAF_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to leaves for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_leaf_understory_si_scls) + call this%set_history_var(vname='FATES_NEP', units='kg m-2 s-1', & + long='net ecosystem production in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, & + index = ih_nep_si) - call this%set_history_var(vname='FATES_FROOT_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to fine roots for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_fnrt_understory_si_scls) + call this%set_history_var(vname='FATES_HET_RESP', units='kg m-2 s-1', & + long='heterotrophic respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_hr_si) - call this%set_history_var(vname='FATES_SAPWOOD_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to sapwood C for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_sapw_understory_si_scls) + + HERE + + if(hlm_hist_level_hifrq>1) then + + call this%set_history_var(vname='FATES_VIS_SOLVE_ERROR_AGE', units='-', & + long='mean two-stream solver error for VIS by patch age', use_default='active', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_vis_solve_err_age_si) - call this%set_history_var(vname='FATES_STRUCT_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to structural C for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_dead_understory_si_scls) + call this%set_history_var(vname='FATES_NIR_SOLVE_ERROR_AGE', units='-', & + long='mean two-stream solver error for NIR by patch age', use_default='active', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_nir_solve_err_age_si) - call this%set_history_var(vname='FATES_SEED_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to reproductive C for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_seed_understory_si_scls) + call this%set_history_var(vname='FATES_VIS_CONSV_ERROR_AGE', units='-', & + long='mean two-stream conservation error for VIS by patch age', use_default='active', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_vis_consv_err_age_si) + + call this%set_history_var(vname='FATES_NIR_CONSV_ERROR_AGE', units='-', & + long='mean two-stream conservation error for NIR by patch age', use_default='active', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & + ivar=ivar, initialize=initialize_variables, index = ih_nir_consv_err_age_si) + + ! This next group are multidimensional variables that are updated + ! over the short timestep. We turn off these variables when we want + ! to save time (and some space) - call this%set_history_var(vname='FATES_STORE_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to storage C for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stor_understory_si_scls) + call this%set_history_var(vname='FATES_NPP_AP', units='kg m-2 s-1', & + long='net primary productivity by age bin in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_si_age) + call this%set_history_var(vname='FATES_GPP_AP', units='kg m-2 s-1', & + long='gross primary productivity by age bin in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_gpp_si_age) + call this%set_history_var(vname='FATES_RDARK_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='dark respiration for understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_rdark_understory_si_scls) - ! CROWN DAMAGE VARIABLES - if_crowndamage: if(hlm_use_tree_damage .eq. itrue) then - - call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 m-2 yr-1', & - long='crownarea lost to damage each year', use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) + call this%set_history_var(vname='FATES_LSTEMMAINTAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='live stem maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, & + index = ih_livestem_mr_understory_si_scls) - call this%set_history_var(vname='FATES_CROWNAREA_USTORY_CD', units = 'm2 m-2 yr-1', & - long='crownarea lost to damage each year', use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) + call this%set_history_var(vname='FATES_CROOTMAINTAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='live coarse root maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, & + index = ih_livecroot_mr_understory_si_scls) - call this%set_history_var(vname='FATES_NPLANT_CDPF', units = 'm-2', & - long='N. plants per damage x size x pft class', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdpf ) + call this%set_history_var(vname='FATES_FROOTMAINTAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='fine root maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, & + index = ih_froot_mr_understory_si_scls) - call this%set_history_var(vname='FATES_NPLANT_CANOPY_CDPF', units = 'm-2', & - long='N. plants per damage x size x pft class', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdpf ) + call this%set_history_var(vname='FATES_GROWAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='growth autotrophic respiration of understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_resp_g_understory_si_scls) - call this%set_history_var(vname='FATES_NPLANT_USTORY_CDPF', units = 'm-2', & - long='N. plants in the understory per damage x size x pft class', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdpf ) + call this%set_history_var(vname='FATES_MAINTAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='maintenance autotrophic respiration of understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', & + upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_resp_m_understory_si_scls) - call this%set_history_var(vname='FATES_M3_CDPF', units = 'm-2 yr-1', & - long='carbon starvation mortality by damaage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdpf ) + call this%set_history_var(vname='FATES_RDARK_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='dark respiration for canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_rdark_canopy_si_scls) - call this%set_history_var(vname='FATES_M11_SZPF', units = 'm-2 yr-1', & - long='damage mortality by pft/size',use_default='inactive', & - avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scpf ) + call this%set_history_var(vname='FATES_CROOTMAINTAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, & + index = ih_livecroot_mr_canopy_si_scls) - call this%set_history_var(vname='FATES_M11_CDPF', units = 'm-2 yr-1', & - long='damage mortality by damaage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdpf ) + call this%set_history_var(vname='FATES_FROOTMAINTAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_froot_mr_canopy_si_scls) - call this%set_history_var(vname='FATES_MORTALITY_CDPF', units = 'm-2 yr-1', & - long='mortality by damage class by size by pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdpf ) + call this%set_history_var(vname='FATES_GROWAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='growth autotrophic respiration of canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_resp_g_canopy_si_scls) - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & - long='C starvation mortality of canopy plants by damage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdpf ) + call this%set_history_var(vname='FATES_MAINTAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='maintenance autotrophic respiration of canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_resp_m_canopy_si_scls) - call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & - long='C starvation mortality of understory plants by pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdpf ) + call this%set_history_var(vname='FATES_LSTEMMAINTAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='live stem maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, & + index = ih_livestem_mr_canopy_si_scls) - call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & - long='damage mortality of canopy plants by damage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdpf ) + call this%set_history_var(vname='FATES_AUTORESP_SZPF', & + units = 'kg m-2 s-1', & + long='total autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_si_scpf) - call this%set_history_var(vname='FATES_M11_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & - long='damage mortality of understory plants by pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdpf ) + call this%set_history_var(vname='FATES_GROWAR_SZPF', & + units = 'kg m-2 s-1', & + long='growth autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_grow_si_scpf) - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & - long='mortality of canopy plants by damage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_cdpf ) + call this%set_history_var(vname='FATES_MAINTAR_SZPF', & + units = 'kg m-2 s-1', & + long='maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_maint_si_scpf) + + call this%set_history_var(vname='FATES_RDARK_SZPF', & + units = 'kg m-2 s-1', & + long='dark portion of maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_darkm_si_scpf) + + call this%set_history_var(vname='FATES_AGSAPMAINTAR_SZPF', & + units = 'kg m-2 s-1', & + long='above-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_agsapm_si_scpf) - call this%set_history_var(vname='FATES_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & - long='mortality of understory plants by pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_cdpf ) + call this%set_history_var(vname='FATES_BGSAPMAINTAR_SZPF', & + units = 'kg m-2 s-1', & + long='below-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_crootm_si_scpf) - call this%set_history_var(vname='FATES_DDBH_CDPF', units = 'm m-2 yr-1', & - long='ddbh annual increment growth by damage x size pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdpf ) + call this%set_history_var(vname='FATES_FROOTMAINTAR_SZPF', & + units = 'kg m-2 s-1', & + long='fine root maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_frootm_si_scpf) - call this%set_history_var(vname='FATES_DDBH_CANOPY_CDPF', units = 'm m-2 yr-1', & - long='ddbh annual canopy increment growth by damage x size pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_canopy_si_cdpf ) + call this%set_history_var(vname='FATES_PARSUN_CLLL', units='W m-2', & + long='PAR absorbed in the sun by each canopy and leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_parsun_z_si_cnlf) - call this%set_history_var(vname='FATES_DDBH_USTORY_CDPF', units = 'm m-2 yr-1', & - long='ddbh annual understory increment growth by damage x size pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_understory_si_cdpf ) + call this%set_history_var(vname='FATES_PARSHA_CLLL', units='W m-2', & + long='PAR absorbed in the shade by each canopy and leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_parsha_z_si_cnlf) - end if if_crowndamage - - ! CARBON BALANCE VARIABLES THAT DEPEND ON HLM BGC INPUTS + call this%set_history_var(vname='FATES_PARSUN_CLLLPF', units='W m-2', & + long='PAR absorbed in the sun by each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_parsun_z_si_cnlfpft) - call this%set_history_var(vname='FATES_NEP', units='kg m-2 s-1', & - long='net ecosystem production in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_nep_si) + call this%set_history_var(vname='FATES_PARSHA_CLLLPF', units='W m-2', & + long='PAR absorbed in the shade by each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_parsha_z_si_cnlfpft) - call this%set_history_var(vname='FATES_HET_RESP', units='kg m-2 s-1', & - long='heterotrophic respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_hr_si) + call this%set_history_var(vname='FATES_PARSUN_CL', units='W m-2', & + long='PAR absorbed by sunlit leaves in each canopy layer', & + use_default='inactive', avgflag='A', vtype=site_can_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_parsun_si_can ) - call this%set_history_var(vname='FATES_FIRE_CLOSS', units='kg m-2 s-1', & - long='carbon loss to atmosphere from fire in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_c_to_atm_si) + call this%set_history_var(vname='FATES_PARSHA_CL', units='W m-2', & + long='PAR absorbed by shaded leaves in each canopy layer', & + use_default='inactive', avgflag='A', vtype=site_can_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_parsha_si_can) - call this%set_history_var(vname='FATES_FIRE_FLUX_EL', units='kg m-2 s-1', & - long='loss to atmosphere from fire by element in kg element per m2 per s', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_burn_flux_elem) + call this%set_history_var(vname='FATES_LAISUN_CLLL', units='m2 m-2', & + long='LAI in the sun by each canopy and leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_laisun_z_si_cnlf) - call this%set_history_var(vname='FATES_CBALANCE_ERROR', & - units='kg s-1', & - long='total carbon error in kg carbon per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_cbal_err_fates_si) + call this%set_history_var(vname='FATES_LAISHA_CLLL', units='m2 m-2', & + long='LAI in the shade by each canopy and leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_laisha_z_si_cnlf) - call this%set_history_var(vname='FATES_ERROR_EL', units='kg s-1', & - long='total mass-balance error in kg per second by element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_err_fates_elem) + call this%set_history_var(vname='FATES_LAISUN_CLLLPF', units='m2 m-2', & + long='Sunlit leaf area by each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_laisun_clllpf) - 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, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fines_ag_elem) + call this%set_history_var(vname='FATES_LAISHA_CLLLPF', units='m2 m-2', & + long='Shaded leaf area by each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_laisha_clllpf) - call this%set_history_var(vname='FATES_LITTER_BG_FINE_EL', units='kg m-2', & - long='mass of belowground litter in fines (fineroots) by element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fines_bg_elem) + call this%set_history_var(vname='FATES_PARPROF_DIR_CLLLPF', units='W m-2', & + long='radiative profile of direct PAR through each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_parprof_dir_si_cnlfpft) - call this%set_history_var(vname='FATES_LITTER_BG_CWD_EL', units='kg m-2', & - long='mass of belowground litter in coarse woody debris (coarse roots) by element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_bg_elem) + call this%set_history_var(vname='FATES_PARPROF_DIF_CLLLPF', units='W m-2', & + long='radiative profile of diffuse PAR through each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_parprof_dif_si_cnlfpft) - call this%set_history_var(vname='FATES_LITTER_AG_CWD_EL', units='kg m-2', & - long='mass of aboveground litter in coarse woody debris (trunks/branches/twigs) by element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_ag_elem) + call this%set_history_var(vname='FATES_LAISUN_CL', units='m2 m-2', & + long='LAI of sunlit leaves by canopy layer', & + use_default='inactive', avgflag='A', vtype=site_can_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_laisun_si_can) - call this%set_history_var(vname='FATES_LITTER_CWD_ELDC', units='kg m-2', & - long='total mass of litter in coarse woody debris by element and coarse woody debris size', & - use_default='active', avgflag='A', vtype=site_elcwd_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_elcwd) + call this%set_history_var(vname='FATES_LAISHA_CL', units='m2 m-2', & + long='LAI of shaded leaves by canopy layer', & + use_default='inactive', avgflag='A', vtype=site_can_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_laisha_si_can) - ! Mass states C/N/P SCPF dimensions - ! CARBON - call this%set_history_var(vname='FATES_VEGC_SZPF', units='kg m-2', & - long='total vegetation biomass in live plants by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_totvegc_scpf) + call this%set_history_var(vname='FATES_PARPROF_DIR_CLLL', units='W m-2', & + long='radiative profile of direct PAR through each canopy and leaf layer (averaged across PFTs)', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_parprof_dir_si_cnlf) - call this%set_history_var(vname='FATES_LEAFC_SZPF', units='kg m-2', & - long='leaf carbon mass by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_leafc_scpf) + call this%set_history_var(vname='FATES_PARPROF_DIF_CLLL', units='W m-2', & + long='radiative profile of diffuse PAR through each canopy and leaf layer (averaged across PFTs)', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_parprof_dif_si_cnlf) - call this%set_history_var(vname='FATES_FROOTC_SZPF', units='kg m-2', & - long='fine-root carbon mass by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fnrtc_scpf) + ! canopy-resolved fluxes and structure - call this%set_history_var(vname='FATES_SAPWOODC_SZPF', units='kg m-2', & - long='sapwood carbon mass by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_sapwc_scpf) + call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLL', & + units='kg m-2 s-1', & + long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_ts_net_uptake_si_cnlf) - call this%set_history_var(vname='FATES_STOREC_SZPF', units='kg m-2', & - long='storage carbon mass by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_storec_scpf) + call this%set_history_var(vname='FATES_CROWNFRAC_CLLLPF', units='m2 m-2', & + long='area fraction of the canopy footprint occupied by each canopy-leaf-pft layer', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_crownfrac_clllpf) - call this%set_history_var(vname='FATES_REPROC_SZPF', units='kg m-2', & - long='reproductive carbon mass (on plant) by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_reproc_scpf) + call this%set_history_var(vname='FATES_LBLAYER_COND_AP', & + units='mol m-2 s-1', & + long='mean leaf boundary layer conductance - by patch age', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & + initialize=initialize_variables, index = ih_c_lblayer_si_age) - ! organ-partitioned NPP / allocation fluxes + ! Canopy resistance + call this%set_history_var(vname='FATES_STOMATAL_COND_AP', & + units='mol m-2 s-1', long='mean stomatal conductance - by patch age', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & + index = ih_c_stomata_si_age) - 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', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_leaf_si) - call this%set_history_var(vname='FATES_SEED_ALLOC', units='kg m-2 s-1', & - long='allocation to seeds in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_seed_si) + HERE - call this%set_history_var(vname='FATES_STEM_ALLOC', units='kg m-2 s-1', & - long='allocation to stem in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stem_si) - call this%set_history_var(vname='FATES_FROOT_ALLOC', units='kg m-2 s-1', & - long='allocation to fine roots in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_froot_si) + ! organ-partitioned NPP / allocation fluxes - call this%set_history_var(vname='FATES_CROOT_ALLOC', units='kg m-2 s-1', & - long='allocation to coarse roots in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_croot_si) - call this%set_history_var(vname='FATES_STORE_ALLOC', units='kg m-2 s-1', & - long='allocation to storage tissues in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stor_si) ! PLANT HYDRAULICS From 34aa3c809a76d79da8d4d517a33c1bba38065c4e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 13 Nov 2023 12:49:49 -0500 Subject: [PATCH 064/300] tweaks/fixes to history density --- main/FatesHistoryInterfaceMod.F90 | 648 ++++++++++++++++-------------- 1 file changed, 352 insertions(+), 296 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index bb661ddd3e..9924e17df7 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -808,8 +808,10 @@ module FatesHistoryInterfaceMod procedure :: assemble_history_output_types procedure :: update_history_dyn - procedure :: update_history_hifrq_simple - procedure :: update_history_hifrq_multi + procedure :: update_history_dyn1 + procedure :: update_history_dyn2 + procedure :: update_history_hifrq1 + procedure :: update_history_hifrq2 procedure :: update_history_hydraulics procedure :: update_history_nutrflux @@ -4671,7 +4673,7 @@ end subroutine update_history_dyn2 ! =============================================================================================== - subroutine update_history_hifrq_simple(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) + subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) ! ! Arguments @@ -4699,6 +4701,11 @@ subroutine update_history_hifrq_simple(this,nc,nsites,sites,bc_in,bc_out,dt_tste type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort + + ! This routine is only called for hlm_hist_level_hifrq >= 1 + if(hlm_hist_level_hifrq<1) return + + associate( hio_gpp_si => this%hvars(ih_gpp_si)%r81d, & hio_gpp_secondary_si => this%hvars(ih_gpp_secondary_si)%r81d, & hio_npp_si => this%hvars(ih_npp_si)%r81d, & @@ -4968,11 +4975,11 @@ subroutine update_history_hifrq_simple(this,nc,nsites,sites,bc_in,bc_out,dt_tste end associate return - end subroutine update_history_hifrq_simple + end subroutine update_history_hifrq1 ! =============================================================================================== - subroutine update_history_hifrq_multi(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) + subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) ! --------------------------------------------------------------------------------- ! This is the call to update the history IO arrays for multi-dimension arrays @@ -5014,8 +5021,9 @@ subroutine update_history_hifrq_multi(this,nc,nsites,sites,bc_in,bc_out,dt_tstep type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort real(r8) :: dt_tstep_inv ! Time step in frequency units (/s) - - if(.not.hio_include_hifr_multi) return + + ! This routine is only called for hlm_hist_level_hifrq >= 1 + if(hlm_hist_level_hifrq<2) return associate( hio_ar_si_scpf => this%hvars(ih_ar_si_scpf)%r82d, & hio_ar_grow_si_scpf => this%hvars(ih_ar_grow_si_scpf)%r82d, & @@ -5419,7 +5427,7 @@ subroutine update_history_hifrq_multi(this,nc,nsites,sites,bc_in,bc_out,dt_tstep end associate - end subroutine update_history_hifrq_multi + end subroutine update_history_hifrq2 ! ===================================================================================== @@ -5497,69 +5505,28 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) per_dt_tstep = 1._r8 / dt_tstep - if(hlm_hist_level_hifrq>0) then - + !!if_hifrq0: if(hlm_hist_level_hifrq>0) then associate( hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d, & hio_rootwgt_soilvwc_si => this%hvars(ih_rootwgt_soilvwc_si)%r81d, & hio_rootwgt_soilvwcsat_si => this%hvars(ih_rootwgt_soilvwcsat_si)%r81d, & hio_rootwgt_soilmatpot_si => this%hvars(ih_rootwgt_soilmatpot_si)%r81d, & hio_sapflow_si => this%hvars(ih_sapflow_si)%r81d, & - hio_rootuptake_si => this%hvars(ih_rootuptake_si)%r81d ) + hio_rootuptake_si => this%hvars(ih_rootuptake_si)%r81d, & + hio_h2oveg_si => this%hvars(ih_h2oveg_si)%r81d ) - associate( hio_errh2o_scpf => this%hvars(ih_errh2o_scpf)%r82d, & - hio_tran_scpf => this%hvars(ih_tran_scpf)%r82d, & - hio_sapflow_scpf => this%hvars(ih_sapflow_scpf)%r82d, & - hio_iterh1_scpf => this%hvars(ih_iterh1_scpf)%r82d, & - hio_iterh2_scpf => this%hvars(ih_iterh2_scpf)%r82d, & - hio_ath_scpf => this%hvars(ih_ath_scpf)%r82d, & - hio_tth_scpf => this%hvars(ih_tth_scpf)%r82d, & - hio_sth_scpf => this%hvars(ih_sth_scpf)%r82d, & - hio_lth_scpf => this%hvars(ih_lth_scpf)%r82d, & - hio_awp_scpf => this%hvars(ih_awp_scpf)%r82d, & - hio_twp_scpf => this%hvars(ih_twp_scpf)%r82d, & - hio_swp_scpf => this%hvars(ih_swp_scpf)%r82d, & - hio_lwp_scpf => this%hvars(ih_lwp_scpf)%r82d, & - hio_aflc_scpf => this%hvars(ih_aflc_scpf)%r82d, & - hio_tflc_scpf => this%hvars(ih_tflc_scpf)%r82d, & - hio_sflc_scpf => this%hvars(ih_sflc_scpf)%r82d, & - hio_lflc_scpf => this%hvars(ih_lflc_scpf)%r82d, & - hio_btran_scpf => this%hvars(ih_btran_scpf)%r82d, & - hio_h2oveg_si => this%hvars(ih_h2oveg_si)%r81d, & - hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & - hio_nplant_si_capf => this%hvars(ih_nplant_si_capf)%r82d, & - hio_soilmatpot_sl => this%hvars(ih_soilmatpot_sl)%r82d, & - hio_soilvwc_sl => this%hvars(ih_soilvwc_sl)%r82d, & - hio_soilvwcsat_sl => this%hvars(ih_soilvwcsat_sl)%r82d, & - hio_rootuptake_sl => this%hvars(ih_rootuptake_sl)%r82d, & - hio_rootuptake0_scpf => this%hvars(ih_rootuptake0_scpf)%r82d, & - hio_rootuptake10_scpf => this%hvars(ih_rootuptake10_scpf)%r82d, & - hio_rootuptake50_scpf => this%hvars(ih_rootuptake50_scpf)%r82d, & - hio_rootuptake100_scpf => this%hvars(ih_rootuptake100_scpf)%r82d ) - - if(print_iterations) then - do iscpf = 1,iterh2_nhist - iterh2_histx(iscpf) = iterh2_dx*real(iscpf-1,r8) - end do - end if + do s = 1,nsites - do s = 1,nsites - - call this%zero_site_hvars(sites(s),upfreq_in=4) - - site_hydr => sites(s)%si_hydr - nlevrhiz = site_hydr%nlevrhiz - nlevsoil = bc_in(s)%nlevsoil - io_si = sites(s)%h_gid - - hio_h2oveg_si(io_si) = site_hydr%h2oveg - hio_h2oveg_hydro_err_si(io_si) = site_hydr%h2oveg_hydro_err - hio_rootuptake_si(io_si) = sum(site_hydr%rootuptake_sl,dim=1) - - - if(hlm_hist_level_hifrq>1) then - hio_rootuptake_sl(io_si,1:nlevsoil) = site_hydr%rootuptake_sl(1:nlevsoil) - end if + call this%zero_site_hvars(sites(s),upfreq_in=4) + + site_hydr => sites(s)%si_hydr + nlevrhiz = site_hydr%nlevrhiz + nlevsoil = bc_in(s)%nlevsoil + io_si = sites(s)%h_gid + + hio_h2oveg_si(io_si) = site_hydr%h2oveg + hio_h2oveg_hydro_err_si(io_si) = site_hydr%h2oveg_hydro_err + hio_rootuptake_si(io_si) = sum(site_hydr%rootuptake_sl,dim=1) ! Get column means of some soil diagnostics, these are weighted ! by the amount of fine-root surface area in each layer @@ -5601,11 +5568,6 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) mean_soil_vwcsat = mean_soil_vwcsat + vwc_sat*layer_areaweight mean_soil_matpot = mean_soil_matpot + psi*layer_areaweight - if(hlm_hist_level_hifrq>1) then - hio_soilmatpot_sl(io_si,j_bc) = psi * pa_per_mpa - hio_soilvwc_sl(io_si,j_bc) = vwc - hio_soilvwcsat_sl(io_si,j_bc) = vwc_sat - end if end do end do @@ -5614,174 +5576,266 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) hio_rootwgt_soilvwcsat_si(io_si) = mean_soil_vwcsat/areaweight hio_rootwgt_soilmatpot_si(io_si) = mean_soil_matpot/areaweight * pa_per_mpa + end do + end associate - ! Normalization counters - nplant_scpf(:) = 0._r8 - ncohort_scpf(:) = 0._r8 - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - ccohort => cpatch%shortest - do while(associated(ccohort)) - if ( .not. ccohort%isnew ) then - ! Calculate index for the scpf class - iscpf = ccohort%size_by_pft_class - nplant_scpf(iscpf) = nplant_scpf(iscpf) + ccohort%n - ncohort_scpf(iscpf) = ncohort_scpf(iscpf) + 1._r8 - end if - ccohort => ccohort%taller - enddo ! cohort loop - cpatch => cpatch%younger - end do !patch loop - + !! if_hifrq1: if(hlm_hist_level_hifrq>1) then + + associate( hio_errh2o_scpf => this%hvars(ih_errh2o_scpf)%r82d, & + hio_tran_scpf => this%hvars(ih_tran_scpf)%r82d, & + hio_sapflow_scpf => this%hvars(ih_sapflow_scpf)%r82d, & + hio_iterh1_scpf => this%hvars(ih_iterh1_scpf)%r82d, & + hio_iterh2_scpf => this%hvars(ih_iterh2_scpf)%r82d, & + hio_ath_scpf => this%hvars(ih_ath_scpf)%r82d, & + hio_tth_scpf => this%hvars(ih_tth_scpf)%r82d, & + hio_sth_scpf => this%hvars(ih_sth_scpf)%r82d, & + hio_lth_scpf => this%hvars(ih_lth_scpf)%r82d, & + hio_awp_scpf => this%hvars(ih_awp_scpf)%r82d, & + hio_twp_scpf => this%hvars(ih_twp_scpf)%r82d, & + hio_swp_scpf => this%hvars(ih_swp_scpf)%r82d, & + hio_lwp_scpf => this%hvars(ih_lwp_scpf)%r82d, & + hio_aflc_scpf => this%hvars(ih_aflc_scpf)%r82d, & + hio_tflc_scpf => this%hvars(ih_tflc_scpf)%r82d, & + hio_sflc_scpf => this%hvars(ih_sflc_scpf)%r82d, & + hio_lflc_scpf => this%hvars(ih_lflc_scpf)%r82d, & + hio_btran_scpf => this%hvars(ih_btran_scpf)%r82d, & + + hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & + hio_nplant_si_capf => this%hvars(ih_nplant_si_capf)%r82d, & + hio_soilmatpot_sl => this%hvars(ih_soilmatpot_sl)%r82d, & + hio_soilvwc_sl => this%hvars(ih_soilvwc_sl)%r82d, & + hio_soilvwcsat_sl => this%hvars(ih_soilvwcsat_sl)%r82d, & + hio_rootuptake_sl => this%hvars(ih_rootuptake_sl)%r82d, & + hio_rootuptake0_scpf => this%hvars(ih_rootuptake0_scpf)%r82d, & + hio_rootuptake10_scpf => this%hvars(ih_rootuptake10_scpf)%r82d, & + hio_rootuptake50_scpf => this%hvars(ih_rootuptake50_scpf)%r82d, & + hio_rootuptake100_scpf => this%hvars(ih_rootuptake100_scpf)%r82d ) + + if(print_iterations) then + do iscpf = 1,iterh2_nhist + iterh2_histx(iscpf) = iterh2_dx*real(iscpf-1,r8) + end do + end if + + do s = 1,nsites + + site_hydr => sites(s)%si_hydr + nlevrhiz = site_hydr%nlevrhiz + nlevsoil = bc_in(s)%nlevsoil + io_si = sites(s)%h_gid + + hio_rootuptake_sl(io_si,1:nlevsoil) = site_hydr%rootuptake_sl(1:nlevsoil) + + ! Get column means of some soil diagnostics, these are weighted + ! by the amount of fine-root surface area in each layer + ! -------------------------------------------------------------------- + + mean_soil_vwc = 0._r8 + mean_soil_matpot = 0._r8 + mean_soil_vwcsat = 0._r8 + areaweight = 0._r8 + + do j=1,nlevrhiz + + j_t = site_hydr%map_r2s(j,1) ! top soil layer matching rhiz layer + j_b = site_hydr%map_r2s(j,2) ! bottom soil layer matching rhiz layer + + do j_bc = j_t,j_b + + vwc = bc_in(s)%h2o_liqvol_sl(j_bc) + psi = site_hydr%wrf_soil(j)%p%psi_from_th(vwc) ! MLO: Any reason for not using smp_sl? + ! cap capillary pressure + ! psi = max(-1e5_r8,psi) Removing cap as that is inconstistent + ! with model internals and physics. Should + ! implement caps inside the functions + ! if desired. (RGK 12-2021) + vwc_sat = bc_in(s)%watsat_sl(j_bc) + depth_frac = bc_in(s)%dz_sisl(j_bc)/site_hydr%dz_rhiz(j) + + ! If there are any roots, we use root weighting + if(sum(site_hydr%l_aroot_layer(:),dim=1) > nearzero) then + layer_areaweight = site_hydr%l_aroot_layer(j)*depth_frac*pi_const*site_hydr%rs1(j)**2.0 + + ! If there are no roots, we use depth weighting + else + layer_areaweight = bc_in(s)%dz_sisl(j_bc) + endif + + areaweight = areaweight + layer_areaweight + mean_soil_vwc = mean_soil_vwc + vwc*layer_areaweight + mean_soil_vwcsat = mean_soil_vwcsat + vwc_sat*layer_areaweight + mean_soil_matpot = mean_soil_matpot + psi*layer_areaweight + + hio_soilmatpot_sl(io_si,j_bc) = psi * pa_per_mpa + hio_soilvwc_sl(io_si,j_bc) = vwc + hio_soilvwcsat_sl(io_si,j_bc) = vwc_sat + + end do + end do - ! Generate a histogram of the the iteration counts - if(print_iterations) then - iterh2_histy(:) = 0._r8 - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - ccohort => cpatch%shortest - do while(associated(ccohort)) - ccohort_hydr => ccohort%co_hydr - ix = count((iterh2_histx(:)-0.00001_r8) < ccohort_hydr%iterh2 ) - iterh2_histy(ix) = iterh2_histy(ix) + 1 + ! Normalization counters + nplant_scpf(:) = 0._r8 + ncohort_scpf(:) = 0._r8 + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) + ccohort => cpatch%shortest + do while(associated(ccohort)) + if ( .not. ccohort%isnew ) then + ! Calculate index for the scpf class + iscpf = ccohort%size_by_pft_class + nplant_scpf(iscpf) = nplant_scpf(iscpf) + ccohort%n + ncohort_scpf(iscpf) = ncohort_scpf(iscpf) + 1._r8 + end if ccohort => ccohort%taller - enddo ! cohort loop - cpatch => cpatch%younger - end do !patch loop - end if + enddo ! cohort loop + cpatch => cpatch%younger + end do !patch loop + + ! Generate a histogram of the the iteration counts + if(print_iterations) then + iterh2_histy(:) = 0._r8 + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) + ccohort => cpatch%shortest + do while(associated(ccohort)) + ccohort_hydr => ccohort%co_hydr + ix = count((iterh2_histx(:)-0.00001_r8) < ccohort_hydr%iterh2 ) + iterh2_histy(ix) = iterh2_histy(ix) + 1 + ccohort => ccohort%taller + enddo ! cohort loop + cpatch => cpatch%younger + end do !patch loop + end if - if(hlm_hist_level_hifrq>1) then - do ipft = 1, numpft - do iscls = 1,nlevsclass - iscpf = (ipft-1)*nlevsclass + iscls - hio_sapflow_scpf(io_si,iscpf) = site_hydr%sapflow_scpf(iscls, ipft) * ha_per_m2 - hio_rootuptake0_scpf(io_si,iscpf) = site_hydr%rootuptake0_scpf(iscls,ipft) * ha_per_m2 - hio_rootuptake10_scpf(io_si,iscpf) = site_hydr%rootuptake10_scpf(iscls,ipft) * ha_per_m2 - hio_rootuptake50_scpf(io_si,iscpf) = site_hydr%rootuptake50_scpf(iscls,ipft) * ha_per_m2 - hio_rootuptake100_scpf(io_si,iscpf) = site_hydr%rootuptake100_scpf(iscls,ipft) * ha_per_m2 - hio_iterh1_scpf(io_si,iscpf) = 0._r8 - hio_iterh2_scpf(io_si,iscpf) = 0._r8 + do ipft = 1, numpft + do iscls = 1,nlevsclass + iscpf = (ipft-1)*nlevsclass + iscls + hio_sapflow_scpf(io_si,iscpf) = site_hydr%sapflow_scpf(iscls, ipft) * ha_per_m2 + hio_rootuptake0_scpf(io_si,iscpf) = site_hydr%rootuptake0_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake10_scpf(io_si,iscpf) = site_hydr%rootuptake10_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake50_scpf(io_si,iscpf) = site_hydr%rootuptake50_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake100_scpf(io_si,iscpf) = site_hydr%rootuptake100_scpf(iscls,ipft) * ha_per_m2 + hio_iterh1_scpf(io_si,iscpf) = 0._r8 + hio_iterh2_scpf(io_si,iscpf) = 0._r8 + end do end do - end do - - ipa = 0 - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - ccohort => cpatch%shortest - do while(associated(ccohort)) + ipa = 0 + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) - ccohort_hydr => ccohort%co_hydr + ccohort => cpatch%shortest + do while(associated(ccohort)) - if ( .not. ccohort%isnew ) then + ccohort_hydr => ccohort%co_hydr - ! Calculate index for the scpf class - iscpf = ccohort%size_by_pft_class + if ( .not. ccohort%isnew ) then - ! scale up cohort fluxes to their sites - number_fraction_rate = (ccohort%n / nplant_scpf(iscpf)) * per_dt_tstep + ! Calculate index for the scpf class + iscpf = ccohort%size_by_pft_class - ! scale cohorts to mean quantity - number_fraction = (ccohort%n / nplant_scpf(iscpf)) + ! scale up cohort fluxes to their sites + number_fraction_rate = (ccohort%n / nplant_scpf(iscpf)) * per_dt_tstep - hio_errh2o_scpf(io_si,iscpf) = hio_errh2o_scpf(io_si,iscpf) + & - ccohort_hydr%errh2o * number_fraction_rate ! [kg/indiv/s] + ! scale cohorts to mean quantity + number_fraction = (ccohort%n / nplant_scpf(iscpf)) - hio_tran_scpf(io_si,iscpf) = hio_tran_scpf(io_si,iscpf) + & - (ccohort_hydr%qtop) * number_fraction_rate ! [kg/indiv/s] + hio_errh2o_scpf(io_si,iscpf) = hio_errh2o_scpf(io_si,iscpf) + & + ccohort_hydr%errh2o * number_fraction_rate ! [kg/indiv/s] - hio_iterh1_scpf(io_si,iscpf) = hio_iterh1_scpf(io_si,iscpf) + & - ccohort_hydr%iterh1/ncohort_scpf(iscpf) + hio_tran_scpf(io_si,iscpf) = hio_tran_scpf(io_si,iscpf) + & + (ccohort_hydr%qtop) * number_fraction_rate ! [kg/indiv/s] - hio_iterh2_scpf(io_si,iscpf) = hio_iterh2_scpf(io_si,iscpf) + & - ccohort_hydr%iterh2/ncohort_scpf(iscpf) + hio_iterh1_scpf(io_si,iscpf) = hio_iterh1_scpf(io_si,iscpf) + & + ccohort_hydr%iterh1/ncohort_scpf(iscpf) - mean_aroot = sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & - sum(ccohort_hydr%v_aroot_layer(:)) + hio_iterh2_scpf(io_si,iscpf) = hio_iterh2_scpf(io_si,iscpf) + & + ccohort_hydr%iterh2/ncohort_scpf(iscpf) - hio_ath_scpf(io_si,iscpf) = hio_ath_scpf(io_si,iscpf) + & - mean_aroot * number_fraction ! [m3 m-3] + mean_aroot = sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & + sum(ccohort_hydr%v_aroot_layer(:)) - hio_tth_scpf(io_si,iscpf) = hio_tth_scpf(io_si,iscpf) + & - ccohort_hydr%th_troot * number_fraction ! [m3 m-3] + hio_ath_scpf(io_si,iscpf) = hio_ath_scpf(io_si,iscpf) + & + mean_aroot * number_fraction ! [m3 m-3] - hio_sth_scpf(io_si,iscpf) = hio_sth_scpf(io_si,iscpf) + & - ccohort_hydr%th_ag(2) * number_fraction ! [m3 m-3] + hio_tth_scpf(io_si,iscpf) = hio_tth_scpf(io_si,iscpf) + & + ccohort_hydr%th_troot * number_fraction ! [m3 m-3] - hio_lth_scpf(io_si,iscpf) = hio_lth_scpf(io_si,iscpf) + & - ccohort_hydr%th_ag(1) * number_fraction ! [m3 m-3] + hio_sth_scpf(io_si,iscpf) = hio_sth_scpf(io_si,iscpf) + & + ccohort_hydr%th_ag(2) * number_fraction ! [m3 m-3] - mean_aroot = sum(ccohort_hydr%psi_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & - sum(ccohort_hydr%v_aroot_layer(:)) + hio_lth_scpf(io_si,iscpf) = hio_lth_scpf(io_si,iscpf) + & + ccohort_hydr%th_ag(1) * number_fraction ! [m3 m-3] - hio_awp_scpf(io_si,iscpf) = hio_awp_scpf(io_si,iscpf) + & - mean_aroot * number_fraction * pa_per_mpa ! [Pa] + mean_aroot = sum(ccohort_hydr%psi_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & + sum(ccohort_hydr%v_aroot_layer(:)) - hio_twp_scpf(io_si,iscpf) = hio_twp_scpf(io_si,iscpf) + & - ccohort_hydr%psi_troot * number_fraction * pa_per_mpa ! [Pa] + hio_awp_scpf(io_si,iscpf) = hio_awp_scpf(io_si,iscpf) + & + mean_aroot * number_fraction * pa_per_mpa ! [Pa] - hio_swp_scpf(io_si,iscpf) = hio_swp_scpf(io_si,iscpf) + & - ccohort_hydr%psi_ag(2) * number_fraction * pa_per_mpa ! [Pa] + hio_twp_scpf(io_si,iscpf) = hio_twp_scpf(io_si,iscpf) + & + ccohort_hydr%psi_troot * number_fraction * pa_per_mpa ! [Pa] - hio_lwp_scpf(io_si,iscpf) = hio_lwp_scpf(io_si,iscpf) + & - ccohort_hydr%psi_ag(1) * number_fraction * pa_per_mpa ! [Pa] + hio_swp_scpf(io_si,iscpf) = hio_swp_scpf(io_si,iscpf) + & + ccohort_hydr%psi_ag(2) * number_fraction * pa_per_mpa ! [Pa] - mean_aroot = sum(ccohort_hydr%ftc_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & - sum(ccohort_hydr%v_aroot_layer(:)) - hio_aflc_scpf(io_si,iscpf) = hio_aflc_scpf(io_si,iscpf) + & - mean_aroot * number_fraction + hio_lwp_scpf(io_si,iscpf) = hio_lwp_scpf(io_si,iscpf) + & + ccohort_hydr%psi_ag(1) * number_fraction * pa_per_mpa ! [Pa] - hio_tflc_scpf(io_si,iscpf) = hio_tflc_scpf(io_si,iscpf) + & - ccohort_hydr%ftc_troot * number_fraction + mean_aroot = sum(ccohort_hydr%ftc_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & + sum(ccohort_hydr%v_aroot_layer(:)) + hio_aflc_scpf(io_si,iscpf) = hio_aflc_scpf(io_si,iscpf) + & + mean_aroot * number_fraction - hio_sflc_scpf(io_si,iscpf) = hio_sflc_scpf(io_si,iscpf) + & - ccohort_hydr%ftc_ag(2) * number_fraction + hio_tflc_scpf(io_si,iscpf) = hio_tflc_scpf(io_si,iscpf) + & + ccohort_hydr%ftc_troot * number_fraction - hio_lflc_scpf(io_si,iscpf) = hio_lflc_scpf(io_si,iscpf) + & - ccohort_hydr%ftc_ag(1) * number_fraction + hio_sflc_scpf(io_si,iscpf) = hio_sflc_scpf(io_si,iscpf) + & + ccohort_hydr%ftc_ag(2) * number_fraction - hio_btran_scpf(io_si,iscpf) = hio_btran_scpf(io_si,iscpf) + & - ccohort_hydr%btran * number_fraction ! [-] + hio_lflc_scpf(io_si,iscpf) = hio_lflc_scpf(io_si,iscpf) + & + ccohort_hydr%ftc_ag(1) * number_fraction - endif + hio_btran_scpf(io_si,iscpf) = hio_btran_scpf(io_si,iscpf) + & + ccohort_hydr%btran * number_fraction ! [-] - ccohort => ccohort%taller - enddo ! cohort loop - ipa = ipa + 1 - cpatch => cpatch%younger - end do !patch loop - end if - - if((hlm_use_ed_st3.eq.ifalse) .and. (hlm_hist_level_hifrq>1)) then - do iscpf=1,nlevsclass*numpft - if ((abs(hio_nplant_si_scpf(io_si, iscpf)-(nplant_scpf(iscpf)*ha_per_m2)) > 1.0E-8_r8) .and. & - (hio_nplant_si_scpf(io_si, iscpf) .ne. hlm_hio_ignore_val)) then - write(fates_log(),*) 'numpft:',numpft - write(fates_log(),*) 'nlevsclass:',nlevsclass - write(fates_log(),*) 'scpf:',iscpf - write(fates_log(),*) 'io_si:',io_si - write(fates_log(),*) 'hio_nplant_si_scpf:',hio_nplant_si_scpf(io_si, iscpf) - write(fates_log(),*) 'nplant_scpf:',nplant_scpf(iscpf) - write(fates_log(),*) 'nplant check on hio_nplant_si_scpf fails during hydraulics history updates' - call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + + ccohort => ccohort%taller + enddo ! cohort loop + ipa = ipa + 1 + cpatch => cpatch%younger + end do !patch loop + + if((hlm_use_ed_st3.eq.ifalse) ) then + do iscpf=1,nlevsclass*numpft + if ((abs(hio_nplant_si_scpf(io_si, iscpf)-(nplant_scpf(iscpf)*ha_per_m2)) > 1.0E-8_r8) .and. & + (hio_nplant_si_scpf(io_si, iscpf) .ne. hlm_hio_ignore_val)) then + write(fates_log(),*) 'numpft:',numpft + write(fates_log(),*) 'nlevsclass:',nlevsclass + write(fates_log(),*) 'scpf:',iscpf + write(fates_log(),*) 'io_si:',io_si + write(fates_log(),*) 'hio_nplant_si_scpf:',hio_nplant_si_scpf(io_si, iscpf) + write(fates_log(),*) 'nplant_scpf:',nplant_scpf(iscpf) + write(fates_log(),*) 'nplant check on hio_nplant_si_scpf fails during hydraulics history updates' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end do end if + end do - end if - end do - - if(print_iterations) then - write(fmt_char,'(I2)') iterh2_nhist - write(fates_log(),fmt='(A,'//fmt_char//'I5)') 'Solves: ',int(iterh2_histy(:)) - end if - + end associate + if(print_iterations) then + write(fmt_char,'(I2)') iterh2_nhist + write(fates_log(),fmt='(A,'//fmt_char//'I5)') 'Solves: ',int(iterh2_histy(:)) + end if - enddo ! site loop - - end associate - - end subroutine update_history_hydraulics + !!end if if_hifrq1 + !!end if if_hifrq0 + end subroutine update_history_hydraulics + ! ==================================================================================== integer function num_history_vars(this) @@ -5899,7 +5953,7 @@ subroutine define_history_vars(this, initialize_variables) ! cohort size x crown damage x pft (site_cdpf_r8) : CDPF - if(hlm_hist_level_dynam>0) then + if_dyn0: if(hlm_hist_level_dynam>0) then ! Site level counting variables @@ -5933,10 +5987,6 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_trimming_si) - - - - call this%set_history_var(vname='FATES_AREA_PLANTS', units='m2 m-2', & long='area occupied by all plants per m2 land area', use_default='active', & @@ -6253,7 +6303,8 @@ subroutine define_history_vars(this, initialize_variables) index = ih_nfix_si) end select - nitrogen_active_if: if(any(element_list(:)==nitrogen_element)) then + + nitrogen_active_if0: if(any(element_list(:)==nitrogen_element)) then call this%set_history_var(vname='FATES_STOREN', units='kg m-2', & long='total nitrogen in live plant storage', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & @@ -6290,9 +6341,9 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_repron_si) - end if nitrogen_active_if + end if nitrogen_active_if0 - phosphorus_active_if: if(any(element_list(:)==phosphorus_element)) then + phosphorus_active_if0: if(any(element_list(:)==phosphorus_element)) then call this%set_history_var(vname='FATES_STOREP', units='kg m-2', & long='total phosphorus in live plant storage', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -6350,8 +6401,9 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=5, ivar=ivar, initialize=initialize_variables, & index = ih_pdemand_si) - end if phosphorus_active_if - call this%set_history_var(vname='FATES_STRUCTC', units='kg m-2', & + end if phosphorus_active_if0 + + call this%set_history_var(vname='FATES_STRUCTC', units='kg m-2', & long='structural biomass in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & @@ -6568,12 +6620,33 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_npp_stor_si) - - HERE + + hydro_active_if: if(hlm_use_planthydro.eq.itrue) then + call this%set_history_var(vname='FATES_VEGH2O_DEAD', units = 'kg m-2', & + long='cumulative water stored in dead biomass due to mortality', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_dead_si) + + call this%set_history_var(vname='FATES_VEGH2O_RECRUIT', & + units = 'kg m-2', long='amount of water in new recruits', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_recruit_si) - if(hlm_hist_level_dynam>1) then + call this%set_history_var(vname='FATES_VEGH2O_GROWTURN_ERR', & + units = 'kg m-2', & + long='cumulative net borrowed (+) or lost (-) from water storage due to combined growth & turnover', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_growturn_err_si) + end if hydro_active_if + + !HERE + + if_dyn1: if(hlm_hist_level_dynam>1) then - call this%set_history_var(vname='FATES_VEGC_PF', units='kg m-2', & + call this%set_history_var(vname='FATES_VEGC_PF', units='kg m-2', & long='total PFT-level biomass in kg of carbon per land area', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=1, ivar=ivar, initialize=initialize_variables, & @@ -6982,7 +7055,7 @@ subroutine define_history_vars(this, initialize_variables) end select - nitrogen_active_if: if(any(element_list(:)==nitrogen_element)) then + nitrogen_active_if1: if(any(element_list(:)==nitrogen_element)) then call this%set_history_var(vname='FATES_VEGN_SZPF', units='kg m-2', & long='total (live) vegetation nitrogen mass by size-class x pft in kg N per m2', & @@ -7035,9 +7108,9 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=1, ivar=ivar, & initialize=initialize_variables, index = ih_repron_scpf) - end if nitrogen_active_if + end if nitrogen_active_if1 - phosphorus_active_if: if(any(element_list(:)==phosphorus_element)) then + phosphorus_active_if1: if(any(element_list(:)==phosphorus_element)) then call this%set_history_var(vname='FATES_VEGP_SZPF', units='kg m-2', & long='total (live) vegetation phosphorus mass by size-class x pft in kg P per m2', & @@ -7109,7 +7182,7 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=5, ivar=ivar, & initialize=initialize_variables, index = ih_pdemand_scpf) - end if phosphorus_active_if + end if phosphorus_active_if1 call this%set_history_var(vname='FATES_CROWNAREA_CLLL', units='m2 m-2', & long='area fraction of the total ground occupied by each canopy-leaf layer', & @@ -8278,11 +8351,16 @@ subroutine define_history_vars(this, initialize_variables) use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_reproc_scpf) + + + + end if if_dyn1 +end if if_dyn0 - HERE +!HERE - if(hlm_hist_level_hifrq>0) then +!! if_hifrq0: if(hlm_hist_level_hifrq>0) then ! Canopy Resistance @@ -8476,10 +8554,54 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_hr_si) + hydro_active_if0: if(hlm_use_planthydro.eq.itrue) then + call this%set_history_var(vname='FATES_SAPFLOW', units='kg m-2 s-1', & + long='areal sap flow rate in kg per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=4, ivar=ivar, initialize=initialize_variables, & + index = ih_sapflow_si) + call this%set_history_var(vname='FATES_ROOTWGT_SOILVWC', units='m3 m-3', & + long='soil volumetric water content, weighted by root area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=4, ivar=ivar, initialize=initialize_variables, & + index = ih_rootwgt_soilvwc_si) + + call this%set_history_var(vname='FATES_ROOTWGT_SOILVWCSAT', & + units='m3 m-3', & + long='soil saturated volumetric water content, weighted by root area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=4, ivar=ivar, initialize=initialize_variables, & + index = ih_rootwgt_soilvwcsat_si) + + call this%set_history_var(vname='FATES_ROOTWGT_SOILMATPOT', units='Pa', & + long='soil matric potential, weighted by root area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=4, ivar=ivar, initialize=initialize_variables, & + index = ih_rootwgt_soilmatpot_si) + + call this%set_history_var(vname='FATES_ROOTUPTAKE', units='kg m-2 s-1', & + long='root water uptake rate', use_default='active', avgflag='A', & + vtype=site_r8, hlms='CLM:ALM', upfreq=4, ivar=ivar, & + initialize=initialize_variables, index = ih_rootuptake_si) + + + call this%set_history_var(vname='FATES_VEGH2O', units = 'kg m-2', & + long='water stored inside vegetation tissues (leaf, stem, roots)', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=4, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_si) + + call this%set_history_var(vname='FATES_VEGH2O_HYDRO_ERR', & + units = 'kg m-2', & + long='cumulative net borrowed (+) from plant_stored_h2o due to plant hydrodynamics', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=4, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_hydro_err_si) + end if hydro_active_if0 + + !HERE - HERE - - if(hlm_hist_level_hifrq>1) then +!! if_hifrq1: if(hlm_hist_level_hifrq>1) then call this%set_history_var(vname='FATES_VIS_SOLVE_ERROR_AGE', units='-', & long='mean two-stream solver error for VIS by patch age', use_default='active', & @@ -8782,18 +8904,9 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & index = ih_c_stomata_si_age) - - HERE - - - ! organ-partitioned NPP / allocation fluxes - - - - ! PLANT HYDRAULICS - hydro_active_if: if(hlm_use_planthydro.eq.itrue) then + hydro_active_if1: if(hlm_use_planthydro.eq.itrue) then call this%set_history_var(vname='FATES_ERRH2O_SZPF', units='kg s-1', & long='mean individual water balance error in kg per individual per second', & @@ -8813,11 +8926,6 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=4, ivar=ivar, & initialize=initialize_variables, index = ih_sapflow_scpf) - call this%set_history_var(vname='FATES_SAPFLOW', units='kg m-2 s-1', & - long='areal sap flow rate in kg per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, & - index = ih_sapflow_si) call this%set_history_var(vname='FATES_ITERH1_SZPF', units='count indiv-1 step-1', & long='water balance error iteration diagnostic 1', & @@ -8911,25 +9019,6 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=4, ivar=ivar, & initialize=initialize_variables, index = ih_btran_scpf) - call this%set_history_var(vname='FATES_ROOTWGT_SOILVWC', units='m3 m-3', & - long='soil volumetric water content, weighted by root area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, & - index = ih_rootwgt_soilvwc_si) - - call this%set_history_var(vname='FATES_ROOTWGT_SOILVWCSAT', & - units='m3 m-3', & - long='soil saturated volumetric water content, weighted by root area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, & - index = ih_rootwgt_soilvwcsat_si) - - call this%set_history_var(vname='FATES_ROOTWGT_SOILMATPOT', units='Pa', & - long='soil matric potential, weighted by root area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, & - index = ih_rootwgt_soilmatpot_si) - call this%set_history_var(vname='FATES_SOILMATPOT_SL', units='Pa', & long='soil water matric potenial by soil layer', & use_default='inactive', avgflag='A', vtype=site_soil_r8, & @@ -8948,12 +9037,7 @@ subroutine define_history_vars(this, initialize_variables) hlms='CLM:ALM', upfreq=4, ivar=ivar, & initialize=initialize_variables, index = ih_soilvwcsat_sl) - call this%set_history_var(vname='FATES_ROOTUPTAKE', units='kg m-2 s-1', & - long='root water uptake rate', use_default='active', avgflag='A', & - vtype=site_r8, hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_rootuptake_si) - - call this%set_history_var(vname='FATES_ROOTUPTAKE_SL', & + call this%set_history_var(vname='FATES_ROOTUPTAKE_SL', & units='kg m-2 s-1', & long='root water uptake rate by soil layer', & use_default='inactive', avgflag='A', vtype=site_soil_r8, & @@ -8987,43 +9071,15 @@ subroutine define_history_vars(this, initialize_variables) use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=4, ivar=ivar, & initialize=initialize_variables, index = ih_rootuptake100_scpf) + + end if hydro_active_if1 - call this%set_history_var(vname='FATES_VEGH2O', units = 'kg m-2', & - long='water stored inside vegetation tissues (leaf, stem, roots)', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_si) - - call this%set_history_var(vname='FATES_VEGH2O_DEAD', units = 'kg m-2', & - long='cumulative water stored in dead biomass due to mortality', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_dead_si) - - call this%set_history_var(vname='FATES_VEGH2O_RECRUIT', & - units = 'kg m-2', long='amount of water in new recruits', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_recruit_si) - - call this%set_history_var(vname='FATES_VEGH2O_GROWTURN_ERR', & - units = 'kg m-2', & - long='cumulative net borrowed (+) or lost (-) from water storage due to combined growth & turnover', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_growturn_err_si) - - call this%set_history_var(vname='FATES_VEGH2O_HYDRO_ERR', & - units = 'kg m-2', & - long='cumulative net borrowed (+) from plant_stored_h2o due to plant hydrodynamics', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_hydro_err_si) - end if hydro_active_if - +!! end if if_hifrq1 +!!end if if_hifrq0 + ! Must be last thing before return this%num_history_vars_ = ivar - + end subroutine define_history_vars From 3f091666e6ac8c596766b70f9415953e10bd3d1d Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 22 Nov 2023 10:17:14 -0800 Subject: [PATCH 065/300] added logic to handle case where LU type was below min area and then exceeds it --- biogeochem/EDLoggingMortalityMod.F90 | 17 +++++++++++++++-- biogeochem/EDPatchDynamicsMod.F90 | 27 +++++++++++++++++++++++---- biogeochem/FatesLandUseChangeMod.F90 | 25 ++++++++++++++++++++----- main/EDInitMod.F90 | 12 +++++++++++- main/EDTypesMod.F90 | 1 + main/FatesRestartInterfaceMod.F90 | 28 ++++++++++++++++++++++++++++ 6 files changed, 98 insertions(+), 12 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index e6494afb1c..9124259c59 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -28,6 +28,7 @@ module EDLoggingMortalityMod use FatesConstantsMod , only : dtype_ilog use FatesConstantsMod , only : dtype_ifall use FatesConstantsMod , only : dtype_ifire + use FatesConstantsMod , only : n_landuse_cats use EDPftvarcon , only : EDPftvarcon_inst use EDPftvarcon , only : GetDecompyFrac use PRTParametersMod , only : prt_params @@ -71,6 +72,7 @@ module EDLoggingMortalityMod use FatesConstantsMod, only : fates_check_param_set use FatesInterfaceTypesMod , only : numpft use FatesLandUseChangeMod, only : get_init_landuse_harvest_rate + use FatesLandUseChangeMod, only : get_luh_statedata implicit none private @@ -206,7 +208,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, harvest_tag) ! Arguments - type(ed_site_type), intent(in), target :: currentSite ! site structure + type(ed_site_type), intent(inout), target :: currentSite ! site structure type(bc_in_type), intent(in) :: bc_in integer, intent(in) :: pft_i ! pft index real(r8), intent(in) :: dbh ! diameter at breast height (cm) @@ -237,6 +239,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, ! Local variables integer :: cur_harvest_tag ! the harvest tag of the cohort today real(r8) :: harvest_rate ! the final harvest rate to apply to this cohort today + real(r8) :: state_vector(n_landuse_cats) ! todo: probably lower the dbhmin default value to 30 cm ! todo: change the default logging_event_code to 1 september (-244) @@ -296,6 +299,15 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, endif + ! if the total intended area of secondary lands are less than what we can consider without having too-small patches, + ! or if that was the case until just now, then there is special logic + call get_luh_statedata(bc_in, state_vector) + if (state_vector(secondaryland) .le. currentSite%min_allowed_landuse_fraction) then + harvest_rate = 0._r8 + else if (.not. currentSite%landuse_vector_gt_min(secondaryland)) then + harvest_rate = state_vector(secondaryland) + end if + ! transfer of area to secondary land is based on overall area affected, not just logged crown area ! l_degrad accounts for the affected area between logged crowns if(prt_params%woody(pft_i) == itrue)then ! only set logging rates for trees @@ -349,7 +361,8 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, l_degrad = 0.0_r8 end if else - call get_init_landuse_harvest_rate(bc_in, currentSite%min_allowed_landuse_fraction, harvest_rate) + call get_init_landuse_harvest_rate(bc_in, currentSite%min_allowed_landuse_fraction, & + harvest_rate, currentSite%landuse_vector_gt_min) if(prt_params%woody(pft_i) == itrue)then lmort_direct = harvest_rate lmort_collateral = 0.0_r8 diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 833b3497e9..6f592109c1 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -214,6 +214,7 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats) integer :: harvest_tag(hlm_num_lu_harvest_cats) real(r8) :: current_fates_landuse_state_vector(n_landuse_cats) ! [m2/m2] + real(r8) :: state_vector(n_landuse_cats) real(r8), parameter :: max_daily_disturbance_rate = 0.999_r8 !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) @@ -286,9 +287,11 @@ subroutine disturbance_rates( site_in, bc_in) if ( hlm_use_luh .eq. itrue ) then if(.not. site_in%transition_landuse_from_off_to_on) then - call get_landuse_transition_rates(bc_in, site_in%min_allowed_landuse_fraction, site_in%landuse_transition_matrix) + call get_landuse_transition_rates(bc_in, site_in%min_allowed_landuse_fraction, & + site_in%landuse_transition_matrix, site_in%landuse_vector_gt_min) else - call get_init_landuse_transition_rates(bc_in, site_in%min_allowed_landuse_fraction, site_in%landuse_transition_matrix) + call get_init_landuse_transition_rates(bc_in, site_in%min_allowed_landuse_fraction, & + site_in%landuse_transition_matrix, site_in%landuse_vector_gt_min) endif else site_in%landuse_transition_matrix(:,:) = 0._r8 @@ -312,6 +315,8 @@ subroutine disturbance_rates( site_in, bc_in) currentPatch => currentPatch%younger end do + call get_luh_statedata(bc_in, state_vector) + currentPatch => site_in%oldest_patch do while (associated(currentPatch)) @@ -387,8 +392,17 @@ subroutine disturbance_rates( site_in, bc_in) current_fates_landuse_state_vector(secondaryland), & currentPatch%age_since_anthro_disturbance, harvest_rate) end if + + ! if the total intended area of secondary lands are less than what we can consider without having too-small patches, + ! or if that was the case until just now, then there is special logic + if (state_vector(secondaryland) .le. site_in%min_allowed_landuse_fraction) then + harvest_rate = 0._r8 + else if (.not. site_in%landuse_vector_gt_min(secondaryland)) then + harvest_rate = state_vector(secondaryland) + end if else - call get_init_landuse_harvest_rate(bc_in, site_in%min_allowed_landuse_fraction, harvest_rate) + call get_init_landuse_harvest_rate(bc_in, site_in%min_allowed_landuse_fraction, & + harvest_rate, site_in%landuse_vector_gt_min) endif currentPatch%disturbance_rates(dtype_ilog) = currentPatch%disturbance_rates(dtype_ilog) + & @@ -434,7 +448,12 @@ subroutine disturbance_rates( site_in, bc_in) currentPatch => currentPatch%younger - enddo !patch loop + enddo !patch loop + + ! if the area of secondary land has just exceeded the minimum below which we ignore things, set the flag to keep track of that. + if ( (state_vector(secondaryland) .gt. site_in%min_allowed_landuse_fraction) .and. (.not. site_in%landuse_vector_gt_min(secondaryland)) ) then + site_in%landuse_vector_gt_min(secondaryland) = .true. + end if end subroutine disturbance_rates diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 2ce8a28968..200d574464 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -61,7 +61,7 @@ module FatesLandUseChangeMod contains ! ============================================================================ - subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix) + subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, landuse_vector_gt_min) ! The purpose of this routine is to ingest the land use transition rate information that the host model has read in from a dataset, @@ -72,6 +72,7 @@ subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, lan type(bc_in_type) , intent(in) :: bc_in real(r8), intent(in) :: min_allowed_landuse_fraction real(r8), intent(inout) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! [m2/m2/day] + logical, intent(inout) :: landuse_vector_gt_min(n_landuse_cats) ! !LOCAL VARIABLES: type(luh2_fates_lutype_map) :: lumap @@ -122,11 +123,17 @@ subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, lan end if end do transitions_loop - ! zero all transitions where the state vector is less than the minimum allowed + ! zero all transitions where the state vector is less than the minimum allowed, + ! and otherwise if this is the first timestep where the minimum was exceeded, + ! then apply all transitions from primary to this type and reset the flag call get_luh_statedata(bc_in, state_vector) - do i_lu = 1, n_landuse_cats + do i_lu = secondaryland +1, n_landuse_cats if ( state_vector(i_lu) .le. min_allowed_landuse_fraction ) then landuse_transition_matrix(:,i_lu) = 0._r8 + else if (.not. landuse_vector_gt_min(i_lu) ) then + landuse_transition_matrix(:,i_lu) = 0._r8 + landuse_transition_matrix(primaryland,i_lu) = state_vector(i_lu) + landuse_vector_gt_min(i_lu) = .true. end if end do end if @@ -331,7 +338,7 @@ subroutine CheckLUHData(luh_vector,modified_flag) end subroutine CheckLUHData - subroutine get_init_landuse_harvest_rate(bc_in, min_allowed_landuse_fraction, harvest_rate) + subroutine get_init_landuse_harvest_rate(bc_in, min_allowed_landuse_fraction, harvest_rate, landuse_vector_gt_min) ! the purpose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for @@ -342,19 +349,23 @@ subroutine get_init_landuse_harvest_rate(bc_in, min_allowed_landuse_fraction, ha type(bc_in_type) , intent(in) :: bc_in real(r8), intent(in) :: min_allowed_landuse_fraction real(r8), intent(out) :: harvest_rate ! [m2/ m2 / day] + logical, intent(inout) :: landuse_vector_gt_min(n_landuse_cats) ! LOCALS real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] call get_luh_statedata(bc_in, state_vector) + ! only do this if the state vector exceeds the minimum viable patch size, and if so, note that in the + ! landuse_vector_gt_min flag (which will be coming in as .false. because of the use_potentialveg logic). if ( state_vector(secondaryland) .gt. min_allowed_landuse_fraction) then harvest_rate = state_vector(secondaryland) + landuse_vector_gt_min(secondaryland) = .true. endif end subroutine get_init_landuse_harvest_rate - subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix) + subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, landuse_vector_gt_min) ! The purose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for @@ -364,6 +375,7 @@ subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction type(bc_in_type) , intent(in) :: bc_in real(r8), intent(in) :: min_allowed_landuse_fraction real(r8), intent(inout) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! [m2/m2/day] + logical, intent(inout) :: landuse_vector_gt_min(n_landuse_cats) ! LOCALS real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] @@ -373,9 +385,12 @@ subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction call get_luh_statedata(bc_in, state_vector) + ! only do this if the state vector exceeds the minimum viable patch size, and if so, note that in the + ! landuse_vector_gt_min flag (which will be coming in as .false. because of the use_potentialveg logic). do i = secondaryland+1,n_landuse_cats if ( state_vector(i) .gt. min_allowed_landuse_fraction) then landuse_transition_matrix(1,i) = state_vector(i) + landuse_vector_gt_min(i) = .true. end if end do diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 3efd6fe68e..f960a349b8 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -192,7 +192,7 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%z_soil(site_in%nlevsoil)) allocate(site_in%area_pft(1:numpft,1:n_landuse_cats)) - + allocate(site_in%landuse_vector_gt_min(1:n_landuse_cats)) allocate(site_in%use_this_pft(1:numpft)) allocate(site_in%area_by_age(1:nlevage)) @@ -717,6 +717,16 @@ subroutine init_patches( nsites, sites, bc_in) n_active_landuse_cats = n_landuse_cats call get_luh_statedata(bc_in(s), state_vector) + ! if the land use state vector is greater than the minimum value, set landuse_vector_gt_min flag to true + ! otherwise set to false. + do i_lu_state = 1, n_landuse_cats + if (state_vector(i_lu_state) .gt. sites(s)%min_allowed_landuse_fraction) then + sites(s)%landuse_vector_gt_min(i_lu_state) = .true. + else + sites(s)%landuse_vector_gt_min(i_lu_state) = .false. + end if + end do + else ! If LUH2 data is not being used, we initialize with primarylands, ! i.e. array index equals '1' diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index c0c49d1619..eb747b5121 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -430,6 +430,7 @@ module EDTypesMod real(r8) :: landuse_transition_matrix(n_landuse_cats, n_landuse_cats) ! land use transition matrix as read in from HLM and aggregated to FATES land use types [m2/m2/year] real(r8) :: min_allowed_landuse_fraction ! minimum amount of land-use type below which the resulting patches would be too small [m2/m2] + logical, allocatable :: landuse_vector_gt_min(:) ! is the land use state vector for each land use type greater than the minimum below which we ignore? logical :: transition_landuse_from_off_to_on ! special flag to use only when reading restarts, which triggers procedure to initialize land use end type ed_site_type diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 28eaa652fe..e3404e5a2e 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -100,6 +100,7 @@ module FatesRestartInterfaceMod integer :: ir_acc_ni_si integer :: ir_gdd_si integer :: ir_min_allowed_landuse_fraction_si + integer :: ir_landuse_vector_gt_min_si integer :: ir_area_bareground_si integer :: ir_snow_depth_si integer :: ir_trunk_product_si @@ -708,6 +709,10 @@ subroutine define_restart_vars(this, initialize_variables) long_name='minimum allowed land use fraction at each site', units='degC days', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_min_allowed_landuse_fraction_si ) + call this%set_restart_var(vname='fates_landuse_vector_gt_min_site', vtype=cohort_int, & + long_name='minimum allowed land use fraction at each site', units='degC days', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_landuse_vector_gt_min_si ) + call this%set_restart_var(vname='fates_area_bareground_site', vtype=site_r8, & long_name='minimum allowed land use fraction at each site', units='degC days', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_area_bareground_si ) @@ -1980,6 +1985,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) integer :: io_idx_si_vtmem ! indices for veg-temp memory at site integer :: io_idx_pa_ncl ! each canopy layer within each patch integer :: io_idx_si_luludi ! site-level lu x lu x ndist index + integer :: io_idx_si_lu ! site-level lu index ! Some counters (for checking mostly) integer :: totalcohorts ! total cohort count on this thread (diagnostic) @@ -2022,6 +2028,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_min_allowed_landuse_fraction_si => this%rvars(ir_min_allowed_landuse_fraction_si)%r81d, & + rio_landuse_vector_gt_min_si => this%rvars(ir_landuse_vector_gt_min_si)%int1d, & rio_area_bareground_si => this%rvars(ir_area_bareground_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & @@ -2167,6 +2174,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_scpf = io_idx_co_1st io_idx_si_pft = io_idx_co_1st io_idx_si_luludi = io_idx_co_1st + io_idx_si_lu = io_idx_co_1st ! recruitment rate do i_pft = 1,numpft @@ -2185,6 +2193,15 @@ subroutine set_restart_vectors(this,nc,nsites,sites) end do rio_min_allowed_landuse_fraction_si(io_idx_si) = sites(s)%min_allowed_landuse_fraction + do i_landuse = 1, n_landuse_cats + if ( sites(s)%landuse_vector_gt_min(i_landuse)) then + rio_landuse_vector_gt_min_si(io_idx_si_lu) = itrue + else + rio_landuse_vector_gt_min_si(io_idx_si_lu) = ifalse + endif + io_idx_si_lu = io_idx_si_lu + 1 + end do + rio_area_bareground_si(io_idx_si) = sites(s)%area_bareground do i_scls = 1, nlevsclass @@ -2956,6 +2973,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) integer :: io_idx_pa_ncl ! each canopy layer within each patch integer :: io_idx_si_luludi ! site-level lu x lu x ndist index + integer :: io_idx_si_lu ! site-level lu x lu x ndist index ! Some counters (for checking mostly) integer :: totalcohorts ! total cohort count on this thread (diagnostic) @@ -2990,6 +3008,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_min_allowed_landuse_fraction_si => this%rvars(ir_min_allowed_landuse_fraction_si)%r81d, & + rio_landuse_vector_gt_min_si => this%rvars(ir_landuse_vector_gt_min_si)%int1d, & rio_area_bareground_si => this%rvars(ir_area_bareground_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & @@ -3124,6 +3143,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_scpf = io_idx_co_1st io_idx_si_pft = io_idx_co_1st io_idx_si_luludi = io_idx_co_1st + io_idx_si_lu = io_idx_co_1st ! read seed_bank info(site-level, but PFT-resolved) do i_pft = 1,numpft @@ -3140,6 +3160,14 @@ subroutine get_restart_vectors(this, nc, nsites, sites) enddo sites(s)%min_allowed_landuse_fraction = rio_min_allowed_landuse_fraction_si(io_idx_si) + do i_landuse = 1, n_landuse_cats + if ( rio_landuse_vector_gt_min_si(io_idx_si_lu) .eq. itrue ) then + sites(s)%landuse_vector_gt_min(i_landuse) = .true. + else + sites(s)%landuse_vector_gt_min(i_landuse) = .false. + endif + io_idx_si_lu = io_idx_si_lu + 1 + end do sites(s)%area_bareground = rio_area_bareground_si(io_idx_si) do i_scls = 1,nlevsclass From 00241bf3d33ea3f866c9ed4c8d933acb4249c53e Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Mon, 27 Nov 2023 11:42:35 -0800 Subject: [PATCH 066/300] bugfix to handle case of abandonment to secondary when secondary area is small --- biogeochem/EDPatchDynamicsMod.F90 | 1 + biogeochem/FatesLandUseChangeMod.F90 | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 6f592109c1..f5d72d9143 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -3536,6 +3536,7 @@ subroutine terminate_patches(currentSite, bc_in) call get_luh_statedata(bc_in, state_vector) write(fates_log(),*) 'driver data landuse state vector: ', state_vector write(fates_log(),*) 'min_allowed_landuse_fraction: ', currentSite%min_allowed_landuse_fraction + write(fates_log(),*) 'landuse_vector_gt_min: ', currentSite%landuse_vector_gt_min call endrun(msg=errMsg(sourcefile, __LINE__)) ! Note to user. If you DO decide to remove the end-run above this line diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 200d574464..f0d9613361 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -126,11 +126,12 @@ subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, lan ! zero all transitions where the state vector is less than the minimum allowed, ! and otherwise if this is the first timestep where the minimum was exceeded, ! then apply all transitions from primary to this type and reset the flag + ! note that the flag resetting should not happen for secondary lands, as this is handled in the logging logic call get_luh_statedata(bc_in, state_vector) - do i_lu = secondaryland +1, n_landuse_cats + do i_lu = secondaryland, n_landuse_cats if ( state_vector(i_lu) .le. min_allowed_landuse_fraction ) then landuse_transition_matrix(:,i_lu) = 0._r8 - else if (.not. landuse_vector_gt_min(i_lu) ) then + else if ((.not. landuse_vector_gt_min(i_lu)) .and. (i_lu .ne. secondaryland)) then landuse_transition_matrix(:,i_lu) = 0._r8 landuse_transition_matrix(primaryland,i_lu) = state_vector(i_lu) landuse_vector_gt_min(i_lu) = .true. @@ -389,7 +390,7 @@ subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction ! landuse_vector_gt_min flag (which will be coming in as .false. because of the use_potentialveg logic). do i = secondaryland+1,n_landuse_cats if ( state_vector(i) .gt. min_allowed_landuse_fraction) then - landuse_transition_matrix(1,i) = state_vector(i) + landuse_transition_matrix(primaryland,i) = state_vector(i) landuse_vector_gt_min(i) = .true. end if end do From 689e7b2f514a3e381bf12b0fa57deb2b6b4ccca7 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Tue, 28 Nov 2023 16:45:49 -0800 Subject: [PATCH 067/300] another bugfix to handle another edge condition --- biogeochem/EDPatchDynamicsMod.F90 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index f5d72d9143..43e0ffb13e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -216,6 +216,7 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: current_fates_landuse_state_vector(n_landuse_cats) ! [m2/m2] real(r8) :: state_vector(n_landuse_cats) real(r8), parameter :: max_daily_disturbance_rate = 0.999_r8 + logical :: site_secondaryland_first_exceeding_min !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) ! And the same rates in understory plants have already been applied to %dndt @@ -315,7 +316,10 @@ subroutine disturbance_rates( site_in, bc_in) currentPatch => currentPatch%younger end do + ! get some info needed to determine whether or not to apply land use change call get_luh_statedata(bc_in, state_vector) + site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. site_in%min_allowed_landuse_fraction) & + .and. (.not. site_in%landuse_vector_gt_min(secondaryland)) currentPatch => site_in%oldest_patch do while (associated(currentPatch)) @@ -377,7 +381,7 @@ subroutine disturbance_rates( site_in, bc_in) ! for non-closed-canopy areas subject to logging, add an additional increment of area disturbed ! equivalent to the fraction logged to account for transfer of interstitial ground area to new secondary lands - if ( (logging_time .or. site_in%transition_landuse_from_off_to_on) .and. & + if ( (logging_time .or. site_in%transition_landuse_from_off_to_on .or. site_secondaryland_first_exceeding_min) .and. & (currentPatch%area - currentPatch%total_canopy_area) .gt. fates_tiny ) then ! The canopy is NOT closed. From 8943478cb2b53cae627e1e5ac99b25cd041d1e9c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 30 Nov 2023 11:23:15 -0500 Subject: [PATCH 068/300] Changed history density pass in method, from char to int --- main/FatesInterfaceMod.F90 | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index d5a51fe9a0..efbfd92777 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1908,6 +1908,19 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_use_inventory_init= ',ival,' to FATES' end if + case('hist_hifrq_dense_level') + hlm_hist_level_hifrq = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_hist_level_hifrq= ',ival,' to FATES' + end if + + case('hist_dynam_dense_level') + hlm_hist_level_dynam = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_hist_level_dynam= ',ival,' to FATES' + end if + + case default write(fates_log(), *) 'fates NL tag not recognized:',trim(tag) !! call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1931,11 +1944,7 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) if(present(cval))then select case (trim(tag)) - case('hist_dense_level') - read(cval,'(I1,I1)') hlm_hist_level_hifrq,hlm_hist_level_dynam - if (fates_global_verbose()) then - write(fates_log(),*) 'Transfering hlm_hist_dense_level= ',trim(cval) - end if + case('hlm_name') hlm_name = trim(cval) From 416f70f1e56d3760982dbee3e28e1eec9fb7d012 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Wed, 6 Dec 2023 07:44:07 -0800 Subject: [PATCH 069/300] Add new allometric modes for multiple quantities, plus a few minor improvements. 1. New allometric function for above-ground biomass (allom_amode = 4), which is similar to Chave et al. (2014), except that the exponent for wood density is independent of the one for "tree size" (i.e., DBH*DBH*Height). 2. New allometric function for leaf biomass and crown area (allom_lmode = 4), which uses tree size as the predictor. In the case of leaf biomass, the function also is a function of top-canopy SLA, using a similar formulation as the one for above-ground biomass. 3. Crown depth has now allometric modes too (variable allom_dmode). If allom_dmode=1, crown depth is a constant fraction of height; when allom_dmode=2, crown depth is defined as p1 * Height^p2. Former parameter crown_depth_frac was replaced with parameter allom_h2cd1 (p1), a new parameter allom_h2cd2 was added for the exponent. 4. All allometric mode variables were converted to integers when they are loaded. This avoids converting them to integers every time the allometric function is called. 5. Small edit to CheckParams. The current implementation of allom_hmode=2 is a bit unusual because the minus sign of the Weibull function is incorporated in parameter p2 (meaning that p2 must be negative). Also, instead of aborting the run as soon as an inconsistency in parameters is spotted, the subroutine now continues to check other parameters, and report all the errors before stopping the run. This avoids users submitting FATES multiple times to get one inconsistency at a time. --- biogeochem/EDCanopyStructureMod.F90 | 15 +- biogeochem/FatesAllometryMod.F90 | 662 +++++++++++++++++++++-- parameter_files/fates_params_default.cdl | 22 +- parteh/PRTParametersMod.F90 | 22 +- parteh/PRTParamsFATESMod.F90 | 343 +++++++++--- 5 files changed, 925 insertions(+), 139 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index a52be9a30e..7845bf72c8 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -19,6 +19,7 @@ module EDCanopyStructureMod use EDCohortDynamicsMod , only : InitPRTObject use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai + use FatesAllometryMod , only : CrownDepth use EDtypesMod , only : ed_site_type use FatesPatchMod, only : fates_patch_type use FatesCohortMod, only : fates_cohort_type @@ -1527,6 +1528,7 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: max_cheight ! top of cohort canopy (m) real(r8) :: lai ! leaf area per canopy area real(r8) :: sai ! stem area per canopy area + real(r8) :: crown_depth ! Current cohort's crown depth !---------------------------------------------------------------------- @@ -1603,6 +1605,13 @@ subroutine leaf_area_profile( currentSite ) end if + !---~--- + ! Find current crown depth using the allometric function. + !---~--- + call CrownDepth(currentCohort%height,currentCohort%pft,crown_depth) + !---~--- + + ! -------------------------------------------------------------------------- ! Whole layers. Make a weighted average of the leaf area in each layer ! before dividing it by the total area. Fill up layer for whole layers. @@ -1616,12 +1625,10 @@ subroutine leaf_area_profile( currentSite ) ! is obscured by snow. layer_top_height = currentCohort%height - & - ( real(iv-1,r8)/currentCohort%NV * currentCohort%height * & - prt_params%crown_depth_frac(currentCohort%pft) ) + ( real(iv-1,r8)/currentCohort%NV * crown_depth ) layer_bottom_height = currentCohort%height - & - ( real(iv,r8)/currentCohort%NV * currentCohort%height * & - prt_params%crown_depth_frac(currentCohort%pft) ) + ( real(iv,r8)/currentCohort%NV * crown_depth ) fraction_exposed = 1.0_r8 if(currentSite%snow_depth > layer_top_height)then diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 431219cfda..45b8217518 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -92,6 +92,7 @@ module FatesAllometryMod use FatesConstantsMod, only : calloc_abs_error use FatesConstantsMod, only : fates_unset_r8 use FatesConstantsMod, only : itrue + use FatesConstantsMod, only : nearzero use shr_log_mod , only : errMsg => shr_log_errMsg use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun @@ -305,7 +306,7 @@ subroutine h2d_allom(h,ipft,d,dddh) p3 => prt_params%allom_d2h3(ipft), & allom_hmode => prt_params%allom_hmode(ipft)) - select case(int(allom_hmode)) + select case(allom_hmode) case (1) ! O'Brien et al 1995, BCI call h2d_obrien(h,p1,p2,d,dddh) case (2) ! poorter 2006 @@ -344,7 +345,7 @@ subroutine h_allom(d,ipft,h,dhdd) p3 => prt_params%allom_d2h3(ipft), & allom_hmode => prt_params%allom_hmode(ipft)) - select case(int(allom_hmode)) + select case(allom_hmode) case (1) ! "obrien" call d2h_obrien(d,p1,p2,dbh_maxh,h,dhdd) case (2) ! "poorter06" @@ -397,7 +398,7 @@ subroutine bagw_allom(d,ipft,crowndamage, elongf_stem, bagw,dbagwdd) branch_frac = param_derived%branch_frac(ipft) - select case(int(allom_amode)) + select case(allom_amode) case (1) !"salda") call h_allom(d,ipft,h,dhdd) call dh2bagw_salda(d,h,dhdd,p1,p2,p3,p4,wood_density,c2b,agb_frac,bagw,dbagwdd) @@ -407,6 +408,9 @@ subroutine bagw_allom(d,ipft,crowndamage, elongf_stem, bagw,dbagwdd) case (3) !"chave14") call h_allom(d,ipft,h,dhdd) call dh2bagw_chave2014(d,h,dhdd,p1,p2,wood_density,c2b,bagw,dbagwdd) + case (4) ! 3par_pwr + call h_allom(d,ipft,h,dhdd) + call dh2bagw_3pwr(d,h,dhdd,p1,p2,p3,wood_density,c2b,bagw,dbagwdd) case DEFAULT write(fates_log(),*) 'An undefined AGB allometry was specified: ',allom_amode write(fates_log(),*) 'Aborting' @@ -444,21 +448,28 @@ subroutine blmax_allom(d,ipft,blmax,dblmaxdd) real(r8),intent(out) :: blmax ! plant leaf biomass [kg] real(r8),intent(out),optional :: dblmaxdd ! change leaf bio per diameter [kgC/cm] + real(r8) :: h ! height + real(r8) :: dhdd ! change in height wrt d + associate( dbh_maxh => prt_params%allom_dbh_maxheight(ipft), & rho => prt_params%wood_density(ipft), & + slatop => prt_params%slatop(ipft), & c2b => prt_params%c2b(ipft), & allom_lmode => prt_params%allom_lmode(ipft), & p1 => prt_params%allom_d2bl1(ipft), & p2 => prt_params%allom_d2bl2(ipft), & p3 => prt_params%allom_d2bl3(ipft)) - select case(int(allom_lmode)) + select case(allom_lmode) case(1) !"salda") call d2blmax_salda(d,p1,p2,p3,rho,dbh_maxh,c2b,blmax,dblmaxdd) case(2) !"2par_pwr") call d2blmax_2pwr(d,p1,p2,c2b,blmax,dblmaxdd) case(3) ! dh2blmax_2pwr call dh2blmax_2pwr(d,p1,p2,dbh_maxh,c2b,blmax,dblmaxdd) + case(4) ! dh2blmax_3pwr + call h_allom(d,ipft,h,dhdd) + call dh2blmax_3pwr(d,h,dhdd,p1,p2,p3,slatop,dbh_maxh,c2b,blmax,dblmaxdd) case DEFAULT write(fates_log(),*) 'An undefined leaf allometry was specified: ', & allom_lmode @@ -485,6 +496,7 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) ! instead of crown area from dbh real(r8) :: dbh_eff ! Effective diameter (cm) + real(r8) :: height ! height logical :: do_inverse ! local copy of the inverse argument ! defaults to false logical :: capped_allom ! if we are using an allometry that caps @@ -507,7 +519,7 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) endif endif - select case(int(allom_lmode)) + select case(allom_lmode) case(1) dbh_eff = min(dbh,dbh_maxh) call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & @@ -522,6 +534,12 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & crowndamage, c_area, do_inverse) capped_allom = .true. + case (4) + dbh_eff = min(dbh,dbh_maxh) + call h_allom(dbh,ipft,height) + call carea_3pwr(dbh_eff,height,ipft,dbh_maxh, site_spread,d2bl_p2, & + d2bl_ediff, d2ca_min,d2ca_max,crowndamage, c_area, do_inverse) + capped_allom = .true. case DEFAULT write(fates_log(),*) 'An undefined leaf allometry was specified: ', & allom_lmode @@ -959,7 +977,7 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,elongf_stem, sapw_area,bsap branch_frac = param_derived%branch_frac(ipft) - select case(int(prt_params%allom_smode(ipft))) + select case(prt_params%allom_smode(ipft)) ! --------------------------------------------------------------------- ! Currently only one sapwood allometry model. the slope ! of the la:sa to diameter line is zero. @@ -1033,7 +1051,7 @@ subroutine bbgw_allom(d,ipft,elongf_stem,bbgw,dbbgwdd) real(r8) :: bagw ! above ground biomass [kgC] real(r8) :: dbagwdd ! change in agb per diameter [kgC/cm] - select case(int(prt_params%allom_cmode(ipft))) + select case(prt_params%allom_cmode(ipft)) case(1) !"constant") ! bbgw not affected by damage so use target allometry no damage. But note that bbgw ! is affected by stem phenology (typically applied only to grasses). We do not need @@ -1078,7 +1096,7 @@ subroutine bfineroot(d,ipft,canopy_trim,l2fr,elongf_fnrt,bfr,dbfrdd) real(r8) :: dbfrmaxdd real(r8) :: slascaler - select case(int(prt_params%allom_fmode(ipft))) + select case(prt_params%allom_fmode(ipft)) case(1) ! "constant proportionality with TRIMMED target bleaf" call blmax_allom(d,ipft,blmax,dblmaxdd) @@ -1139,7 +1157,7 @@ subroutine bstore_allom(d,ipft,crowndamage, canopy_trim,bstore,dbstoredd) associate( allom_stmode => prt_params%allom_stmode(ipft), & cushion => prt_params%cushion(ipft) ) - select case(int(allom_stmode)) + select case(allom_stmode) case(1) ! Storage is constant proportionality of trimmed maximum leaf ! biomass (ie cushion * bleaf), and thus leaf phenology is ignored. call bleaf(d,ipft, crowndamage, canopy_trim, 1.0_r8, bl, dbldd) @@ -1190,7 +1208,7 @@ subroutine bdead_allom(bagw,bbgw,bsap,ipft,bdead,dbagwdd,dbbgwdd,dbsapdd,dbdeadd associate( agb_fraction => prt_params%allom_agb_frac(ipft)) - select case(int(prt_params%allom_amode(ipft))) + select case(prt_params%allom_amode(ipft)) case(1) ! Saldariagga mass allometry originally calculated bdead directly. ! we assume proportionality between bdead and bagw @@ -1199,7 +1217,7 @@ subroutine bdead_allom(bagw,bbgw,bsap,ipft,bdead,dbagwdd,dbbgwdd,dbsapdd,dbdeadd dbdeaddd = dbagwdd/agb_fraction end if - case(2,3) + case(2,3,4) bdead = bagw + bbgw - bsap if(present(dbagwdd) .and. present(dbbgwdd) .and. & @@ -1318,7 +1336,7 @@ subroutine bsap_ltarg_slatop(d,h,dhdd,bleaf,dbleafdd,ipft, & hbl2bsap = slatop * g_per_kg * wood_density * kg_per_Megag / (c2b*cm2_per_m2 ) ! Calculate area. Note that no c2b conversion here, because it is - ! wood density that is in biomass units, SLA is in units [m2/gC. + ! wood density that is in biomass units, SLA is in units [m2/gC]. ! [m2] = [m2/gC] * [kgC] * [gC/kgC] / ( [m2/cm2] * [cm2/m2]) la_per_sa = la_per_sa_int + h*la_per_sa_slp sapw_area = slatop * bleaf * g_per_kg / (la_per_sa*cm2_per_m2 ) @@ -1489,7 +1507,109 @@ subroutine dh2blmax_2pwr(d,p1,p2,dbh_maxh,c2b,blmax,dblmaxdd) return end subroutine dh2blmax_2pwr - + + ! =========================================================================== + + subroutine dh2blmax_3pwr(d,h,dhdd,p1,p2,p3,slatop,c2b,dbh_maxh,blmax,dblmaxdd) + !-------------------------------------------------------------------------- + ! + ! This function calculates the maximum leaf biomass from reference + ! diameter, plant height and top-of-the-canopy (fully sunlit) SLA. This + ! functional form is similar to Lescure et al. (1983) and Longo et al. + ! (2020), except that it uses SLA as an additional scaler for the + ! allometric equation that can have a different exponent from + ! (DBH^2 * Height). + ! + ! ----------------- + ! References + ! ----------------- + ! Lescure JP, Puig H, Riera B, Leclerc D, Beekman A , Beneteau A. 1983. + ! La phytomasse epigee d'une foret dense en Guiane Francaise + ! Acta Oecol.-Oec. Gen. 4: 237-251. + ! URL http://www.documentation.ird.fr/hor/fdi:010005089 + ! + ! Longo M, Saatchi SS, Keller M, Bowman KW, Ferraz A, Moorcroft PR, + ! Morton D, Bonal D, Brando P, Burban B et al. 2020. Impacts of + ! degradation on water, energy, and carbon cycling of the Amazon + ! tropical forests. J. Geophys. Res.-Biogeosci. 125: + ! e2020JG005677. doi:10.1029/2020JG005677. + ! + ! ----------------- + ! Input arguments + ! ----------------- + ! d -- Diameter at breast height [ cm] + ! h -- Total tree height [ m] + ! dhdd -- Height derivative with dbh [ m/cm] + ! p1 -- Parameter 1 (log-intercept) [ --] + ! p2 -- Parameter 2 (power, or log-slope) [ --] + ! p3 -- Parameter 3 (power, or log-slope) [ --] + ! slatop -- Top-of-canopy specific leaf area [ m2/gC] + ! c2b -- Carbon to biomass multiplier ~ 2 [ kg/kgC] + ! dbh_maxh -- DBH at maximum height [ cm] + ! + ! ------------------ + ! Output arguments + ! ------------------ + ! blmax -- Plant leaf biomass [ kgC] + ! dblmaxdd -- Plant leaf biomass derivative [ kgC/cm] + ! + !-------------------------------------------------------------------------- + + + !--- Arguments + real(r8), intent(in) :: d ! plant diameter [ cm] + real(r8), intent(in) :: h ! plant height [ m] + real(r8), intent(in) :: dhdd ! Height derivative wrt diameter [ m/cm] + real(r8), intent(in) :: p1 ! Log-intercept parameter [ -] + real(r8), intent(in) :: p2 ! Log-slope parameter for size [ -] + real(r8), intent(in) :: p3 ! Log-slope parameter for SLA [ -] + real(r8), intent(in) :: slatop ! Top canopy specific leaf area [ m2/gC] + real(r8), intent(in) :: c2b ! Carbon to biomass multiplier [kg/kgC] + real(r8), intent(in) :: dbh_maxh ! dbh at maximum height [ cm] + real(r8), intent(out) :: blmax ! Leaf biomass [ kgC] + real(r8), intent(out), optional :: dblmaxdd ! Leaf biomass derivative [kgC/cm] + !--- Local variables + real(r8) :: duse + !---~--- + + + + !--- Cap DBH + duse = min(d,dbh_maxh) + !---~--- + + + !--- Find leaf biomass + blmax = p1 * (duse*duse*h)**p2 * slatop**p3 / c2b + !---~--- + + + !---~--- + ! Compute the leaf biomass derivative with DBH if needed. + !---~--- + if (present(dblmaxdd)) then + if (d >= dbh_maxh) then + !---~--- + ! Leaf area is capped at the maximum DBH. This may be removed in the + ! future. + !---~--- + dblmaxdd = 0._r8 + !---~--- + else + !---~--- + ! Find the leaf biomass derivative, noting that height is actually + ! a function of DBH. + !---~--- + dblmaxdd = p2 * blmax * ( 2._r8 / duse + dhdd / h ) + !---~--- + end if + end if + !---~--- + + return + end subroutine dh2blmax_3pwr + + ! ========================================================================= ! Diameter to height (D2H) functions ! ========================================================================= @@ -1500,7 +1620,7 @@ subroutine d2h_chave2014(d,p1,p2,p3,dbh_maxh,h,dhdd) ! "d to height via Chave et al. 2014" ! This function calculates tree height based on tree diameter and the - ! environmental stress factor "E", as per Chave et al. 2015 GCB + ! environmental stress factor "E", as per Chave et al. 2014 GCB ! As opposed to previous allometric models in ED, in this formulation ! we do not impose a hard cap on tree height. But, maximum_height ! is an important parameter, but instead of imposing a hard limit, in @@ -1509,7 +1629,7 @@ subroutine d2h_chave2014(d,p1,p2,p3,dbh_maxh,h,dhdd) ! begin to route available NPP into seed and defense respiration. ! ! The stress function is based on the geographic location of the site. If - ! a user decides to use Chave2015 allometry, the E factor will be read in + ! a user decides to use Chave2014 allometry, the E factor will be read in ! from a global gridded dataset and assigned for each ED patch (note it ! will be the same for each ED patch, but this distinction will help in ! porting ED into different models (patches are pure ED). It @@ -1747,7 +1867,7 @@ subroutine dh2bagw_chave2014(d,h,dhdd,p1,p2,wood_density,c2b,bagw,dbagwdd) ! height and wood density. ! ! Chave et al. Improved allometric models to estimate the abovegroud - ! biomass of tropical trees. Global Change Biology. V20, p3177-3190. 2015. + ! biomass of tropical trees. Global Change Biology. V20, p3177-3190. 2014. ! ! Input arguments: ! d: Diameter at breast height [cm] @@ -1791,6 +1911,90 @@ subroutine dh2bagw_chave2014(d,h,dhdd,p1,p2,wood_density,c2b,bagw,dbagwdd) return end subroutine dh2bagw_chave2014 + ! ============================================================================ + + + + subroutine dh2bagw_3pwr(d,h,dhdd,p1,p2,p3,wood_density,c2b,bagw,dbagwdd) + !-------------------------------------------------------------------------- + ! + ! This function calculates the maximum above-ground biomass from + ! reference diameter, plant height and wood density. This functional form + ! is an intermediate between Saldarriaga et al. (1988) and Chave et al. + ! (2014), because the wood-density exponent is independent on the + ! plant size (DBH^2 * Height) but the diameter and height are scaled + ! together through the size function. + ! + ! ----------------- + ! References + ! ----------------- + ! Chave J, Rejou-Mechain M, Burquez A, Chidumayo E, Colgan MS, Delitti WB, + ! Duque A, Eid T, Fearnside PM, Goodman RC et al. 2014. Improved + ! allometric models to estimate the aboveground biomass of tropical + ! trees. Glob. Change Biol. 20: 3177-3190. doi:10.1111/gcb.12629. + ! + ! Saldarriaga JG, West DC, Tharp ML , Uhl C. 1988. Long-term + ! chronosequence of forest succession in the upper Rio Negro of + ! Colombia and Venezuela. J. Ecol. 76: 938-958. + ! doi:10.2307/2260625. + ! + ! ----------------- + ! Input arguments + ! ----------------- + ! d -- Diameter at breast height [ cm] + ! h -- Total tree height [ m] + ! dhdd -- Height derivative with dbh [ m/cm] + ! p1 -- Parameter 1 (log-intercept) [ --] + ! p2 -- Parameter 2 (power, or log-slope) [ --] + ! p3 -- Parameter 3 (power, or log-slope) [ --] + ! wood_density -- Wood density [ g/cm3] + ! c2b -- Carbon to biomass multiplier ~ 2 [ kg/kgC] + ! dbh_maxh -- DBH at maximum height [ cm] + ! + ! ------------------ + ! Output arguments + ! ------------------ + ! bagw -- Above-ground biomass per individual [ kgC] + ! dbagwdd -- Above-ground biomass derivative [ kgC/cm] + ! + !-------------------------------------------------------------------------- + + + !--- Arguments + real(r8), intent(in) :: d ! plant diameter [ cm] + real(r8), intent(in) :: h ! plant height [ m] + real(r8), intent(in) :: dhdd ! Height deriv. wrt diameter [ m/cm] + real(r8), intent(in) :: p1 ! Log-intercept parameter [ -] + real(r8), intent(in) :: p2 ! Log-slope parameter (size) [ -] + real(r8), intent(in) :: p3 ! Log-slope parameter (WD) [ -] + real(r8), intent(in) :: wood_density ! Wood density [ g/cm3] + real(r8), intent(in) :: c2b ! Carbon to biomass factor [kg/kgC] + real(r8), intent(out) :: bagw ! Above-ground biomass [ kgC] + real(r8), intent(out), optional :: dbagwdd ! AG biomass derivative [kgC/cm] + !---~--- + + + !--- Find above-ground biomass + bagw = p1 * (d*d*h)**p2 * wood_density**p3 / c2b + !---~--- + + + !---~--- + ! Compute the above-ground biomass derivative with DBH if needed, noting that + ! height is actually a function of DBH. + !---~--- + if (present(dbagwdd)) then + dbagwdd = p2 * bagw * ( 2._r8 / d + dhdd / h ) + end if + !---~--- + + return + end subroutine dh2bagw_3pwr + + + ! ============================================================================ + + subroutine d2bagw_2pwr(d,p1,p2,c2b,bagw,dbagwdd) ! ========================================================================= @@ -2077,36 +2281,62 @@ subroutine h2d_martcano(h,p1,p2,p3,d,dddh) return end subroutine h2d_martcano - ! ===================================================================================== + ! ===================================================================================== - subroutine CrownDepth(height,ft,crown_depth) - ! ----------------------------------------------------------------------------------- - ! This routine returns the depth of a plant's crown. Which is the length - ! from the bottom of the crown to the top in the vertical dimension. - ! - ! This code may be used as a wrapper if different hypotheses are wished to be - ! optioned. - ! ----------------------------------------------------------------------------------- - - real(r8),intent(in) :: height ! The height of the plant [m] - integer,intent(in) :: ft ! functional type index - real(r8),intent(out) :: crown_depth ! The depth of the crown [m] + subroutine CrownDepth(height,ipft,crown_depth) - ! Alternative Hypothesis: - ! crown depth from Poorter, Bongers & Bongers - ! crown_depth = exp(-1.169_r8)*cCohort%height**1.098_r8 + !-------------------------------------------------------------------------- + ! This routine returns the depth of a plant's crown. Which is the + ! length from the bottom of the crown to the top in the vertical dimension. + ! + ! The original mode (now allom_dmode = 1) used only a fraction of the + ! plant's height. Alternatively, allom_dmode = 2 uses the same functional + ! form as Poorter et al. (2006), with an additional constraint to prevent + ! crown depth to exceed the plant's height. + ! + ! ----------------- + ! References + ! ----------------- + ! Poorter L, Bongers L , Bongers F. 2006. Architecture of 54 moist-forest + ! tree species: traits, trade-offs, and functional groups. Ecology 87: + ! 1289-1301. doi:10.1890/0012-9658(2006)87[1289:AOMTST]2.0.CO;2. + ! + !-------------------------------------------------------------------------- + + real(r8),intent(in) :: height ! The height of the plant [m] + integer ,intent(in) :: ipft ! functional type index + real(r8),intent(out) :: crown_depth ! The depth of the crown [m] + + associate( p1 => prt_params%allom_h2cd1(ipft), & + p2 => prt_params%allom_h2cd2(ipft), & + allom_dmode => prt_params%allom_dmode(ipft)) + + select case (allom_dmode) + case (1) ! Default, linear relationship with height + crown_depth = p1 * height + case (2) ! Power law, akin to Poorter et al. (2006). + !---~--- + ! Apply the two coefficients, but make sure crown depth does not exceed + ! the plant's height. + !---~--- + crown_depth = min(height, p1 * height ** p2) + !---~--- + case default + write(fates_log(),*) 'Invalid settings for crown depth mode for PFT ',ipft,'.' + write(fates_log(),*) 'Current allom_dmode: ',allom_dmode,'.' + write(fates_log(),*) 'Valid allom_dmode values: 1 or 2.' + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + end associate - ! Alternative Hypothesis: - ! Original FATES crown depth heigh used for hydraulics - ! crown_depth = min(height,0.1_r8) + return + end subroutine CrownDepth + ! ===================================================================================== - crown_depth = prt_params%crown_depth_frac(ft) * height - - return - end subroutine CrownDepth @@ -2173,7 +2403,99 @@ subroutine carea_2pwr(dbh,spread,d2bl_p2,d2bl_ediff,d2ca_min, & endif end subroutine carea_2pwr - + + + ! ============================================================================= + + + subroutine carea_3pwr(dbh,height,ipft,dbh_maxh,spread,dh2bl_p2,dh2bl_ediff, & + dh2ca_min,dh2ca_max,crowndamage,c_area,inverse) + !---~--- + ! Calculate area of ground covered by entire cohort. (m2) + ! Function of DBH (cm), height (m), canopy spread (m/cm) and number of + ! individuals. + !---~--- + + !--- List of arguments + real(r8) , intent(inout) :: dbh ! Diameter at breast/ref/ height [ cm] + real(r8) , intent(inout) :: height ! Height [ m] + integer(i4), intent(in) :: ipft ! PFT index + real(r8) , intent(in) :: dbh_maxh ! Minimum DBH at maximum height [ m] + real(r8) , intent(in) :: spread ! site level relative spread score [ 0-1] + real(r8) , intent(in) :: dh2bl_p2 ! Exponent for size (bleaf) [ -] + real(r8) , intent(in) :: dh2bl_ediff ! Difference in size exponent [ -] + ! between crown area and bleaf + real(r8) , intent(in) :: dh2ca_min ! Minimum (closed forest) scaling [ -] + ! coefficient for crown area + real(r8) , intent(in) :: dh2ca_max ! Maximum (savannah) scaling [ -] + ! coefficient for crown area + integer , intent(in) :: crowndamage ! Crown damage class [ -] + ! [1: undamaged, >1: damaged] + real(r8) , intent(inout) :: c_area ! crown area for one plant [ m2] + logical , intent(in) :: inverse ! If true, calculate dbh from crown + ! area rather than its reverse + !--- Local variables + real(r8) :: size ! Size (Diameter^2 * Height) [cm2 m] + real(r8) :: dh2ca_p1 ! Effective scaling factor (crown area) [ -] + real(r8) :: dh2ca_p2 ! Effective exponent (crown area) [ -] + real(r8) :: crown_reduction ! Crown area reduction due to damage. [ -] + !---~--- + + + !---~--- + ! Define the scaling (log-intercept) and exponent (log-slope) parameters for + ! crown area. The scaling parameter accounts for the site-level spread elasticity. + ! The exponent is defined in terms of the leaf biomass exponent plus an offset + ! parameter (allom_blca_expnt_diff). This is done because the default in FATES is + ! for both exponents to be same (i.e., allom_blca_expnt_diff = 0.) so the per-plant + ! canopy area remains invariant during growth. However, allometric models in general + ! predict that leaf area grows faster than crown area. + !---~--- + dh2ca_p1 = spread * dh2ca_max + (1._r8 - spread) * dh2ca_min + dh2ca_p2 = dh2bl_p2 + dh2bl_ediff + !---~--- + + + + !---~--- + ! Decide whether to use DBH and height to find crown area (default) or the + ! other way round. + !---~--- + select case (inverse) + case (.false.) + !--- Find the maximum area + size = dbh * dbh * height + c_area = dh2ca_p1 * size ** dh2ca_p2 + !---~--- + + !--- Reduce area if the crown is damaged. + if (crowndamage > 1) then + call GetCrownReduction(crowndamage, crown_reduction) + c_area = c_area * (1.0_r8 - crown_reduction) + end if + !---~--- + case (.true.) + !--- Reduce area if the crown is damaged. + if (crowndamage > 1) then + call GetCrownReduction(crowndamage, crown_reduction) + c_area = c_area * (1.0_r8 - crown_reduction) + end if + !---~--- + + + !---~--- + ! Find the size, then use a root-finding algorithm to find DBH. + !---~--- + size = ( c_area / dh2ca_p1 ) ** ( 1.0_r8 / dh2ca_p2 ) + call size2dbh(size,ipft,dbh,dbh_maxh) + !---~--- + end select + !---~--- + + return + end subroutine carea_3pwr + + ! ========================================================================= subroutine set_root_fraction(root_fraction, ft, zi, max_nlevroot) @@ -2625,7 +2947,265 @@ subroutine cspline(x1,x2,y1,y2,dydx1,dydx2,x,y,dydx) dydx = (y2-y1)/(x2-x1) + (1.0_r8-2.0_r8*t)*(a*(1.0_r8-t)+b*t)/(x2-x1) + t*(1.0_r8-t)*(b-a)/(x2-x1) return end subroutine cspline - + ! ============================================================================ + + + + ! ============================================================================ + ! This function finds the DBH when size (DBH^2 * Height) is known but we + ! cannot find DBH analytically due to the non-linear relationship between DBH + ! and height. This is borrowed from the same approach applied in ED2 for + ! root finding. It starts with the Newton's method, which should quickly + ! converge to the solution. In the unlikely case of failure, we use the + ! Regula Falsi (Illinois) method as a back-up. + ! ============================================================================ + subroutine size2dbh(size,ipft,dbh,dbh_maxh) + !--- Arguments. + real(r8) , intent(in) :: size ! Size (DBH^2 * Height) [cm2 m] + integer(i4), intent(in) :: ipft ! PFT index [ -] + real(r8) , intent(inout) :: dbh ! Diameter at breast height [ cm] + real(r8) , intent(in) :: dbh_maxh ! Minimum DBH at maximum height [ cm] + !--- Local variables + real(r8) :: hgt ! Height [ m] + real(r8) :: dhgtddbh ! Height derivative [ m/cm] + real(r8) :: size_maxh ! Minimum size at maximum height [cm2 m] + real(r8) :: deriv ! Function derivative [ cm m] + real(r8) :: afun ! Function value (lower guess) [cm2 m] + real(r8) :: rfun ! Function value (RF new guess) [cm2 m] + real(r8) :: zfun ! Function value (upper guess) [cm2 m] + real(r8) :: adbh ! DBH: lower guess [ cm] + real(r8) :: rdbh ! DBH: updated guess (Reg. Falsi) [ cm] + real(r8) :: zdbh ! DBH: upper guess [ cm] + real(r8) :: delta ! Second guess for the RF method [ cm] + integer :: itn ! Iteration counter -- Newton [ -] + integer :: iti ! Iteration counter -- Reg. Falsi [ -] + logical :: converged ! Has the solution converged? [ T|F] + logical :: zside ! Converging on the upper size? [ T|F] + !--- Local constants. + real(r8) , parameter :: toler =1.0e-12_r8 ! Relative tolerance [ --] + integer , parameter :: maxit_newt = 10 ! Cap in iterations -- Newton [ --] + integer , parameter :: maxit_rf = 100 ! Cap in iterations -- Reg. Falsi [ --] + !---~--- + + + !---~--- + ! Find the maximum size beyond which the height is assumed constant. In this + ! case, DBH can be determined without the iterative approach. + !---~--- + call h_allom(dbh_maxh,ipft,hgt) + size_maxh = dbh_maxh * dbh_maxh * hgt + if (size >= size_maxh) then + dbh = sqrt(size/hgt) + return + end if + !---~--- + + + !--- First guess: use current DBH. + adbh = dbh + call h_allom(adbh,ipft,hgt,dhgtddbh) + afun = adbh * adbh * hgt - size + deriv = 2.0_r8 * adbh * hgt + adbh * adbh * dhgtddbh + !---~--- + + + !--- Copy just in case it fails at the first iteration. + zdbh = adbh + zfun = afun + !---~--- + + + !---~--- + ! Enter the Newton's method loop + !---~--- + converged = .false. + newton_loop: do itn = 1, maxit_newt + !--- If derivative is too flat, go to Regula Falsi + if ( abs(deriv) < toler) exit newton_loop + !---~--- + + + !--- Copy the previous guess. + adbh = zdbh + afun = zfun + !---~--- + + + !--- Find the new guess, and evaluate the function and derivative. + zdbh = adbh - afun / deriv + call h_allom(zdbh,ipft,hgt,dhgtddbh) + zfun = zdbh * zdbh * hgt - size + deriv = 2.0_r8 * zdbh * hgt + zdbh * zdbh * dhgtddbh + !---~--- + + !--- Check convergence. + converged = abs(adbh - zdbh) < toler * zdbh + if (converged) then + !--- Convergence by iterations. + dbh = 0.5_r8 * (adbh + zdbh) + return + !---~--- + else if (abs(zfun) < nearzero) then + !--- Convergence by luck. + dbh = zdbh + return + !---~--- + end if + !---~--- + end do newton_loop + !---~--- + + + + !---~--- + ! If we have reached this point, then Newton's method has failed. Use Regula + ! Falsi instead. For this, we must have two guesses whose function evaluation has + ! opposite signs. + !---~--- + if (afun * zfun <= -nearzero) then + !--- We already have two guesses with opposite signs. + zside = .true. + !---~--- + else + !--- Look for another guess with opposite sign. + if (abs(zfun-afun) < 100._r8 * toler * adbh) then + delta = 100._r8 * toler * adbh + else + delta = max( abs( afun * (zdbh-adbh) / (zfun-afun) ),100._r8 * toler * adbh ) + end if + !---~--- + + + !---~--- + ! Try guesses on both sides of the first guess, sending guesses increasingly + ! further away until we find a good guess. + !---~--- + zdbh = adbh + delta + zside = .false. + zguess_loop: do iti=1,maxit_rf + zdbh = adbh + real((-1)**iti * (iti+3)/2,r8) * delta + call h_allom(zdbh,ipft,hgt) + zfun = zdbh * zdbh * hgt - size + zside = afun * zfun < -nearzero + if (zside) exit zguess_loop + end do zguess_loop + + !---~--- + ! Issue an error in case the function failed finding a second guess. + !---~--- + if (.not. zside) then + write (unit=*,fmt='(a)') '---~---' + write (unit=*,fmt='(a)') ' Failed finding the second guess:' + write (unit=*,fmt='(a)') '---~---' + write (unit=*,fmt='(a)') ' ' + write (unit=*,fmt='(a)') ' Input: ' + write (unit=*,fmt='(a,1x,es14.7)') ' + size =',size + write (unit=*,fmt='(a,1x,es14.7)') ' + dbh =',dbh + write (unit=*,fmt='(a)') ' ' + write (unit=*,fmt='(a)') ' Current guesses and evaluations:' + write (unit=*,fmt='(a,1x,es14.7)') ' + adbh =',adbh + write (unit=*,fmt='(a,1x,es14.7)') ' + afun =',afun + write (unit=*,fmt='(a,1x,es14.7)') ' + zdbh =',zdbh + write (unit=*,fmt='(a,1x,es14.7)') ' + zfun =',zfun + write (unit=*,fmt='(a)') ' ' + write (unit=*,fmt='(a)') '---~---' + write(fates_log(),*) 'Second guess for Regula Falsi method not found.' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + !---~--- + end if + !---~--- + + !---~--- + ! Proceed to the regula falsi loop. + !---~--- + regfalsi_loop: do iti=1,maxit_rf + + !--- Update solution. + rdbh = ( zfun * adbh - afun * zdbh ) / ( zfun - afun) + !---~--- + + + !---~--- + ! Check for convergence. In case it converged, we can exit the sub-routine. + !---~--- + converged = abs(rdbh - adbh) < toler * max(rdbh,adbh) + if (converged) exit regfalsi_loop + !---~--- + + + !--- Find the new function evaluation. + call h_allom(rdbh,ipft,hgt) + rfun = rdbh * rdbh * hgt - size + !---~--- + + + !---~--- + ! Define the new searching interval based on the intermediate value theorem. + !---~--- + if (abs(rfun) < nearzero) then + !--- Converged by luck. + converged = .true. + exit regfalsi_loop + !---~--- + else if (rfun * afun <= -nearzero ) then + !--- Guess is between lower and current guess. + zdbh = rdbh + zfun = rfun + !--- If we are updating the upper side again, halve afun (Regula Falsi method). + if (zside) afun = afun * 0.5_r8 + !--- Flag that we have just updated the upper side. + zside = .true. + !---~--- + else + !--- Guess is between current and upper guess. + adbh = rdbh + afun = rfun + !--- If we are updating the lower side again, halve zfun (Regula Falsi method). + if (.not. zside) zfun = zfun * 0.5_r8 + !--- Flag that we have just updated the lower side. + zside = .false. + end if + end do regfalsi_loop + !---~--- + + + !---~--- + ! Check that the Regula Falsi method indeed converged. + !---~--- + if (converged) then + !--- Yes, return the last guess + dbh = rdbh + !---~--- + else + !--- No, report the bad news + write (unit=*,fmt='(a)') '---~---' + write (unit=*,fmt='(a)') ' Failed finding the solution:' + write (unit=*,fmt='(a)') '---~---' + write (unit=*,fmt='(a)') ' ' + write (unit=*,fmt='(a)') ' Input: ' + write (unit=*,fmt='(a,1x,es14.7)') ' + size =',size + write (unit=*,fmt='(a,1x,es14.7)') ' + dbh =',dbh + write (unit=*,fmt='(a)') ' ' + write (unit=*,fmt='(a)') ' Current guesses and evaluations:' + write (unit=*,fmt='(a,1x,es14.7)') ' + adbh =',adbh + write (unit=*,fmt='(a,1x,es14.7)') ' + afun =',afun + write (unit=*,fmt='(a,1x,es14.7)') ' + rdbh =',rdbh + write (unit=*,fmt='(a,1x,es14.7)') ' + rfun =',rfun + write (unit=*,fmt='(a,1x,es14.7)') ' + zdbh =',zdbh + write (unit=*,fmt='(a,1x,es14.7)') ' + zfun =',zfun + write (unit=*,fmt='(a)') ' ' + write (unit=*,fmt='(a)') '---~---' + write(fates_log(),*) 'Size to DBH routine failed to converge!' + call endrun(msg=errMsg(sourcefile, __LINE__)) + !---~--- + end if + !---~--- + + return + end subroutine size2dbh + ! ============================================================================ + end module FatesAllometryMod diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index f170fe2275..1a3fde13e9 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -80,9 +80,6 @@ variables: double fates_allom_cmode(fates_pft) ; fates_allom_cmode:units = "index" ; fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; double fates_allom_d2bl1(fates_pft) ; fates_allom_d2bl1:units = "variable" ; fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; @@ -110,6 +107,9 @@ variables: double fates_allom_dbh_maxheight(fates_pft) ; fates_allom_dbh_maxheight:units = "cm" ; fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_dmode(fates_pft) ; + fates_allom_dmode:units = "index" ; + fates_allom_dmode:long_name = "crown depth allometry function index." ; double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; @@ -125,6 +125,12 @@ variables: double fates_allom_frbstor_repro(fates_pft) ; fates_allom_frbstor_repro:units = "fraction" ; fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_h2cd1(fates_pft) ; + fates_allom_h2cd1:units = "variable" ; + fates_allom_h2cd1:long_name = "Parameter 1 for h2cd allometry (exp(log-intercept) or scaling). If allom_dmode=1; this is the same as former crown_depth_frac parameter" ; + double fates_allom_h2cd2(fates_pft) ; + fates_allom_h2cd2:units = "variable" ; + fates_allom_h2cd2:long_name = "Parameter 2 for h2cd allometry (log-slope or exponent). If allom_dmode=1; this is not needed (as exponent is assumed 1)" ; double fates_allom_hmode(fates_pft) ; fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; @@ -971,9 +977,6 @@ data: fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; @@ -1002,6 +1005,8 @@ data: fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; @@ -1012,6 +1017,11 @@ data: fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_allom_h2cd1 = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index f2419c3334..bb3f98f6be 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -117,24 +117,24 @@ module PRTParametersMod real(r8), allocatable :: c2b(:) ! Carbon to biomass multiplier [kg/kgC] real(r8), allocatable :: wood_density(:) ! wood density g cm^-3 ... - real(r8), allocatable :: crown_depth_frac(:) ! fraction of the height of the plant integer , allocatable :: woody(:) ! Does the plant have wood? (1=yes, 0=no) ! that is occupied by crown real(r8), allocatable :: slamax(:) ! Maximum specific leaf area of plant (at bottom) [m2/gC] real(r8), allocatable :: slatop(:) ! Specific leaf area at canopy top [m2/gC] real(r8), allocatable :: allom_sai_scaler(:) ! real(r8), allocatable :: allom_dbh_maxheight(:) ! dbh at which height growth ceases - real(r8), allocatable :: allom_hmode(:) ! height allometry function type - real(r8), allocatable :: allom_lmode(:) ! maximum leaf allometry function type - real(r8), allocatable :: allom_fmode(:) ! maximum root allometry function type - real(r8), allocatable :: allom_amode(:) ! AGB allometry function type - real(r8), allocatable :: allom_cmode(:) ! Coarse root allometry function type - real(r8), allocatable :: allom_smode(:) ! sapwood allometry function type - real(r8), allocatable :: allom_stmode(:) ! storage allometry functional type + integer , allocatable :: allom_hmode(:) ! height allometry function type + integer , allocatable :: allom_lmode(:) ! maximum leaf allometry function type + integer , allocatable :: allom_fmode(:) ! maximum root allometry function type + integer , allocatable :: allom_amode(:) ! AGB allometry function type + integer , allocatable :: allom_cmode(:) ! Coarse root allometry function type + integer , allocatable :: allom_smode(:) ! sapwood allometry function type + integer , allocatable :: allom_stmode(:) ! storage allometry functional type ! 0 - storage is proportional to maximum leaf biomass ! (considering trimmed) ! 1 - storage is proportional to maximum leaf biomass ! (untrimmed) + integer , allocatable :: allom_dmode(:) ! crown depth allometry function type ! (HARD-CODED FOR TIME BEING, RGK 11-2017) real(r8), allocatable :: allom_la_per_sa_int(:) ! Leaf area to sap area conversion, intercept ! (sapwood area / leaf area) [cm2/m2] @@ -161,6 +161,12 @@ module PRTParametersMod real(r8), allocatable :: allom_agb3(:) ! Parameter 3 for agb allometry real(r8), allocatable :: allom_agb4(:) ! Parameter 3 for agb allometry + real(r8), allocatable :: allom_h2cd1(:) ! Parameter 1 for crown depth allometry. When allom_dmode=1 + ! this is fraction of the height of the plant that is + ! considered crown (former parameter crown_depth_frac). + real(r8), allocatable :: allom_h2cd2(:) ! Exponent for crown depth allometry. Used only when + ! allom_dmode /= 1. + real(r8), allocatable :: allom_zroot_max_dbh(:) ! dbh at which maximum rooting depth saturates (largest possible) [cm] real(r8), allocatable :: allom_zroot_max_z(:) ! the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh [m] real(r8), allocatable :: allom_zroot_min_dbh(:) ! dbh at which the maximum rooting depth for a recruit is defined [cm] diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 098b1e3738..381546f1d9 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -201,10 +201,6 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_allom_crown_depth_frac' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_wood_density' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -321,6 +317,10 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_allom_dmode' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_allom_la_per_sa_int' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -385,6 +385,14 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_allom_h2cd1' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_allom_h2cd2' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_allom_zroot_max_dbh' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -501,10 +509,6 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%fnrt_prof_mode) - name = 'fates_allom_crown_depth_frac' - call fates_params%RetrieveParameterAllocate(name=name, & - data=prt_params%crown_depth_frac) - name = 'fates_woody' call fates_params%RetrieveParameterAllocate(name=name, & data=tmpreal) @@ -566,31 +570,59 @@ subroutine PRTReceivePFT(fates_params) name = 'fates_allom_hmode' call fates_params%RetrieveParameterAllocate(name=name, & - data=prt_params%allom_hmode) + data=tmpreal) + allocate(prt_params%allom_hmode(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%allom_hmode) + deallocate(tmpreal) name = 'fates_allom_lmode' call fates_params%RetrieveParameterAllocate(name=name, & - data=prt_params%allom_lmode) + data=tmpreal) + allocate(prt_params%allom_lmode(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%allom_lmode) + deallocate(tmpreal) name = 'fates_allom_fmode' call fates_params%RetrieveParameterAllocate(name=name, & - data=prt_params%allom_fmode) + data=tmpreal) + allocate(prt_params%allom_fmode(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%allom_fmode) + deallocate(tmpreal) name = 'fates_allom_amode' call fates_params%RetrieveParameterAllocate(name=name, & - data=prt_params%allom_amode) + data=tmpreal) + allocate(prt_params%allom_amode(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%allom_amode) + deallocate(tmpreal) name = 'fates_allom_stmode' call fates_params%RetrieveParameterAllocate(name=name, & - data=prt_params%allom_stmode) + data=tmpreal) + allocate(prt_params%allom_stmode(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%allom_stmode) + deallocate(tmpreal) name = 'fates_allom_cmode' call fates_params%RetrieveParameterAllocate(name=name, & - data=prt_params%allom_cmode) + data=tmpreal) + allocate(prt_params%allom_cmode(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%allom_cmode) + deallocate(tmpreal) name = 'fates_allom_smode' call fates_params%RetrieveParameterAllocate(name=name, & - data=prt_params%allom_smode) + data=tmpreal) + allocate(prt_params%allom_smode(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%allom_smode) + deallocate(tmpreal) + + name = 'fates_allom_dmode' + call fates_params%RetrieveParameterAllocate(name=name, & + data=tmpreal) + allocate(prt_params%allom_dmode(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%allom_dmode) + deallocate(tmpreal) name = 'fates_allom_la_per_sa_int' call fates_params%RetrieveParameterAllocate(name=name, & @@ -680,6 +712,14 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb4) + name = 'fates_allom_h2cd1' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%allom_h2cd1) + + name = 'fates_allom_h2cd2' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%allom_h2cd2) + name = 'fates_allom_zroot_max_dbh' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_max_dbh) @@ -979,6 +1019,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'allom_agb2 = ',prt_params%allom_agb2 write(fates_log(),fmt0) 'allom_agb3 = ',prt_params%allom_agb3 write(fates_log(),fmt0) 'allom_agb4 = ',prt_params%allom_agb4 + write(fates_log(),fmt0) 'allom_h2cd1 = ',prt_params%allom_h2cd1 + write(fates_log(),fmt0) 'allom_h2cd2 = ',prt_params%allom_h2cd2 write(fates_log(),fmt0) 'allom_zroot_max_dbh = ',prt_params%allom_zroot_max_dbh write(fates_log(),fmt0) 'allom_zroot_max_z = ',prt_params%allom_zroot_max_z @@ -990,7 +1032,6 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'stoich_phos = ',prt_params%phos_stoich_p1 write(fates_log(),fmt0) 'alloc_organ_priority = ',prt_params%alloc_priority write(fates_log(),fmt0) 'woody = ',prt_params%woody - write(fates_log(),fmt0) 'crown_depth_frac = ',prt_params%crown_depth_frac write(fates_log(),fmt0) 'roota_par = ',prt_params%fnrt_prof_a write(fates_log(),fmt0) 'rootb_par = ',prt_params%fnrt_prof_b write(fates_log(),fmt0) 'fnrt_prof_mode = ',prt_params%fnrt_prof_mode @@ -1060,6 +1101,9 @@ subroutine PRTCheckParams(is_master) logical :: is_season_decid ! Is the PFT cold-deciduous? logical :: is_stress_decid ! Is the PFT drought-deciduous? logical :: is_semi_decid ! Is the PFT drought semi-deciduous? + integer :: nerror ! Count number of errors. If this is not + ! zero by theend of the subroutine, stop + ! the run. npft = size(prt_params%evergreen,1) @@ -1070,14 +1114,21 @@ subroutine PRTCheckParams(is_master) if(.not.is_master) return + ! Initialise nerror with zero. If anything is incorrectly set, nerror will be + ! positive, but we will hold on until all checks are performed before stopping + ! the run. + nerror = 0 if( any(prt_params%organ_id(:)<1) .or. & any(prt_params%organ_id(:)>num_organ_types) ) then + write(fates_log(),*) '---~---' write(fates_log(),*) 'prt_organ_ids should match the global ids' write(fates_log(),*) 'of organ types found in PRTGenericMod.F90' write(fates_log(),*) 'organ_ids: ',prt_params%organ_id(:) - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if ! Check to make sure the organ ids are valid if this is the @@ -1087,22 +1138,28 @@ subroutine PRTCheckParams(is_master) do io = 1,norgans if(prt_params%organ_id(io) == repro_organ) then + write(fates_log(),*) '---~---' write(fates_log(),*) 'with flexible cnp or c-only alloc hypotheses' write(fates_log(),*) 'reproductive tissues are a special case' write(fates_log(),*) 'and therefore should not be included in' write(fates_log(),*) 'the parameter file organ list' write(fates_log(),*) 'fates_prt_organ_id: ',prt_params%organ_id(:) - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if if(prt_params%organ_id(io) == store_organ) then + write(fates_log(),*) '---~---' write(fates_log(),*) 'with flexible cnp or c-only alloc hypotheses' write(fates_log(),*) 'storage is a special case' write(fates_log(),*) 'and therefore should not be included in' write(fates_log(),*) 'the parameter file organ list' write(fates_log(),*) 'fates_prt_organ_id: ',prt_params%organ_id(:) - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end do @@ -1112,10 +1169,13 @@ subroutine PRTCheckParams(is_master) ! between 0 and 1 if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then if(any(prt_params%nfix_mresp_scfrac(:)<0._r8) .or. any(prt_params%nfix_mresp_scfrac(:)>1.0_r8)) then + write(fates_log(),*) '---~---' write(fates_log(),*) 'The N fixation surcharge nfix_mresp_sfrac (fates_nfix1) must be between 0-1.' write(fates_log(),*) 'here are the values: ',prt_params%nfix_mresp_scfrac(:) - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end if @@ -1136,14 +1196,17 @@ subroutine PRTCheckParams(is_master) ( is_evergreen .and. is_stress_decid ) .or. & ( is_season_decid .and. is_stress_decid ) ) then + write(fates_log(),*) '---~---' write(fates_log(),*) 'PFT # ',ipft,' must be defined as having one of three' write(fates_log(),*) 'phenology habits, ie, only one of the flags below should' write(fates_log(),*) 'be different than ',ifalse write(fates_log(),*) 'stress_decid: ',prt_params%stress_decid(ipft) write(fates_log(),*) 'season_decid: ',prt_params%season_decid(ipft) write(fates_log(),*) 'evergreen: ',prt_params%evergreen(ipft) - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if @@ -1155,6 +1218,7 @@ subroutine PRTCheckParams(is_master) ! In case the product of the lower and upper thresholds is negative, the ! thresholds are inconsistent as both should be defined using the same ! quantity. + write(fates_log(),*) '---~---' write(fates_log(),*) ' When using drought semi-deciduous phenology,' write(fates_log(),*) ' the moist threshold must have the same sign as' write(fates_log(),*) ' the dry threshold. Positive = soil water content [m3/m3],' @@ -1163,10 +1227,13 @@ subroutine PRTCheckParams(is_master) write(fates_log(),*) ' Stress_decid = ',prt_params%stress_decid(ipft) write(fates_log(),*) ' fates_phen_drought_threshold = ',prt_params%phen_drought_threshold(ipft) write(fates_log(),*) ' fates_phen_moist_threshold = ',prt_params%phen_moist_threshold (ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 elseif ( prt_params%phen_drought_threshold(ipft) >= prt_params%phen_moist_threshold(ipft) ) then + write(fates_log(),*) '---~---' write(fates_log(),*) ' When using drought semi-deciduous phenology,' write(fates_log(),*) ' the moist threshold must be greater than the dry threshold.' write(fates_log(),*) ' By greater we mean more positive or less negative, and' @@ -1175,8 +1242,10 @@ subroutine PRTCheckParams(is_master) write(fates_log(),*) ' Stress_decid = ',prt_params%stress_decid(ipft) write(fates_log(),*) ' fates_phen_drought_threshold = ',prt_params%phen_drought_threshold(ipft) write(fates_log(),*) ' fates_phen_moist_threshold = ',prt_params%phen_moist_threshold (ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end if @@ -1186,13 +1255,16 @@ subroutine PRTCheckParams(is_master) ! is bounded between 0 and 1 (exactly 0 and 1 are acceptable). if ( ( prt_params%phen_fnrt_drop_fraction(ipft) < 0.0_r8 ) .or. & ( prt_params%phen_fnrt_drop_fraction(ipft) > 1.0_r8 ) ) then + write(fates_log(),*) '---~---' write(fates_log(),*) ' Abscission rate for fine roots must be between 0 and 1 for ' write(fates_log(),*) ' deciduous PFTs.' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' evergreen flag: (should be 0):',prt_params%evergreen(ipft) write(fates_log(),*) ' phen_fnrt_drop_fraction: ', prt_params%phen_fnrt_drop_fraction(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if @@ -1203,21 +1275,27 @@ subroutine PRTCheckParams(is_master) if ( ( prt_params%woody(ipft) == itrue ) .and. & ( ( prt_params%phen_stem_drop_fraction(ipft) < 0.0_r8 ) .or. & ( prt_params%phen_stem_drop_fraction(ipft) > nearzero ) ) ) then + write(fates_log(),*) '---~---' write(fates_log(),*) ' Non-zero stem-drop fractions are not allowed for woody plants' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' part_params%woody:',prt_params%woody(ipft) write(fates_log(),*) ' phen_stem_drop_fraction: ', prt_params%phen_stem_drop_fraction(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 elseif ( ( prt_params%phen_stem_drop_fraction(ipft) < 0.0_r8 ) .or. & ( prt_params%phen_stem_drop_fraction(ipft) > 1.0_r8 ) ) then + write(fates_log(),*) '---~---' write(fates_log(),*) ' Deciduous non-wood plants must keep 0-100% of their stems' write(fates_log(),*) ' during the deciduous period.' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' evergreen flag: (should be 0):',prt_params%evergreen(ipft) write(fates_log(),*) ' phen_stem_drop_fraction: ', prt_params%phen_stem_drop_fraction(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end if @@ -1229,14 +1307,16 @@ subroutine PRTCheckParams(is_master) if ( ( prt_params%seed_alloc(ipft) + & prt_params%seed_alloc_mature(ipft)) > 1.0_r8 ) then + write(fates_log(),*) '---~---' write(fates_log(),*) 'The sum of seed allocation from base and mature trees may' write(fates_log(),*) ' not exceed 1.' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' seed_alloc: ',prt_params%seed_alloc(ipft) write(fates_log(),*) ' seed_alloc_mature: ',prt_params%seed_alloc_mature(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if ! Check if woody plants have a structural biomass (agb) intercept @@ -1244,21 +1324,46 @@ subroutine PRTCheckParams(is_master) if ( ( prt_params%allom_agb1(ipft) <= tiny(prt_params%allom_agb1(ipft)) ) .and. & ( prt_params%woody(ipft) .eq. 1 ) ) then + write(fates_log(),*) '---~---' write(fates_log(),*) 'Woody plants are expected to have a non-zero intercept' write(fates_log(),*) ' in the diameter to AGB allometry equations' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' allom_agb1: ',prt_params%allom_agb1(ipft) write(fates_log(),*) ' woody: ',prt_params%woody(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) '---~---' + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if + ! Check if parameter 2 for dbh -> height is negative when allom_hmode is 2 + ! (Weibull function / Poorter et al. (2006) + ! ML: FATES definition for parameter 2 is a bit unusual, which is why I added + ! the check. Normally the minus sign is left outside the parameter for + ! Weibull functions. + ! ---------------------------------------------------------------------------------- + if ( ( prt_params%allom_hmode(ipft) == 2 ) .and. & + ( prt_params%allom_d2h2 (ipft) > 0._r8 ) ) then + write(fates_log(),*) "---~---" + write(fates_log(),*) " Incorrect settings for height allometry." + write(fates_log(),*) ' PFT index: ',ipft + write(fates_log(),*) ' allom_hmode: ',prt_params%allom_hmode(ipft) + write(fates_log(),*) ' allom_d2h2: ',prt_params%allom_d2h2 (ipft) + write(fates_log(),*) " Parameter ""allom_d2h2"" must be negative when using" + write(fates_log(),*) " allom_hmode = 2." + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 + end if + ! Check if non-woody plants have structural biomass (agb) intercept ! ---------------------------------------------------------------------------------- ! if ( ( prt_params%allom_agb1(ipft) > tiny(prt_params%allom_agb1(ipft)) ) .and. & ! ( iprt_params%woody(ipft) .ne. 1 ) ) then ! +! write(fates_log(),*) "---~---" ! write(fates_log(),*) 'Non-woody plants are expected to have a zero intercept' ! write(fates_log(),*) ' in the diameter to AGB allometry equations' ! write(fates_log(),*) ' This is because the definition of AGB (as far as allometry)' @@ -1267,8 +1372,10 @@ subroutine PRTCheckParams(is_master) ! write(fates_log(),*) ' PFT#: ',ipft ! write(fates_log(),*) ' allom_agb1: ',prt_params%allom_agb1(ipft) ! write(fates_log(),*) ' woody: ',prt_params%woody(ipft) -! write(fates_log(),*) ' Aborting' -! call endrun(msg=errMsg(sourcefile, __LINE__)) +! write(fates_log(),*) "---~---" +! write(fates_log(),*) '' +! write(fates_log(),*) '' +! nerror = nerror + 1 ! ! end if @@ -1278,13 +1385,16 @@ subroutine PRTCheckParams(is_master) if ( ( prt_params%leaf_stor_priority(ipft) < 0.0_r8 ) .or. & ( prt_params%leaf_stor_priority(ipft) > 1.0_r8 ) ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'Prioritization of carbon allocation to leaf' write(fates_log(),*) ' and root turnover replacement, must be between' write(fates_log(),*) ' 0 and 1' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) 'leaf_stor_priority: ',prt_params%leaf_stor_priority(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if @@ -1293,18 +1403,26 @@ subroutine PRTCheckParams(is_master) ! Make sure nutrient storage fractions are positive if( prt_params%nitr_store_ratio(ipft) < 0._r8 ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'With parteh allometric CNP hypothesis' write(fates_log(),*) 'nitr_store_ratio must be > 0' write(fates_log(),*) 'PFT#: ',ipft write(fates_log(),*) 'nitr_store_ratio = ',prt_params%nitr_store_ratio(ipft) - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if if( prt_params%phos_store_ratio(ipft) < 0._r8 ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'With parteh allometric CNP hypothesis' write(fates_log(),*) 'phos_store_ratio must be > 0' write(fates_log(),*) 'PFT#: ',ipft write(fates_log(),*) 'nitr_store_ratio = ',prt_params%phos_store_ratio(ipft) - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if do i = 1,norgans @@ -1312,33 +1430,45 @@ subroutine PRTCheckParams(is_master) if(io == sapw_organ) then if ((prt_params%turnover_nitr_retrans(ipft,i) > nearzero)) then + write(fates_log(),*) "---~---" write(fates_log(),*) ' Retranslocation of sapwood tissues should be zero.' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' nitrogen retrans: ',prt_params%turnover_nitr_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if if ((prt_params%turnover_phos_retrans(ipft,i) > nearzero)) then + write(fates_log(),*) "---~---" write(fates_log(),*) ' Retranslocation of sapwood tissues should be zero.' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' phosphorus retrans: ',prt_params%turnover_nitr_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if elseif(io == struct_organ) then if ((prt_params%turnover_nitr_retrans(ipft,i) > nearzero)) then + write(fates_log(),*) "---~---" write(fates_log(),*) ' Retranslocation of structural tissues should be zero.' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' carbon retrans: ',prt_params%turnover_nitr_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if if ((prt_params%turnover_phos_retrans(ipft,i) > nearzero)) then + write(fates_log(),*) "---~---" write(fates_log(),*) ' Retranslocation of structural tissues should be zero.' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' phosphorus retrans: ',prt_params%turnover_nitr_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end if @@ -1347,13 +1477,16 @@ subroutine PRTCheckParams(is_master) (prt_params%turnover_phos_retrans(ipft,i) > 1.0_r8) .or. & (prt_params%turnover_nitr_retrans(ipft,i) < 0.0_r8) .or. & (prt_params%turnover_phos_retrans(ipft,i) < 0.0_r8)) then + write(fates_log(),*) "---~---" write(fates_log(),*) ' Retranslocation should range from 0 to 1.' write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' parameter file organ index: ',i,' global index: ',io write(fates_log(),*) ' nitr: ',prt_params%turnover_nitr_retrans(ipft,i) write(fates_log(),*) ' phos: ',prt_params%turnover_phos_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end do @@ -1365,18 +1498,24 @@ subroutine PRTCheckParams(is_master) ! if (parteh_mode .eq. prt_carbon_allom_hyp) then if ( ( prt_params%grperc(ipft) < 0.0_r8) .or. & ( prt_params%grperc(ipft) > 1.0_r8 ) ) then + write(fates_log(),*) "---~---" write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' Growth respiration must be between 0 and 1: ',prt_params%grperc(ipft) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if ! elseif(parteh_mode .eq. prt_cnp_flex_allom_hyp) then ! if ( ( any(prt_params%grperc_organ(ipft,:) < 0.0_r8)) .or. & ! ( any(prt_params%grperc_organ(ipft,:) >= 1.0_r8)) ) then +! write(fates_log(),*) "---~---" ! write(fates_log(),*) ' PFT#: ',ipft ! write(fates_log(),*) ' Growth respiration must be between 0 and 1: ',prt_params%grperc_organ(ipft,:) -! write(fates_log(),*) ' Aborting' -! call endrun(msg=errMsg(sourcefile, __LINE__)) +! write(fates_log(),*) "---~---" +! write(fates_log(),*) '' +! write(fates_log(),*) '' +! nerror = nerror + 1 ! end if ! end if @@ -1385,11 +1524,14 @@ subroutine PRTCheckParams(is_master) ! The first nitrogen stoichiometry is used in all cases if ( (any(prt_params%nitr_stoich_p1(ipft,:) < 0.0_r8)) .or. & (any(prt_params%nitr_stoich_p1(ipft,:) >= 1.0_r8))) then + write(fates_log(),*) "---~---" write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' N per C stoichiometry must bet between 0-1' write(fates_log(),*) prt_params%nitr_stoich_p1(ipft,:) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end select @@ -1401,6 +1543,7 @@ subroutine PRTCheckParams(is_master) (prt_params%phos_stoich_p1(ipft,i) < 0._r8) .or. & (prt_params%nitr_stoich_p1(ipft,i) > 1._r8) .or. & (prt_params%phos_stoich_p1(ipft,i) > 1._r8) ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'When the C,N,P allocation hypothesis with flexible' write(fates_log(),*) 'stoichiometry is turned on (prt_cnp_flex_allom_hyp),' write(fates_log(),*) 'all stoichiometries must be greater than or equal to zero,' @@ -1410,18 +1553,23 @@ subroutine PRTCheckParams(is_master) write(fates_log(),*) 'organ index (see head of PRTGenericMod): ',io write(fates_log(),*) 'nitr_stoich: ',prt_params%nitr_stoich_p1(ipft,i) write(fates_log(),*) 'phos_stoich: ',prt_params%phos_stoich_p1(ipft,i) - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end do if ( any(prt_params%alloc_priority(ipft,:) < 0) .or. & any(prt_params%alloc_priority(ipft,:) > 6) ) then + write(fates_log(),*) "---~---" write(fates_log(),*) ' PFT#: ',ipft write(fates_log(),*) ' Allocation priorities should be 0-6 for CNP flex hypothesis' write(fates_log(),*) prt_params%alloc_priority(ipft,:) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end select @@ -1437,35 +1585,45 @@ subroutine PRTCheckParams(is_master) ! Check that leaf turnover doesn't exeed 1 day if ( (years_per_day / prt_params%leaf_long(ipft,iage)) > 1._r8 ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'Leaf turnover time-scale is greater than 1 day!' write(fates_log(),*) 'ipft: ',ipft,' iage: ',iage write(fates_log(),*) 'leaf_long(ipft,iage): ',prt_params%leaf_long(ipft,iage),' [years]' - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if ! Check to make sure that all other age-classes for this PFT also ! have non-zero entries, it wouldn't make sense otherwise if ( any(prt_params%leaf_long(ipft,:) <= nearzero) ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'You specified a leaf_long that is zero or' write(fates_log(),*) 'invalid for a particular age class.' write(fates_log(),*) 'Yet, other age classes for this PFT are non-zero.' write(fates_log(),*) 'this doesnt make sense.' write(fates_log(),*) 'ipft = ',ipft write(fates_log(),*) 'leaf_long(ipft,:) = ',prt_params%leaf_long(ipft,:) - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if else if (prt_params%evergreen(ipft) .eq. itrue) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'You specified zero leaf turnover: ' write(fates_log(),*) 'ipft: ',ipft,' iage: ',iage write(fates_log(),*) 'leaf_long(ipft,iage): ',prt_params%leaf_long(ipft,iage) write(fates_log(),*) 'yet this is an evergreen PFT, and it only makes sense' write(fates_log(),*) 'that an evergreen would have leaf maintenance turnover' write(fates_log(),*) 'disable this error if you are ok with this' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end if @@ -1478,23 +1636,30 @@ subroutine PRTCheckParams(is_master) if ( (years_per_day / & (prt_params%leaf_long(ipft,nleafage) * & prt_params%senleaf_long_fdrought(ipft))) > 1._r8 ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'Drought-senescent turnover time-scale is greater than 1 day!' write(fates_log(),*) 'ipft: ',ipft write(fates_log(),*) 'leaf_long(ipft,nleafage)*senleaf_long_fdrought: ', & prt_params%leaf_long(ipft,nleafage)*prt_params%senleaf_long_fdrought(ipft),' [years]' - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end if if ( prt_params%senleaf_long_fdrought(ipft)1._r8 ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'senleaf_long_fdrought(ipft) must be greater than 0 ' write(fates_log(),*) 'or less than or equal to 1.' write(fates_log(),*) 'Set this to 1 if you want no accelerated senescence turnover' write(fates_log(),*) 'ipft = ',ipft write(fates_log(),*) 'senleaf_long_fdrought(ipft) = ',prt_params%senleaf_long_fdrought(ipft) - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if @@ -1502,22 +1667,29 @@ subroutine PRTCheckParams(is_master) ! Check that root turnover doesn't exeed 1 day if ( (years_per_day / prt_params%root_long(ipft)) > 1._r8 ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'Root turnover time-scale is greater than 1 day!' write(fates_log(),*) 'ipft: ',ipft write(fates_log(),*) 'root_long(ipft): ',prt_params%root_long(ipft),' [years]' - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if else if (prt_params%evergreen(ipft) .eq. itrue) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'You specified zero root turnover: ' write(fates_log(),*) 'ipft: ',ipft write(fates_log(),*) 'root_long(ipft): ',prt_params%root_long(ipft) write(fates_log(),*) 'yet this is an evergreen PFT, and it only makes sense' write(fates_log(),*) 'that an evergreen would have root maintenance turnover' write(fates_log(),*) 'disable this error if you are ok with this' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end if @@ -1526,11 +1698,14 @@ subroutine PRTCheckParams(is_master) ! Check that branch turnover doesn't exeed 1 day if ( (years_per_day / prt_params%branch_long(ipft)) > 1._r8 ) then + write(fates_log(),*) "---~---" write(fates_log(),*) 'Branch turnover time-scale is greater than 1 day!' write(fates_log(),*) 'ipft: ',ipft write(fates_log(),*) 'branch_long(ipft): ',prt_params%branch_long(ipft),' [years]' - write(fates_log(),*) 'Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(),*) "---~---" + write(fates_log(),*) '' + write(fates_log(),*) '' + nerror = nerror + 1 end if end if @@ -1538,6 +1713,14 @@ subroutine PRTCheckParams(is_master) end do pftloop + ! If any error was found, abort. We add a single point to abort the run after all + ! checks so users can get all the errors and address them in one go (as opposed to + ! multiple submissions). + if (nerror > 0) then + write(fates_log(),*) 'One or more parameter errors found. Aborting.' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + return end subroutine PRTCheckParams From 3be45867d9cf663c90acf8847ae92474b18a7adc Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Wed, 6 Dec 2023 15:00:18 -0800 Subject: [PATCH 070/300] actually solve the edge case of initial harvest once 2ndry area exceeds min --- biogeochem/EDLoggingMortalityMod.F90 | 101 ++++++++++++++------------- biogeochem/EDPatchDynamicsMod.F90 | 18 ++++- 2 files changed, 70 insertions(+), 49 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 9124259c59..c80244e392 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -240,6 +240,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, integer :: cur_harvest_tag ! the harvest tag of the cohort today real(r8) :: harvest_rate ! the final harvest rate to apply to this cohort today real(r8) :: state_vector(n_landuse_cats) + logical :: site_secondaryland_first_exceeding_min ! todo: probably lower the dbhmin default value to 30 cm ! todo: change the default logging_event_code to 1 september (-244) @@ -248,8 +249,22 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, ! todo: eventually set up distinct harvest practices, each with a set of input paramaeters ! todo: implement harvested carbon inputs + call get_luh_statedata(bc_in, state_vector) + site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. currentSite%min_allowed_landuse_fraction) & + .and. (.not. currentSite%landuse_vector_gt_min(secondaryland)) + if (.not. currentSite%transition_landuse_from_off_to_on) then - if (logging_time) then + if (site_secondaryland_first_exceeding_min) then + + ! if the total intended area of secondary lands are less than what we can consider without having too-small patches, + ! or if that was the case until just now, then there is special logic + harvest_rate = state_vector(secondaryland) / sum(state_vector(:)) + write(fates_log(), *) 'applying state_vector(secondaryland) to plants.', pft_i + + ! For area-based harvest, harvest_tag shall always be 2 (not applicable). + harvest_tag = 2 + cur_harvest_tag = 2 + elseif (logging_time) then ! Pass logging rates to cohort level @@ -299,67 +314,59 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, endif - ! if the total intended area of secondary lands are less than what we can consider without having too-small patches, - ! or if that was the case until just now, then there is special logic - call get_luh_statedata(bc_in, state_vector) - if (state_vector(secondaryland) .le. currentSite%min_allowed_landuse_fraction) then - harvest_rate = 0._r8 - else if (.not. currentSite%landuse_vector_gt_min(secondaryland)) then - harvest_rate = state_vector(secondaryland) - end if + else + harvest_rate = 0._r8 + ! For area-based harvest, harvest_tag shall always be 2 (not applicable). + harvest_tag = 2 + cur_harvest_tag = 2 + endif - ! transfer of area to secondary land is based on overall area affected, not just logged crown area - ! l_degrad accounts for the affected area between logged crowns - if(prt_params%woody(pft_i) == itrue)then ! only set logging rates for trees - if (cur_harvest_tag == 0) then - ! direct logging rates, based on dbh min and max criteria - if (dbh >= logging_dbhmin .and. .not. & - ((logging_dbhmax < fates_check_param_set) .and. (dbh >= logging_dbhmax )) ) then - ! the logic of the above line is a bit unintuitive but allows turning off the dbhmax comparison entirely. - ! since there is an .and. .not. after the first conditional, the dbh:dbhmax comparison needs to be - ! the opposite of what would otherwise be expected... - lmort_direct = harvest_rate * logging_direct_frac - else - lmort_direct = 0.0_r8 - end if + ! transfer of area to secondary land is based on overall area affected, not just logged crown area + ! l_degrad accounts for the affected area between logged crowns + if(prt_params%woody(pft_i) == itrue)then ! only set logging rates for trees + if (cur_harvest_tag == 0) then + ! direct logging rates, based on dbh min and max criteria + if (dbh >= logging_dbhmin .and. .not. & + ((logging_dbhmax < fates_check_param_set) .and. (dbh >= logging_dbhmax )) ) then + ! the logic of the above line is a bit unintuitive but allows turning off the dbhmax comparison entirely. + ! since there is an .and. .not. after the first conditional, the dbh:dbhmax comparison needs to be + ! the opposite of what would otherwise be expected... + lmort_direct = harvest_rate * logging_direct_frac else lmort_direct = 0.0_r8 end if + else + lmort_direct = 0.0_r8 + end if - ! infrastructure (roads, skid trails, etc) mortality rates - if (dbh >= logging_dbhmax_infra) then - lmort_infra = 0.0_r8 - else - lmort_infra = harvest_rate * logging_mechanical_frac - end if - - ! Collateral damage to smaller plants below the direct logging size threshold - ! will be applied via "understory_death" via the disturbance algorithm - if (canopy_layer .eq. 1) then - lmort_collateral = harvest_rate * logging_collateral_frac - else - lmort_collateral = 0._r8 - endif - - else ! non-woody plants still killed by infrastructure - lmort_direct = 0.0_r8 - lmort_collateral = 0.0_r8 + ! infrastructure (roads, skid trails, etc) mortality rates + if (dbh >= logging_dbhmax_infra) then + lmort_infra = 0.0_r8 + else lmort_infra = harvest_rate * logging_mechanical_frac end if - ! the area occupied by all plants in the canopy that aren't killed is still disturbed at the harvest rate + ! Collateral damage to smaller plants below the direct logging size threshold + ! will be applied via "understory_death" via the disturbance algorithm if (canopy_layer .eq. 1) then - l_degrad = harvest_rate - (lmort_direct + lmort_infra + lmort_collateral) ! fraction passed to 'degraded' forest. + lmort_collateral = harvest_rate * logging_collateral_frac else - l_degrad = 0._r8 + lmort_collateral = 0._r8 endif - else + else ! non-woody plants still killed by infrastructure lmort_direct = 0.0_r8 lmort_collateral = 0.0_r8 - lmort_infra = 0.0_r8 - l_degrad = 0.0_r8 + lmort_infra = harvest_rate * logging_mechanical_frac end if + + ! the area occupied by all plants in the canopy that aren't killed is still disturbed at the harvest rate + if (canopy_layer .eq. 1) then + l_degrad = harvest_rate - (lmort_direct + lmort_infra + lmort_collateral) ! fraction passed to 'degraded' forest. + else + l_degrad = 0._r8 + endif + else call get_init_landuse_harvest_rate(bc_in, currentSite%min_allowed_landuse_fraction, & harvest_rate, currentSite%landuse_vector_gt_min) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 43e0ffb13e..3bd71249c7 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -401,8 +401,10 @@ subroutine disturbance_rates( site_in, bc_in) ! or if that was the case until just now, then there is special logic if (state_vector(secondaryland) .le. site_in%min_allowed_landuse_fraction) then harvest_rate = 0._r8 - else if (.not. site_in%landuse_vector_gt_min(secondaryland)) then - harvest_rate = state_vector(secondaryland) + else if (currentPatch%land_use_label .eq. primaryland .and. .not. site_in%landuse_vector_gt_min(secondaryland)) then + harvest_rate = state_vector(secondaryland) / sum(state_vector(:)) + else + harvest_rate = 0._r8 end if else call get_init_landuse_harvest_rate(bc_in, site_in%min_allowed_landuse_fraction, & @@ -457,6 +459,14 @@ subroutine disturbance_rates( site_in, bc_in) ! if the area of secondary land has just exceeded the minimum below which we ignore things, set the flag to keep track of that. if ( (state_vector(secondaryland) .gt. site_in%min_allowed_landuse_fraction) .and. (.not. site_in%landuse_vector_gt_min(secondaryland)) ) then site_in%landuse_vector_gt_min(secondaryland) = .true. + write(fates_log(),*) 'setting site_in%landuse_vector_gt_min(secondaryland) = .true.' + + currentPatch => site_in%oldest_patch + do while (associated(currentPatch)) + write(fates_log(),*) 'cpatch area, LU, distrates(ilog): ', currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label, currentPatch%disturbance_rates(dtype_ilog), currentPatch%area - currentPatch%total_canopy_area + currentPatch => currentPatch%younger + end do + end if end subroutine disturbance_rates @@ -3537,10 +3547,14 @@ subroutine terminate_patches(currentSite, bc_in) end do call get_current_landuse_statevector(currentSite, state_vector) write(fates_log(),*) 'current landuse state vector: ', state_vector + write(fates_log(),*) 'current landuse state vector (not including bare gruond): ', state_vector/(1._r8-currentSite%area_bareground) call get_luh_statedata(bc_in, state_vector) write(fates_log(),*) 'driver data landuse state vector: ', state_vector write(fates_log(),*) 'min_allowed_landuse_fraction: ', currentSite%min_allowed_landuse_fraction write(fates_log(),*) 'landuse_vector_gt_min: ', currentSite%landuse_vector_gt_min + do i_landuse = 1, n_landuse_cats + write(fates_log(),*) 'trans matrix from: ', i_landuse, currentSite%landuse_transition_matrix(i_landuse,:) + end do call endrun(msg=errMsg(sourcefile, __LINE__)) ! Note to user. If you DO decide to remove the end-run above this line From d29e1820ee1514d7aabae3b676b7994f9fa43eea Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Wed, 6 Dec 2023 21:59:40 -0800 Subject: [PATCH 071/300] Fix swapped arguments for leaf biomass allometry. --- biogeochem/FatesAllometryMod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 45b8217518..3b5f4b3f77 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1508,9 +1508,11 @@ subroutine dh2blmax_2pwr(d,p1,p2,dbh_maxh,c2b,blmax,dblmaxdd) return end subroutine dh2blmax_2pwr + ! =========================================================================== - subroutine dh2blmax_3pwr(d,h,dhdd,p1,p2,p3,slatop,c2b,dbh_maxh,blmax,dblmaxdd) + + subroutine dh2blmax_3pwr(d,h,dhdd,p1,p2,p3,slatop,dbh_maxh,c2b,blmax,dblmaxdd) !-------------------------------------------------------------------------- ! ! This function calculates the maximum leaf biomass from reference @@ -1544,8 +1546,8 @@ subroutine dh2blmax_3pwr(d,h,dhdd,p1,p2,p3,slatop,c2b,dbh_maxh,blmax,dblmaxdd) ! p2 -- Parameter 2 (power, or log-slope) [ --] ! p3 -- Parameter 3 (power, or log-slope) [ --] ! slatop -- Top-of-canopy specific leaf area [ m2/gC] - ! c2b -- Carbon to biomass multiplier ~ 2 [ kg/kgC] ! dbh_maxh -- DBH at maximum height [ cm] + ! c2b -- Carbon to biomass multiplier ~ 2 [ kg/kgC] ! ! ------------------ ! Output arguments From eef328b633ff07fbdad8adb4bca4c5d9e1aa7d54 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Thu, 11 Jan 2024 10:46:13 -0800 Subject: [PATCH 072/300] Add option to change vertical scaling of leaf MR --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 52 +++++++++++++++------- main/EDPftvarcon.F90 | 12 ++++- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 50bb0464bf..1e29f75704 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -543,7 +543,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) case (lmrmodel_atkin_etal_2017) call LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! in - nscaler, & ! in + cumulative_lai, & ! in + currentCohort%vcmax25top, & ! in ft, & ! in bc_in(s)%t_veg_pa(ifp), & ! in currentPatch%tveg_lpa%GetMean(), & ! in @@ -2131,11 +2132,12 @@ end subroutine LeafLayerMaintenanceRespiration_Ryan_1991 ! ==================================================================================== subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & - nscaler, & - ft, & - veg_tempk, & - tgrowth, & - lmr) + cumulative_lai, & + vcmax25top, & + ft, & + veg_tempk, & + tgrowth, & + lmr) use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod, only : umolC_to_kgC @@ -2148,19 +2150,24 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & use EDPftvarcon , only : EDPftvarcon_inst ! Arguments - real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] - integer, intent(in) :: ft ! (plant) Functional Type Index - real(r8), intent(in) :: nscaler ! Scale for leaf nitrogen profile - real(r8), intent(in) :: veg_tempk ! vegetation temperature (degrees K) - real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale (degrees K) - real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) + real(r8), intent(in) :: lnc_top ! Leaf nitrogen content per unit area at canopy top [gN/m2] + integer, intent(in) :: ft ! (plant) Functional Type Index + real(r8), intent(in) :: vcmax25top ! top of canopy vcmax + real(r8), intent(in) :: cumulative_lai ! cumulative lai above the current leaf layer + real(r8), intent(in) :: veg_tempk ! vegetation temperature (degrees K) + real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale (degrees K) + real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) ! Locals real(r8) :: lmr25 ! leaf layer: leaf maintenance respiration rate at 25C (umol CO2/m**2/s) real(r8) :: r_0 ! base respiration rate, PFT-dependent (umol CO2/m**2/s) real(r8) :: r_t_ref ! acclimated ref respiration rate (umol CO2/m**2/s) real(r8) :: lmr25top ! canopy top leaf maint resp rate at 25C for this pft (umol CO2/m**2/s) + real(r8) :: rdark_scaler ! negative exponential scaling of rdark + real(r8) :: kn ! decay coefficient + real(r8) :: rdark_decay ! determines rate of rdark decay through canopy + ! parameter values of r_0 as listed in Atkin et al 2017: (umol CO2/m**2/s) ! Broad-leaved trees 1.7560 ! Needle-leaf trees 1.4995 @@ -2168,14 +2175,25 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! C3 herbs/grasses 2.1956 ! In the absence of better information, we use the same value for C4 grasses as C3 grasses. - ! note that this code uses the relationship between leaf N and respiration from Atkin et al - ! for the top of the canopy, but then assumes proportionality with N through the canopy. - + ! r_0 currently put into the EDPftvarcon_inst%dev_arbitrary_pft ! all figs in Atkin et al 2017 stop at zero Celsius so we will assume acclimation is fixed below that r_0 = EDPftvarcon_inst%maintresp_leaf_atkin2017_baserate(ft) - r_t_ref = max( 0._r8, nscaler * (r_0 + lmr_r_1 * lnc_top + lmr_r_2 * max(0._r8, (tgrowth - tfrz) )) ) - + rdark_decay = EDPftvarcon_inst%maintresp_leaf_decay(ft) + + ! This code uses the relationship between leaf N and respiration from Atkin et al + ! for the top of the canopy, but then scales through the canopy based on a rdark_scaler. + ! To assume proportionality with N through the canopy following Lloyd et al. 2010, use the + ! default parameter value of 2.43, which results in the scaling of photosynthesis and respiraiton + ! being proportional through the canopy. To have a steeper decrease in respiration than photosynthesis + ! this number can be smaller. There is some observational evidence for this being the case + ! in Lamour et al. 2023. + + kn = exp(0.00963_r8 * vcmax25top - rdark_decay) + rdark_scaler = exp(-kn * cumulative_lai) + + r_t_ref = max(0._r8, rdark_scaler * (r_0 + lmr_r_1 * lnc_top + lmr_r_2 * max(0._r8, (tgrowth - tfrz) )) ) + if (r_t_ref .eq. 0._r8) then warn_msg = 'Rdark is negative at this temperature and is capped at 0. tgrowth (C): '//trim(N2S(tgrowth-tfrz))//' pft: '//trim(I2S(ft)) call FatesWarn(warn_msg,index=4) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index d344f82c8d..9e44cc0218 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -89,7 +89,9 @@ module EDPftvarcon ! per Atkin et al 2017 real(r8), allocatable :: maintresp_leaf_ryan1991_baserate(:) ! leaf maintenance respiration per Ryan et al 1991 - + real(r8), allocatable :: maintresp_leaf_decay(:) ! leaf maintenance respiration decrease through the canopy + ! only with Atkin et al. 2017 + real(r8), allocatable :: bmort(:) real(r8), allocatable :: mort_ip_size_senescence(:) ! inflection point of dbh dependent senescence real(r8), allocatable :: mort_r_size_senescence(:) ! rate of change in mortality with dbh @@ -469,6 +471,10 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_maintresp_leaf_decay' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_prescribed_npp_canopy' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -910,6 +916,10 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%maintresp_leaf_ryan1991_baserate) + name = 'fates_maintresp_leaf_decay' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%maintresp_leaf_decay) + name = 'fates_prescribed_npp_canopy' call fates_params%RetrieveParameterAllocate(name=name, & data=this%prescribed_npp_canopy) From dec866cf2aef5da3c7b330ed5777d64a28008ec5 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Thu, 11 Jan 2024 12:14:36 -0800 Subject: [PATCH 073/300] update parameter file --- parameter_files/fates_params_default.cdl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index e288664751..f4fb48202e 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -386,7 +386,10 @@ variables: fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; - fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_leaf_decay(fates_pft) ; + fates_maintresp_leaf_decay:units = "unitless" ; + fates_maintresp_leaf_decay:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the default value of 2.43." ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -1310,6 +1313,9 @@ data: 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06 ; + fates_maintresp_leaf_decay = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; From f3fafd3221d37712f228727c05fddbe1f789ceae Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 15 Jan 2024 17:15:19 -0800 Subject: [PATCH 074/300] update parameters with latest changes --- .../archive/api28.0.0_103023_pr1093.xml | 54 ++++++++++++++----- parameter_files/fates_params_default.cdl | 44 +++++++-------- 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/parameter_files/archive/api28.0.0_103023_pr1093.xml b/parameter_files/archive/api28.0.0_103023_pr1093.xml index 8a3a957fe6..9665168836 100644 --- a/parameter_files/archive/api28.0.0_103023_pr1093.xml +++ b/parameter_files/archive/api28.0.0_103023_pr1093.xml @@ -22,14 +22,14 @@ fates_pft - 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, 0.07286975, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 + 0.06896,0.06896, 0.06896, 0.06896, 0.06896,0.06896, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 --> + 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 fates_pft - 0.976, 0.94490413, 1.08733502, 0.83213205, 0.976, 1.03732112, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 + 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 --> + 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 fates_pft @@ -37,29 +37,59 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 --> 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 + + fates_pft + + 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 + + + fates_pft + + 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 + + + fates_pft + + 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 + fates_pft - -0.12366731, -0.3447603, -0.31791391, -0.21568348, -0.12366731, -0.3521357, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 --> + -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, 0, 0, 0, 0, 0 + + + fates_pft + + 0.2715891, 0.3693718, 1.0787259, 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 + + + fates_pft + + 0.2715891, 0.3693718, 1.0787259, 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 fates_pft - 78.40877039, 306.842667, 106.8745821, 104.3586841, 78.40877039, 29.69929379, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 + 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 --> + 78.4087704, 306.842667, 106.8745821, 104.3586841, 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 fates_pft - 0.81243829, 0.75237703, 0.94713018, 1.11469727, 0.81243829, 1.12959569, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 + 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37--> + 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 fates_pft - 47.66661644, 196.6865691, 93.97904614, 160.6835089, 47.66661644, 25.12579143, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 + -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 --> + 47.6666164, 196.6865691, 93.9790461, 160.6835089, 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 fates_pft diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index a6667f9c3c..6a6f4909db 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -950,11 +950,11 @@ data: fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; - fates_allom_agb1 = 0.0673, 0.13640117, 0.03930566, 0.26536947, 0.0673, - 0.07286975, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + fates_allom_agb1 = 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, + 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.976, 0.94490413, 1.08733502, 0.83213205, 0.976, - 1.03732112, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; + fates_allom_agb2 = 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, + 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; @@ -967,39 +967,39 @@ data: fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; - fates_allom_blca_expnt_diff = -0.12366731, -0.3447603, -0.31791391, - -0.21568348, -0.12366731, -0.3521357, 0, 0, 0, 0, 0, 0 ; + fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, + 0, 0, 0, 0, 0 ; fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; + fates_allom_d2bl2 = 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, + 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; + fates_allom_d2ca_coefficient_min = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2h1 = 78.40877039, 306.842667, 106.8745821, 104.3586841, - 78.40877039, 29.69929379, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; + fates_allom_d2h1 = 78.4087704, 306.842667, 106.8745821, 104.3586841, + 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.81243829, 0.75237703, 0.94713018, 1.11469727, - 0.81243829, 1.12959569, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; + fates_allom_d2h2 = 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, + 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = 47.66661644, 196.6865691, 93.97904614, 160.6835089, - 47.66661644, 25.12579143, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; + fates_allom_d2h3 = 47.6666164, 196.6865691, 93.9790461, 160.6835089, + 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, 0.35, 0.35, 0.35 ; @@ -1023,7 +1023,7 @@ data: fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 ; fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; From 70b1a22aa411d90b771557f770b3e9a200f98875 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 19 Jan 2024 13:12:21 -0500 Subject: [PATCH 075/300] going with solver error structure from main, not history-density PR --- biogeochem/FatesPatchMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 15f4e60fb5..d86e5c5d51 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -466,8 +466,7 @@ subroutine ZeroValues(this) this%frac_burnt = 0.0_r8 this%tfc_ros = 0.0_r8 this%burnt_frac_litter(:) = 0.0_r8 - this%solve_err(:) = 0._r8 - this%consv_err(:) = 0._r8 + end subroutine ZeroValues !=========================================================================== From 72d8ec364c818b97391184593d1b19ab807157e7 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 19 Jan 2024 13:24:16 -0500 Subject: [PATCH 076/300] reconciled rad_error updates in two-stream and history_density --- main/FatesHistoryInterfaceMod.F90 | 127 +++++------------------------- 1 file changed, 18 insertions(+), 109 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 9924e17df7..4b9a22cdb6 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -376,19 +376,10 @@ module FatesHistoryInterfaceMod integer :: ih_c_stomata_si integer :: ih_c_lblayer_si - integer :: ih_rad_error_si - integer :: ih_vis_solve_err_si - integer :: ih_nir_solve_err_si - integer :: ih_vis_consv_err_si - integer :: ih_nir_consv_err_si - integer :: ih_vis_solve_err_age_si - integer :: ih_nir_solve_err_age_si - integer :: ih_vis_consv_err_age_si - integer :: ih_nir_consv_err_age_si - + integer :: ih_vis_rad_err_si + integer :: ih_nir_rad_err_si integer :: ih_fire_c_to_atm_si - integer :: ih_cbal_err_fates_si integer :: ih_err_fates_elem @@ -4718,15 +4709,8 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_growth_resp_secondary_si => this%hvars(ih_growth_resp_secondary_si)%r81d, & hio_c_stomata_si => this%hvars(ih_c_stomata_si)%r81d, & hio_c_lblayer_si => this%hvars(ih_c_lblayer_si)%r81d, & - hio_rad_error_si => this%hvars(ih_rad_error_si)%r81d, & - hio_vis_solve_err_si => this%hvars(ih_vis_solve_err_si)%r81d, & - hio_nir_solve_err_si => this%hvars(ih_nir_solve_err_si)%r81d, & - hio_vis_consv_err_si => this%hvars(ih_vis_consv_err_si)%r81d, & - hio_nir_consv_err_si => this%hvars(ih_nir_consv_err_si)%r81d, & - hio_vis_solve_err_age_si => this%hvars(ih_vis_solve_err_age_si)%r82d, & - hio_nir_solve_err_age_si => this%hvars(ih_nir_solve_err_age_si)%r82d, & - hio_vis_consv_err_age_si => this%hvars(ih_vis_consv_err_age_si)%r82d, & - hio_nir_consv_err_age_si => this%hvars(ih_nir_consv_err_age_si)%r82d, & + hio_vis_rad_err_si => this%hvars(ih_vis_rad_err_si)%r81d, & + hio_nir_rad_err_si => this%hvars(ih_nir_rad_err_si)%r81d, & hio_nep_si => this%hvars(ih_nep_si)%r81d, & hio_hr_si => this%hvars(ih_hr_si)%r81d, & hio_gpp_canopy_si => this%hvars(ih_gpp_canopy_si)%r81d, & @@ -4769,7 +4753,7 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) ! solver was called. The solver will be called for NIR ! if VIS is called, and likewise the same for conservation ! error. So the check on VIS solve error will catch all. - if( abs(cpatch%solve_err(ivis)-hlm_hio_ignore_val)>nearzero ) then + if( abs(cpatch%rad_error(ivis))>nearzero ) then age_class = get_age_class_index(cpatch%age) age_area_rad(age_class) = age_area_rad(age_class) + cpatch%total_canopy_area end if @@ -4779,56 +4763,22 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) sum_area_rad = sum(age_area_rad(:)) if_anyrad: if(sum_area_rad sites(s)%oldest_patch do while(associated(cpatch)) - if( abs(cpatch%solve_err(ivis)-hlm_hio_ignore_val)>nearzero ) then + if( abs(cpatch%rad_error(ivis))>nearzero ) then age_class = get_age_class_index(cpatch%age) - hio_vis_solve_err_age_si(io_si,age_class) = hio_vis_solve_err_age_si(io_si,age_class) + & - cpatch%solve_err(ivis) * cpatch%total_canopy_area/age_area_rad(age_class) - hio_nir_solve_err_age_si(io_si,age_class) = hio_nir_solve_err_age_si(io_si,age_class) + & - cpatch%solve_err(inir) * cpatch%total_canopy_area/age_area_rad(age_class) - hio_vis_consv_err_age_si(io_si,age_class) = hio_vis_consv_err_age_si(io_si,age_class) + & - cpatch%consv_err(ivis) * cpatch%total_canopy_area/age_area_rad(age_class) - hio_nir_consv_err_age_si(io_si,age_class) = hio_nir_consv_err_age_si(io_si,age_class) + & - cpatch%consv_err(inir) * cpatch%total_canopy_area/age_area_rad(age_class) - - hio_vis_solve_err_si(io_si) = hio_vis_solve_err_si(io_si) + & - cpatch%solve_err(ivis)*cpatch%total_canopy_area/sum(age_area_rad(:)) - hio_nir_solve_err_si(io_si) = hio_nir_solve_err_si(io_si) + & - cpatch%solve_err(inir)*cpatch%total_canopy_area/sum(age_area_rad(:)) - hio_vis_consv_err_si(io_si) = hio_vis_consv_err_si(io_si) + & - cpatch%consv_err(ivis)*cpatch%total_canopy_area/sum(age_area_rad(:)) - hio_nir_consv_err_si(io_si) = hio_nir_consv_err_si(io_si) + & - cpatch%consv_err(inir)*cpatch%total_canopy_area/sum(age_area_rad(:)) + hio_vis_rad_err_si(io_si) = hio_vis_rad_err_si(io_si) + & + cpatch%rad_err(ivis)*cpatch%total_canopy_area/sum_area_rad + hio_nir_rad_err_si(io_si) = hio_nir_rad_err_si(io_si) + & + cpatch%rad_err(inir)*cpatch%total_canopy_area/sum_area_rad end if cpatch => cpatch%younger @@ -4850,7 +4800,6 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_c_stomata_si(io_si) = hlm_hio_ignore_val hio_c_lblayer_si(io_si) = hlm_hio_ignore_val - hio_rad_error_si(io_si) = hlm_hio_ignore_val hio_tveg(io_si) = hlm_hio_ignore_val exit if_veg_area @@ -4871,10 +4820,6 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_c_lblayer_si(io_si) = hio_c_lblayer_si(io_si) + & cpatch%c_lblayer * cpatch%total_canopy_area * mol_per_umol * site_area_veg_inv - - hio_rad_error_si(io_si) = hio_rad_error_si(io_si) + & - cpatch%radiation_error * cpatch%total_canopy_area * site_area_veg_inv - ! Only accumulate the instantaneous vegetation temperature for vegetated patches if (cpatch%patchno .ne. 0) then @@ -8383,32 +8328,16 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) - ! radiation error - call this%set_history_var(vname='FATES_RAD_ERROR', units='W m-2 ', & - long='radiation error in FATES RTM', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_rad_error_si) - - call this%set_history_var(vname='FATES_VIS_SOLVE_ERROR', units='-', & + call this%set_history_var(vname='FATES_VIS_RAD_ERROR', units='-', & long='mean two-stream solver error for VIS', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_vis_solve_err_si) + ivar=ivar, initialize=initialize_variables, index = ih_vis_rad_err_si) - call this%set_history_var(vname='FATES_NIR_SOLVE_ERROR', units='-', & + call this%set_history_var(vname='FATES_NIR_RAD_ERROR', units='-', & long='mean two-stream solver error for NIR', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_nir_solve_err_si) + ivar=ivar, initialize=initialize_variables, index = ih_nir_rad_err_si) - call this%set_history_var(vname='FATES_VIS_CONSV_ERROR', units='-', & - long='mean two-stream conservation error for VIS', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_vis_consv_err_si) - - call this%set_history_var(vname='FATES_NIR_CONSV_ERROR', units='-', & - long='mean two-stream conservation error for NIR', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_nir_consv_err_si) - call this%set_history_var(vname='FATES_AR', units='gC/m^2/s', & long='autotrophic respiration', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & @@ -8602,26 +8531,6 @@ subroutine define_history_vars(this, initialize_variables) !HERE !! if_hifrq1: if(hlm_hist_level_hifrq>1) then - - call this%set_history_var(vname='FATES_VIS_SOLVE_ERROR_AGE', units='-', & - long='mean two-stream solver error for VIS by patch age', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_vis_solve_err_age_si) - - call this%set_history_var(vname='FATES_NIR_SOLVE_ERROR_AGE', units='-', & - long='mean two-stream solver error for NIR by patch age', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_nir_solve_err_age_si) - - call this%set_history_var(vname='FATES_VIS_CONSV_ERROR_AGE', units='-', & - long='mean two-stream conservation error for VIS by patch age', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_vis_consv_err_age_si) - - call this%set_history_var(vname='FATES_NIR_CONSV_ERROR_AGE', units='-', & - long='mean two-stream conservation error for NIR by patch age', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_nir_consv_err_age_si) ! This next group are multidimensional variables that are updated ! over the short timestep. We turn off these variables when we want From 82650edd72eb44083a18d1a2a46cd2fbea1938f8 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 19 Jan 2024 14:59:15 -0500 Subject: [PATCH 077/300] imported luh1 uppdates to history into new framework --- main/FatesHistoryInterfaceMod.F90 | 283 ++++++++++++++++++++---------- 1 file changed, 186 insertions(+), 97 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 4b9a22cdb6..4f139df282 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -60,8 +60,18 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog use FatesRadiationMemMod , only : ivis,inir use FatesInterfaceTypesMod , only : hlm_hist_level_hifrq,hlm_hist_level_dynam - - + use FatesIOVariableKindMod, only : site_r8, site_soil_r8, site_size_pft_r8 + use FatesIOVariableKindMod, only : site_size_r8, site_pft_r8, site_age_r8 + use FatesIOVariableKindMod, only : site_coage_r8, site_coage_pft_r8 + use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 + use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 + use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 + use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 + use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 + use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8, site_clscpf_r8 + use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdam_r8 + use FatesIOVariableKindMod, only : site_landuse_r8, site_lulu_r8, site_lupft_r8 + use FatesConstantsMod , only : n_landuse_cats use FatesAllometryMod , only : CrownDepth use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : set_root_fraction @@ -92,7 +102,7 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : dens_fresh_liquid_water use FatesConstantsMod , only : grav_earth use FatesLitterMod , only : litter_type - use FatesConstantsMod , only : secondaryforest + use FatesConstantsMod , only : secondaryland use PRTGenericMod , only : leaf_organ, fnrt_organ, sapw_organ use PRTGenericMod , only : struct_organ, store_organ, repro_organ @@ -338,13 +348,13 @@ module FatesHistoryInterfaceMod integer :: ih_growth_resp_secondary_si integer :: ih_primaryland_fusion_error_si - integer :: ih_disturbance_rate_p2p_si - integer :: ih_disturbance_rate_p2s_si - integer :: ih_disturbance_rate_s2s_si + + integer :: ih_area_si_landuse + integer :: ih_disturbance_rate_si_lulu + integer :: ih_fire_disturbance_rate_si integer :: ih_logging_disturbance_rate_si integer :: ih_fall_disturbance_rate_si - integer :: ih_potential_disturbance_rate_si integer :: ih_harvest_carbonflux_si integer :: ih_harvest_debt_si integer :: ih_harvest_debt_sec_si @@ -636,7 +646,7 @@ module FatesHistoryInterfaceMod integer :: ih_c_stomata_si_age integer :: ih_c_lblayer_si_age integer :: ih_agesince_anthrodist_si_age - integer :: ih_secondaryforest_area_si_age + integer :: ih_secondarylands_area_si_age integer :: ih_area_burnt_si_age ! integer :: ih_fire_rate_of_spread_front_si_age integer :: ih_fire_intensity_si_age @@ -790,7 +800,8 @@ module FatesHistoryInterfaceMod integer, private :: levelcwd_index_, levelage_index_ integer, private :: levcacls_index_, levcapf_index_ integer, private :: levclscpf_index_ - + integer, private :: levlanduse_index_, levlulu_index_, levlupft_index_ + contains procedure :: Init @@ -835,6 +846,9 @@ module FatesHistoryInterfaceMod procedure :: levelage_index procedure :: levagefuel_index procedure :: levclscpf_index + procedure :: levlanduse_index + procedure :: levlulu_index + procedure :: levlupft_index ! private work functions procedure, private :: define_history_vars @@ -863,7 +877,9 @@ module FatesHistoryInterfaceMod procedure, private :: set_levheight_index procedure, private :: set_levagefuel_index procedure, private :: set_levclscpf_index - + procedure, private :: set_levlanduse_index + procedure, private :: set_levlulu_index + procedure, private :: set_levlupft_index procedure, private :: set_levelem_index procedure, private :: set_levelpft_index procedure, private :: set_levelcwd_index @@ -901,7 +917,8 @@ subroutine Init(this, num_threads, fates_bounds) use FatesIODimensionsMod, only : levelem, levelpft use FatesIODimensionsMod, only : levelcwd, levelage, levclscpf use FatesIODimensionsMod, only : levcdpf, levcdsc, levcdam - + use FatesIODimensionsMod, only : levlanduse, levlulu, levlupft + implicit none class(fates_history_interface_type), intent(inout) :: this @@ -1039,6 +1056,21 @@ subroutine Init(this, num_threads, fates_bounds) call this%set_levclscpf_index(dim_count) call this%dim_bounds(dim_count)%Init(levclscpf, num_threads, & fates_bounds%clscpf_begin, fates_bounds%clscpf_end) + + dim_count = dim_count + 1 + call this%set_levlanduse_index(dim_count) + call this%dim_bounds(dim_count)%Init(levlanduse, num_threads, & + fates_bounds%landuse_begin, fates_bounds%landuse_end) + + dim_count = dim_count + 1 + call this%set_levlulu_index(dim_count) + call this%dim_bounds(dim_count)%Init(levlulu, num_threads, & + fates_bounds%lulu_begin, fates_bounds%lulu_end) + + dim_count = dim_count + 1 + call this%set_levlupft_index(dim_count) + call this%dim_bounds(dim_count)%Init(levlupft, num_threads, & + fates_bounds%lupft_begin, fates_bounds%lupft_end) end subroutine Init @@ -1160,21 +1192,25 @@ subroutine SetThreadBoundsEach(this, thread_index, thread_bounds) call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%clscpf_begin, thread_bounds%clscpf_end) + index = this%levlanduse_index() + call this%dim_bounds(index)%SetThreadBounds(thread_index, & + thread_bounds%landuse_begin, thread_bounds%landuse_end) + + index = this%levlulu_index() + call this%dim_bounds(index)%SetThreadBounds(thread_index, & + thread_bounds%lulu_begin, thread_bounds%lulu_end) + + index = this%levlupft_index() + call this%dim_bounds(index)%SetThreadBounds(thread_index, & + thread_bounds%lupft_begin, thread_bounds%lupft_end) + + end subroutine SetThreadBoundsEach ! =================================================================================== subroutine assemble_history_output_types(this) - use FatesIOVariableKindMod, only : site_r8, site_soil_r8, site_size_pft_r8 - use FatesIOVariableKindMod, only : site_size_r8, site_pft_r8, site_age_r8 - use FatesIOVariableKindMod, only : site_coage_r8, site_coage_pft_r8 - use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 - use FatesIOVariableKindMod, only : site_scagpft_r8, site_agepft_r8 - use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 - use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 - use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 - use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8, site_clscpf_r8 - use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdam_r8 + implicit none @@ -1258,6 +1294,15 @@ subroutine assemble_history_output_types(this) call this%set_dim_indices(site_clscpf_r8, 1, this%column_index()) call this%set_dim_indices(site_clscpf_r8, 2, this%levclscpf_index()) + + call this%set_dim_indices(site_landuse_r8, 1, this%column_index()) + call this%set_dim_indices(site_landuse_r8, 2, this%levlanduse_index()) + + call this%set_dim_indices(site_lulu_r8, 1, this%column_index()) + call this%set_dim_indices(site_lulu_r8, 2, this%levlulu_index()) + + call this%set_dim_indices(site_lupft_r8, 1, this%column_index()) + call this%set_dim_indices(site_lupft_r8, 2, this%levlupft_index()) end subroutine assemble_history_output_types @@ -1672,6 +1717,51 @@ end function levclscpf_index ! ====================================================================================== + subroutine set_levlanduse_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levlanduse_index_ = index + end subroutine set_levlanduse_index + + integer function levlanduse_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levlanduse_index = this%levlanduse_index_ + end function levlanduse_index + + ! ====================================================================================== + + subroutine set_levlulu_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levlulu_index_ = index + end subroutine set_levlulu_index + + integer function levlulu_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levlulu_index = this%levlulu_index_ + end function levlulu_index + + ! ====================================================================================== + + subroutine set_levlupft_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levlupft_index_ = index + end subroutine set_levlupft_index + + integer function levlupft_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levlupft_index = this%levlupft_index_ + end function levlupft_index + + ! ===================================================================================== + subroutine zero_site_hvars(this, currentSite, upfreq_in) ! This routine zero's a history diagnostic variable @@ -1931,6 +2021,18 @@ subroutine init_dim_kinds_maps(this) index = index + 1 call this%dim_kinds(index)%Init(site_clscpf_r8, 2) + ! site x land use class + index = index + 1 + call this%dim_kinds(index)%Init(site_landuse_r8, 2) + + ! site x land use x land use class + index = index + 1 + call this%dim_kinds(index)%Init(site_lulu_r8, 2) + + ! site x land use x pft + index = index + 1 + call this%dim_kinds(index)%Init(site_lupft_r8, 2) + ! FIXME(bja, 2016-10) assert(index == fates_history_num_dim_kinds) end subroutine init_dim_kinds_maps @@ -2226,6 +2328,8 @@ end subroutine update_history_dyn subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) + + ! Arguments class(fates_history_interface_type) :: this integer , intent(in) :: nc ! clump index @@ -2307,13 +2411,9 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_canopy_biomass_si => this%hvars(ih_canopy_biomass_si)%r81d, & hio_ustory_biomass_si => this%hvars(ih_understory_biomass_si)%r81d, & hio_primaryland_fusion_error_si => this%hvars(ih_primaryland_fusion_error_si)%r81d, & - hio_disturbance_rate_p2p_si => this%hvars(ih_disturbance_rate_p2p_si)%r81d, & - hio_disturbance_rate_p2s_si => this%hvars(ih_disturbance_rate_p2s_si)%r81d, & - hio_disturbance_rate_s2s_si => this%hvars(ih_disturbance_rate_s2s_si)%r81d, & hio_fire_disturbance_rate_si => this%hvars(ih_fire_disturbance_rate_si)%r81d, & hio_logging_disturbance_rate_si => this%hvars(ih_logging_disturbance_rate_si)%r81d, & hio_fall_disturbance_rate_si => this%hvars(ih_fall_disturbance_rate_si)%r81d, & - hio_potential_disturbance_rate_si => this%hvars(ih_potential_disturbance_rate_si)%r81d, & hio_harvest_carbonflux_si => this%hvars(ih_harvest_carbonflux_si)%r81d, & hio_harvest_debt_si => this%hvars(ih_harvest_debt_si)%r81d, & hio_harvest_debt_sec_si => this%hvars(ih_harvest_debt_sec_si)%r81d, & @@ -2431,30 +2531,23 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! error in primary lands from patch fusion [m2 m-2 day-1] -> [m2 m-2 yr-1] hio_primaryland_fusion_error_si(io_si) = sites(s)%primary_land_patchfusion_error * days_per_year + + ! output site-level disturbance rates [m2 m-2 day-1] -> [m2 m-2 yr-1] - TO DO rework this - ! output site-level disturbance rates [m2 m-2 day-1] -> [m2 m-2 yr-1] - hio_disturbance_rate_p2p_si(io_si) = sum(sites(s)%disturbance_rates_primary_to_primary(1:N_DIST_TYPES)) * days_per_year - hio_disturbance_rate_p2s_si(io_si) = sum(sites(s)%disturbance_rates_primary_to_secondary(1:N_DIST_TYPES)) * days_per_year - hio_disturbance_rate_s2s_si(io_si) = sum(sites(s)%disturbance_rates_secondary_to_secondary(1:N_DIST_TYPES)) * days_per_year - - hio_fire_disturbance_rate_si(io_si) = (sites(s)%disturbance_rates_primary_to_primary(dtype_ifire) + & - sites(s)%disturbance_rates_primary_to_secondary(dtype_ifire) + & - sites(s)%disturbance_rates_secondary_to_secondary(dtype_ifire)) * & + hio_fire_disturbance_rate_si(io_si) = & + sum(sites(s)%disturbance_rates(dtype_ifire,1:n_landuse_cats,1:n_landuse_cats)) * & days_per_year - - hio_logging_disturbance_rate_si(io_si) = (sites(s)%disturbance_rates_primary_to_primary(dtype_ilog) + & - sites(s)%disturbance_rates_primary_to_secondary(dtype_ilog) + & - sites(s)%disturbance_rates_secondary_to_secondary(dtype_ilog)) * & + + hio_logging_disturbance_rate_si(io_si) = & + sum(sites(s)%disturbance_rates(dtype_ilog,1:n_landuse_cats,1:n_landuse_cats)) * & days_per_year - - hio_fall_disturbance_rate_si(io_si) = (sites(s)%disturbance_rates_primary_to_primary(dtype_ifall) + & - sites(s)%disturbance_rates_primary_to_secondary(dtype_ifall) + & - sites(s)%disturbance_rates_secondary_to_secondary(dtype_ifall)) * & + + hio_fall_disturbance_rate_si(io_si) = & + sum(sites(s)%disturbance_rates(dtype_ifall,1:n_landuse_cats,1:n_landuse_cats)) * & days_per_year - hio_potential_disturbance_rate_si(io_si) = sum(sites(s)%potential_disturbance_rates(1:N_DIST_TYPES)) * days_per_year - - hio_harvest_carbonflux_si(io_si) = sites(s)%mass_balance(element_pos(carbon12_element))%wood_product * AREA_INV + hio_harvest_carbonflux_si(io_si) = & + sites(s)%mass_balance(element_pos(carbon12_element))%wood_product * AREA_INV ! carbon flux associated with mortality of trees dying by fire @@ -2513,7 +2606,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! Increment the number of patches per site hio_npatches_si(io_si) = hio_npatches_si(io_si) + 1._r8 - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + if ( cpatch%land_use_label .eq. secondaryland ) then hio_npatches_sec_si(io_si) = hio_npatches_sec_si(io_si) + 1._r8 end if @@ -2533,7 +2626,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) (cpatch%tveg_lpa%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV ! some diagnostics on secondary forest area and its age distribution - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + if ( cpatch%land_use_label .eq. secondaryland ) then hio_fraction_secondary_forest_si(io_si) = hio_fraction_secondary_forest_si(io_si) + & cpatch%area * AREA_INV @@ -2617,7 +2710,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! Increment the number of cohorts per site hio_ncohorts_si(io_si) = hio_ncohorts_si(io_si) + 1._r8 - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + if ( cpatch%land_use_label .eq. secondaryland ) then hio_ncohorts_sec_si(io_si) = hio_ncohorts_sec_si(io_si) + 1._r8 end if @@ -2671,7 +2764,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ( leaf_m + (sapw_m + struct_m + store_m) * prt_params%allom_agb_frac(ccohort%pft) ) ! track the total biomass on all secondary lands - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + if ( cpatch%land_use_label .eq. secondaryland ) then hio_biomass_secondary_forest_si(io_si) = hio_biomass_secondary_forest_si(io_si) + & total_m * ccohort%n * AREA_INV endif @@ -2956,6 +3049,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) real(r8) :: storep_understory_scpf(numpft*nlevsclass) real(r8) :: storec_canopy_scpf(numpft*nlevsclass) real(r8) :: storec_understory_scpf(numpft*nlevsclass) + + integer :: i_dist, j_dist type(site_fluxdiags_type), pointer :: flux_diags type(site_fluxdiags_type), pointer :: flux_diags_c @@ -3133,7 +3228,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_zstar_si_age => this%hvars(ih_zstar_si_age)%r82d, & hio_biomass_si_age => this%hvars(ih_biomass_si_age)%r82d, & hio_agesince_anthrodist_si_age => this%hvars(ih_agesince_anthrodist_si_age)%r82d, & - hio_secondaryforest_area_si_age => this%hvars(ih_secondaryforest_area_si_age)%r82d, & + hio_secondarylands_area_si_age => this%hvars(ih_secondarylands_area_si_age)%r82d, & + hio_area_si_landuse => this%hvars(ih_area_si_landuse)%r82d, & hio_area_burnt_si_age => this%hvars(ih_area_burnt_si_age)%r82d, & ! hio_fire_rate_of_spread_front_si_age => this%hvars(ih_fire_rate_of_spread_front_si_age)%r82d, & hio_fire_intensity_si_age => this%hvars(ih_fire_intensity_si_age)%r82d, & @@ -3169,7 +3265,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_elong_factor_si_pft => this%hvars(ih_elong_factor_si_pft)%r82d, & hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & 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_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) model_day_int = nint(hlm_model_day) @@ -3190,6 +3287,16 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) storec_canopy_scpf(:) = 0._r8 storec_understory_scpf(:) = 0._r8 + ! roll up disturbance rates in land-use x land-use array into a single dimension + do i_dist = 1, n_landuse_cats + do j_dist = 1, n_landuse_cats + hio_disturbance_rate_si_lulu(io_si, i_dist+n_landuse_cats*(j_dist-1)) = & + sum(sites(s)%disturbance_rates(1:n_dist_types,i_dist, j_dist)) * & + days_per_year + end do + end do + + do el = 1, num_elements ! Total model error [kg/day -> kg/s] (all elements) @@ -3240,6 +3347,10 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_area_si_age(io_si,cpatch%age_class) = hio_area_si_age(io_si,cpatch%age_class) & + cpatch%area * AREA_INV + hio_area_si_landuse(io_si, cpatch%land_use_label) = & + hio_area_si_landuse(io_si, cpatch%land_use_label) & + + cpatch%area * AREA_INV + ! Increment some patch-age-resolved diagnostics hio_lai_si_age(io_si,cpatch%age_class) = hio_lai_si_age(io_si,cpatch%age_class) & + sum(cpatch%tlai_profile(:,:,:)) * cpatch%area @@ -3256,7 +3367,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) endif ! some diagnostics on secondary forest area and its age distribution - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + if ( cpatch%land_use_label .eq. secondaryland ) then ageclass_since_anthrodist = get_age_class_index(cpatch%age_since_anthro_disturbance) @@ -3264,9 +3375,9 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_agesince_anthrodist_si_age(io_si,ageclass_since_anthrodist) & + cpatch%area * AREA_INV - hio_secondaryforest_area_si_age(io_si,cpatch%age_class) = & - hio_secondaryforest_area_si_age(io_si,cpatch%age_class) & - + cpatch%area * AREA_INV + hio_secondarylands_area_si_age(io_si,cpatch%age_class) = & + hio_secondarylands_area_si_age(io_si,cpatch%age_class) & + + cpatch%area * AREA_INV endif @@ -3404,19 +3515,16 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_nindivs_si_pft(io_si,ft) = hio_nindivs_si_pft(io_si,ft) + & ccohort%n * AREA_INV - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + if ( cpatch%land_use_label .eq. secondaryland ) then hio_nindivs_sec_si_pft(io_si,ft) = hio_nindivs_sec_si_pft(io_si,ft) + & - ccohort%n * AREA_INV + ccohort%n * AREA_INV + hio_biomass_sec_si_pft(io_si, ft) = hio_biomass_sec_si_pft(io_si, ft) + & + (ccohort%n * AREA_INV) * total_m end if hio_biomass_si_pft(io_si, ft) = hio_biomass_si_pft(io_si, ft) + & (ccohort%n * AREA_INV) * total_m - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then - hio_biomass_sec_si_pft(io_si, ft) = hio_biomass_sec_si_pft(io_si, ft) + & - (ccohort%n * AREA_INV) * total_m - end if - ! update total biomass per age bin hio_biomass_si_age(io_si,cpatch%age_class) = hio_biomass_si_age(io_si,cpatch%age_class) & + total_m * ccohort%n * AREA_INV @@ -3500,7 +3608,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_npp_si_pft(io_si, ft) = hio_npp_si_pft(io_si, ft) + & ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + if ( cpatch%land_use_label .eq. secondaryland ) then hio_gpp_sec_si_pft(io_si, ft) = hio_gpp_sec_si_pft(io_si, ft) + & ccohort%gpp_acc_hold * n_perm2 / days_per_year / sec_per_day hio_npp_sec_si_pft(io_si, ft) = hio_npp_sec_si_pft(io_si, ft) + & @@ -3620,8 +3728,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_m9_si_scls(io_si,scls) = hio_m9_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha ! Examine secondary forest mortality and mortality rates - if(cpatch%anthro_disturbance_label .eq. secondaryforest) then - + if(cpatch%land_use_label .eq. secondaryland) then if (hlm_use_cohort_age_tracking .eq.itrue) then hio_m10_sec_si_scls(io_si,scls) = hio_m10_sec_si_scls(io_si,scls) + & ccohort%asmort*ccohort%n / m2_per_ha @@ -3914,7 +4021,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_m3_mortality_understory_si_scpf(io_si,scpf) = hio_m3_mortality_understory_si_scpf(io_si,scpf) + & ccohort%cmort * ccohort%n / m2_per_ha - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + if(cpatch%land_use_label .eq. secondaryland) then hio_mortality_canopy_secondary_si_scls(io_si,scls) = hio_mortality_canopy_secondary_si_scls(io_si,scls) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n / m2_per_ha + & @@ -4197,7 +4304,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha ! Shijie: Think about how to add later? - !if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + !if ( cpatch%land_use_label .eq. secondaryland ) then ! hio_mortality_canopy_secondary_si_scls(io_si,i_scls) = hio_mortality_canopy_secondary_si_scls(io_si,i_scls) + & ! sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha !end if @@ -4859,10 +4966,10 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) ccohort%resp_m_unreduced * n_perm2 * dt_tstep_inv ! Secondary forest only - if ( cpatch%anthro_disturbance_label .eq. secondaryforest ) then + if(cpatch%land_use_label .eq. secondaryland) then hio_npp_secondary_si(io_si) = hio_npp_secondary_si(io_si) + & ccohort%npp_tstep * n_perm2 * dt_tstep_inv - + hio_gpp_secondary_si(io_si) = hio_gpp_secondary_si(io_si) + & ccohort%gpp_tstep * n_perm2 * dt_tstep_inv @@ -6015,6 +6122,16 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_lai_secondary_si) + call this%set_history_var(vname='FATES_PATCHAREA_LU', units='m2 m-2', & + long='patch area by land use type', use_default='active', & + avgflag='A', vtype=site_landuse_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index=ih_area_si_landuse) + + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_MATRIX_LULU', units='m2 m-2 yr-1', & + long='disturbance rates by land use type x land use type matrix', use_default='active', & + avgflag='A', vtype=site_lulu_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index=ih_disturbance_rate_si_lulu) + ! Secondary forest area and age diagnostics call this%set_history_var(vname='FATES_SECONDARY_FOREST_FRACTION', & @@ -6387,27 +6504,6 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_primaryland_fusion_error_si) - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_P2P', & - units='m2 m-2 yr-1', & - long='disturbance rate from primary to primary lands', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_disturbance_rate_p2p_si) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_P2S', & - units='m2 m-2 yr-1', & - long='disturbance rate from primary to secondary lands', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_disturbance_rate_p2s_si ) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_S2S', & - units='m2 m-2 yr-1', & - long='disturbance rate from secondary to secondary lands', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_disturbance_rate_s2s_si) - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_FIRE', & units='m2 m-2 yr-1', long='disturbance rate from fire', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & @@ -6426,13 +6522,6 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_fall_disturbance_rate_si) - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_POTENTIAL', & - units='m2 m-2 yr-1', & - long='potential (i.e., including unresolved) disturbance rate', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_potential_disturbance_rate_si) - call this%set_history_var(vname='FATES_HARVEST_CARBON_FLUX', & units='kg m-2 yr-1', & long='harvest carbon flux in kg carbon per m2 per year', & @@ -6825,7 +6914,7 @@ subroutine define_history_vars(this, initialize_variables) long='secondary forest patch area age distribution since any kind of disturbance', & use_default='inactive', avgflag='A', vtype=site_age_r8, & hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_secondaryforest_area_si_age) + index=ih_secondarylands_area_si_age) call this%set_history_var(vname='FATES_FRAGMENTATION_SCALER_SL', units='', & long='factor (0-1) by which litter/cwd fragmentation proceeds relative to max rate by soil layer', & From 84addd678d13fa3ecc6779eb4192d552caf4bbeb Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sat, 20 Jan 2024 15:42:18 -0500 Subject: [PATCH 078/300] Added a wrapper for hi frequency history updates --- main/FatesHistoryInterfaceMod.F90 | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 4f139df282..e43ec6a524 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -812,6 +812,7 @@ module FatesHistoryInterfaceMod procedure :: update_history_dyn procedure :: update_history_dyn1 procedure :: update_history_dyn2 + procedure :: update_history_hifrq procedure :: update_history_hifrq1 procedure :: update_history_hifrq2 procedure :: update_history_hydraulics @@ -2225,10 +2226,9 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! --------------------------------------------------------------------------------- ! This is the call to update the history IO arrays that are expected to only change ! after Ecosystem Dynamics have been processed. + ! This is the general routine that will call the single or multi-dimensional + ! routines if they are called for by the user ! --------------------------------------------------------------------------------- - - - ! Arguments class(fates_history_interface_type) :: this @@ -4769,8 +4769,28 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) return end subroutine update_history_dyn2 - ! =============================================================================================== + ! =============================================================================================== + +subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) + + ! --------------------------------------------------------------------------------- + ! This is the call to update the history IO arrays that are expected to only change + ! at the model time-step frequency. + ! This is the general routine that will call the single or multi-dimensional + ! routines if they are called for by the user + ! --------------------------------------------------------------------------------- + + if(hlm_hist_level_hifrq>0) then + call update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) + if(hlm_hist_level_hifrq>1) then + call update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) + end if + end if + + return +end subroutine update_history_hifrq + subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) ! From ec9a57853fcf4720a37675c59d54b77cd565db56 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 25 Jan 2024 12:27:14 -0500 Subject: [PATCH 079/300] history density updates --- main/FatesHistoryInterfaceMod.F90 | 12004 ++++++++++++++-------------- main/FatesHistoryVariableType.F90 | 6 +- main/FatesIOVariableKindMod.F90 | 11 + 3 files changed, 6025 insertions(+), 5996 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index e43ec6a524..b9b5f66360 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -26,7 +26,9 @@ module FatesHistoryInterfaceMod use EDTypesMod , only : numWaterMem use EDTypesMod , only : num_vegtemp_mem use PRTGenericMod , only : element_list - use FatesIOVariableKindMod , only : upfreq_hifr_multi + use FatesIOVariableKindMod , only : group_dyna_simple, group_dyna_complx + use FatesIOVariableKindMod , only : group_hifr_simple, group_hifr_complx + use FatesIOVariableKindMod , only : group_hydr_simple, group_hydr_complx use FatesConstantsMod , only : N_DIST_TYPES use FatesConstantsMod , only : dtype_ifall use FatesConstantsMod , only : dtype_ifire @@ -44,7 +46,6 @@ module FatesHistoryInterfaceMod use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod , only : hlm_freq_day use FatesInterfaceTypesMod , only : hlm_parteh_mode - use FatesInterfaceTypesMod , only : hio_include_hifr_multi use EDParamsMod , only : ED_val_comp_excln use EDParamsMod , only : ED_val_phen_coldtemp use EDParamsMod , only : nlevleaf @@ -75,7 +76,7 @@ module FatesHistoryInterfaceMod use FatesAllometryMod , only : CrownDepth use FatesAllometryMod , only : bstore_allom use FatesAllometryMod , only : set_root_fraction - + use EDPftvarcon , only : EDPftvarcon_inst use PRTParametersMod , only : prt_params @@ -128,7 +129,7 @@ module FatesHistoryInterfaceMod use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index use FatesInterfaceTypesMod , only : nlevdamage - + implicit none private ! By default everything is private @@ -208,7 +209,7 @@ module FatesHistoryInterfaceMod ! SPLIT INTO HIFRQ AND DYNAMICS ! GO UP IN ORDER - + ! Indices to 1D Patch variables integer :: ih_storec_si @@ -240,7 +241,7 @@ module FatesHistoryInterfaceMod integer :: ih_repron_scpf integer :: ih_storentfrac_canopy_scpf integer :: ih_storentfrac_understory_scpf - + ! These are active if if(any(element_list(:)==phosphorus_element)) integer :: ih_storep_si integer :: ih_leafp_si @@ -279,7 +280,7 @@ module FatesHistoryInterfaceMod integer :: ih_pdemand_scpf integer :: ih_nfix_si integer :: ih_nfix_scpf - + integer :: ih_trimming_si integer :: ih_area_plant_si integer :: ih_area_trees_si @@ -351,7 +352,7 @@ module FatesHistoryInterfaceMod integer :: ih_area_si_landuse integer :: ih_disturbance_rate_si_lulu - + integer :: ih_fire_disturbance_rate_si integer :: ih_logging_disturbance_rate_si integer :: ih_fall_disturbance_rate_si @@ -423,7 +424,7 @@ module FatesHistoryInterfaceMod integer :: ih_h2oveg_growturn_err_si integer :: ih_h2oveg_hydro_err_si integer :: ih_lai_si - + integer :: ih_site_cstatus_si integer :: ih_gdd_si integer :: ih_site_nchilldays_si @@ -488,7 +489,7 @@ module FatesHistoryInterfaceMod integer :: ih_m9_si_scpf integer :: ih_m10_si_scpf integer :: ih_m11_si_scpf - + integer :: ih_crownfiremort_si_scpf integer :: ih_cambialfiremort_si_scpf @@ -521,7 +522,7 @@ module FatesHistoryInterfaceMod integer :: ih_mortality_understory_si_scls integer :: ih_m3_mortality_canopy_si_scls integer :: ih_m3_mortality_understory_si_scls - + integer :: ih_demotion_rate_si_scls integer :: ih_promotion_rate_si_scls integer :: ih_trimming_canopy_si_scls @@ -663,7 +664,7 @@ module FatesHistoryInterfaceMod integer :: ih_errh2o_scpf integer :: ih_tran_scpf -! integer :: ih_h2osoi_si_scagpft ! hijacking the scagpft dimension instead of creating a new shsl dimension + ! integer :: ih_h2osoi_si_scagpft ! hijacking the scagpft dimension instead of creating a new shsl dimension integer :: ih_sapflow_scpf integer :: ih_sapflow_si integer :: ih_iterh1_scpf @@ -733,7 +734,7 @@ module FatesHistoryInterfaceMod integer :: ih_parprof_dir_si_cnlfpft integer :: ih_parprof_dif_si_cnlfpft integer :: ih_crownfrac_clllpf - + ! indices to site x crown damage variables ! site x crown damage x pft x sizeclass ! site x crown damage x size class @@ -756,7 +757,7 @@ module FatesHistoryInterfaceMod ! crownarea damaged integer :: ih_crownarea_canopy_damage_si integer :: ih_crownarea_ustory_damage_si - + ! indices to (site x canopy layer) variables integer :: ih_parsun_si_can integer :: ih_parsha_si_can @@ -801,7 +802,7 @@ module FatesHistoryInterfaceMod integer, private :: levcacls_index_, levcapf_index_ integer, private :: levclscpf_index_ integer, private :: levlanduse_index_, levlulu_index_, levlupft_index_ - + contains procedure :: Init @@ -817,7 +818,7 @@ module FatesHistoryInterfaceMod procedure :: update_history_hifrq2 procedure :: update_history_hydraulics procedure :: update_history_nutrflux - + ! 'get' methods used by external callers to access private read only data procedure :: num_history_vars @@ -850,7 +851,7 @@ module FatesHistoryInterfaceMod procedure :: levlanduse_index procedure :: levlulu_index procedure :: levlupft_index - + ! private work functions procedure, private :: define_history_vars procedure, private :: set_history_var @@ -893,7 +894,7 @@ module FatesHistoryInterfaceMod end type fates_history_interface_type character(len=*), parameter :: sourcefile = & - __FILE__ + __FILE__ ! The instance of the type @@ -919,7 +920,7 @@ subroutine Init(this, num_threads, fates_bounds) use FatesIODimensionsMod, only : levelcwd, levelage, levclscpf use FatesIODimensionsMod, only : levcdpf, levcdsc, levcdam use FatesIODimensionsMod, only : levlanduse, levlulu, levlupft - + implicit none class(fates_history_interface_type), intent(inout) :: this @@ -1007,7 +1008,7 @@ subroutine Init(this, num_threads, fates_bounds) call this%set_levcdam_index(dim_count) call this%dim_bounds(dim_count)%Init(levcdam, num_threads, & fates_bounds%cdam_begin, fates_bounds%cdam_end) - + dim_count = dim_count + 1 call this%set_levscag_index(dim_count) call this%dim_bounds(dim_count)%Init(levscag, num_threads, & @@ -1036,7 +1037,7 @@ subroutine Init(this, num_threads, fates_bounds) dim_count = dim_count + 1 call this%set_levelpft_index(dim_count) call this%dim_bounds(dim_count)%Init(levelpft, num_threads, & - fates_bounds%elpft_begin, fates_bounds%elpft_end) + fates_bounds%elpft_begin, fates_bounds%elpft_end) dim_count = dim_count + 1 call this%set_levelcwd_index(dim_count) @@ -1046,7 +1047,7 @@ subroutine Init(this, num_threads, fates_bounds) dim_count = dim_count + 1 call this%set_levelage_index(dim_count) call this%dim_bounds(dim_count)%Init(levelage, num_threads, & - fates_bounds%elage_begin, fates_bounds%elage_end) + fates_bounds%elage_begin, fates_bounds%elage_end) dim_count = dim_count + 1 call this%set_levagefuel_index(dim_count) @@ -1072,7 +1073,7 @@ subroutine Init(this, num_threads, fates_bounds) call this%set_levlupft_index(dim_count) call this%dim_bounds(dim_count)%Init(levlupft, num_threads, & fates_bounds%lupft_begin, fates_bounds%lupft_end) - + end subroutine Init ! ====================================================================== @@ -1139,7 +1140,7 @@ subroutine SetThreadBoundsEach(this, thread_index, thread_bounds) index = this%levcnlfpft_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & - thread_bounds%cnlfpft_begin, thread_bounds%cnlfpft_end) + thread_bounds%cnlfpft_begin, thread_bounds%cnlfpft_end) index = this%levcdpf_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & @@ -1152,22 +1153,22 @@ subroutine SetThreadBoundsEach(this, thread_index, thread_bounds) index = this%levcdam_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%cdam_begin, thread_bounds%cdam_end) - + index = this%levscag_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & - thread_bounds%sizeage_class_begin, thread_bounds%sizeage_class_end) + thread_bounds%sizeage_class_begin, thread_bounds%sizeage_class_end) index = this%levscagpft_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & - thread_bounds%sizeagepft_class_begin, thread_bounds%sizeagepft_class_end) + thread_bounds%sizeagepft_class_begin, thread_bounds%sizeagepft_class_end) index = this%levagepft_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & - thread_bounds%agepft_class_begin, thread_bounds%agepft_class_end) + thread_bounds%agepft_class_begin, thread_bounds%agepft_class_end) index = this%levheight_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & - thread_bounds%height_begin, thread_bounds%height_end) + thread_bounds%height_begin, thread_bounds%height_end) index = this%levelem_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & @@ -1196,24 +1197,24 @@ subroutine SetThreadBoundsEach(this, thread_index, thread_bounds) index = this%levlanduse_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%landuse_begin, thread_bounds%landuse_end) - + index = this%levlulu_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%lulu_begin, thread_bounds%lulu_end) - + index = this%levlupft_index() call this%dim_bounds(index)%SetThreadBounds(thread_index, & thread_bounds%lupft_begin, thread_bounds%lupft_end) - + end subroutine SetThreadBoundsEach ! =================================================================================== subroutine assemble_history_output_types(this) - - - implicit none + + + implicit none class(fates_history_interface_type), intent(inout) :: this @@ -1265,7 +1266,7 @@ subroutine assemble_history_output_types(this) call this%set_dim_indices(site_cdam_r8, 1, this%column_index()) call this%set_dim_indices(site_cdam_r8, 2, this%levcdam_index()) - + call this%set_dim_indices(site_scag_r8, 1, this%column_index()) call this%set_dim_indices(site_scag_r8, 2, this%levscag_index()) @@ -1304,7 +1305,7 @@ subroutine assemble_history_output_types(this) call this%set_dim_indices(site_lupft_r8, 1, this%column_index()) call this%set_dim_indices(site_lupft_r8, 2, this%levlupft_index()) - + end subroutine assemble_history_output_types ! =================================================================================== @@ -1345,478 +1346,478 @@ subroutine set_dim_indices(this, dk_name, idim, dim_index) this%dim_kinds(ityp)%dimsize(idim) = this%dim_bounds(dim_index)%upper_bound - & this%dim_bounds(dim_index)%lower_bound + 1 - end subroutine set_dim_indices - - ! ======================================================================= - subroutine set_column_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%column_index_ = index - end subroutine set_column_index - - integer function column_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - column_index = this%column_index_ - end function column_index - - ! ======================================================================= - subroutine set_levsoil_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levsoil_index_ = index - end subroutine set_levsoil_index - - integer function levsoil_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levsoil_index = this%levsoil_index_ - end function levsoil_index - - ! ======================================================================= - subroutine set_levscpf_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levscpf_index_ = index - end subroutine set_levscpf_index - - integer function levscpf_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levscpf_index = this%levscpf_index_ - end function levscpf_index - - ! ======================================================================= - subroutine set_levscls_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levscls_index_ = index - end subroutine set_levscls_index - - integer function levscls_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levscls_index = this%levscls_index_ - end function levscls_index - -!========================================================================= - subroutine set_levcacls_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcacls_index_ = index -end subroutine set_levcacls_index + end subroutine set_dim_indices -integer function levcacls_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcacls_index = this%levcacls_index_ -end function levcacls_index - -!========================================================================= - subroutine set_levcapf_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcapf_index_ = index - end subroutine set_levcapf_index - -integer function levcapf_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcapf_index = this%levcapf_index_ -end function levcapf_index - - ! ======================================================================= - subroutine set_levpft_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levpft_index_ = index - end subroutine set_levpft_index - - integer function levpft_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levpft_index = this%levpft_index_ - end function levpft_index - - ! ======================================================================= - subroutine set_levage_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levage_index_ = index - end subroutine set_levage_index - - integer function levage_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levage_index = this%levage_index_ - end function levage_index - - ! ======================================================================= - subroutine set_levfuel_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levfuel_index_ = index - end subroutine set_levfuel_index - - integer function levfuel_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levfuel_index = this%levfuel_index_ - end function levfuel_index - - ! ======================================================================= - subroutine set_levcwdsc_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcwdsc_index_ = index - end subroutine set_levcwdsc_index - - integer function levcwdsc_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcwdsc_index = this%levcwdsc_index_ - end function levcwdsc_index - - ! ======================================================================= - subroutine set_levcan_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcan_index_ = index - end subroutine set_levcan_index - - integer function levcan_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcan_index = this%levcan_index_ - end function levcan_index - - ! ======================================================================= - subroutine set_levcnlf_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcnlf_index_ = index - end subroutine set_levcnlf_index - - integer function levcnlf_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcnlf_index = this%levcnlf_index_ - end function levcnlf_index - - ! ======================================================================= - subroutine set_levcnlfpft_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcnlfpft_index_ = index - end subroutine set_levcnlfpft_index - - integer function levcnlfpft_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcnlfpft_index = this%levcnlfpft_index_ - end function levcnlfpft_index - - ! ======================================================================= - subroutine set_levcdpf_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcdpf_index_ = index - end subroutine set_levcdpf_index - - integer function levcdpf_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcdpf_index = this%levcdpf_index_ - end function levcdpf_index - - ! ======================================================================= - subroutine set_levcdsc_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcdsc_index_ = index - end subroutine set_levcdsc_index - - integer function levcdsc_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcdsc_index = this%levcdsc_index_ - end function levcdsc_index + ! ======================================================================= + subroutine set_column_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%column_index_ = index + end subroutine set_column_index + + integer function column_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + column_index = this%column_index_ + end function column_index + + ! ======================================================================= + subroutine set_levsoil_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levsoil_index_ = index + end subroutine set_levsoil_index + + integer function levsoil_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levsoil_index = this%levsoil_index_ + end function levsoil_index + + ! ======================================================================= + subroutine set_levscpf_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levscpf_index_ = index + end subroutine set_levscpf_index + + integer function levscpf_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levscpf_index = this%levscpf_index_ + end function levscpf_index + + ! ======================================================================= + subroutine set_levscls_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levscls_index_ = index + end subroutine set_levscls_index + + integer function levscls_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levscls_index = this%levscls_index_ + end function levscls_index + + !========================================================================= + subroutine set_levcacls_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcacls_index_ = index + end subroutine set_levcacls_index + + integer function levcacls_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcacls_index = this%levcacls_index_ + end function levcacls_index + + !========================================================================= + subroutine set_levcapf_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcapf_index_ = index + end subroutine set_levcapf_index + + integer function levcapf_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcapf_index = this%levcapf_index_ + end function levcapf_index + + ! ======================================================================= + subroutine set_levpft_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levpft_index_ = index + end subroutine set_levpft_index + + integer function levpft_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levpft_index = this%levpft_index_ + end function levpft_index + + ! ======================================================================= + subroutine set_levage_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levage_index_ = index + end subroutine set_levage_index + + integer function levage_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levage_index = this%levage_index_ + end function levage_index + + ! ======================================================================= + subroutine set_levfuel_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levfuel_index_ = index + end subroutine set_levfuel_index + + integer function levfuel_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levfuel_index = this%levfuel_index_ + end function levfuel_index + + ! ======================================================================= + subroutine set_levcwdsc_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcwdsc_index_ = index + end subroutine set_levcwdsc_index + + integer function levcwdsc_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcwdsc_index = this%levcwdsc_index_ + end function levcwdsc_index + + ! ======================================================================= + subroutine set_levcan_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcan_index_ = index + end subroutine set_levcan_index + + integer function levcan_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcan_index = this%levcan_index_ + end function levcan_index + + ! ======================================================================= + subroutine set_levcnlf_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcnlf_index_ = index + end subroutine set_levcnlf_index + + integer function levcnlf_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcnlf_index = this%levcnlf_index_ + end function levcnlf_index + + ! ======================================================================= + subroutine set_levcnlfpft_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcnlfpft_index_ = index + end subroutine set_levcnlfpft_index + + integer function levcnlfpft_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcnlfpft_index = this%levcnlfpft_index_ + end function levcnlfpft_index + + ! ======================================================================= + subroutine set_levcdpf_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcdpf_index_ = index + end subroutine set_levcdpf_index + + integer function levcdpf_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcdpf_index = this%levcdpf_index_ + end function levcdpf_index + + ! ======================================================================= + subroutine set_levcdsc_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcdsc_index_ = index + end subroutine set_levcdsc_index + + integer function levcdsc_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcdsc_index = this%levcdsc_index_ + end function levcdsc_index ! ======================================================================= - subroutine set_levcdam_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levcdam_index_ = index - end subroutine set_levcdam_index - - integer function levcdam_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levcdam_index = this%levcdam_index_ - end function levcdam_index - - ! ====================================================================================== - subroutine set_levscag_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levscag_index_ = index - end subroutine set_levscag_index - - integer function levscag_index(this) + subroutine set_levcdam_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levcdam_index_ = index + end subroutine set_levcdam_index + + integer function levcdam_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levcdam_index = this%levcdam_index_ + end function levcdam_index + + ! ====================================================================================== + subroutine set_levscag_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levscag_index_ = index + end subroutine set_levscag_index + + integer function levscag_index(this) implicit none class(fates_history_interface_type), intent(in) :: this levscag_index = this%levscag_index_ - end function levscag_index + end function levscag_index - ! ====================================================================================== - subroutine set_levscagpft_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levscagpft_index_ = index - end subroutine set_levscagpft_index + ! ====================================================================================== + subroutine set_levscagpft_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levscagpft_index_ = index + end subroutine set_levscagpft_index - integer function levscagpft_index(this) + integer function levscagpft_index(this) implicit none class(fates_history_interface_type), intent(in) :: this levscagpft_index = this%levscagpft_index_ - end function levscagpft_index + end function levscagpft_index - ! ====================================================================================== - subroutine set_levagepft_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levagepft_index_ = index - end subroutine set_levagepft_index + ! ====================================================================================== + subroutine set_levagepft_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levagepft_index_ = index + end subroutine set_levagepft_index - integer function levagepft_index(this) + integer function levagepft_index(this) implicit none class(fates_history_interface_type), intent(in) :: this levagepft_index = this%levagepft_index_ - end function levagepft_index + end function levagepft_index - ! ====================================================================================== - subroutine set_levheight_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levheight_index_ = index - end subroutine set_levheight_index + ! ====================================================================================== + subroutine set_levheight_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levheight_index_ = index + end subroutine set_levheight_index - integer function levheight_index(this) + integer function levheight_index(this) implicit none class(fates_history_interface_type), intent(in) :: this levheight_index = this%levheight_index_ - end function levheight_index + end function levheight_index - ! ====================================================================================== + ! ====================================================================================== - subroutine set_levelem_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levelem_index_ = index - end subroutine set_levelem_index + subroutine set_levelem_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levelem_index_ = index + end subroutine set_levelem_index - integer function levelem_index(this) + integer function levelem_index(this) implicit none class(fates_history_interface_type), intent(in) :: this levelem_index = this%levelem_index_ end function levelem_index - ! ====================================================================================== + ! ====================================================================================== - subroutine set_levelpft_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levelpft_index_ = index - end subroutine set_levelpft_index + subroutine set_levelpft_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levelpft_index_ = index + end subroutine set_levelpft_index - integer function levelpft_index(this) + integer function levelpft_index(this) implicit none class(fates_history_interface_type), intent(in) :: this levelpft_index = this%levelpft_index_ - end function levelpft_index + end function levelpft_index - ! ====================================================================================== + ! ====================================================================================== - subroutine set_levelcwd_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levelcwd_index_ = index - end subroutine set_levelcwd_index + subroutine set_levelcwd_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levelcwd_index_ = index + end subroutine set_levelcwd_index - integer function levelcwd_index(this) + integer function levelcwd_index(this) implicit none class(fates_history_interface_type), intent(in) :: this levelcwd_index = this%levelcwd_index_ end function levelcwd_index - ! ====================================================================================== + ! ====================================================================================== - subroutine set_levelage_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levelage_index_ = index - end subroutine set_levelage_index + subroutine set_levelage_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levelage_index_ = index + end subroutine set_levelage_index - integer function levelage_index(this) + integer function levelage_index(this) implicit none class(fates_history_interface_type), intent(in) :: this levelage_index = this%levelage_index_ - end function levelage_index - - ! ====================================================================================== - - subroutine set_levagefuel_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levagefuel_index_ = index - end subroutine set_levagefuel_index - - integer function levagefuel_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levagefuel_index = this%levagefuel_index_ - end function levagefuel_index - ! ====================================================================================== - - subroutine set_levclscpf_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levclscpf_index_ = index - end subroutine set_levclscpf_index - - integer function levclscpf_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levclscpf_index = this%levclscpf_index_ - end function levclscpf_index - - ! ====================================================================================== - - subroutine set_levlanduse_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levlanduse_index_ = index - end subroutine set_levlanduse_index - - integer function levlanduse_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levlanduse_index = this%levlanduse_index_ - end function levlanduse_index - - ! ====================================================================================== - - subroutine set_levlulu_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levlulu_index_ = index - end subroutine set_levlulu_index - - integer function levlulu_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levlulu_index = this%levlulu_index_ - end function levlulu_index - - ! ====================================================================================== - - subroutine set_levlupft_index(this, index) - implicit none - class(fates_history_interface_type), intent(inout) :: this - integer, intent(in) :: index - this%levlupft_index_ = index - end subroutine set_levlupft_index - - integer function levlupft_index(this) - implicit none - class(fates_history_interface_type), intent(in) :: this - levlupft_index = this%levlupft_index_ - end function levlupft_index - - ! ===================================================================================== - - subroutine zero_site_hvars(this, currentSite, upfreq_in) - - ! This routine zero's a history diagnostic variable - ! but only zero's on fates sites - ! This should be called prior to filling the variable - ! and after they have been flushed to the ignore value - - class(fates_history_interface_type) :: this ! hvars_interface instance - integer, intent(in) :: upfreq_in ! - type(ed_site_type), intent(in), target :: currentSite ! site instance - - integer :: ivar ! history variable index - integer :: ndims ! number of dimensions - - do ivar=1,ubound(this%hvars,1) - if (this%hvars(ivar)%upfreq == upfreq_in) then - - ndims = this%dim_kinds(this%hvars(ivar)%dim_kinds_index)%ndims - - if(trim(this%dim_kinds(this%hvars(ivar)%dim_kinds_index)%name) == site_int)then - write(fates_log(),*)'add in zeroing provision for SI_INT' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - if(ndims==1) then - this%hvars(ivar)%r81d(currentSite%h_gid) = 0._r8 - elseif(ndims==2) then - this%hvars(ivar)%r82d(currentSite%h_gid,:) = 0._r8 - elseif(ndims==3) then - this%hvars(ivar)%r83d(currentSite%h_gid,:,:) = 0._r8 - end if - end if - end do - - return - end subroutine zero_site_hvars - - ! ====================================================================================== - - subroutine flush_hvars(this,nc,upfreq_in) - - class(fates_history_interface_type) :: this - integer,intent(in) :: nc - integer,intent(in) :: upfreq_in - integer :: ivar - integer :: lb1,ub1,lb2,ub2 - - do ivar=1,ubound(this%hvars,1) - if (this%hvars(ivar)%upfreq == upfreq_in) then ! Only flush variables with update on dynamics step - call this%hvars(ivar)%flush(nc, this%dim_bounds, this%dim_kinds) - end if - end do - -end subroutine flush_hvars + end function levelage_index + + ! ====================================================================================== + + subroutine set_levagefuel_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levagefuel_index_ = index + end subroutine set_levagefuel_index + + integer function levagefuel_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levagefuel_index = this%levagefuel_index_ + end function levagefuel_index + ! ====================================================================================== + + subroutine set_levclscpf_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levclscpf_index_ = index + end subroutine set_levclscpf_index + + integer function levclscpf_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levclscpf_index = this%levclscpf_index_ + end function levclscpf_index + + ! ====================================================================================== + + subroutine set_levlanduse_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levlanduse_index_ = index + end subroutine set_levlanduse_index + + integer function levlanduse_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levlanduse_index = this%levlanduse_index_ + end function levlanduse_index + + ! ====================================================================================== + + subroutine set_levlulu_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levlulu_index_ = index + end subroutine set_levlulu_index + + integer function levlulu_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levlulu_index = this%levlulu_index_ + end function levlulu_index + + ! ====================================================================================== + + subroutine set_levlupft_index(this, index) + implicit none + class(fates_history_interface_type), intent(inout) :: this + integer, intent(in) :: index + this%levlupft_index_ = index + end subroutine set_levlupft_index + + integer function levlupft_index(this) + implicit none + class(fates_history_interface_type), intent(in) :: this + levlupft_index = this%levlupft_index_ + end function levlupft_index + + ! ===================================================================================== + + subroutine zero_site_hvars(this, currentSite, upfreq_in) + + ! This routine zero's a history diagnostic variable + ! but only zero's on fates sites + ! This should be called prior to filling the variable + ! and after they have been flushed to the ignore value + + class(fates_history_interface_type) :: this ! hvars_interface instance + integer, intent(in) :: upfreq_in ! + type(ed_site_type), intent(in), target :: currentSite ! site instance + + integer :: ivar ! history variable index + integer :: ndims ! number of dimensions + + do ivar=1,ubound(this%hvars,1) + if (this%hvars(ivar)%upfreq == upfreq_in) then + + ndims = this%dim_kinds(this%hvars(ivar)%dim_kinds_index)%ndims + + if(trim(this%dim_kinds(this%hvars(ivar)%dim_kinds_index)%name) == site_int)then + write(fates_log(),*)'add in zeroing provision for SI_INT' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + if(ndims==1) then + this%hvars(ivar)%r81d(currentSite%h_gid) = 0._r8 + elseif(ndims==2) then + this%hvars(ivar)%r82d(currentSite%h_gid,:) = 0._r8 + elseif(ndims==3) then + this%hvars(ivar)%r83d(currentSite%h_gid,:,:) = 0._r8 + end if + end if + end do + + return + end subroutine zero_site_hvars + + ! ====================================================================================== + + subroutine flush_hvars(this,nc,upfreq_in) + + class(fates_history_interface_type) :: this + integer,intent(in) :: nc + integer,intent(in) :: upfreq_in + integer :: ivar + integer :: lb1,ub1,lb2,ub2 + + do ivar=1,ubound(this%hvars,1) + if (this%hvars(ivar)%upfreq == upfreq_in) then ! Only flush variables with update on dynamics step + call this%hvars(ivar)%HFlush(nc, this%dim_bounds, this%dim_kinds) + end if + end do + + end subroutine flush_hvars ! ===================================================================================== @@ -1842,10 +1843,10 @@ subroutine set_history_var(this, vname, units, long, use_default, avgflag, vtype logical, intent(in) :: initialize integer, intent(inout) :: ivar integer, intent(inout) :: index ! This is the index for the variable of - ! interest that is associated with an - ! explict name (for fast reference during update) - ! A zero is passed back when the variable is - ! not used + ! interest that is associated with an + ! explict name (for fast reference during update) + ! A zero is passed back when the variable is + ! not used logical, intent(in), optional :: flush_to_zero ! locals @@ -1909,7 +1910,7 @@ subroutine init_dim_kinds_maps(this) use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8, site_clscpf_r8 use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_cdam_r8 - + implicit none ! Arguments @@ -1981,7 +1982,7 @@ subroutine init_dim_kinds_maps(this) ! site x crown damage index = index + 1 call this%dim_kinds(index)%Init(site_cdam_r8, 2) - + ! site x size-class x age class index = index + 1 call this%dim_kinds(index)%Init(site_scag_r8, 2) @@ -2033,14 +2034,25 @@ subroutine init_dim_kinds_maps(this) ! site x land use x pft index = index + 1 call this%dim_kinds(index)%Init(site_lupft_r8, 2) - + ! FIXME(bja, 2016-10) assert(index == fates_history_num_dim_kinds) end subroutine init_dim_kinds_maps ! ======================================================================= - + subroutine update_history_nutrflux(this,csite) + ! TODO IN FUTURE PR: + ! CHANGE THIS NAME FROM NUTRFLUX TO + ! DYNAM_FLUX AND THE EXISISTING DYNAMICS + ! TO DYNAM_STATE. MOVE FLUX DIAGNOSTIC + ! TO THIS ROUTINE, AND USE THIS ROUTINE + ! TO TRACK ALL DYNAMICS FLUX DIAGNOSTICS + ! AND CALL THIS AFTER DISTURBANCE RATES + ! HAVE BEEN CALLED, BUT BEFORE PATCHES + ! HAVE BEEN SPLIT AND SPAWNED + + ! Update history diagnostics for nutrient dynamics variables. ! This is a separate routine because we like to handle these ! things before patches are reshuffled during disturbance, and @@ -2055,181 +2067,231 @@ subroutine update_history_nutrflux(this,csite) type(fates_patch_type), pointer :: cpatch type(fates_cohort_type), pointer :: ccohort - integer :: iclscpf ! layer x size x pft class index - integer :: iscpf ! Size x pft class index - integer :: io_si ! site's global index in the history vector - integer :: el ! element loop index - integer :: ft - real(r8):: uconv ! combined unit conversion factor - - ! We use gpp and fineroot C for weighted averages - real(r8) :: gpp_si - real(r8) :: fnrtc_si - real(r8) :: fnrt_c - - associate( & - !hio_l2fr_clscpf => this%hvars(ih_l2fr_clscpf)%r82d, & - hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d, & - hio_recl2fr_canopy_pf => this%hvars(ih_recl2fr_canopy_pf)%r82d, & - hio_recl2fr_ustory_pf => this%hvars(ih_recl2fr_ustory_pf)%r82d ) - - gpp_si = 0._r8 - fnrtc_si = 0._r8 - - ! history site index - io_si = csite%h_gid - - cpatch => csite%youngest_patch - do while(associated(cpatch)) - - ccohort => cpatch%shortest - do while(associated(ccohort)) - - ! If this is a new cohort, do not make diagnostics - if(ccohort%isnew) then - ccohort => ccohort%taller - cycle - end if - - ! size class index - iscpf = ccohort%size_by_pft_class - - ! layer by size by pft index - iclscpf = get_layersizetype_class_index(ccohort%canopy_layer,ccohort%dbh,ccohort%pft) - - ! unit conversion factor to get x/plant/day -> x/m2/sec - uconv = ccohort%n * ha_per_m2 * days_per_sec + integer :: iclscpf ! layer x size x pft class index + integer :: iscpf ! Size x pft class index + integer :: io_si ! site's global index in the history vector + integer :: el ! element loop index + integer :: ft ! pft loop index + real(r8):: uconv ! combined unit conversion factor + real(r8) :: fnrtc_si ! site level fine-root c + real(r8) :: fnrt_c ! cohort fine-root c + + ! Process variables with time-space dimensions only + ! --------------------------------------------------------------------------------------------- + + if_dynam1: if(hlm_hist_level_dynam>0) then + + associate(hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d) + fnrtc_si = 0._r8 - fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - !hio_l2fr_clscpf(io_si,iclscpf) = & - ! hio_l2fr_clscpf(io_si,iclscpf) + ccohort%n*fnrt_c*ccohort%l2fr + ! history site index + io_si = csite%h_gid - hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_c*ccohort%l2fr - - ! These are used for normalizing weighted averages - gpp_si = gpp_si + ccohort%n*ccohort%gpp_acc_hold - fnrtc_si = fnrtc_si + ccohort%n*fnrt_c - - ! Loop over the different elements. - do el = 1, num_elements + cpatch => csite%youngest_patch + do while(associated(cpatch)) - select case (element_list(el)) - case (carbon12_element) + ccohort => cpatch%shortest + do while(associated(ccohort)) - ! Excess carbon respired - this%hvars(ih_excess_resp_si)%r81d(io_si) = & - this%hvars(ih_excess_resp_si)%r81d(io_si) + & - ccohort%resp_excess*uconv + ! If this is a new cohort, do not make diagnostics + if(ccohort%isnew) then + ccohort => ccohort%taller + cycle + end if - case (nitrogen_element) + ! unit conversion factor to get x/plant/day -> x/m2/sec + uconv = ccohort%n * ha_per_m2 * days_per_sec - ! Mineralized uptake of NH4, NO3 - fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_nh4_uptake*uconv + fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_no3_uptake*uconv + hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_c*ccohort%l2fr - fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) = & - fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) + & - ccohort%daily_nh4_uptake*uconv + ! These are used for normalizing weighted averages + fnrtc_si = fnrtc_si + ccohort%n*fnrt_c - fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) = & - fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) + & - ccohort%daily_no3_uptake*uconv + ! Loop over the different elements. + do el = 1, num_elements - ! Symbiotic Fixation - fates_hist%hvars(ih_nfix_si)%r81d(io_si) = & - fates_hist%hvars(ih_nfix_si)%r81d(io_si) + & - ccohort%sym_nfix_daily*uconv + select case (element_list(el)) + case (carbon12_element) - fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) + & - ccohort%sym_nfix_daily*uconv + ! Excess carbon respired + this%hvars(ih_excess_resp_si)%r81d(io_si) = & + this%hvars(ih_excess_resp_si)%r81d(io_si) + & + ccohort%resp_excess*uconv - ! Efflux/exudation - this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_n_efflux*uconv + case (nitrogen_element) - this%hvars(ih_nefflux_si)%r81d(io_si) = & - this%hvars(ih_nefflux_si)%r81d(io_si) + & - ccohort%daily_n_efflux*uconv + ! Mineralized uptake of NH4, NO3 + fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) = & + fates_hist%hvars(ih_nh4uptake_si)%r81d(io_si) + & + ccohort%daily_nh4_uptake*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 + fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) = & + fates_hist%hvars(ih_no3uptake_si)%r81d(io_si) + & + ccohort%daily_no3_uptake*uconv - this%hvars(ih_ndemand_si)%r81d(io_si) = & - this%hvars(ih_ndemand_si)%r81d(io_si) + & - ccohort%daily_n_demand*uconv + ! Symbiotic Fixation + fates_hist%hvars(ih_nfix_si)%r81d(io_si) = & + fates_hist%hvars(ih_nfix_si)%r81d(io_si) + & + ccohort%sym_nfix_daily*uconv - case (phosphorus_element) + ! Efflux/exudation + this%hvars(ih_nefflux_si)%r81d(io_si) = & + this%hvars(ih_nefflux_si)%r81d(io_si) + & + ccohort%daily_n_efflux*uconv - fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) = & - fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_p_gain*uconv + ! Demand + this%hvars(ih_ndemand_si)%r81d(io_si) = & + this%hvars(ih_ndemand_si)%r81d(io_si) + & + ccohort%daily_n_demand*uconv - fates_hist%hvars(ih_puptake_si)%r81d(io_si) = & - fates_hist%hvars(ih_puptake_si)%r81d(io_si) + & - ccohort%daily_p_gain*uconv + case (phosphorus_element) - this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_pefflux_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_p_efflux*uconv + ! Mineralized uptake of PO4 + fates_hist%hvars(ih_puptake_si)%r81d(io_si) = & + fates_hist%hvars(ih_puptake_si)%r81d(io_si) + & + ccohort%daily_p_gain*uconv - this%hvars(ih_pefflux_si)%r81d(io_si) = & - this%hvars(ih_pefflux_si)%r81d(io_si) + & - ccohort%daily_p_efflux*uconv + ! Efflux + this%hvars(ih_pefflux_si)%r81d(io_si) = & + this%hvars(ih_pefflux_si)%r81d(io_si) + & + ccohort%daily_p_efflux*uconv - this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) = & - this%hvars(ih_pdemand_scpf)%r82d(io_si,iscpf) + & - ccohort%daily_p_demand*uconv + ! Demand + this%hvars(ih_pdemand_si)%r81d(io_si) = & + ccohort%daily_p_demand*uconv + end select + end do - this%hvars(ih_pdemand_si)%r81d(io_si) = & - ccohort%daily_p_demand*uconv - end select + ccohort => ccohort%taller end do - ccohort => ccohort%taller + cpatch => cpatch%older end do - cpatch => cpatch%older - end do - - do ft = 1,numpft - hio_recl2fr_canopy_pf(io_si,ft) = csite%rec_l2fr(ft,1) - hio_recl2fr_ustory_pf(io_si,ft) = csite%rec_l2fr(ft,2) - end do - - if(fnrtc_si>nearzero)then - hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/fnrtc_si - else - hio_l2fr_si(io_si) = hlm_hio_ignore_val - end if - - - - end associate + if(fnrtc_si>nearzero)then + hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/fnrtc_si + else + hio_l2fr_si(io_si) = hlm_hio_ignore_val + end if - return - end subroutine update_history_nutrflux + end associate + end if if_dynam1 - ! ==================================================================================== + ! Process multiplexed variables + ! --------------------------------------------------------------------------------------------- + + if_dynam2: if(hlm_hist_level_dynam>1) then - subroutine update_history_dyn(this,nc,nsites,sites,bc_in) + associate( & + hio_recl2fr_canopy_pf => this%hvars(ih_recl2fr_canopy_pf)%r82d, & + hio_recl2fr_ustory_pf => this%hvars(ih_recl2fr_ustory_pf)%r82d ) - ! --------------------------------------------------------------------------------- + ! history site index + io_si = csite%h_gid + + cpatch => csite%youngest_patch + do while(associated(cpatch)) + + ccohort => cpatch%shortest + do while(associated(ccohort)) + + ! If this is a new cohort, do not make diagnostics + if(ccohort%isnew) then + ccohort => ccohort%taller + cycle + end if + + ! size class index + iscpf = ccohort%size_by_pft_class + + ! layer by size by pft index + iclscpf = get_layersizetype_class_index(ccohort%canopy_layer,ccohort%dbh,ccohort%pft) + + ! unit conversion factor to get x/plant/day -> x/m2/sec + uconv = ccohort%n * ha_per_m2 * days_per_sec + + ! Loop over the different elements. + do el = 1, num_elements + + select case (element_list(el)) + + case (nitrogen_element) + + ! Mineralized uptake of NH4, NO3 + fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_nh4uptake_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_nh4_uptake*uconv + + fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_no3uptake_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_no3_uptake*uconv + + ! Fixation + fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_nfix_scpf)%r82d(io_si,iscpf) + & + ccohort%sym_nfix_daily*uconv + + ! Efflux/exudation + this%hvars(ih_nefflux_scpf)%r82d(io_si,iscpf) = & + 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 + fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) = & + fates_hist%hvars(ih_puptake_scpf)%r82d(io_si,iscpf) + & + ccohort%daily_p_gain*uconv + + ! Efflux + 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 + + ccohort => ccohort%taller + end do + + cpatch => cpatch%older + end do + + do ft = 1,numpft + hio_recl2fr_canopy_pf(io_si,ft) = csite%rec_l2fr(ft,1) + hio_recl2fr_ustory_pf(io_si,ft) = csite%rec_l2fr(ft,2) + end do + + end associate + end if if_dynam2 + + return + end subroutine update_history_nutrflux + + ! ==================================================================================== + + subroutine update_history_dyn(this,nc,nsites,sites,bc_in) + + ! --------------------------------------------------------------------------------- ! This is the call to update the history IO arrays that are expected to only change ! after Ecosystem Dynamics have been processed. ! This is the general routine that will call the single or multi-dimensional ! routines if they are called for by the user ! --------------------------------------------------------------------------------- - + ! Arguments class(fates_history_interface_type) :: this integer , intent(in) :: nc ! clump index @@ -2237,81 +2299,57 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) type(ed_site_type) , intent(inout), target :: sites(nsites) type(bc_in_type) , intent(in) :: bc_in(nsites) ! Locals - - - type(site_fluxdiags_type), pointer :: flux_diags - type(site_fluxdiags_type), pointer :: flux_diags_c - - integer :: s ! The local site index - integer :: io_si ! The site index of the IO array - - integer :: ipa, ipa2 ! The local "I"ndex of "PA"tches - integer :: ft ! functional type index - integer :: elcwd, elpft ! combined index of element and pft or cwd - integer :: i_scpf,i_pft,i_scls ! iterators for scpf, pft, and scls dims - integer :: i_cacls, i_capf ! iterators for cohort age and cohort age x pft - - - - - - - - - integer :: el ! Loop index for elements - - - - real(r8) :: store_max ! The target nutrient mass for storage element of interest [kg] - real(r8) :: n_perm2 ! individuals per m2 for the whole column - real(r8) :: dbh ! diameter ("at breast height") - real(r8) :: coage ! cohort age - real(r8) :: npp_partition_error ! a check that the NPP partitions sum to carbon allocation - - + !type(site_fluxdiags_type), pointer :: flux_diags + !type(site_fluxdiags_type), pointer :: flux_diags_c + !integer :: s ! The local site index + !integer :: io_si ! The site index of the IO array + !integer :: ipa, ipa2 ! The local "I"ndex of "PA"tches + !integer :: ft ! functional type index + !integer :: elcwd, elpft ! combined index of element and pft or cwd + !integer :: i_scpf,i_pft,i_scls ! iterators for scpf, pft, and scls dims + !integer :: i_cacls, i_capf ! iterators for cohort age and cohort age x pft + !integer :: el ! Loop index for elements + !real(r8) :: store_max ! The target nutrient mass for storage element of interest [kg] + !real(r8) :: n_perm2 ! individuals per m2 for the whole column + !real(r8) :: dbh ! diameter ("at breast height") + !real(r8) :: coage ! cohort age + !real(r8) :: npp_partition_error ! a check that the NPP partitions sum to carbon allocation ! The following are all carbon states, turnover and net allocation flux variables ! the organs of relevance should be self explanatory - real(r8) :: sapw_m ! Sapwood mass (elemental, c,n or p) [kg/plant] - real(r8) :: struct_m ! Structural mass "" - real(r8) :: leaf_m ! Leaf mass "" - real(r8) :: fnrt_m ! Fineroot mass "" - real(r8) :: store_m ! Storage mass "" - real(r8) :: alive_m ! Alive biomass (sap+leaf+fineroot+repro+storage) "" - real(r8) :: total_m ! Total vegetation mass - real(r8) :: repro_m ! Total reproductive mass (on plant) "" - real(r8) :: sapw_m_turnover ! Sapwood turnover rate - real(r8) :: store_m_turnover - real(r8) :: leaf_m_turnover - real(r8) :: fnrt_m_turnover - real(r8) :: struct_m_turnover - real(r8) :: sapw_m_net_alloc - real(r8) :: store_m_net_alloc - real(r8) :: leaf_m_net_alloc - real(r8) :: fnrt_m_net_alloc - real(r8) :: struct_m_net_alloc - real(r8) :: repro_m_net_alloc - - - - - integer :: return_code - - type(fates_patch_type),pointer :: cpatch - type(fates_cohort_type),pointer :: ccohort - - - - integer :: tmp - + ! real(r8) :: sapw_m ! Sapwood mass (elemental, c,n or p) [kg/plant] + ! real(r8) :: struct_m ! Structural mass "" + ! real(r8) :: leaf_m ! Leaf mass "" + ! real(r8) :: fnrt_m ! Fineroot mass "" + ! real(r8) :: store_m ! Storage mass "" + ! real(r8) :: alive_m ! Alive biomass (sap+leaf+fineroot+repro+storage) "" + ! real(r8) :: total_m ! Total vegetation mass + ! real(r8) :: repro_m ! Total reproductive mass (on plant) "" + ! real(r8) :: sapw_m_turnover ! Sapwood turnover rate + ! real(r8) :: store_m_turnover + ! real(r8) :: leaf_m_turnover + ! real(r8) :: fnrt_m_turnover + ! real(r8) :: struct_m_turnover + ! real(r8) :: sapw_m_net_alloc + ! real(r8) :: store_m_net_alloc + ! real(r8) :: leaf_m_net_alloc + ! real(r8) :: fnrt_m_net_alloc + ! real(r8) :: struct_m_net_alloc + ! real(r8) :: repro_m_net_alloc + ! integer :: return_code + ! type(fates_patch_type),pointer :: cpatch + ! type(fates_cohort_type),pointer :: ccohort + ! integer :: tmp ! If we don't have dynamics turned on, we just abort these diagnostics ! CONVERT THIS TO FORCE DYNAM LEVEL 0 - + + ! MAKE SURE THAT MARCOS' PHENOLOGY PR DOES NOT GET MESSED + ! UP ON THE MERGE. ST3 SHOULD ALLOW FOR ALL STATES, BUT + ! NO FLUXES IN THE FUTURE if (hlm_use_ed_st3.eq.itrue) return - if(hlm_hist_level_dynam>0) then call update_history_dyn1(this,nc,nsites,sites,bc_in) if(hlm_hist_level_dynam>1) then @@ -2325,11 +2363,11 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) end subroutine update_history_dyn ! ========================================================================= - + subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) - - + + ! Arguments class(fates_history_interface_type) :: this integer , intent(in) :: nc ! clump index @@ -2341,7 +2379,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) type(fates_patch_type), pointer :: cpatch type(site_fluxdiags_type), pointer :: flux_diags_c ! Pointer to site level carbon fluxes type(litter_type), pointer :: litt ! Generic pointer to any litter pool - + integer :: s ! site counter integer :: ipa ! patch index matching host model array space integer :: io_si ! site's index in the history output array space @@ -2372,7 +2410,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) real(r8) :: repro_m_net_alloc ! mass allocated to reproduction [kg/yr] real(r8) :: n_perm2 ! abundance per m2 real(r8) :: area_frac ! Fraction of area for this patch - + associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & @@ -2446,11 +2484,11 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_tgrowth => this%hvars(ih_tgrowth_si)%r81d, & hio_lai_si => this%hvars(ih_lai_si)%r81d ) - + ! --------------------------------------------------------------------------------- ! Loop through the FATES scale hierarchy and fill the history IO arrays ! --------------------------------------------------------------------------------- - + siteloop: do s = 1,nsites io_si = sites(s)%h_gid @@ -2458,15 +2496,14 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) site_ba = 0._r8 site_ca = 0._r8 - ! set the fates fraction to one, since it is zero on non-fates columns, & ! the average is the total gridcell fates fraction hio_fates_fraction_si(io_si) = 1._r8 - + ! Total carbon model error [kgC/day -> kgC/s] 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 * & @@ -2474,50 +2511,50 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! damage variables - site level - this needs to be OUT of the patch loop if(hlm_use_tree_damage .eq. itrue) then - + this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) = & this%hvars(ih_crownarea_canopy_damage_si)%r81d(io_si) + & sites(s)%crownarea_canopy_damage * days_per_year * 1 / m2_per_ha - + this%hvars(ih_crownarea_ustory_damage_si)%r81d(io_si) = & this%hvars(ih_crownarea_ustory_damage_si)%r81d(io_si) + & sites(s)%crownarea_ustory_damage * days_per_year * 1 / m2_per_ha - + end if - + ! Canopy spread index (0-1) hio_canopy_spread_si(io_si) = sites(s)%spread - + ! Update the site status for cold deciduous (drought deciduous is now PFT dependent) hio_site_cstatus_si(io_si) = real(sites(s)%cstatus,r8) - + ! Number of chill days and cold days hio_site_nchilldays_si(io_si) = real(sites(s)%nchilldays,r8) hio_site_ncolddays_si(io_si) = real(sites(s)%ncolddays,r8) - + ! Growing degree-days hio_gdd_si(io_si) = sites(s)%grow_deg_days - + ! Model days elapsed since leaf on/off for cold-deciduous hio_cleafoff_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafoffdate,r8) hio_cleafon_si(io_si) = real(sites(s)%phen_model_date - sites(s)%cleafondate,r8) - + ! track total wood product accumulation at the site level hio_woodproduct_si(io_si) = sites(s)%resources_management%trunk_product_site & * AREA_INV - + ! site-level fire variables: ! Nesterov index (unitless) hio_nesterov_fire_danger_si(io_si) = sites(s)%acc_NI - + ! number of ignitions [#/km2/day -> #/m2/s] hio_fire_nignitions_si(io_si) = sites(s)%NF_successful / m2_per_km2 / & sec_per_day - + ! Fire danger index (FDI) (0-1) hio_fire_fdi_si(io_si) = sites(s)%FDI - + ! If hydraulics are turned on, track the error terms associated with ! dynamics [kg/m2] if(hlm_use_planthydro.eq.itrue)then @@ -2525,15 +2562,15 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) this%hvars(ih_h2oveg_recruit_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_recruit this%hvars(ih_h2oveg_growturn_err_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_growturn_err end if - + hio_harvest_debt_si(io_si) = sites(s)%resources_management%harvest_debt hio_harvest_debt_sec_si(io_si) = sites(s)%resources_management%harvest_debt_sec - + ! error in primary lands from patch fusion [m2 m-2 day-1] -> [m2 m-2 yr-1] hio_primaryland_fusion_error_si(io_si) = sites(s)%primary_land_patchfusion_error * days_per_year ! output site-level disturbance rates [m2 m-2 day-1] -> [m2 m-2 yr-1] - TO DO rework this - + hio_fire_disturbance_rate_si(io_si) = & sum(sites(s)%disturbance_rates(dtype_ifire,1:n_landuse_cats,1:n_landuse_cats)) * & days_per_year @@ -2545,7 +2582,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_fall_disturbance_rate_si(io_si) = & sum(sites(s)%disturbance_rates(dtype_ifall,1:n_landuse_cats,1:n_landuse_cats)) * & days_per_year - + hio_harvest_carbonflux_si(io_si) = & sites(s)%mass_balance(element_pos(carbon12_element))%wood_product * AREA_INV @@ -2553,52 +2590,52 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! carbon flux associated with mortality of trees dying by fire hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & sum(sites(s)%fmort_carbonflux_canopy(:)) / g_per_kg - + hio_ustory_mortality_carbonflux_si(io_si) = hio_ustory_mortality_carbonflux_si(io_si) + & sum(sites(s)%fmort_carbonflux_ustory(:)) / g_per_kg - + ! treat carbon flux from imort the same way hio_ustory_mortality_carbonflux_si(io_si) = hio_ustory_mortality_carbonflux_si(io_si) + & sum(sites(s)%imort_carbonflux(:)) - + ! convert kg C / ha / day to kgc / m2 / sec hio_demotion_carbonflux_si(io_si) = sites(s)%demotion_carbonflux * ha_per_m2 * days_per_sec hio_promotion_carbonflux_si(io_si) = sites(s)%promotion_carbonflux * ha_per_m2 * days_per_sec ! ! mortality-associated carbon fluxes - + hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & sum(sites(s)%term_carbonflux_canopy(:)) * days_per_sec * ha_per_m2 - + hio_ustory_mortality_carbonflux_si(io_si) = hio_ustory_mortality_carbonflux_si(io_si) + & sum(sites(s)%term_carbonflux_ustory(:)) * days_per_sec * ha_per_m2 - + ! add site level mortality counting to crownarea diagnostic hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & sites(s)%fmort_crownarea_canopy + & sites(s)%term_crownarea_canopy * days_per_year - + hio_ustory_mortality_crownarea_si(io_si) = hio_ustory_mortality_crownarea_si(io_si) + & sites(s)%fmort_crownarea_ustory + & sites(s)%term_crownarea_ustory * days_per_year + & sites(s)%imort_crownarea flux_diags_c => sites(s)%flux_diags(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(:))) * & AREA_INV * days_per_sec - + hio_litter_out_si(io_si) = 0._r8 hio_seed_bank_si(io_si) = 0._r8 hio_ungerm_seed_bank_si(io_si) = 0._r8 hio_seedling_pool_si(io_si) = 0._r8 hio_seeds_in_si(io_si) = 0._r8 hio_seeds_in_local_si(io_si) = 0._r8 - - + + ! Loop through patches to sum up diagonistics ipa = 0 cpatch => sites(s)%oldest_patch @@ -2609,22 +2646,22 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) if ( cpatch%land_use_label .eq. secondaryland ) then hio_npatches_sec_si(io_si) = hio_npatches_sec_si(io_si) + 1._r8 end if - + hio_lai_si(io_si) = hio_lai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%elai_profile(:,:,:) ) * & cpatch%total_canopy_area * AREA_INV ! 24hr veg temperature hio_tveg24(io_si) = hio_tveg24(io_si) + & (cpatch%tveg24%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV - + ! long-term veg temperature hio_tlongterm(io_si) = hio_tlongterm(io_si) + & (cpatch%tveg_longterm%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV - + ! long-term running mean veg temperature (tgrowth) hio_tgrowth(io_si) = hio_tgrowth(io_si) + & (cpatch%tveg_lpa%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV - + ! some diagnostics on secondary forest area and its age distribution if ( cpatch%land_use_label .eq. secondaryland ) then hio_fraction_secondary_forest_si(io_si) = hio_fraction_secondary_forest_si(io_si) + & @@ -2648,7 +2685,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! Patch specific variables that are already calculated ! These things are all duplicated. Should they all be converted to LL or array structures RF? ! define scalar to counteract the patch albedo scaling logic for conserved quantities - + ! Update Fire Variables hio_spitfire_ros_si(io_si) = hio_spitfire_ros_si(io_si) + cpatch%ROS_front * cpatch%area * AREA_INV / sec_per_min hio_effect_wspeed_si(io_si) = hio_effect_wspeed_si(io_si) + cpatch%effect_wspeed * cpatch%area * AREA_INV / sec_per_min @@ -2667,7 +2704,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) litt => cpatch%litter(element_pos(carbon12_element)) area_frac = cpatch%area * AREA_INV - + ! Sum up all output fluxes (fragmentation) kgC/m2/day -> kgC/m2/s hio_litter_out_si(io_si) = hio_litter_out_si(io_si) + & (sum(litt%leaf_fines_frag(:)) + & @@ -2677,39 +2714,39 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) sum(litt%seed_decay(:)) + & sum(litt%seed_germ_decay(:))) * & area_frac * days_per_sec - + ! Sum up total seed bank (germinated and ungerminated) hio_seed_bank_si(io_si) = hio_seed_bank_si(io_si) + & (sum(litt%seed(:))+sum(litt%seed_germ(:))) * & area_frac - + ! Sum up total seed bank (just ungerminated) hio_ungerm_seed_bank_si(io_si) = hio_ungerm_seed_bank_si(io_si) + & sum(litt%seed(:)) * area_frac - + ! Sum up total seedling pool hio_seedling_pool_si(io_si) = hio_seedling_pool_si(io_si) + & sum(litt%seed_germ(:)) * area_frac - + ! Sum up the input flux into the seed bank (local and external) hio_seeds_in_si(io_si) = hio_seeds_in_si(io_si) + & (sum(litt%seed_in_local(:)) + sum(litt%seed_in_extern(:))) * & area_frac * days_per_sec - + hio_seeds_in_local_si(io_si) = hio_seeds_in_local_si(io_si) + & sum(litt%seed_in_local(:)) * & area_frac * days_per_sec - + ! loop through cohorts on patch ccohort => cpatch%shortest cohortloop: do while(associated(ccohort)) - + ft = ccohort%pft n_perm2 = ccohort%n * AREA_INV - + ! Increment the number of cohorts per site hio_ncohorts_si(io_si) = hio_ncohorts_si(io_si) + 1._r8 - + if ( cpatch%land_use_label .eq. secondaryland ) then hio_ncohorts_sec_si(io_si) = hio_ncohorts_sec_si(io_si) + 1._r8 end if @@ -2717,21 +2754,21 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! Update biomass components ! Mass pools [kg] elloop: do el = 1, num_elements - + sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) store_m = ccohort%prt%GetState(store_organ, element_list(el)) repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) - + alive_m = leaf_m + fnrt_m + sapw_m total_m = alive_m + store_m + struct_m - + ! Plant multi-element states and fluxes ! Zero states, and set the fluxes if( element_list(el).eq.carbon12_element )then - + ! mass in different tissues [kg/ha] -> [kg/m2] this%hvars(ih_storec_si)%r81d(io_si) = & this%hvars(ih_storec_si)%r81d(io_si) + ccohort%n * & @@ -2751,15 +2788,15 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) this%hvars(ih_totvegc_si)%r81d(io_si) = & this%hvars(ih_totvegc_si)%r81d(io_si)+ ccohort%n * & total_m / m2_per_ha - + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage,ccohort%canopy_trim, store_max) this%hvars(ih_storectfrac_si)%r81d(io_si) = & this%hvars(ih_storectfrac_si)%r81d(io_si) + ccohort%n * store_max/m2_per_ha - + hio_bdead_si(io_si) = hio_bdead_si(io_si) + n_perm2 * struct_m hio_balive_si(io_si) = hio_balive_si(io_si) + n_perm2 * alive_m - + hio_agb_si(io_si) = hio_agb_si(io_si) + n_perm2 * & ( leaf_m + (sapw_m + struct_m + store_m) * prt_params%allom_agb_frac(ccohort%pft) ) @@ -2768,11 +2805,11 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_biomass_secondary_forest_si(io_si) = hio_biomass_secondary_forest_si(io_si) + & total_m * ccohort%n * AREA_INV endif - + elseif(element_list(el).eq.nitrogen_element)then store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) - + this%hvars(ih_storen_si)%r81d(io_si) = & this%hvars(ih_storen_si)%r81d(io_si) + ccohort%n * & store_m / m2_per_ha @@ -2796,9 +2833,9 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) total_m / m2_per_ha elseif(element_list(el).eq.phosphorus_element) then - + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) - + this%hvars(ih_storep_si)%r81d(io_si) = & this%hvars(ih_storep_si)%r81d(io_si) + ccohort%n * & store_m / m2_per_ha @@ -2827,7 +2864,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! Flux Variables (cohorts must had experienced a day before any of these values ! have any meaning, otherwise they are just inialization values notnew: if( .not.(ccohort%isnew) ) then - + ! Turnover pools [kgC/day] * [day/yr] = [kgC/yr] sapw_m_turnover = ccohort%prt%GetTurnover(sapw_organ, carbon12_element) * days_per_year store_m_turnover = ccohort%prt%GetTurnover(store_organ, carbon12_element) * days_per_year @@ -2871,7 +2908,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ccohort%height * cohort_ba site_ba = site_ba + cohort_ba - + end if ! THIS NEEDS TO BE NORMALIZED (RGK) @@ -2891,14 +2928,14 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & ccohort%n * ha_per_m2 - + hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & ccohort%c_area + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%c_area * sec_per_day * days_per_year - + else hio_ustory_biomass_si(io_si) = hio_ustory_biomass_si(io_si) + n_perm2 * total_m @@ -2908,21 +2945,21 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & ccohort%n * ha_per_m2 - + hio_ustory_mortality_crownarea_si(io_si) = hio_ustory_mortality_crownarea_si(io_si) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & ccohort%c_area + & (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & ccohort%c_area * sec_per_day * days_per_year - + end if - + end if notnew - + ccohort => ccohort%taller enddo cohortloop ! cohort loop - + ipa = ipa + 1 cpatch => cpatch%younger end do patchloop !patch loop @@ -2936,8 +2973,8 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) else hio_lai_secondary_si(io_si) = 0._r8 end if - - + + ! divide basal-area-weighted height by basal area to get mean if ( site_ba .gt. nearzero ) then hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) / site_ba @@ -2965,23 +3002,23 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) end do elloop2 - - + + ! zero the site-level termination carbon flux variable sites(s)%term_carbonflux_canopy(:) = 0._r8 sites(s)%term_carbonflux_ustory(:) = 0._r8 - + end do siteloop - + end associate return end subroutine update_history_dyn1 - + ! ========================================================================================= - + subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! Arguments @@ -3051,1745 +3088,1754 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) real(r8) :: storec_understory_scpf(numpft*nlevsclass) integer :: i_dist, j_dist - + type(site_fluxdiags_type), pointer :: flux_diags type(site_fluxdiags_type), pointer :: flux_diags_c - + real(r8), parameter :: reallytalltrees = 1000. ! some large number (m) associate( hio_err_fates_elem => this%hvars(ih_err_fates_elem)%r82d, & - hio_biomass_si_pft => this%hvars(ih_biomass_si_pft)%r82d, & - hio_biomass_sec_si_pft => this%hvars(ih_biomass_sec_si_pft)%r82d, & - hio_leafbiomass_si_pft => this%hvars(ih_leafbiomass_si_pft)%r82d, & - hio_storebiomass_si_pft => this%hvars(ih_storebiomass_si_pft)%r82d, & - hio_nindivs_si_pft => this%hvars(ih_nindivs_si_pft)%r82d, & - hio_nindivs_sec_si_pft => this%hvars(ih_nindivs_sec_si_pft)%r82d, & - hio_recruitment_si_pft => this%hvars(ih_recruitment_si_pft)%r82d, & - hio_seeds_out_gc_si_pft => this%hvars(ih_seeds_out_gc_si_pft)%r82d, & - hio_seeds_in_gc_si_pft => this%hvars(ih_seeds_in_gc_si_pft)%r82d, & - hio_mortality_si_pft => this%hvars(ih_mortality_si_pft)%r82d, & - hio_mortality_carbonflux_si_pft => this%hvars(ih_mortality_carbonflux_si_pft)%r82d, & - hio_cstarvmortality_carbonflux_si_pft => this%hvars(ih_cstarvmortality_carbonflux_si_pft)%r82d, & - hio_hydraulicmortality_carbonflux_si_pft => this%hvars(ih_hydraulicmortality_carbonflux_si_pft)%r82d, & - hio_firemortality_carbonflux_si_pft => this%hvars(ih_firemortality_carbonflux_si_pft)%r82d, & - hio_crownarea_si_pft => this%hvars(ih_crownarea_si_pft)%r82d, & - hio_canopycrownarea_si_pft => this%hvars(ih_canopycrownarea_si_pft)%r82d, & - hio_gpp_si_pft => this%hvars(ih_gpp_si_pft)%r82d, & - hio_gpp_sec_si_pft => this%hvars(ih_gpp_sec_si_pft)%r82d, & - hio_npp_si_pft => this%hvars(ih_npp_si_pft)%r82d, & - hio_npp_sec_si_pft => this%hvars(ih_npp_sec_si_pft)%r82d, & - hio_fragmentation_scaler_sl => this%hvars(ih_fragmentation_scaler_sl)%r82d, & - hio_litter_in_elem => this%hvars(ih_litter_in_elem)%r82d, & - hio_litter_out_elem => this%hvars(ih_litter_out_elem)%r82d, & - hio_seed_bank_elem => this%hvars(ih_seed_bank_elem)%r82d, & - hio_seeds_in_local_elem => this%hvars(ih_seeds_in_local_elem)%r82d, & - hio_seed_in_extern_elem => this%hvars(ih_seeds_in_extern_elem)%r82d, & - hio_seed_decay_elem => this%hvars(ih_seed_decay_elem)%r82d, & - hio_seed_germ_elem => this%hvars(ih_seed_germ_elem)%r82d, & - hio_gpp_si_scpf => this%hvars(ih_gpp_si_scpf)%r82d, & - hio_npp_totl_si_scpf => this%hvars(ih_npp_totl_si_scpf)%r82d, & - hio_npp_leaf_si_scpf => this%hvars(ih_npp_leaf_si_scpf)%r82d, & - hio_npp_seed_si_scpf => this%hvars(ih_npp_seed_si_scpf)%r82d, & - hio_npp_fnrt_si_scpf => this%hvars(ih_npp_fnrt_si_scpf)%r82d, & - hio_npp_bgsw_si_scpf => this%hvars(ih_npp_bgsw_si_scpf)%r82d, & - hio_npp_bgdw_si_scpf => this%hvars(ih_npp_bgdw_si_scpf)%r82d, & - hio_npp_agsw_si_scpf => this%hvars(ih_npp_agsw_si_scpf)%r82d, & - hio_npp_agdw_si_scpf => this%hvars(ih_npp_agdw_si_scpf)%r82d, & - hio_npp_stor_si_scpf => this%hvars(ih_npp_stor_si_scpf)%r82d, & - hio_bstor_canopy_si_scpf => this%hvars(ih_bstor_canopy_si_scpf)%r82d, & - hio_bstor_understory_si_scpf => this%hvars(ih_bstor_understory_si_scpf)%r82d, & - hio_bleaf_canopy_si_scpf => this%hvars(ih_bleaf_canopy_si_scpf)%r82d, & - hio_bleaf_understory_si_scpf => this%hvars(ih_bleaf_understory_si_scpf)%r82d, & - hio_lai_canopy_si_scpf => this%hvars(ih_lai_canopy_si_scpf)%r82d, & - hio_lai_understory_si_scpf => this%hvars(ih_lai_understory_si_scpf)%r82d, & - hio_mortality_canopy_si_scpf => this%hvars(ih_mortality_canopy_si_scpf)%r82d, & - hio_mortality_canopy_secondary_si_scls => this%hvars(ih_mortality_canopy_secondary_si_scls)%r82d, & - hio_mortality_understory_si_scpf => this%hvars(ih_mortality_understory_si_scpf)%r82d, & - hio_m3_mortality_canopy_si_scpf => this%hvars(ih_m3_mortality_canopy_si_scpf)%r82d, & - hio_m3_mortality_understory_si_scpf => this%hvars(ih_m3_mortality_understory_si_scpf)%r82d, & - hio_m3_mortality_canopy_si_scls => this%hvars(ih_m3_mortality_canopy_si_scls)%r82d, & - hio_m3_mortality_understory_si_scls => this%hvars(ih_m3_mortality_understory_si_scls)%r82d, & - hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & - hio_nplant_understory_si_scpf => this%hvars(ih_nplant_understory_si_scpf)%r82d, & - hio_ddbh_canopy_si_scpf => this%hvars(ih_ddbh_canopy_si_scpf)%r82d, & - hio_ddbh_understory_si_scpf => this%hvars(ih_ddbh_understory_si_scpf)%r82d, & - hio_ddbh_canopy_si_scls => this%hvars(ih_ddbh_canopy_si_scls)%r82d, & - hio_ddbh_understory_si_scls => this%hvars(ih_ddbh_understory_si_scls)%r82d, & - hio_gpp_canopy_si_scpf => this%hvars(ih_gpp_canopy_si_scpf)%r82d, & - hio_gpp_understory_si_scpf => this%hvars(ih_gpp_understory_si_scpf)%r82d, & - hio_ar_canopy_si_scpf => this%hvars(ih_ar_canopy_si_scpf)%r82d, & - hio_ar_understory_si_scpf => this%hvars(ih_ar_understory_si_scpf)%r82d, & - hio_ddbh_si_scpf => this%hvars(ih_ddbh_si_scpf)%r82d, & - hio_growthflux_si_scpf => this%hvars(ih_growthflux_si_scpf)%r82d, & - hio_growthflux_fusion_si_scpf => this%hvars(ih_growthflux_fusion_si_scpf)%r82d, & - hio_ba_si_scpf => this%hvars(ih_ba_si_scpf)%r82d, & - hio_agb_si_scpf => this%hvars(ih_agb_si_scpf)%r82d, & - hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & - hio_nplant_si_capf => this%hvars(ih_nplant_si_capf)%r82d, & - hio_m1_si_scpf => this%hvars(ih_m1_si_scpf)%r82d, & - hio_m2_si_scpf => this%hvars(ih_m2_si_scpf)%r82d, & - hio_m3_si_scpf => this%hvars(ih_m3_si_scpf)%r82d, & - hio_m4_si_scpf => this%hvars(ih_m4_si_scpf)%r82d, & - hio_m5_si_scpf => this%hvars(ih_m5_si_scpf)%r82d, & - hio_m6_si_scpf => this%hvars(ih_m6_si_scpf)%r82d, & - hio_m7_si_scpf => this%hvars(ih_m7_si_scpf)%r82d, & - hio_m8_si_scpf => this%hvars(ih_m8_si_scpf)%r82d, & - hio_m9_si_scpf => this%hvars(ih_m9_si_scpf)%r82d, & - hio_m10_si_scpf => this%hvars(ih_m10_si_scpf)%r82d, & - hio_m10_si_capf => this%hvars(ih_m10_si_capf)%r82d, & - hio_crownfiremort_si_scpf => this%hvars(ih_crownfiremort_si_scpf)%r82d, & - hio_cambialfiremort_si_scpf => this%hvars(ih_cambialfiremort_si_scpf)%r82d, & - hio_abg_mortality_cflux_si_scpf => this%hvars(ih_abg_mortality_cflux_si_scpf)%r82d, & - hio_abg_productivity_cflux_si_scpf => this%hvars(ih_abg_productivity_cflux_si_scpf)%r82d, & - hio_burn_flux_elem => this%hvars(ih_burn_flux_elem)%r82d, & - hio_m1_si_scls => this%hvars(ih_m1_si_scls)%r82d, & - hio_m2_si_scls => this%hvars(ih_m2_si_scls)%r82d, & - hio_m3_si_scls => this%hvars(ih_m3_si_scls)%r82d, & - hio_m4_si_scls => this%hvars(ih_m4_si_scls)%r82d, & - hio_m5_si_scls => this%hvars(ih_m5_si_scls)%r82d, & - hio_m6_si_scls => this%hvars(ih_m6_si_scls)%r82d, & - hio_m7_si_scls => this%hvars(ih_m7_si_scls)%r82d, & - hio_m8_si_scls => this%hvars(ih_m8_si_scls)%r82d, & - hio_m9_si_scls => this%hvars(ih_m9_si_scls)%r82d, & - hio_m10_si_scls => this%hvars(ih_m10_si_scls)%r82d, & - hio_m10_si_cacls => this%hvars(ih_m10_si_cacls)%r82d) + hio_biomass_si_pft => this%hvars(ih_biomass_si_pft)%r82d, & + hio_biomass_sec_si_pft => this%hvars(ih_biomass_sec_si_pft)%r82d, & + hio_leafbiomass_si_pft => this%hvars(ih_leafbiomass_si_pft)%r82d, & + hio_storebiomass_si_pft => this%hvars(ih_storebiomass_si_pft)%r82d, & + hio_nindivs_si_pft => this%hvars(ih_nindivs_si_pft)%r82d, & + hio_nindivs_sec_si_pft => this%hvars(ih_nindivs_sec_si_pft)%r82d, & + hio_recruitment_si_pft => this%hvars(ih_recruitment_si_pft)%r82d, & + hio_seeds_out_gc_si_pft => this%hvars(ih_seeds_out_gc_si_pft)%r82d, & + hio_seeds_in_gc_si_pft => this%hvars(ih_seeds_in_gc_si_pft)%r82d, & + hio_mortality_si_pft => this%hvars(ih_mortality_si_pft)%r82d, & + hio_mortality_carbonflux_si_pft => this%hvars(ih_mortality_carbonflux_si_pft)%r82d, & + hio_cstarvmortality_carbonflux_si_pft => this%hvars(ih_cstarvmortality_carbonflux_si_pft)%r82d, & + hio_hydraulicmortality_carbonflux_si_pft => this%hvars(ih_hydraulicmortality_carbonflux_si_pft)%r82d, & + hio_firemortality_carbonflux_si_pft => this%hvars(ih_firemortality_carbonflux_si_pft)%r82d, & + hio_crownarea_si_pft => this%hvars(ih_crownarea_si_pft)%r82d, & + hio_canopycrownarea_si_pft => this%hvars(ih_canopycrownarea_si_pft)%r82d, & + hio_gpp_si_pft => this%hvars(ih_gpp_si_pft)%r82d, & + hio_gpp_sec_si_pft => this%hvars(ih_gpp_sec_si_pft)%r82d, & + hio_npp_si_pft => this%hvars(ih_npp_si_pft)%r82d, & + hio_npp_sec_si_pft => this%hvars(ih_npp_sec_si_pft)%r82d, & + hio_fragmentation_scaler_sl => this%hvars(ih_fragmentation_scaler_sl)%r82d, & + hio_litter_in_elem => this%hvars(ih_litter_in_elem)%r82d, & + hio_litter_out_elem => this%hvars(ih_litter_out_elem)%r82d, & + hio_seed_bank_elem => this%hvars(ih_seed_bank_elem)%r82d, & + hio_seeds_in_local_elem => this%hvars(ih_seeds_in_local_elem)%r82d, & + hio_seed_in_extern_elem => this%hvars(ih_seeds_in_extern_elem)%r82d, & + hio_seed_decay_elem => this%hvars(ih_seed_decay_elem)%r82d, & + hio_seed_germ_elem => this%hvars(ih_seed_germ_elem)%r82d, & + hio_gpp_si_scpf => this%hvars(ih_gpp_si_scpf)%r82d, & + hio_npp_totl_si_scpf => this%hvars(ih_npp_totl_si_scpf)%r82d, & + hio_npp_leaf_si_scpf => this%hvars(ih_npp_leaf_si_scpf)%r82d, & + hio_npp_seed_si_scpf => this%hvars(ih_npp_seed_si_scpf)%r82d, & + hio_npp_fnrt_si_scpf => this%hvars(ih_npp_fnrt_si_scpf)%r82d, & + hio_npp_bgsw_si_scpf => this%hvars(ih_npp_bgsw_si_scpf)%r82d, & + hio_npp_bgdw_si_scpf => this%hvars(ih_npp_bgdw_si_scpf)%r82d, & + hio_npp_agsw_si_scpf => this%hvars(ih_npp_agsw_si_scpf)%r82d, & + hio_npp_agdw_si_scpf => this%hvars(ih_npp_agdw_si_scpf)%r82d, & + hio_npp_stor_si_scpf => this%hvars(ih_npp_stor_si_scpf)%r82d, & + hio_bstor_canopy_si_scpf => this%hvars(ih_bstor_canopy_si_scpf)%r82d, & + hio_bstor_understory_si_scpf => this%hvars(ih_bstor_understory_si_scpf)%r82d, & + hio_bleaf_canopy_si_scpf => this%hvars(ih_bleaf_canopy_si_scpf)%r82d, & + hio_bleaf_understory_si_scpf => this%hvars(ih_bleaf_understory_si_scpf)%r82d, & + hio_lai_canopy_si_scpf => this%hvars(ih_lai_canopy_si_scpf)%r82d, & + hio_lai_understory_si_scpf => this%hvars(ih_lai_understory_si_scpf)%r82d, & + hio_mortality_canopy_si_scpf => this%hvars(ih_mortality_canopy_si_scpf)%r82d, & + hio_mortality_canopy_secondary_si_scls => this%hvars(ih_mortality_canopy_secondary_si_scls)%r82d, & + hio_mortality_understory_si_scpf => this%hvars(ih_mortality_understory_si_scpf)%r82d, & + hio_m3_mortality_canopy_si_scpf => this%hvars(ih_m3_mortality_canopy_si_scpf)%r82d, & + hio_m3_mortality_understory_si_scpf => this%hvars(ih_m3_mortality_understory_si_scpf)%r82d, & + hio_m3_mortality_canopy_si_scls => this%hvars(ih_m3_mortality_canopy_si_scls)%r82d, & + hio_m3_mortality_understory_si_scls => this%hvars(ih_m3_mortality_understory_si_scls)%r82d, & + hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & + hio_nplant_understory_si_scpf => this%hvars(ih_nplant_understory_si_scpf)%r82d, & + hio_ddbh_canopy_si_scpf => this%hvars(ih_ddbh_canopy_si_scpf)%r82d, & + hio_ddbh_understory_si_scpf => this%hvars(ih_ddbh_understory_si_scpf)%r82d, & + hio_ddbh_canopy_si_scls => this%hvars(ih_ddbh_canopy_si_scls)%r82d, & + hio_ddbh_understory_si_scls => this%hvars(ih_ddbh_understory_si_scls)%r82d, & + hio_gpp_canopy_si_scpf => this%hvars(ih_gpp_canopy_si_scpf)%r82d, & + hio_gpp_understory_si_scpf => this%hvars(ih_gpp_understory_si_scpf)%r82d, & + hio_ar_canopy_si_scpf => this%hvars(ih_ar_canopy_si_scpf)%r82d, & + hio_ar_understory_si_scpf => this%hvars(ih_ar_understory_si_scpf)%r82d, & + hio_ddbh_si_scpf => this%hvars(ih_ddbh_si_scpf)%r82d, & + hio_growthflux_si_scpf => this%hvars(ih_growthflux_si_scpf)%r82d, & + hio_growthflux_fusion_si_scpf => this%hvars(ih_growthflux_fusion_si_scpf)%r82d, & + hio_ba_si_scpf => this%hvars(ih_ba_si_scpf)%r82d, & + hio_agb_si_scpf => this%hvars(ih_agb_si_scpf)%r82d, & + hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & + hio_nplant_si_capf => this%hvars(ih_nplant_si_capf)%r82d, & + hio_m1_si_scpf => this%hvars(ih_m1_si_scpf)%r82d, & + hio_m2_si_scpf => this%hvars(ih_m2_si_scpf)%r82d, & + hio_m3_si_scpf => this%hvars(ih_m3_si_scpf)%r82d, & + hio_m4_si_scpf => this%hvars(ih_m4_si_scpf)%r82d, & + hio_m5_si_scpf => this%hvars(ih_m5_si_scpf)%r82d, & + hio_m6_si_scpf => this%hvars(ih_m6_si_scpf)%r82d, & + hio_m7_si_scpf => this%hvars(ih_m7_si_scpf)%r82d, & + hio_m8_si_scpf => this%hvars(ih_m8_si_scpf)%r82d, & + hio_m9_si_scpf => this%hvars(ih_m9_si_scpf)%r82d, & + hio_m10_si_scpf => this%hvars(ih_m10_si_scpf)%r82d, & + hio_m10_si_capf => this%hvars(ih_m10_si_capf)%r82d, & + hio_crownfiremort_si_scpf => this%hvars(ih_crownfiremort_si_scpf)%r82d, & + hio_cambialfiremort_si_scpf => this%hvars(ih_cambialfiremort_si_scpf)%r82d, & + hio_abg_mortality_cflux_si_scpf => this%hvars(ih_abg_mortality_cflux_si_scpf)%r82d, & + hio_abg_productivity_cflux_si_scpf => this%hvars(ih_abg_productivity_cflux_si_scpf)%r82d, & + hio_burn_flux_elem => this%hvars(ih_burn_flux_elem)%r82d, & + hio_m1_si_scls => this%hvars(ih_m1_si_scls)%r82d, & + hio_m2_si_scls => this%hvars(ih_m2_si_scls)%r82d, & + hio_m3_si_scls => this%hvars(ih_m3_si_scls)%r82d, & + hio_m4_si_scls => this%hvars(ih_m4_si_scls)%r82d, & + hio_m5_si_scls => this%hvars(ih_m5_si_scls)%r82d, & + hio_m6_si_scls => this%hvars(ih_m6_si_scls)%r82d, & + hio_m7_si_scls => this%hvars(ih_m7_si_scls)%r82d, & + hio_m8_si_scls => this%hvars(ih_m8_si_scls)%r82d, & + hio_m9_si_scls => this%hvars(ih_m9_si_scls)%r82d, & + hio_m10_si_scls => this%hvars(ih_m10_si_scls)%r82d, & + hio_m10_si_cacls => this%hvars(ih_m10_si_cacls)%r82d) ! Break up associates for NAG compilers associate(hio_m1_sec_si_scls => this%hvars(ih_m1_sec_si_scls)%r82d, & - hio_m2_sec_si_scls => this%hvars(ih_m2_sec_si_scls)%r82d, & - hio_m3_sec_si_scls => this%hvars(ih_m3_sec_si_scls)%r82d, & - hio_m7_sec_si_scls => this%hvars(ih_m7_sec_si_scls)%r82d, & - hio_m8_sec_si_scls => this%hvars(ih_m8_sec_si_scls)%r82d, & - hio_m9_sec_si_scls => this%hvars(ih_m9_sec_si_scls)%r82d, & - hio_m10_sec_si_scls => this%hvars(ih_m10_sec_si_scls)%r82d, & - hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & - hio_cwd_elcwd => this%hvars(ih_cwd_elcwd)%r82d, & - hio_cwd_ag_elem => this%hvars(ih_cwd_ag_elem)%r82d, & - hio_cwd_bg_elem => this%hvars(ih_cwd_bg_elem)%r82d, & - hio_fines_ag_elem => this%hvars(ih_fines_ag_elem)%r82d, & - hio_fines_bg_elem => this%hvars(ih_fines_bg_elem)%r82d, & - hio_ba_si_scls => this%hvars(ih_ba_si_scls)%r82d, & - hio_agb_si_scls => this%hvars(ih_agb_si_scls)%r82d, & - hio_biomass_si_scls => this%hvars(ih_biomass_si_scls)%r82d, & - hio_nplant_si_scls => this%hvars(ih_nplant_si_scls)%r82d, & - hio_nplant_si_cacls => this%hvars(ih_nplant_si_cacls)%r82d, & - hio_nplant_canopy_si_scls => this%hvars(ih_nplant_canopy_si_scls)%r82d, & - hio_nplant_understory_si_scls => this%hvars(ih_nplant_understory_si_scls)%r82d, & - hio_lai_canopy_si_scls => this%hvars(ih_lai_canopy_si_scls)%r82d, & - hio_lai_understory_si_scls => this%hvars(ih_lai_understory_si_scls)%r82d, & - hio_sai_canopy_si_scls => this%hvars(ih_sai_canopy_si_scls)%r82d, & - hio_sai_understory_si_scls => this%hvars(ih_sai_understory_si_scls)%r82d, & - hio_mortality_canopy_si_scls => this%hvars(ih_mortality_canopy_si_scls)%r82d, & - hio_mortality_understory_si_scls => this%hvars(ih_mortality_understory_si_scls)%r82d, & - hio_demotion_rate_si_scls => this%hvars(ih_demotion_rate_si_scls)%r82d, & - hio_promotion_rate_si_scls => this%hvars(ih_promotion_rate_si_scls)%r82d, & - hio_trimming_canopy_si_scls => this%hvars(ih_trimming_canopy_si_scls)%r82d, & - hio_trimming_understory_si_scls => this%hvars(ih_trimming_understory_si_scls)%r82d, & - hio_crown_area_canopy_si_scls => this%hvars(ih_crown_area_canopy_si_scls)%r82d, & - hio_crown_area_understory_si_scls => this%hvars(ih_crown_area_understory_si_scls)%r82d, & - hio_leaf_md_canopy_si_scls => this%hvars(ih_leaf_md_canopy_si_scls)%r82d, & - hio_root_md_canopy_si_scls => this%hvars(ih_root_md_canopy_si_scls)%r82d, & - hio_carbon_balance_canopy_si_scls => this%hvars(ih_carbon_balance_canopy_si_scls)%r82d, & - hio_bsw_md_canopy_si_scls => this%hvars(ih_bsw_md_canopy_si_scls)%r82d, & - hio_bdead_md_canopy_si_scls => this%hvars(ih_bdead_md_canopy_si_scls)%r82d, & - hio_bstore_md_canopy_si_scls => this%hvars(ih_bstore_md_canopy_si_scls)%r82d, & - hio_seed_prod_canopy_si_scls => this%hvars(ih_seed_prod_canopy_si_scls)%r82d, & - hio_npp_leaf_canopy_si_scls => this%hvars(ih_npp_leaf_canopy_si_scls)%r82d, & - hio_npp_fnrt_canopy_si_scls => this%hvars(ih_npp_fnrt_canopy_si_scls)%r82d, & - hio_npp_sapw_canopy_si_scls => this%hvars(ih_npp_sapw_canopy_si_scls)%r82d, & - hio_npp_dead_canopy_si_scls => this%hvars(ih_npp_dead_canopy_si_scls)%r82d, & - hio_npp_seed_canopy_si_scls => this%hvars(ih_npp_seed_canopy_si_scls)%r82d, & - hio_npp_stor_canopy_si_scls => this%hvars(ih_npp_stor_canopy_si_scls)%r82d, & - hio_leaf_md_understory_si_scls => this%hvars(ih_leaf_md_understory_si_scls)%r82d, & - hio_root_md_understory_si_scls => this%hvars(ih_root_md_understory_si_scls)%r82d, & - hio_carbon_balance_understory_si_scls=> this%hvars(ih_carbon_balance_understory_si_scls)%r82d, & - hio_bstore_md_understory_si_scls => this%hvars(ih_bstore_md_understory_si_scls)%r82d, & - hio_bsw_md_understory_si_scls => this%hvars(ih_bsw_md_understory_si_scls)%r82d, & - hio_bdead_md_understory_si_scls => this%hvars(ih_bdead_md_understory_si_scls)%r82d, & - hio_seed_prod_understory_si_scls => this%hvars(ih_seed_prod_understory_si_scls)%r82d, & - hio_npp_leaf_understory_si_scls => this%hvars(ih_npp_leaf_understory_si_scls)%r82d, & - hio_npp_fnrt_understory_si_scls => this%hvars(ih_npp_fnrt_understory_si_scls)%r82d, & - hio_npp_sapw_understory_si_scls => this%hvars(ih_npp_sapw_understory_si_scls)%r82d, & - hio_npp_dead_understory_si_scls => this%hvars(ih_npp_dead_understory_si_scls)%r82d, & - hio_npp_seed_understory_si_scls => this%hvars(ih_npp_seed_understory_si_scls)%r82d, & - hio_npp_stor_understory_si_scls => this%hvars(ih_npp_stor_understory_si_scls)%r82d, & - hio_nplant_si_scagpft => this%hvars(ih_nplant_si_scagpft)%r82d, & - hio_npp_si_agepft => this%hvars(ih_npp_si_agepft)%r82d, & - hio_biomass_si_agepft => this%hvars(ih_biomass_si_agepft)%r82d, & - hio_scorch_height_si_agepft => this%hvars(ih_scorch_height_si_agepft)%r82d, & - hio_yesterdaycanopylevel_canopy_si_scls => this%hvars(ih_yesterdaycanopylevel_canopy_si_scls)%r82d, & - hio_yesterdaycanopylevel_understory_si_scls => this%hvars(ih_yesterdaycanopylevel_understory_si_scls)%r82d, & - hio_area_si_age => this%hvars(ih_area_si_age)%r82d, & - hio_lai_si_age => this%hvars(ih_lai_si_age)%r82d, & - hio_canopy_area_si_age => this%hvars(ih_canopy_area_si_age)%r82d, & - hio_ncl_si_age => this%hvars(ih_ncl_si_age)%r82d, & - hio_npatches_si_age => this%hvars(ih_npatches_si_age)%r82d, & - hio_zstar_si_age => this%hvars(ih_zstar_si_age)%r82d, & - hio_biomass_si_age => this%hvars(ih_biomass_si_age)%r82d, & - hio_agesince_anthrodist_si_age => this%hvars(ih_agesince_anthrodist_si_age)%r82d, & - hio_secondarylands_area_si_age => this%hvars(ih_secondarylands_area_si_age)%r82d, & - hio_area_si_landuse => this%hvars(ih_area_si_landuse)%r82d, & - hio_area_burnt_si_age => this%hvars(ih_area_burnt_si_age)%r82d, & - ! hio_fire_rate_of_spread_front_si_age => this%hvars(ih_fire_rate_of_spread_front_si_age)%r82d, & - hio_fire_intensity_si_age => this%hvars(ih_fire_intensity_si_age)%r82d, & - hio_fire_sum_fuel_si_age => this%hvars(ih_fire_sum_fuel_si_age)%r82d, & - hio_burnt_frac_litter_si_fuel => this%hvars(ih_burnt_frac_litter_si_fuel)%r82d, & - hio_fuel_amount_si_fuel => this%hvars(ih_fuel_amount_si_fuel)%r82d, & - hio_fuel_amount_age_fuel => this%hvars(ih_fuel_amount_age_fuel)%r82d, & - hio_canopy_height_dist_si_height => this%hvars(ih_canopy_height_dist_si_height)%r82d, & - hio_leaf_height_dist_si_height => this%hvars(ih_leaf_height_dist_si_height)%r82d, & - hio_litter_moisture_si_fuel => this%hvars(ih_litter_moisture_si_fuel)%r82d, & - hio_cwd_ag_si_cwdsc => this%hvars(ih_cwd_ag_si_cwdsc)%r82d, & - hio_cwd_bg_si_cwdsc => this%hvars(ih_cwd_bg_si_cwdsc)%r82d, & - hio_cwd_ag_in_si_cwdsc => this%hvars(ih_cwd_ag_in_si_cwdsc)%r82d, & - hio_cwd_bg_in_si_cwdsc => this%hvars(ih_cwd_bg_in_si_cwdsc)%r82d, & - hio_cwd_ag_out_si_cwdsc => this%hvars(ih_cwd_ag_out_si_cwdsc)%r82d, & - hio_cwd_bg_out_si_cwdsc => this%hvars(ih_cwd_bg_out_si_cwdsc)%r82d, & - hio_crownarea_si_cnlf => this%hvars(ih_crownarea_si_cnlf)%r82d, & - hio_crownarea_cl => this%hvars(ih_crownarea_cl)%r82d, & - hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & - 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_ddbh_canopy_si_scag => this%hvars(ih_ddbh_canopy_si_scag)%r82d, & - hio_ddbh_understory_si_scag => this%hvars(ih_ddbh_understory_si_scag)%r82d, & - hio_mortality_canopy_si_scag => this%hvars(ih_mortality_canopy_si_scag)%r82d, & - hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d ) - - ! Break up associates for NAG compilers - associate( hio_site_dstatus_si_pft => this%hvars(ih_site_dstatus_si_pft)%r82d, & - hio_dleafoff_si_pft => this%hvars(ih_dleafoff_si_pft)%r82d, & - hio_dleafon_si_pft => this%hvars(ih_dleafon_si_pft)%r82d, & - hio_meanliqvol_si_pft => this%hvars(ih_meanliqvol_si_pft)%r82d, & - hio_meansmp_si_pft => this%hvars(ih_meansmp_si_pft)%r82d, & - hio_elong_factor_si_pft => this%hvars(ih_elong_factor_si_pft)%r82d, & - hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & - 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) - - - model_day_int = nint(hlm_model_day) - - ! --------------------------------------------------------------------------------- - ! Loop through the FATES scale hierarchy and fill the history IO arrays - ! --------------------------------------------------------------------------------- - - siteloop: do s = 1,nsites - - io_si = sites(s)%h_gid - - ! These are weighting factors - storen_canopy_scpf(:) = 0._r8 - storen_understory_scpf(:) = 0._r8 - storep_canopy_scpf(:) = 0._r8 - storep_understory_scpf(:) = 0._r8 - storec_canopy_scpf(:) = 0._r8 - storec_understory_scpf(:) = 0._r8 - - ! roll up disturbance rates in land-use x land-use array into a single dimension - do i_dist = 1, n_landuse_cats - do j_dist = 1, n_landuse_cats - hio_disturbance_rate_si_lulu(io_si, i_dist+n_landuse_cats*(j_dist-1)) = & - sum(sites(s)%disturbance_rates(1:n_dist_types,i_dist, j_dist)) * & - days_per_year - end do - end do + hio_m2_sec_si_scls => this%hvars(ih_m2_sec_si_scls)%r82d, & + hio_m3_sec_si_scls => this%hvars(ih_m3_sec_si_scls)%r82d, & + hio_m7_sec_si_scls => this%hvars(ih_m7_sec_si_scls)%r82d, & + hio_m8_sec_si_scls => this%hvars(ih_m8_sec_si_scls)%r82d, & + hio_m9_sec_si_scls => this%hvars(ih_m9_sec_si_scls)%r82d, & + hio_m10_sec_si_scls => this%hvars(ih_m10_sec_si_scls)%r82d, & + hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & + hio_cwd_elcwd => this%hvars(ih_cwd_elcwd)%r82d, & + hio_cwd_ag_elem => this%hvars(ih_cwd_ag_elem)%r82d, & + hio_cwd_bg_elem => this%hvars(ih_cwd_bg_elem)%r82d, & + hio_fines_ag_elem => this%hvars(ih_fines_ag_elem)%r82d, & + hio_fines_bg_elem => this%hvars(ih_fines_bg_elem)%r82d, & + hio_ba_si_scls => this%hvars(ih_ba_si_scls)%r82d, & + hio_agb_si_scls => this%hvars(ih_agb_si_scls)%r82d, & + hio_biomass_si_scls => this%hvars(ih_biomass_si_scls)%r82d, & + hio_nplant_si_scls => this%hvars(ih_nplant_si_scls)%r82d, & + hio_nplant_si_cacls => this%hvars(ih_nplant_si_cacls)%r82d, & + hio_nplant_canopy_si_scls => this%hvars(ih_nplant_canopy_si_scls)%r82d, & + hio_nplant_understory_si_scls => this%hvars(ih_nplant_understory_si_scls)%r82d, & + hio_lai_canopy_si_scls => this%hvars(ih_lai_canopy_si_scls)%r82d, & + hio_lai_understory_si_scls => this%hvars(ih_lai_understory_si_scls)%r82d, & + hio_sai_canopy_si_scls => this%hvars(ih_sai_canopy_si_scls)%r82d, & + hio_sai_understory_si_scls => this%hvars(ih_sai_understory_si_scls)%r82d, & + hio_mortality_canopy_si_scls => this%hvars(ih_mortality_canopy_si_scls)%r82d, & + hio_mortality_understory_si_scls => this%hvars(ih_mortality_understory_si_scls)%r82d, & + hio_demotion_rate_si_scls => this%hvars(ih_demotion_rate_si_scls)%r82d, & + hio_promotion_rate_si_scls => this%hvars(ih_promotion_rate_si_scls)%r82d, & + hio_trimming_canopy_si_scls => this%hvars(ih_trimming_canopy_si_scls)%r82d, & + hio_trimming_understory_si_scls => this%hvars(ih_trimming_understory_si_scls)%r82d, & + hio_crown_area_canopy_si_scls => this%hvars(ih_crown_area_canopy_si_scls)%r82d, & + hio_crown_area_understory_si_scls => this%hvars(ih_crown_area_understory_si_scls)%r82d, & + hio_leaf_md_canopy_si_scls => this%hvars(ih_leaf_md_canopy_si_scls)%r82d, & + hio_root_md_canopy_si_scls => this%hvars(ih_root_md_canopy_si_scls)%r82d, & + hio_carbon_balance_canopy_si_scls => this%hvars(ih_carbon_balance_canopy_si_scls)%r82d, & + hio_bsw_md_canopy_si_scls => this%hvars(ih_bsw_md_canopy_si_scls)%r82d, & + hio_bdead_md_canopy_si_scls => this%hvars(ih_bdead_md_canopy_si_scls)%r82d, & + hio_bstore_md_canopy_si_scls => this%hvars(ih_bstore_md_canopy_si_scls)%r82d, & + hio_seed_prod_canopy_si_scls => this%hvars(ih_seed_prod_canopy_si_scls)%r82d, & + hio_npp_leaf_canopy_si_scls => this%hvars(ih_npp_leaf_canopy_si_scls)%r82d, & + hio_npp_fnrt_canopy_si_scls => this%hvars(ih_npp_fnrt_canopy_si_scls)%r82d, & + hio_npp_sapw_canopy_si_scls => this%hvars(ih_npp_sapw_canopy_si_scls)%r82d, & + hio_npp_dead_canopy_si_scls => this%hvars(ih_npp_dead_canopy_si_scls)%r82d, & + hio_npp_seed_canopy_si_scls => this%hvars(ih_npp_seed_canopy_si_scls)%r82d, & + hio_npp_stor_canopy_si_scls => this%hvars(ih_npp_stor_canopy_si_scls)%r82d, & + hio_leaf_md_understory_si_scls => this%hvars(ih_leaf_md_understory_si_scls)%r82d, & + hio_root_md_understory_si_scls => this%hvars(ih_root_md_understory_si_scls)%r82d, & + hio_carbon_balance_understory_si_scls=> this%hvars(ih_carbon_balance_understory_si_scls)%r82d, & + hio_bstore_md_understory_si_scls => this%hvars(ih_bstore_md_understory_si_scls)%r82d, & + hio_bsw_md_understory_si_scls => this%hvars(ih_bsw_md_understory_si_scls)%r82d, & + hio_bdead_md_understory_si_scls => this%hvars(ih_bdead_md_understory_si_scls)%r82d, & + hio_seed_prod_understory_si_scls => this%hvars(ih_seed_prod_understory_si_scls)%r82d, & + hio_npp_leaf_understory_si_scls => this%hvars(ih_npp_leaf_understory_si_scls)%r82d, & + hio_npp_fnrt_understory_si_scls => this%hvars(ih_npp_fnrt_understory_si_scls)%r82d, & + hio_npp_sapw_understory_si_scls => this%hvars(ih_npp_sapw_understory_si_scls)%r82d, & + hio_npp_dead_understory_si_scls => this%hvars(ih_npp_dead_understory_si_scls)%r82d, & + hio_npp_seed_understory_si_scls => this%hvars(ih_npp_seed_understory_si_scls)%r82d, & + hio_npp_stor_understory_si_scls => this%hvars(ih_npp_stor_understory_si_scls)%r82d, & + hio_nplant_si_scagpft => this%hvars(ih_nplant_si_scagpft)%r82d, & + hio_npp_si_agepft => this%hvars(ih_npp_si_agepft)%r82d, & + hio_biomass_si_agepft => this%hvars(ih_biomass_si_agepft)%r82d, & + hio_scorch_height_si_agepft => this%hvars(ih_scorch_height_si_agepft)%r82d, & + hio_yesterdaycanopylevel_canopy_si_scls => this%hvars(ih_yesterdaycanopylevel_canopy_si_scls)%r82d, & + hio_yesterdaycanopylevel_understory_si_scls => this%hvars(ih_yesterdaycanopylevel_understory_si_scls)%r82d, & + hio_area_si_age => this%hvars(ih_area_si_age)%r82d, & + hio_lai_si_age => this%hvars(ih_lai_si_age)%r82d, & + hio_canopy_area_si_age => this%hvars(ih_canopy_area_si_age)%r82d, & + hio_ncl_si_age => this%hvars(ih_ncl_si_age)%r82d, & + hio_npatches_si_age => this%hvars(ih_npatches_si_age)%r82d, & + hio_zstar_si_age => this%hvars(ih_zstar_si_age)%r82d, & + hio_biomass_si_age => this%hvars(ih_biomass_si_age)%r82d, & + hio_agesince_anthrodist_si_age => this%hvars(ih_agesince_anthrodist_si_age)%r82d, & + hio_secondarylands_area_si_age => this%hvars(ih_secondarylands_area_si_age)%r82d, & + hio_area_si_landuse => this%hvars(ih_area_si_landuse)%r82d, & + hio_area_burnt_si_age => this%hvars(ih_area_burnt_si_age)%r82d, & + ! hio_fire_rate_of_spread_front_si_age => this%hvars(ih_fire_rate_of_spread_front_si_age)%r82d, & + hio_fire_intensity_si_age => this%hvars(ih_fire_intensity_si_age)%r82d, & + hio_fire_sum_fuel_si_age => this%hvars(ih_fire_sum_fuel_si_age)%r82d, & + hio_burnt_frac_litter_si_fuel => this%hvars(ih_burnt_frac_litter_si_fuel)%r82d, & + hio_fuel_amount_si_fuel => this%hvars(ih_fuel_amount_si_fuel)%r82d, & + hio_fuel_amount_age_fuel => this%hvars(ih_fuel_amount_age_fuel)%r82d, & + hio_canopy_height_dist_si_height => this%hvars(ih_canopy_height_dist_si_height)%r82d, & + hio_leaf_height_dist_si_height => this%hvars(ih_leaf_height_dist_si_height)%r82d, & + hio_litter_moisture_si_fuel => this%hvars(ih_litter_moisture_si_fuel)%r82d, & + hio_cwd_ag_si_cwdsc => this%hvars(ih_cwd_ag_si_cwdsc)%r82d, & + hio_cwd_bg_si_cwdsc => this%hvars(ih_cwd_bg_si_cwdsc)%r82d, & + hio_cwd_ag_in_si_cwdsc => this%hvars(ih_cwd_ag_in_si_cwdsc)%r82d, & + hio_cwd_bg_in_si_cwdsc => this%hvars(ih_cwd_bg_in_si_cwdsc)%r82d, & + hio_cwd_ag_out_si_cwdsc => this%hvars(ih_cwd_ag_out_si_cwdsc)%r82d, & + hio_cwd_bg_out_si_cwdsc => this%hvars(ih_cwd_bg_out_si_cwdsc)%r82d, & + hio_crownarea_si_cnlf => this%hvars(ih_crownarea_si_cnlf)%r82d, & + hio_crownarea_cl => this%hvars(ih_crownarea_cl)%r82d, & + hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & + 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_ddbh_canopy_si_scag => this%hvars(ih_ddbh_canopy_si_scag)%r82d, & + hio_ddbh_understory_si_scag => this%hvars(ih_ddbh_understory_si_scag)%r82d, & + hio_mortality_canopy_si_scag => this%hvars(ih_mortality_canopy_si_scag)%r82d, & + hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d ) + + ! Break up associates for NAG compilers + associate( hio_site_dstatus_si_pft => this%hvars(ih_site_dstatus_si_pft)%r82d, & + hio_dleafoff_si_pft => this%hvars(ih_dleafoff_si_pft)%r82d, & + hio_dleafon_si_pft => this%hvars(ih_dleafon_si_pft)%r82d, & + hio_meanliqvol_si_pft => this%hvars(ih_meanliqvol_si_pft)%r82d, & + hio_meansmp_si_pft => this%hvars(ih_meansmp_si_pft)%r82d, & + hio_elong_factor_si_pft => this%hvars(ih_elong_factor_si_pft)%r82d, & + hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & + 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) + + + model_day_int = nint(hlm_model_day) + + ! --------------------------------------------------------------------------------- + ! Loop through the FATES scale hierarchy and fill the history IO arrays + ! --------------------------------------------------------------------------------- + + siteloop: do s = 1,nsites + + io_si = sites(s)%h_gid + + ! These are weighting factors + storen_canopy_scpf(:) = 0._r8 + storen_understory_scpf(:) = 0._r8 + storep_canopy_scpf(:) = 0._r8 + storep_understory_scpf(:) = 0._r8 + storec_canopy_scpf(:) = 0._r8 + storec_understory_scpf(:) = 0._r8 + + ! roll up disturbance rates in land-use x land-use array into a single dimension + do i_dist = 1, n_landuse_cats + do j_dist = 1, n_landuse_cats + hio_disturbance_rate_si_lulu(io_si, i_dist+n_landuse_cats*(j_dist-1)) = & + sum(sites(s)%disturbance_rates(1:n_dist_types,i_dist, j_dist)) * & + days_per_year + end do + end do + + + do el = 1, num_elements + + ! 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 + + ! 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 * & + days_per_sec + + end do + + + ! Update drought deciduous information (now separated by PFT). + do ft = 1,numpft + ! Update the site-PFT status for drought deciduous + hio_site_dstatus_si_pft(io_si,ft) = real(sites(s)%dstatus(ft),r8) + + ! Model days elapsed since leaf off/on for drought deciduous + hio_dleafoff_si_pft(io_si,ft) = real(sites(s)%dndaysleafon (ft),r8) + hio_dleafon_si_pft(io_si,ft) = real(sites(s)%dndaysleafoff(ft),r8) + + ! Leaf elongation factor (0 means fully abscissed, 1 means fully flushed). + hio_elong_factor_si_pft(io_si,ft) = sites(s)%elong_factor(ft) + + if(model_day_int>numWaterMem)then + ! Mean liquid water content (m3/m3) used for drought phenology + hio_meanliqvol_si_pft(io_si,ft) = & + sum(sites(s)%liqvol_memory(1:numWaterMem,ft))/real(numWaterMem,r8) + + ! Mean soil matric potential (Pa) used for drought phenology + hio_meansmp_si_pft(io_si,ft) = & + sum(sites(s)%smp_memory(1:numWaterMem,ft))/real(numWaterMem,r8) & + * dens_fresh_liquid_water * grav_earth * m_per_mm + end if + end do - - do el = 1, num_elements - ! 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 + ! Loop through patches to sum up diagonistics + ipa = 0 + cpatch => sites(s)%oldest_patch + patchloop: do while(associated(cpatch)) - ! 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 * & - days_per_sec - end do + cpatch%age_class = get_age_class_index(cpatch%age) + ! Increment the fractional area in each age class bin + hio_area_si_age(io_si,cpatch%age_class) = hio_area_si_age(io_si,cpatch%age_class) & + + cpatch%area * AREA_INV - ! Update drought deciduous information (now separated by PFT). - do ft = 1,numpft - ! Update the site-PFT status for drought deciduous - hio_site_dstatus_si_pft(io_si,ft) = real(sites(s)%dstatus(ft),r8) + hio_area_si_landuse(io_si, cpatch%land_use_label) = & + hio_area_si_landuse(io_si, cpatch%land_use_label) & + + cpatch%area * AREA_INV - ! Model days elapsed since leaf off/on for drought deciduous - hio_dleafoff_si_pft(io_si,ft) = real(sites(s)%dndaysleafon (ft),r8) - hio_dleafon_si_pft(io_si,ft) = real(sites(s)%dndaysleafoff(ft),r8) + ! Increment some patch-age-resolved diagnostics + hio_lai_si_age(io_si,cpatch%age_class) = hio_lai_si_age(io_si,cpatch%age_class) & + + sum(cpatch%tlai_profile(:,:,:)) * cpatch%area - ! Leaf elongation factor (0 means fully abscissed, 1 means fully flushed). - hio_elong_factor_si_pft(io_si,ft) = sites(s)%elong_factor(ft) + hio_ncl_si_age(io_si,cpatch%age_class) = hio_ncl_si_age(io_si,cpatch%age_class) & + + cpatch%ncl_p * cpatch%area + hio_npatches_si_age(io_si,cpatch%age_class) = hio_npatches_si_age(io_si,cpatch%age_class) + 1._r8 - if(model_day_int>numWaterMem)then - ! Mean liquid water content (m3/m3) used for drought phenology - hio_meanliqvol_si_pft(io_si,ft) = & - sum(sites(s)%liqvol_memory(1:numWaterMem,ft))/real(numWaterMem,r8) - ! Mean soil matric potential (Pa) used for drought phenology - hio_meansmp_si_pft(io_si,ft) = & - sum(sites(s)%smp_memory(1:numWaterMem,ft))/real(numWaterMem,r8) & - * dens_fresh_liquid_water * grav_earth * m_per_mm - end if - end do - - - ! Loop through patches to sum up diagonistics - ipa = 0 - cpatch => sites(s)%oldest_patch - patchloop: do while(associated(cpatch)) - - - cpatch%age_class = get_age_class_index(cpatch%age) - - ! Increment the fractional area in each age class bin - hio_area_si_age(io_si,cpatch%age_class) = hio_area_si_age(io_si,cpatch%age_class) & - + cpatch%area * AREA_INV - - hio_area_si_landuse(io_si, cpatch%land_use_label) = & - hio_area_si_landuse(io_si, cpatch%land_use_label) & - + cpatch%area * AREA_INV - - ! Increment some patch-age-resolved diagnostics - hio_lai_si_age(io_si,cpatch%age_class) = hio_lai_si_age(io_si,cpatch%age_class) & - + sum(cpatch%tlai_profile(:,:,:)) * cpatch%area - hio_ncl_si_age(io_si,cpatch%age_class) = hio_ncl_si_age(io_si,cpatch%age_class) & - + cpatch%ncl_p * cpatch%area - hio_npatches_si_age(io_si,cpatch%age_class) = hio_npatches_si_age(io_si,cpatch%age_class) + 1._r8 + if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled + hio_zstar_si_age(io_si,cpatch%age_class) = hio_zstar_si_age(io_si,cpatch%age_class) & + + cpatch%zstar * cpatch%area * AREA_INV + endif - + ! some diagnostics on secondary forest area and its age distribution + if ( cpatch%land_use_label .eq. secondaryland ) then - if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled - hio_zstar_si_age(io_si,cpatch%age_class) = hio_zstar_si_age(io_si,cpatch%age_class) & - + cpatch%zstar * cpatch%area * AREA_INV - endif + ageclass_since_anthrodist = get_age_class_index(cpatch%age_since_anthro_disturbance) - ! some diagnostics on secondary forest area and its age distribution - if ( cpatch%land_use_label .eq. secondaryland ) then + hio_agesince_anthrodist_si_age(io_si,ageclass_since_anthrodist) = & + hio_agesince_anthrodist_si_age(io_si,ageclass_since_anthrodist) & + + cpatch%area * AREA_INV - ageclass_since_anthrodist = get_age_class_index(cpatch%age_since_anthro_disturbance) + hio_secondarylands_area_si_age(io_si,cpatch%age_class) = & + hio_secondarylands_area_si_age(io_si,cpatch%age_class) & + + cpatch%area * AREA_INV + endif - hio_agesince_anthrodist_si_age(io_si,ageclass_since_anthrodist) = & - hio_agesince_anthrodist_si_age(io_si,ageclass_since_anthrodist) & - + cpatch%area * AREA_INV - hio_secondarylands_area_si_age(io_si,cpatch%age_class) = & - hio_secondarylands_area_si_age(io_si,cpatch%age_class) & - + cpatch%area * AREA_INV - endif - + ! patch-age-resolved fire variables + do ft = 1,numpft + ! for scorch height, weight the value by patch area within any + ! given age class - in the event that there is more than one + ! patch per age class. + iagepft = cpatch%age_class + (ft-1) * nlevage + hio_scorch_height_si_agepft(io_si,iagepft) = hio_scorch_height_si_agepft(io_si,iagepft) + & + cpatch%Scorch_ht(ft) * cpatch%area - ! patch-age-resolved fire variables - do ft = 1,numpft - ! for scorch height, weight the value by patch area within any - ! given age class - in the event that there is more than one - ! patch per age class. - iagepft = cpatch%age_class + (ft-1) * nlevage - hio_scorch_height_si_agepft(io_si,iagepft) = hio_scorch_height_si_agepft(io_si,iagepft) + & - cpatch%Scorch_ht(ft) * cpatch%area - - ! and also pft-labeled patch areas in the event that we are in nocomp mode - if ( hlm_use_nocomp .eq. itrue .and. cpatch%nocomp_pft_label .eq. ft) then - this%hvars(ih_nocomp_pftpatchfraction_si_pft)%r82d(io_si,ft) = & - this%hvars(ih_nocomp_pftpatchfraction_si_pft)%r82d(io_si,ft) + cpatch%area * AREA_INV - - this%hvars(ih_nocomp_pftnpatches_si_pft)%r82d(io_si,ft) = & - this%hvars(ih_nocomp_pftnpatches_si_pft)%r82d(io_si,ft) + 1._r8 - - this%hvars(ih_nocomp_pftburnedarea_si_pft)%r82d(io_si,ft) = & - this%hvars(ih_nocomp_pftburnedarea_si_pft)%r82d(io_si,ft) + & - cpatch%frac_burnt * cpatch%area * AREA_INV / sec_per_day - endif - - end do + ! and also pft-labeled patch areas in the event that we are in nocomp mode + if ( hlm_use_nocomp .eq. itrue .and. cpatch%nocomp_pft_label .eq. ft) then + this%hvars(ih_nocomp_pftpatchfraction_si_pft)%r82d(io_si,ft) = & + this%hvars(ih_nocomp_pftpatchfraction_si_pft)%r82d(io_si,ft) + cpatch%area * AREA_INV - ! fractional area burnt [frac/day] -> [frac/sec] - hio_area_burnt_si_age(io_si,cpatch%age_class) = hio_area_burnt_si_age(io_si,cpatch%age_class) + & - cpatch%frac_burnt * cpatch%area * AREA_INV / sec_per_day + this%hvars(ih_nocomp_pftnpatches_si_pft)%r82d(io_si,ft) = & + this%hvars(ih_nocomp_pftnpatches_si_pft)%r82d(io_si,ft) + 1._r8 - ! hio_fire_rate_of_spread_front_si_age(io_si, cpatch%age_class) = hio_fire_rate_of_spread_si_age(io_si, cpatch%age_class) + & - ! cpatch%ros_front * cpatch*frac_burnt * cpatch%area * AREA_INV + this%hvars(ih_nocomp_pftburnedarea_si_pft)%r82d(io_si,ft) = & + this%hvars(ih_nocomp_pftburnedarea_si_pft)%r82d(io_si,ft) + & + cpatch%frac_burnt * cpatch%area * AREA_INV / sec_per_day + endif - ! Fire intensity weighted by burned fraction [kJ/m/s] -> [J/m/s] - hio_fire_intensity_si_age(io_si, cpatch%age_class) = hio_fire_intensity_si_age(io_si, cpatch%age_class) + & - cpatch%FI * cpatch%frac_burnt * cpatch%area * AREA_INV * J_per_kJ + end do - ! Fuel sum [kg/m2] - hio_fire_sum_fuel_si_age(io_si, cpatch%age_class) = hio_fire_sum_fuel_si_age(io_si, cpatch%age_class) + & - cpatch%sum_fuel * cpatch%area * AREA_INV + ! fractional area burnt [frac/day] -> [frac/sec] + hio_area_burnt_si_age(io_si,cpatch%age_class) = hio_area_burnt_si_age(io_si,cpatch%age_class) + & + cpatch%frac_burnt * cpatch%area * AREA_INV / sec_per_day - + ! hio_fire_rate_of_spread_front_si_age(io_si, cpatch%age_class) = hio_fire_rate_of_spread_si_age(io_si, cpatch%age_class) + & + ! cpatch%ros_front * cpatch*frac_burnt * cpatch%area * AREA_INV - ! loop through cohorts on patch - ccohort => cpatch%shortest - cohortloop: do while(associated(ccohort)) - - ft = ccohort%pft - - ! get indices for size class x pft and cohort age x pft - ! size class is the fastest changing dimension - call sizetype_class_index(ccohort%dbh, ccohort%pft, & - ccohort%size_class, ccohort%size_by_pft_class) - ! cohort age is the fastest changing dimension - call coagetype_class_index(ccohort%coage, ccohort%pft, & - ccohort%coage_class, ccohort%coage_by_pft_class) - - n_perm2 = ccohort%n * AREA_INV - - hio_canopy_area_si_age(io_si,cpatch%age_class) = hio_canopy_area_si_age(io_si,cpatch%age_class) & - + ccohort%c_area * AREA_INV - - ! calculate leaf height distribution, assuming leaf area is evenly distributed thru crown depth - call CrownDepth(ccohort%height,ft,crown_depth) - height_bin_max = get_height_index(ccohort%height) - height_bin_min = get_height_index(ccohort%height - crown_depth) - do i_heightbin = height_bin_min, height_bin_max - binbottom = ED_val_history_height_bin_edges(i_heightbin) - if (i_heightbin .eq. nlevheight) then - bintop = reallytalltrees - else - bintop = ED_val_history_height_bin_edges(i_heightbin+1) - endif - ! what fraction of a cohort's crown is in this height bin? - frac_canopy_in_bin = (min(bintop,ccohort%height) - & - max(binbottom,ccohort%height-crown_depth)) / & - (crown_depth) - - hio_leaf_height_dist_si_height(io_si,i_heightbin) = & - hio_leaf_height_dist_si_height(io_si,i_heightbin) + & - ccohort%c_area * AREA_INV * ccohort%treelai * frac_canopy_in_bin - - ! if ( ( ccohort%c_area * AREA_INV * ccohort%treelai * frac_canopy_in_bin) .lt. 0._r8) then - ! write(fates_log(),*) ' negative hio_leaf_height_dist_si_height:' - ! write(fates_log(),*) ' c_area, treelai, frac_canopy_in_bin:', ccohort%c_area, ccohort%treelai, frac_canopy_in_bin - ! endif - end do + ! Fire intensity weighted by burned fraction [kJ/m/s] -> [J/m/s] + hio_fire_intensity_si_age(io_si, cpatch%age_class) = hio_fire_intensity_si_age(io_si, cpatch%age_class) + & + cpatch%FI * cpatch%frac_burnt * cpatch%area * AREA_INV * J_per_kJ - if (ccohort%canopy_layer .eq. 1) then - ! calculate the area of canopy that is within each height bin - hio_canopy_height_dist_si_height(io_si,height_bin_max) = & - hio_canopy_height_dist_si_height(io_si,height_bin_max) + ccohort%c_area * AREA_INV - endif + ! Fuel sum [kg/m2] + hio_fire_sum_fuel_si_age(io_si, cpatch%age_class) = hio_fire_sum_fuel_si_age(io_si, cpatch%age_class) + & + cpatch%sum_fuel * cpatch%area * AREA_INV - call set_root_fraction(sites(s)%rootfrac_scr, ccohort%pft, sites(s)%zi_soil, & - bc_in(s)%max_rooting_depth_index_col ) - - ! Update biomass components - ! Mass pools [kg] - elloop: do el = 1, num_elements - - sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) - struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) - leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) - fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) - store_m = ccohort%prt%GetState(store_organ, element_list(el)) - repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) - alive_m = leaf_m + fnrt_m + sapw_m - total_m = alive_m + store_m + struct_m - - i_scpf = ccohort%size_by_pft_class - - - ! Plant multi-element states and fluxes - ! Zero states, and set the fluxes - if( element_list(el).eq.carbon12_element )then - - ! Determine the root carbon biomass in kg/m3 - ! [kg/m3] = [kg/plant] * [plant/ha] / [m3/ha] * [fraction] / [m] - - do ilyr = 1,sites(s)%nlevsoil - this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) = this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) + & - fnrt_m * ccohort%n / area * sites(s)%rootfrac_scr(ilyr) / sites(s)%dz_soil(ilyr) - end do - - ! Update PFT partitioned biomass components - hio_leafbiomass_si_pft(io_si,ft) = hio_leafbiomass_si_pft(io_si,ft) + & - (ccohort%n * AREA_INV) * leaf_m - - hio_storebiomass_si_pft(io_si,ft) = hio_storebiomass_si_pft(io_si,ft) + & - (ccohort%n * AREA_INV) * store_m - - hio_nindivs_si_pft(io_si,ft) = hio_nindivs_si_pft(io_si,ft) + & - ccohort%n * AREA_INV - - if ( cpatch%land_use_label .eq. secondaryland ) then - hio_nindivs_sec_si_pft(io_si,ft) = hio_nindivs_sec_si_pft(io_si,ft) + & - ccohort%n * AREA_INV - hio_biomass_sec_si_pft(io_si, ft) = hio_biomass_sec_si_pft(io_si, ft) + & - (ccohort%n * AREA_INV) * total_m - end if - hio_biomass_si_pft(io_si, ft) = hio_biomass_si_pft(io_si, ft) + & - (ccohort%n * AREA_INV) * total_m - ! update total biomass per age bin - hio_biomass_si_age(io_si,cpatch%age_class) = hio_biomass_si_age(io_si,cpatch%age_class) & - + total_m * ccohort%n * AREA_INV + ! loop through cohorts on patch + ccohort => cpatch%shortest + cohortloop: do while(associated(ccohort)) - if (ccohort%canopy_layer .eq. 1) then - storec_canopy_scpf(i_scpf) = & - storec_canopy_scpf(i_scpf) + ccohort%n * store_m - this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) + & - ccohort%n * store_max - else - storec_understory_scpf(i_scpf) = & - storec_understory_scpf(i_scpf) + ccohort%n * store_m - this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) + & - ccohort%n * store_max - end if + ft = ccohort%pft - - elseif(element_list(el).eq.nitrogen_element)then + ! get indices for size class x pft and cohort age x pft + ! size class is the fastest changing dimension + call sizetype_class_index(ccohort%dbh, ccohort%pft, & + ccohort%size_class, ccohort%size_by_pft_class) + ! cohort age is the fastest changing dimension + call coagetype_class_index(ccohort%coage, ccohort%pft, & + ccohort%coage_class, ccohort%coage_by_pft_class) - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) + n_perm2 = ccohort%n * AREA_INV - if (ccohort%canopy_layer .eq. 1) then - storen_canopy_scpf(i_scpf) = & - storen_canopy_scpf(i_scpf) + ccohort%n * store_m - this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) + & - ccohort%n * store_max - else - storen_understory_scpf(i_scpf) = & - storen_understory_scpf(i_scpf) + ccohort%n * store_m - this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) + & - ccohort%n * store_max - end if - - elseif(element_list(el).eq.phosphorus_element) then + hio_canopy_area_si_age(io_si,cpatch%age_class) = hio_canopy_area_si_age(io_si,cpatch%age_class) & + + ccohort%c_area * AREA_INV + + ! calculate leaf height distribution, assuming leaf area is evenly distributed thru crown depth + call CrownDepth(ccohort%height,ft,crown_depth) + height_bin_max = get_height_index(ccohort%height) + height_bin_min = get_height_index(ccohort%height - crown_depth) + do i_heightbin = height_bin_min, height_bin_max + binbottom = ED_val_history_height_bin_edges(i_heightbin) + if (i_heightbin .eq. nlevheight) then + bintop = reallytalltrees + else + bintop = ED_val_history_height_bin_edges(i_heightbin+1) + endif + ! what fraction of a cohort's crown is in this height bin? + frac_canopy_in_bin = (min(bintop,ccohort%height) - & + max(binbottom,ccohort%height-crown_depth)) / & + (crown_depth) + + hio_leaf_height_dist_si_height(io_si,i_heightbin) = & + hio_leaf_height_dist_si_height(io_si,i_heightbin) + & + ccohort%c_area * AREA_INV * ccohort%treelai * frac_canopy_in_bin + + ! if ( ( ccohort%c_area * AREA_INV * ccohort%treelai * frac_canopy_in_bin) .lt. 0._r8) then + ! write(fates_log(),*) ' negative hio_leaf_height_dist_si_height:' + ! write(fates_log(),*) ' c_area, treelai, frac_canopy_in_bin:', ccohort%c_area, ccohort%treelai, frac_canopy_in_bin + ! endif + end do + + if (ccohort%canopy_layer .eq. 1) then + ! calculate the area of canopy that is within each height bin + hio_canopy_height_dist_si_height(io_si,height_bin_max) = & + hio_canopy_height_dist_si_height(io_si,height_bin_max) + ccohort%c_area * AREA_INV + endif + + call set_root_fraction(sites(s)%rootfrac_scr, ccohort%pft, sites(s)%zi_soil, & + bc_in(s)%max_rooting_depth_index_col ) + + ! Update biomass components + ! Mass pools [kg] + elloop: do el = 1, num_elements + + sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) + struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) + fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) + store_m = ccohort%prt%GetState(store_organ, element_list(el)) + repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) + alive_m = leaf_m + fnrt_m + sapw_m + total_m = alive_m + store_m + struct_m + + i_scpf = ccohort%size_by_pft_class + + + ! Plant multi-element states and fluxes + ! Zero states, and set the fluxes + if( element_list(el).eq.carbon12_element )then + + ! Determine the root carbon biomass in kg/m3 + ! [kg/m3] = [kg/plant] * [plant/ha] / [m3/ha] * [fraction] / [m] + + do ilyr = 1,sites(s)%nlevsoil + this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) = this%hvars(ih_fnrtc_sl)%r82d(io_si,ilyr) + & + fnrt_m * ccohort%n / area * sites(s)%rootfrac_scr(ilyr) / sites(s)%dz_soil(ilyr) + end do + + ! Update PFT partitioned biomass components + hio_leafbiomass_si_pft(io_si,ft) = hio_leafbiomass_si_pft(io_si,ft) + & + (ccohort%n * AREA_INV) * leaf_m + + hio_storebiomass_si_pft(io_si,ft) = hio_storebiomass_si_pft(io_si,ft) + & + (ccohort%n * AREA_INV) * store_m + + hio_nindivs_si_pft(io_si,ft) = hio_nindivs_si_pft(io_si,ft) + & + ccohort%n * AREA_INV + + if ( cpatch%land_use_label .eq. secondaryland ) then + hio_nindivs_sec_si_pft(io_si,ft) = hio_nindivs_sec_si_pft(io_si,ft) + & + ccohort%n * AREA_INV + hio_biomass_sec_si_pft(io_si, ft) = hio_biomass_sec_si_pft(io_si, ft) + & + (ccohort%n * AREA_INV) * total_m + end if + + hio_biomass_si_pft(io_si, ft) = hio_biomass_si_pft(io_si, ft) + & + (ccohort%n * AREA_INV) * total_m + + ! update total biomass per age bin + hio_biomass_si_age(io_si,cpatch%age_class) = hio_biomass_si_age(io_si,cpatch%age_class) & + + total_m * ccohort%n * AREA_INV + + if (ccohort%canopy_layer .eq. 1) then + storec_canopy_scpf(i_scpf) = & + storec_canopy_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + else + storec_understory_scpf(i_scpf) = & + storec_understory_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + end if + + + elseif(element_list(el).eq.nitrogen_element)then + + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) + + if (ccohort%canopy_layer .eq. 1) then + storen_canopy_scpf(i_scpf) = & + storen_canopy_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + else + storen_understory_scpf(i_scpf) = & + storen_understory_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + end if + + elseif(element_list(el).eq.phosphorus_element) then + + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) + + if (ccohort%canopy_layer .eq. 1) then + storep_canopy_scpf(i_scpf) = & + storep_canopy_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + else + storep_understory_scpf(i_scpf) = & + storep_understory_scpf(i_scpf) + ccohort%n * store_m + this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) + & + ccohort%n * store_max + end if + + + end if + end do elloop + + ! Update PFT crown area + hio_crownarea_si_pft(io_si, ft) = hio_crownarea_si_pft(io_si, ft) + & + ccohort%c_area * AREA_INV + + if (ccohort%canopy_layer .eq. 1) then + ! Update PFT canopy crown area + hio_canopycrownarea_si_pft(io_si, ft) = hio_canopycrownarea_si_pft(io_si, ft) + & + ccohort%c_area * AREA_INV + end if + + ! Site by Size-Class x PFT (SCPF) + ! ------------------------------------------------------------------------ + + ! Flux Variables (cohorts must had experienced a day before any of these values + ! have any meaning, otherwise they are just inialization values + notnew: if( .not.(ccohort%isnew) ) then + + ! update pft-resolved NPP and GPP fluxes + hio_gpp_si_pft(io_si, ft) = hio_gpp_si_pft(io_si, ft) + & + ccohort%gpp_acc_hold * n_perm2 / days_per_year / sec_per_day + + hio_npp_si_pft(io_si, ft) = hio_npp_si_pft(io_si, ft) + & + ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + + if ( cpatch%land_use_label .eq. secondaryland ) then + hio_gpp_sec_si_pft(io_si, ft) = hio_gpp_sec_si_pft(io_si, ft) + & + ccohort%gpp_acc_hold * n_perm2 / days_per_year / sec_per_day + hio_npp_sec_si_pft(io_si, ft) = hio_npp_sec_si_pft(io_si, ft) + & + ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + end if + + ! Turnover pools [kgC/day] * [day/yr] = [kgC/yr] + sapw_m_turnover = ccohort%prt%GetTurnover(sapw_organ, carbon12_element) * days_per_year + store_m_turnover = ccohort%prt%GetTurnover(store_organ, carbon12_element) * days_per_year + leaf_m_turnover = ccohort%prt%GetTurnover(leaf_organ, carbon12_element) * days_per_year + fnrt_m_turnover = ccohort%prt%GetTurnover(fnrt_organ, carbon12_element) * days_per_year + struct_m_turnover = ccohort%prt%GetTurnover(struct_organ, carbon12_element) * days_per_year + + ! Net change from allocation and transport [kgC/day] * [day/yr] = [kgC/yr] + sapw_m_net_alloc = ccohort%prt%GetNetAlloc(sapw_organ, carbon12_element) * days_per_year + store_m_net_alloc = ccohort%prt%GetNetAlloc(store_organ, carbon12_element) * days_per_year + leaf_m_net_alloc = ccohort%prt%GetNetAlloc(leaf_organ, carbon12_element) * days_per_year + fnrt_m_net_alloc = ccohort%prt%GetNetAlloc(fnrt_organ, carbon12_element) * days_per_year + struct_m_net_alloc = ccohort%prt%GetNetAlloc(struct_organ, carbon12_element) * days_per_year + repro_m_net_alloc = ccohort%prt%GetNetAlloc(repro_organ, carbon12_element) * days_per_year + + + + associate( scpf => ccohort%size_by_pft_class, & + scls => ccohort%size_class, & + cacls => ccohort%coage_class, & + capf => ccohort%coage_by_pft_class, & + cdam => ccohort%crowndamage) + + gpp_cached = (hio_gpp_si_scpf(io_si,scpf)) * & + days_per_year * sec_per_day + + ! [kgC/m2/s] + hio_gpp_si_scpf(io_si,scpf) = hio_gpp_si_scpf(io_si,scpf) + & + n_perm2*ccohort%gpp_acc_hold / days_per_year / sec_per_day + hio_npp_totl_si_scpf(io_si,scpf) = hio_npp_totl_si_scpf(io_si,scpf) + & + ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + + hio_npp_leaf_si_scpf(io_si,scpf) = hio_npp_leaf_si_scpf(io_si,scpf) + & + leaf_m_net_alloc*n_perm2 / days_per_year / sec_per_day + hio_npp_fnrt_si_scpf(io_si,scpf) = hio_npp_fnrt_si_scpf(io_si,scpf) + & + fnrt_m_net_alloc*n_perm2 / days_per_year / sec_per_day + hio_npp_bgsw_si_scpf(io_si,scpf) = hio_npp_bgsw_si_scpf(io_si,scpf) + & + sapw_m_net_alloc*n_perm2*(1._r8-prt_params%allom_agb_frac(ccohort%pft)) / & + days_per_year / sec_per_day + hio_npp_agsw_si_scpf(io_si,scpf) = hio_npp_agsw_si_scpf(io_si,scpf) + & + sapw_m_net_alloc*n_perm2*prt_params%allom_agb_frac(ccohort%pft) / & + days_per_year / sec_per_day + hio_npp_bgdw_si_scpf(io_si,scpf) = hio_npp_bgdw_si_scpf(io_si,scpf) + & + struct_m_net_alloc*n_perm2*(1._r8-prt_params%allom_agb_frac(ccohort%pft)) / & + days_per_year / sec_per_day + hio_npp_agdw_si_scpf(io_si,scpf) = hio_npp_agdw_si_scpf(io_si,scpf) + & + struct_m_net_alloc*n_perm2*prt_params%allom_agb_frac(ccohort%pft) / & + days_per_year / sec_per_day + hio_npp_seed_si_scpf(io_si,scpf) = hio_npp_seed_si_scpf(io_si,scpf) + & + repro_m_net_alloc*n_perm2 / days_per_year / sec_per_day + hio_npp_stor_si_scpf(io_si,scpf) = hio_npp_stor_si_scpf(io_si,scpf) + & + store_m_net_alloc*n_perm2 / days_per_year / sec_per_day + + + ! Woody State Variables (basal area growth increment) + if ( prt_params%woody(ft) == itrue) then + + ! basal area [m2/m2] + hio_ba_si_scpf(io_si,scpf) = hio_ba_si_scpf(io_si,scpf) + & + 0.25_r8*pi_const*((ccohort%dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha + + ! also by size class only + hio_ba_si_scls(io_si,scls) = hio_ba_si_scls(io_si,scls) + & + 0.25_r8*pi_const*((ccohort%dbh/100.0_r8)**2.0_r8)* & + ccohort%n / m2_per_ha + + ! growth increment + hio_ddbh_si_scpf(io_si,scpf) = hio_ddbh_si_scpf(io_si,scpf) + & + ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm + + end if + + ! mortality sums [#/m2] + hio_m1_si_scpf(io_si,scpf) = hio_m1_si_scpf(io_si,scpf) + & + ccohort%bmort*ccohort%n / m2_per_ha + hio_m2_si_scpf(io_si,scpf) = hio_m2_si_scpf(io_si,scpf) + & + ccohort%hmort*ccohort%n / m2_per_ha + hio_m3_si_scpf(io_si,scpf) = hio_m3_si_scpf(io_si,scpf) + & + ccohort%cmort*ccohort%n / m2_per_ha + + hio_m7_si_scpf(io_si,scpf) = hio_m7_si_scpf(io_si,scpf) + & + (ccohort%lmort_direct + ccohort%lmort_collateral + & + ccohort%lmort_infra) * ccohort%n / m2_per_ha + + hio_m8_si_scpf(io_si,scpf) = hio_m8_si_scpf(io_si,scpf) + & + ccohort%frmort*ccohort%n / m2_per_ha + hio_m9_si_scpf(io_si,scpf) = hio_m9_si_scpf(io_si,scpf) + & + ccohort%smort*ccohort%n / m2_per_ha + + if (hlm_use_cohort_age_tracking .eq.itrue) then + hio_m10_si_scpf(io_si,scpf) = hio_m10_si_scpf(io_si,scpf) + & + ccohort%asmort*ccohort%n / m2_per_ha + hio_m10_si_capf(io_si,capf) = hio_m10_si_capf(io_si,capf) + & + ccohort%asmort*ccohort%n / m2_per_ha + hio_m10_si_scls(io_si,scls) = hio_m10_si_scls(io_si,scls) + & + ccohort%asmort*ccohort%n / m2_per_ha + hio_m10_si_cacls(io_si,cacls) = hio_m10_si_cacls(io_si,cacls)+ & + ccohort%asmort*ccohort%n / m2_per_ha + end if + + + + + hio_m1_si_scls(io_si,scls) = hio_m1_si_scls(io_si,scls) + ccohort%bmort*ccohort%n / m2_per_ha + hio_m2_si_scls(io_si,scls) = hio_m2_si_scls(io_si,scls) + ccohort%hmort*ccohort%n / m2_per_ha + hio_m3_si_scls(io_si,scls) = hio_m3_si_scls(io_si,scls) + ccohort%cmort*ccohort%n / m2_per_ha + hio_m7_si_scls(io_si,scls) = hio_m7_si_scls(io_si,scls) + & + (ccohort%lmort_direct+ccohort%lmort_collateral+ccohort%lmort_infra) * ccohort%n / m2_per_ha + hio_m8_si_scls(io_si,scls) = hio_m8_si_scls(io_si,scls) + & + ccohort%frmort*ccohort%n / m2_per_ha + hio_m9_si_scls(io_si,scls) = hio_m9_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha + + ! Examine secondary forest mortality and mortality rates + if(cpatch%land_use_label .eq. secondaryland) then + if (hlm_use_cohort_age_tracking .eq.itrue) then + hio_m10_sec_si_scls(io_si,scls) = hio_m10_sec_si_scls(io_si,scls) + & + ccohort%asmort*ccohort%n / m2_per_ha + end if + + hio_m1_sec_si_scls(io_si,scls) = hio_m1_sec_si_scls(io_si,scls) + ccohort%bmort*ccohort%n / m2_per_ha + hio_m2_sec_si_scls(io_si,scls) = hio_m2_sec_si_scls(io_si,scls) + ccohort%hmort*ccohort%n / m2_per_ha + hio_m3_sec_si_scls(io_si,scls) = hio_m3_sec_si_scls(io_si,scls) + ccohort%cmort*ccohort%n / m2_per_ha + hio_m7_sec_si_scls(io_si,scls) = hio_m7_sec_si_scls(io_si,scls) + & + (ccohort%lmort_direct+ccohort%lmort_collateral+ccohort%lmort_infra) * ccohort%n / m2_per_ha + hio_m8_sec_si_scls(io_si,scls) = hio_m8_sec_si_scls(io_si,scls) + & + ccohort%frmort*ccohort%n / m2_per_ha + hio_m9_sec_si_scls(io_si,scls) = hio_m9_sec_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha + end if + + !C13 discrimination + if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then + hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & + (ccohort%c13disc_acc * ccohort%gpp_acc_hold)) / (gpp_cached + ccohort%gpp_acc_hold) + else + hio_c13disc_si_scpf(io_si,scpf) = 0.0_r8 + endif + + ! number density [/m2] + hio_nplant_si_scpf(io_si,scpf) = hio_nplant_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha + + ! number density along the cohort age dimension + if (hlm_use_cohort_age_tracking .eq.itrue) then + hio_nplant_si_capf(io_si,capf) = hio_nplant_si_capf(io_si,capf) + ccohort%n / m2_per_ha + hio_nplant_si_cacls(io_si,cacls) = hio_nplant_si_cacls(io_si,cacls)+ccohort%n / m2_per_ha + end if + + ! damage variables - cohort level + if(hlm_use_tree_damage .eq. itrue) then + + icdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) + + this%hvars(ih_mortality_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_si_cdpf)%r82d(io_si,icdpf) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + + ! crown damage by size by pft + this%hvars(ih_nplant_si_cdpf)%r82d(io_si, icdpf) = & + this%hvars(ih_nplant_si_cdpf)%r82d(io_si, icdpf) + ccohort%n / m2_per_ha + this%hvars(ih_m3_si_cdpf)%r82d(io_si, icdpf) = & + this%hvars(ih_m3_si_cdpf)%r82d(io_si, icdpf) + & + ccohort%cmort * ccohort%n / m2_per_ha + + ! mortality + this%hvars(ih_m11_si_scpf)%r82d(io_si,scpf) = & + this%hvars(ih_m11_si_scpf)%r82d(io_si,scpf) + & + ccohort%dgmort*ccohort%n / m2_per_ha + this%hvars(ih_m11_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m11_si_cdpf)%r82d(io_si,icdpf) + & + ccohort%dgmort*ccohort%n / m2_per_ha + + this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,icdpf) + & + ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm + + end if + + ! Carbon only metrics + sapw_m = ccohort%prt%GetState(sapw_organ, carbon12_element) + struct_m = ccohort%prt%GetState(struct_organ, carbon12_element) + leaf_m = ccohort%prt%GetState(leaf_organ, carbon12_element) + fnrt_m = ccohort%prt%GetState(fnrt_organ, carbon12_element) + store_m = ccohort%prt%GetState(store_organ, carbon12_element) + repro_m = ccohort%prt%GetState(repro_organ, carbon12_element) + alive_m = leaf_m + fnrt_m + sapw_m + total_m = alive_m + store_m + struct_m + + hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & + total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & + ccohort%n * ha_per_m2 + + + hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) + & + ccohort%hmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + + hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) + & + ccohort%cmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + + ! Aboveground mortality + hio_abg_mortality_cflux_si_scpf(io_si,scpf) = hio_abg_mortality_cflux_si_scpf(io_si,scpf) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort) * & + ( (sapw_m + struct_m + store_m ) * prt_params%allom_agb_frac(ccohort%pft) + & + leaf_m ) * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ( (sapw_m + struct_m + store_m ) * prt_params%allom_agb_frac(ccohort%pft) + & + leaf_m ) * ccohort%n * ha_per_m2 + + ! Aboveground woody productivity + hio_abg_productivity_cflux_si_scpf(io_si,scpf) = hio_abg_productivity_cflux_si_scpf(io_si,scpf) + & + ( (sapw_m_net_alloc + struct_m_net_alloc + store_m_net_alloc) * prt_params%allom_agb_frac(ccohort%pft) + & + leaf_m_net_alloc ) * n_perm2 / & + days_per_year / sec_per_day + + + ! number density by size and biomass + hio_agb_si_scls(io_si,scls) = hio_agb_si_scls(io_si,scls) + & + total_m * ccohort%n * prt_params%allom_agb_frac(ccohort%pft) * AREA_INV + + hio_agb_si_scpf(io_si,scpf) = hio_agb_si_scpf(io_si,scpf) + & + total_m * ccohort%n * prt_params%allom_agb_frac(ccohort%pft) * AREA_INV + + hio_biomass_si_scls(io_si,scls) = hio_biomass_si_scls(io_si,scls) + & + total_m * ccohort%n * AREA_INV - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) + ! update size-class x patch-age related quantities - if (ccohort%canopy_layer .eq. 1) then - storep_canopy_scpf(i_scpf) = & - storep_canopy_scpf(i_scpf) + ccohort%n * store_m - this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) + & - ccohort%n * store_max - else - storep_understory_scpf(i_scpf) = & - storep_understory_scpf(i_scpf) + ccohort%n * store_m - this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) + & - ccohort%n * store_max - end if - + iscag = get_sizeage_class_index(ccohort%dbh,cpatch%age) - end if - end do elloop + hio_nplant_si_scag(io_si,iscag) = hio_nplant_si_scag(io_si,iscag) + ccohort%n / m2_per_ha - ! Update PFT crown area - hio_crownarea_si_pft(io_si, ft) = hio_crownarea_si_pft(io_si, ft) + & - ccohort%c_area * AREA_INV + hio_nplant_si_scls(io_si,scls) = hio_nplant_si_scls(io_si,scls) + ccohort%n / m2_per_ha - if (ccohort%canopy_layer .eq. 1) then - ! Update PFT canopy crown area - hio_canopycrownarea_si_pft(io_si, ft) = hio_canopycrownarea_si_pft(io_si, ft) + & - ccohort%c_area * AREA_INV - end if - ! Site by Size-Class x PFT (SCPF) - ! ------------------------------------------------------------------------ + ! update size, age, and PFT - indexed quantities + iscagpft = get_sizeagepft_class_index(ccohort%dbh,cpatch%age,ccohort%pft) - ! Flux Variables (cohorts must had experienced a day before any of these values - ! have any meaning, otherwise they are just inialization values - notnew: if( .not.(ccohort%isnew) ) then + hio_nplant_si_scagpft(io_si,iscagpft) = hio_nplant_si_scagpft(io_si,iscagpft) + ccohort%n / m2_per_ha - ! update pft-resolved NPP and GPP fluxes - hio_gpp_si_pft(io_si, ft) = hio_gpp_si_pft(io_si, ft) + & - ccohort%gpp_acc_hold * n_perm2 / days_per_year / sec_per_day + ! update age and PFT - indexed quantities + iagepft = get_agepft_class_index(cpatch%age,ccohort%pft) - hio_npp_si_pft(io_si, ft) = hio_npp_si_pft(io_si, ft) + & - ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day - - if ( cpatch%land_use_label .eq. secondaryland ) then - hio_gpp_sec_si_pft(io_si, ft) = hio_gpp_sec_si_pft(io_si, ft) + & - ccohort%gpp_acc_hold * n_perm2 / days_per_year / sec_per_day - hio_npp_sec_si_pft(io_si, ft) = hio_npp_sec_si_pft(io_si, ft) + & - ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day - end if - - ! Turnover pools [kgC/day] * [day/yr] = [kgC/yr] - sapw_m_turnover = ccohort%prt%GetTurnover(sapw_organ, carbon12_element) * days_per_year - store_m_turnover = ccohort%prt%GetTurnover(store_organ, carbon12_element) * days_per_year - leaf_m_turnover = ccohort%prt%GetTurnover(leaf_organ, carbon12_element) * days_per_year - fnrt_m_turnover = ccohort%prt%GetTurnover(fnrt_organ, carbon12_element) * days_per_year - struct_m_turnover = ccohort%prt%GetTurnover(struct_organ, carbon12_element) * days_per_year - - ! Net change from allocation and transport [kgC/day] * [day/yr] = [kgC/yr] - sapw_m_net_alloc = ccohort%prt%GetNetAlloc(sapw_organ, carbon12_element) * days_per_year - store_m_net_alloc = ccohort%prt%GetNetAlloc(store_organ, carbon12_element) * days_per_year - leaf_m_net_alloc = ccohort%prt%GetNetAlloc(leaf_organ, carbon12_element) * days_per_year - fnrt_m_net_alloc = ccohort%prt%GetNetAlloc(fnrt_organ, carbon12_element) * days_per_year - struct_m_net_alloc = ccohort%prt%GetNetAlloc(struct_organ, carbon12_element) * days_per_year - repro_m_net_alloc = ccohort%prt%GetNetAlloc(repro_organ, carbon12_element) * days_per_year - - - - associate( scpf => ccohort%size_by_pft_class, & - scls => ccohort%size_class, & - cacls => ccohort%coage_class, & - capf => ccohort%coage_by_pft_class, & - cdam => ccohort%crowndamage) - - gpp_cached = (hio_gpp_si_scpf(io_si,scpf)) * & - days_per_year * sec_per_day - - ! [kgC/m2/s] - hio_gpp_si_scpf(io_si,scpf) = hio_gpp_si_scpf(io_si,scpf) + & - n_perm2*ccohort%gpp_acc_hold / days_per_year / sec_per_day - hio_npp_totl_si_scpf(io_si,scpf) = hio_npp_totl_si_scpf(io_si,scpf) + & - ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day - - hio_npp_leaf_si_scpf(io_si,scpf) = hio_npp_leaf_si_scpf(io_si,scpf) + & - leaf_m_net_alloc*n_perm2 / days_per_year / sec_per_day - hio_npp_fnrt_si_scpf(io_si,scpf) = hio_npp_fnrt_si_scpf(io_si,scpf) + & - fnrt_m_net_alloc*n_perm2 / days_per_year / sec_per_day - hio_npp_bgsw_si_scpf(io_si,scpf) = hio_npp_bgsw_si_scpf(io_si,scpf) + & - sapw_m_net_alloc*n_perm2*(1._r8-prt_params%allom_agb_frac(ccohort%pft)) / & - days_per_year / sec_per_day - hio_npp_agsw_si_scpf(io_si,scpf) = hio_npp_agsw_si_scpf(io_si,scpf) + & - sapw_m_net_alloc*n_perm2*prt_params%allom_agb_frac(ccohort%pft) / & - days_per_year / sec_per_day - hio_npp_bgdw_si_scpf(io_si,scpf) = hio_npp_bgdw_si_scpf(io_si,scpf) + & - struct_m_net_alloc*n_perm2*(1._r8-prt_params%allom_agb_frac(ccohort%pft)) / & - days_per_year / sec_per_day - hio_npp_agdw_si_scpf(io_si,scpf) = hio_npp_agdw_si_scpf(io_si,scpf) + & - struct_m_net_alloc*n_perm2*prt_params%allom_agb_frac(ccohort%pft) / & - days_per_year / sec_per_day - hio_npp_seed_si_scpf(io_si,scpf) = hio_npp_seed_si_scpf(io_si,scpf) + & - repro_m_net_alloc*n_perm2 / days_per_year / sec_per_day - hio_npp_stor_si_scpf(io_si,scpf) = hio_npp_stor_si_scpf(io_si,scpf) + & - store_m_net_alloc*n_perm2 / days_per_year / sec_per_day - - - ! Woody State Variables (basal area growth increment) - if ( prt_params%woody(ft) == itrue) then - - ! basal area [m2/m2] - hio_ba_si_scpf(io_si,scpf) = hio_ba_si_scpf(io_si,scpf) + & - 0.25_r8*pi_const*((ccohort%dbh/100.0_r8)**2.0_r8)*ccohort%n / m2_per_ha - - ! also by size class only - hio_ba_si_scls(io_si,scls) = hio_ba_si_scls(io_si,scls) + & - 0.25_r8*pi_const*((ccohort%dbh/100.0_r8)**2.0_r8)* & - ccohort%n / m2_per_ha - - ! growth increment - hio_ddbh_si_scpf(io_si,scpf) = hio_ddbh_si_scpf(io_si,scpf) + & - ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm + hio_npp_si_agepft(io_si,iagepft) = hio_npp_si_agepft(io_si,iagepft) + & + ccohort%n * ccohort%npp_acc_hold * AREA_INV / days_per_year / sec_per_day - end if + hio_biomass_si_agepft(io_si,iagepft) = hio_biomass_si_agepft(io_si,iagepft) + & + total_m * ccohort%n * AREA_INV - ! mortality sums [#/m2] - hio_m1_si_scpf(io_si,scpf) = hio_m1_si_scpf(io_si,scpf) + & - ccohort%bmort*ccohort%n / m2_per_ha - hio_m2_si_scpf(io_si,scpf) = hio_m2_si_scpf(io_si,scpf) + & - ccohort%hmort*ccohort%n / m2_per_ha - hio_m3_si_scpf(io_si,scpf) = hio_m3_si_scpf(io_si,scpf) + & - ccohort%cmort*ccohort%n / m2_per_ha - - hio_m7_si_scpf(io_si,scpf) = hio_m7_si_scpf(io_si,scpf) + & - (ccohort%lmort_direct + ccohort%lmort_collateral + & - ccohort%lmort_infra) * ccohort%n / m2_per_ha - - hio_m8_si_scpf(io_si,scpf) = hio_m8_si_scpf(io_si,scpf) + & - ccohort%frmort*ccohort%n / m2_per_ha - hio_m9_si_scpf(io_si,scpf) = hio_m9_si_scpf(io_si,scpf) + & - ccohort%smort*ccohort%n / m2_per_ha - - if (hlm_use_cohort_age_tracking .eq.itrue) then - hio_m10_si_scpf(io_si,scpf) = hio_m10_si_scpf(io_si,scpf) + & - ccohort%asmort*ccohort%n / m2_per_ha - hio_m10_si_capf(io_si,capf) = hio_m10_si_capf(io_si,capf) + & - ccohort%asmort*ccohort%n / m2_per_ha - hio_m10_si_scls(io_si,scls) = hio_m10_si_scls(io_si,scls) + & - ccohort%asmort*ccohort%n / m2_per_ha - hio_m10_si_cacls(io_si,cacls) = hio_m10_si_cacls(io_si,cacls)+ & - ccohort%asmort*ccohort%n / m2_per_ha - end if + ! update SCPF/SCLS- and canopy/subcanopy- partitioned quantities + canlayer: if (ccohort%canopy_layer .eq. 1) then + hio_nplant_canopy_si_scag(io_si,iscag) = hio_nplant_canopy_si_scag(io_si,iscag) + ccohort%n / m2_per_ha + hio_mortality_canopy_si_scag(io_si,iscag) = hio_mortality_canopy_si_scag(io_si,iscag) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + hio_ddbh_canopy_si_scag(io_si,iscag) = hio_ddbh_canopy_si_scag(io_si,iscag) + & + ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha + hio_bstor_canopy_si_scpf(io_si,scpf) = hio_bstor_canopy_si_scpf(io_si,scpf) + & + store_m * ccohort%n / m2_per_ha + hio_bleaf_canopy_si_scpf(io_si,scpf) = hio_bleaf_canopy_si_scpf(io_si,scpf) + & + leaf_m * ccohort%n / m2_per_ha + hio_lai_canopy_si_scpf(io_si,scpf) = hio_lai_canopy_si_scpf(io_si,scpf) + & + ccohort%treelai*ccohort%c_area * AREA_INV + + !hio_mortality_canopy_si_scpf(io_si,scpf) = hio_mortality_canopy_si_scpf(io_si,scpf)+ & + ! (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ! ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n + + hio_mortality_canopy_si_scpf(io_si,scpf) = hio_mortality_canopy_si_scpf(io_si,scpf)+ & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + + hio_m3_mortality_canopy_si_scpf(io_si,scpf) = hio_m3_mortality_canopy_si_scpf(io_si,scpf) + & + ccohort%cmort * ccohort%n / m2_per_ha + + hio_nplant_canopy_si_scpf(io_si,scpf) = hio_nplant_canopy_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha + hio_nplant_canopy_si_scls(io_si,scls) = hio_nplant_canopy_si_scls(io_si,scls) + ccohort%n / m2_per_ha + hio_lai_canopy_si_scls(io_si,scls) = hio_lai_canopy_si_scls(io_si,scls) + & + ccohort%treelai*ccohort%c_area * AREA_INV + hio_sai_canopy_si_scls(io_si,scls) = hio_sai_canopy_si_scls(io_si,scls) + & + ccohort%treesai*ccohort%c_area * AREA_INV + hio_trimming_canopy_si_scls(io_si,scls) = hio_trimming_canopy_si_scls(io_si,scls) + & + ccohort%n * ccohort%canopy_trim / m2_per_ha + hio_crown_area_canopy_si_scls(io_si,scls) = hio_crown_area_canopy_si_scls(io_si,scls) + & + ccohort%c_area / m2_per_ha + hio_gpp_canopy_si_scpf(io_si,scpf) = hio_gpp_canopy_si_scpf(io_si,scpf) + & + n_perm2*ccohort%gpp_acc_hold / days_per_year / sec_per_day + hio_ar_canopy_si_scpf(io_si,scpf) = hio_ar_canopy_si_scpf(io_si,scpf) + & + n_perm2*ccohort%resp_acc_hold / days_per_year / sec_per_day + ! growth increment + hio_ddbh_canopy_si_scpf(io_si,scpf) = hio_ddbh_canopy_si_scpf(io_si,scpf) + & + ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha + hio_ddbh_canopy_si_scls(io_si,scls) = hio_ddbh_canopy_si_scls(io_si,scls) + & + ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha + + ! sum of all mortality + hio_mortality_canopy_si_scls(io_si,scls) = hio_mortality_canopy_si_scls(io_si,scls) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + + hio_m3_mortality_canopy_si_scls(io_si,scls) = hio_m3_mortality_canopy_si_scls(io_si,scls) + & + ccohort%cmort * ccohort%n / m2_per_ha + + hio_carbon_balance_canopy_si_scls(io_si,scls) = hio_carbon_balance_canopy_si_scls(io_si,scls) + & + ccohort%n * ccohort%npp_acc_hold / m2_per_ha / days_per_year / sec_per_day + + ! damage variables - canopy + if(hlm_use_tree_damage .eq. itrue) then + + ! carbon starvation mortality in the canopy by size x damage x pft + this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,icdpf)+& + ccohort%cmort * ccohort%n / m2_per_ha + + ! damage mortality in the canopy by size x damage x pft + this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,icdpf)+& + ccohort%dgmort * ccohort%n / m2_per_ha + + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf)+ & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + ccohort%smort + & + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + + ! nplants by damage + this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,icdpf) + & + ccohort%n / m2_per_ha + + ! growth rate by damage x size x pft in the canopy + this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,icdpf) + & + ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm + + end if ! end if damage + + + hio_leaf_md_canopy_si_scls(io_si,scls) = hio_leaf_md_canopy_si_scls(io_si,scls) + & + leaf_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_root_md_canopy_si_scls(io_si,scls) = hio_root_md_canopy_si_scls(io_si,scls) + & + fnrt_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_bsw_md_canopy_si_scls(io_si,scls) = hio_bsw_md_canopy_si_scls(io_si,scls) + & + sapw_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_bstore_md_canopy_si_scls(io_si,scls) = hio_bstore_md_canopy_si_scls(io_si,scls) + & + store_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day + 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 + + 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 + hio_npp_fnrt_canopy_si_scls(io_si,scls) = hio_npp_fnrt_canopy_si_scls(io_si,scls) + & + fnrt_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_npp_sapw_canopy_si_scls(io_si,scls) = hio_npp_sapw_canopy_si_scls(io_si,scls) + & + sapw_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_npp_dead_canopy_si_scls(io_si,scls) = hio_npp_dead_canopy_si_scls(io_si,scls) + & + struct_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_npp_seed_canopy_si_scls(io_si,scls) = hio_npp_seed_canopy_si_scls(io_si,scls) + & + repro_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_npp_stor_canopy_si_scls(io_si,scls) = hio_npp_stor_canopy_si_scls(io_si,scls) + & + store_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + + hio_yesterdaycanopylevel_canopy_si_scls(io_si,scls) = & + hio_yesterdaycanopylevel_canopy_si_scls(io_si,scls) + & + ccohort%canopy_layer_yesterday * ccohort%n / m2_per_ha + + + else canlayer + hio_nplant_understory_si_scag(io_si,iscag) = hio_nplant_understory_si_scag(io_si,iscag) + ccohort%n / m2_per_ha + hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + hio_ddbh_understory_si_scag(io_si,iscag) = hio_ddbh_understory_si_scag(io_si,iscag) + & + ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha + hio_bstor_understory_si_scpf(io_si,scpf) = hio_bstor_understory_si_scpf(io_si,scpf) + & + store_m * ccohort%n / m2_per_ha + hio_bleaf_understory_si_scpf(io_si,scpf) = hio_bleaf_understory_si_scpf(io_si,scpf) + & + leaf_m * ccohort%n / m2_per_ha + + hio_lai_understory_si_scpf(io_si,scpf) = hio_lai_understory_si_scpf(io_si,scpf) + & + ccohort%treelai*ccohort%c_area * AREA_INV + + !hio_mortality_understory_si_scpf(io_si,scpf) = hio_mortality_understory_si_scpf(io_si,scpf)+ & + ! (ccohort%bmort + ccohort%hmort + ccohort%cmort + + ! ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n + + hio_mortality_understory_si_scpf(io_si,scpf) = hio_mortality_understory_si_scpf(io_si,scpf)+ & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + + hio_m3_mortality_understory_si_scpf(io_si,scpf) = hio_m3_mortality_understory_si_scpf(io_si,scpf) + & + ccohort%cmort * ccohort%n / m2_per_ha + + if(cpatch%land_use_label .eq. secondaryland) then + hio_mortality_canopy_secondary_si_scls(io_si,scls) = hio_mortality_canopy_secondary_si_scls(io_si,scls) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + end if + + hio_nplant_understory_si_scpf(io_si,scpf) = hio_nplant_understory_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha + hio_nplant_understory_si_scls(io_si,scls) = hio_nplant_understory_si_scls(io_si,scls) + ccohort%n / m2_per_ha + hio_lai_understory_si_scls(io_si,scls) = hio_lai_understory_si_scls(io_si,scls) + & + ccohort%treelai*ccohort%c_area * AREA_INV + hio_sai_understory_si_scls(io_si,scls) = hio_sai_understory_si_scls(io_si,scls) + & + ccohort%treelai*ccohort%c_area * AREA_INV + hio_trimming_understory_si_scls(io_si,scls) = hio_trimming_understory_si_scls(io_si,scls) + & + ccohort%n * ccohort%canopy_trim / m2_per_ha + hio_crown_area_understory_si_scls(io_si,scls) = hio_crown_area_understory_si_scls(io_si,scls) + & + ccohort%c_area / m2_per_ha + hio_gpp_understory_si_scpf(io_si,scpf) = hio_gpp_understory_si_scpf(io_si,scpf) + & + n_perm2*ccohort%gpp_acc_hold / days_per_year / sec_per_day + hio_ar_understory_si_scpf(io_si,scpf) = hio_ar_understory_si_scpf(io_si,scpf) + & + n_perm2*ccohort%resp_acc_hold / days_per_year / sec_per_day + + ! growth increment + hio_ddbh_understory_si_scpf(io_si,scpf) = hio_ddbh_understory_si_scpf(io_si,scpf) + & + ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha + hio_ddbh_understory_si_scls(io_si,scls) = hio_ddbh_understory_si_scls(io_si,scls) + & + ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha + + ! sum of all mortality + hio_mortality_understory_si_scls(io_si,scls) = hio_mortality_understory_si_scls(io_si,scls) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + & + ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + + hio_m3_mortality_understory_si_scls(io_si,scls) = hio_m3_mortality_understory_si_scls(io_si,scls) + & + ccohort%cmort * ccohort%n / m2_per_ha + + + + hio_carbon_balance_understory_si_scls(io_si,scls) = hio_carbon_balance_understory_si_scls(io_si,scls) + & + ccohort%npp_acc_hold * ccohort%n / m2_per_ha / days_per_year / sec_per_day + + ! damage variables - understory + if(hlm_use_tree_damage .eq. itrue) then + + ! carbon mortality in the understory by damage x size x pft + this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & + ccohort%cmort * ccohort%n / m2_per_ha + + ! damage in the understory by damage x size x pft + this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & + ccohort%dgmort * ccohort%n / m2_per_ha + + ! total mortality of understory cohorts by damage x size x pft + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & + (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & + (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & + ccohort%n * sec_per_day * days_per_year / m2_per_ha + + this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,icdpf) + & + ccohort%n / m2_per_ha + + ! growth rate by size x damage x pft - understory + this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,icdpf) + & + ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm + + end if ! end if damage + + hio_leaf_md_understory_si_scls(io_si,scls) = hio_leaf_md_understory_si_scls(io_si,scls) + & + leaf_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_root_md_understory_si_scls(io_si,scls) = hio_root_md_understory_si_scls(io_si,scls) + & + fnrt_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_bsw_md_understory_si_scls(io_si,scls) = hio_bsw_md_understory_si_scls(io_si,scls) + & + sapw_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_bstore_md_understory_si_scls(io_si,scls) = hio_bstore_md_understory_si_scls(io_si,scls) + & + store_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day + 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 + + 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 + hio_npp_fnrt_understory_si_scls(io_si,scls) = hio_npp_fnrt_understory_si_scls(io_si,scls) + & + fnrt_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_npp_sapw_understory_si_scls(io_si,scls) = hio_npp_sapw_understory_si_scls(io_si,scls) + & + sapw_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_npp_dead_understory_si_scls(io_si,scls) = hio_npp_dead_understory_si_scls(io_si,scls) + & + struct_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_npp_seed_understory_si_scls(io_si,scls) = hio_npp_seed_understory_si_scls(io_si,scls) + & + repro_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + hio_npp_stor_understory_si_scls(io_si,scls) = hio_npp_stor_understory_si_scls(io_si,scls) + & + store_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day + + hio_yesterdaycanopylevel_understory_si_scls(io_si,scls) = & + hio_yesterdaycanopylevel_understory_si_scls(io_si,scls) + & + ccohort%canopy_layer_yesterday * ccohort%n / m2_per_ha + endif canlayer + ! + ! + ccohort%canopy_layer_yesterday = real(ccohort%canopy_layer, r8) + ! + ! growth flux of individuals into a given bin + ! track the actual growth here, the virtual growth from fusion lower down + if ( (scls - ccohort%size_class_lasttimestep ) .gt. 0) then + do i_scls = ccohort%size_class_lasttimestep + 1, scls + i_scpf = (ccohort%pft-1)*nlevsclass+i_scls + hio_growthflux_si_scpf(io_si,i_scpf) = hio_growthflux_si_scpf(io_si,i_scpf) + & + ccohort%n * days_per_year / m2_per_ha + end do + end if + ccohort%size_class_lasttimestep = scls + + end associate + else notnew ! i.e. cohort%isnew + ! + ! if cohort is new, track its growth flux into the first size bin + i_scpf = (ccohort%pft-1)*nlevsclass+1 + hio_growthflux_si_scpf(io_si,i_scpf) = & + hio_growthflux_si_scpf(io_si,i_scpf) + ccohort%n * & + days_per_year / m2_per_ha + ccohort%size_class_lasttimestep = 1 + + end if notnew + + ! resolve some canopy area profiles, both total and of occupied leaves + ican = ccohort%canopy_layer + ! + hio_crownarea_cl(io_si, ican) = hio_crownarea_cl(io_si, ican) + ccohort%c_area / AREA + ! + do ileaf=1,ccohort%nv + cnlf_indx = ileaf + (ican-1) * nlevleaf + hio_crownarea_si_cnlf(io_si, cnlf_indx) = hio_crownarea_si_cnlf(io_si, cnlf_indx) + & + ccohort%c_area / AREA + end do + + ccohort => ccohort%taller + enddo cohortloop ! cohort loop + + + + do ilyr = 1,sites(s)%nlevsoil + hio_fragmentation_scaler_sl(io_si,ilyr) = hio_fragmentation_scaler_sl(io_si,ilyr) + cpatch%fragmentation_scaler(ilyr) * cpatch%area * AREA_INV + end do + + do i_fuel = 1,nfsc + + i_agefuel = get_agefuel_class_index(cpatch%age,i_fuel) + hio_fuel_amount_age_fuel(io_si,i_agefuel) = hio_fuel_amount_age_fuel(io_si,i_agefuel) + & + cpatch%fuel_frac(i_fuel) * cpatch%sum_fuel * cpatch%area * AREA_INV + + hio_litter_moisture_si_fuel(io_si, i_fuel) = hio_litter_moisture_si_fuel(io_si, i_fuel) + & + cpatch%litter_moisture(i_fuel) * cpatch%area * AREA_INV + + hio_fuel_amount_si_fuel(io_si, i_fuel) = hio_fuel_amount_si_fuel(io_si, i_fuel) + & + cpatch%fuel_frac(i_fuel) * cpatch%sum_fuel * cpatch%area * AREA_INV + + hio_burnt_frac_litter_si_fuel(io_si, i_fuel) = hio_burnt_frac_litter_si_fuel(io_si, i_fuel) + & + cpatch%burnt_frac_litter(i_fuel) * cpatch%frac_burnt * cpatch%area * AREA_INV + end do + + + + + ! Update Litter Flux Variables + + litt_c => cpatch%litter(element_pos(carbon12_element)) + + + do i_cwd = 1, ncwd + + hio_cwd_ag_si_cwdsc(io_si, i_cwd) = hio_cwd_ag_si_cwdsc(io_si, i_cwd) + & + litt_c%ag_cwd(i_cwd)*cpatch%area * AREA_INV + hio_cwd_bg_si_cwdsc(io_si, i_cwd) = hio_cwd_bg_si_cwdsc(io_si, i_cwd) + & + sum(litt_c%bg_cwd(i_cwd,:)) * cpatch%area * AREA_INV + + hio_cwd_ag_out_si_cwdsc(io_si, i_cwd) = hio_cwd_ag_out_si_cwdsc(io_si, i_cwd) + & + litt_c%ag_cwd_frag(i_cwd)*cpatch%area * AREA_INV / & + days_per_year / sec_per_day + + hio_cwd_bg_out_si_cwdsc(io_si, i_cwd) = hio_cwd_bg_out_si_cwdsc(io_si, i_cwd) + & + sum(litt_c%bg_cwd_frag(i_cwd,:)) * cpatch%area * AREA_INV / & + days_per_year / sec_per_day + + end do + + ipa = ipa + 1 + cpatch => cpatch%younger + end do patchloop !patch loop + + + + + ! divide so-far-just-summed but to-be-averaged patch-age-class + ! variables by patch-age-class area to get mean values + do ipa2 = 1, nlevage + if (hio_area_si_age(io_si, ipa2) .gt. nearzero) then + hio_lai_si_age(io_si, ipa2) = hio_lai_si_age(io_si, ipa2) / (hio_area_si_age(io_si, ipa2)*AREA) + hio_ncl_si_age(io_si, ipa2) = hio_ncl_si_age(io_si, ipa2) / (hio_area_si_age(io_si, ipa2)*AREA) + do ft = 1, numpft + iagepft = ipa2 + (ft-1) * nlevage + hio_scorch_height_si_agepft(io_si, iagepft) = & + hio_scorch_height_si_agepft(io_si, iagepft) / (hio_area_si_age(io_si, ipa2)*AREA) + enddo + else + hio_lai_si_age(io_si, ipa2) = 0._r8 + hio_ncl_si_age(io_si, ipa2) = 0._r8 + endif + end do + + + + ! pass the cohort termination mortality as a flux to the history, and then reset the termination mortality buffer + ! note there are various ways of reporting the total mortality, so pass to these as well + do ft = 1, numpft + do i_scls = 1,nlevsclass + i_scpf = (ft-1)*nlevsclass + i_scls + ! + ! termination mortality. sum of canopy and understory indices + hio_m6_si_scpf(io_si,i_scpf) = (sites(s)%term_nindivs_canopy(i_scls,ft) + & + sites(s)%term_nindivs_ustory(i_scls,ft)) * & + days_per_year / m2_per_ha + + hio_m6_si_scls(io_si,i_scls) = hio_m6_si_scls(io_si,i_scls) + & + (sites(s)%term_nindivs_canopy(i_scls,ft) + & + sites(s)%term_nindivs_ustory(i_scls,ft)) * & + days_per_year / m2_per_ha + ! + ! add termination mortality to canopy and understory mortality + hio_mortality_canopy_si_scls(io_si,i_scls) = hio_mortality_canopy_si_scls(io_si,i_scls) + & + sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha + + hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & + sites(s)%term_nindivs_ustory(i_scls,ft) * days_per_year / m2_per_ha - + hio_mortality_canopy_si_scpf(io_si,i_scpf) = hio_mortality_canopy_si_scpf(io_si,i_scpf) + & + sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha + hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & + sites(s)%term_nindivs_ustory(i_scls,ft) * days_per_year / m2_per_ha + + ! + ! imort on its own + hio_m4_si_scpf(io_si,i_scpf) = sites(s)%imort_rate(i_scls, ft) / m2_per_ha + hio_m4_si_scls(io_si,i_scls) = hio_m4_si_scls(io_si,i_scls) + sites(s)%imort_rate(i_scls, ft) / m2_per_ha + ! + ! add imort to other mortality terms. consider imort as understory mortality even if it happens in + ! cohorts that may have been promoted as part of the patch creation, and use the pre-calculated site-level + ! values to avoid biasing the results by the dramatically-reduced number densities in cohorts that are subject to imort + hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & + sites(s)%imort_rate(i_scls, ft) / m2_per_ha + hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & + sites(s)%imort_rate(i_scls, ft) / m2_per_ha + ! + iscag = i_scls ! since imort is by definition something that only happens in newly disturbed patches, treat as such + hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & + sites(s)%imort_rate(i_scls, ft) / m2_per_ha + + ! fire mortality from the site-level diagnostic rates + hio_m5_si_scpf(io_si,i_scpf) = (sites(s)%fmort_rate_canopy(i_scls, ft) + & + sites(s)%fmort_rate_ustory(i_scls, ft)) / m2_per_ha + hio_m5_si_scls(io_si,i_scls) = hio_m5_si_scls(io_si,i_scls) + & + (sites(s)%fmort_rate_canopy(i_scls, ft) + & + sites(s)%fmort_rate_ustory(i_scls, ft)) / m2_per_ha + ! + hio_crownfiremort_si_scpf(io_si,i_scpf) = sites(s)%fmort_rate_crown(i_scls, ft) / m2_per_ha + hio_cambialfiremort_si_scpf(io_si,i_scpf) = sites(s)%fmort_rate_cambial(i_scls, ft) / m2_per_ha + ! + ! fire components of overall canopy and understory mortality + hio_mortality_canopy_si_scpf(io_si,i_scpf) = hio_mortality_canopy_si_scpf(io_si,i_scpf) + & + sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha + hio_mortality_canopy_si_scls(io_si,i_scls) = hio_mortality_canopy_si_scls(io_si,i_scls) + & + sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha + + ! Shijie: Think about how to add later? + !if ( cpatch%land_use_label .eq. secondaryland ) then + ! hio_mortality_canopy_secondary_si_scls(io_si,i_scls) = hio_mortality_canopy_secondary_si_scls(io_si,i_scls) + & + ! sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha + !end if + + ! the fire mortality rates for each layer are total dead, since the usable + ! output will then normalize by the counts, we are allowed to sum over layers + hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & + sites(s)%fmort_rate_ustory(i_scls, ft) / m2_per_ha + + hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & + sites(s)%fmort_rate_ustory(i_scls, ft) / m2_per_ha + + ! + ! for scag variables, also treat as happening in the newly-disurbed patch + + hio_mortality_canopy_si_scag(io_si,iscag) = hio_mortality_canopy_si_scag(io_si,iscag) + & + sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha + hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & + sites(s)%fmort_rate_ustory(i_scls, ft) / m2_per_ha + + ! while in this loop, pass the fusion-induced growth rate flux to history + hio_growthflux_fusion_si_scpf(io_si,i_scpf) = hio_growthflux_fusion_si_scpf(io_si,i_scpf) + & + sites(s)%growthflux_fusion(i_scls, ft) * days_per_year / m2_per_ha + + end do + end do + + + + do ft = 1, numpft + hio_mortality_carbonflux_si_pft(io_si,ft) = hio_mortality_carbonflux_si_pft(io_si,ft) + & + (sites(s)%fmort_carbonflux_canopy(ft) + & + sites(s)%fmort_carbonflux_ustory(ft) ) / g_per_kg + & + sites(s)%imort_carbonflux(ft) + & + sites(s)%term_carbonflux_ustory(ft) * days_per_sec * ha_per_m2 + & + sites(s)%term_carbonflux_canopy(ft) * days_per_sec * ha_per_m2 + + hio_firemortality_carbonflux_si_pft(io_si,ft) = sites(s)%fmort_carbonflux_canopy(ft) / g_per_kg + end do + + ! add imort and fmort to aboveground woody mortality + do ft = 1, numpft + do i_scls = 1,nlevsclass + i_scpf = (ft-1)*nlevsclass + i_scls + hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) = hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) + & + (sites(s)%fmort_abg_flux(i_scls,ft) / g_per_kg ) + & + sites(s)%imort_abg_flux(i_scls,ft) + & + (sites(s)%term_abg_flux(i_scls,ft) * days_per_sec * ha_per_m2 ) + end do + end do + + + if(hlm_use_tree_damage .eq. itrue) then + + do ft = 1, numpft + do icdam = 1, nlevdamage + do i_scls = 1,nlevsclass + + icdsc = (icdam-1)*nlevsclass + i_scls + icdpf = (icdam-1)*nlevsclass + i_scls + & + (ft-1) * nlevsclass * nlevdamage + + this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) = & + this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) + & + ( (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, ft) * days_per_year) + & + (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, ft) * days_per_year) + & + sites(s)%imort_rate_damage(icdam, i_scls, ft) + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, ft) + & + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, ft) ) / m2_per_ha + + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) + & + ( sites(s)%term_nindivs_canopy_damage(icdam,i_scls,ft) * days_per_year + & + sites(s)%fmort_rate_canopy_damage(icdam, i_scls, ft) )/ m2_per_ha + + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & + this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & + ( sites(s)%term_nindivs_ustory_damage(icdam, i_scls,ft) * days_per_year + & + sites(s)%imort_rate_damage(icdam, i_scls, ft) + & + sites(s)%fmort_rate_ustory_damage(icdam, i_scls, ft) )/ m2_per_ha + + end do + end do + end do + end if + + sites(s)%term_nindivs_canopy(:,:) = 0._r8 + sites(s)%term_nindivs_ustory(:,:) = 0._r8 + sites(s)%imort_carbonflux(:) = 0._r8 + sites(s)%imort_rate(:,:) = 0._r8 + sites(s)%fmort_rate_canopy(:,:) = 0._r8 + sites(s)%fmort_rate_ustory(:,:) = 0._r8 + sites(s)%fmort_carbonflux_canopy(:) = 0._r8 + sites(s)%fmort_carbonflux_ustory(:) = 0._r8 + sites(s)%fmort_rate_cambial(:,:) = 0._r8 + sites(s)%fmort_rate_crown(:,:) = 0._r8 + sites(s)%growthflux_fusion(:,:) = 0._r8 + sites(s)%fmort_abg_flux(:,:) = 0._r8 + sites(s)%imort_abg_flux(:,:) = 0._r8 + sites(s)%term_abg_flux(:,:) = 0._r8 + + sites(s)%imort_rate_damage(:,:,:) = 0.0_r8 + sites(s)%term_nindivs_canopy_damage(:,:,:) = 0.0_r8 + sites(s)%term_nindivs_ustory_damage(:,:,:) = 0.0_r8 + sites(s)%imort_cflux_damage(:,:) = 0._r8 + sites(s)%term_cflux_canopy_damage(:,:) = 0._r8 + sites(s)%term_cflux_ustory_damage(:,:) = 0._r8 + sites(s)%fmort_rate_canopy_damage(:,:,:) = 0._r8 + sites(s)%fmort_rate_ustory_damage(:,:,:) = 0._r8 + sites(s)%fmort_cflux_canopy_damage(:,:) = 0._r8 + sites(s)%fmort_cflux_ustory_damage(:,:) = 0._r8 + sites(s)%crownarea_canopy_damage = 0._r8 + sites(s)%crownarea_ustory_damage = 0._r8 + + ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer + do ft = 1, numpft + ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer + hio_recruitment_si_pft(io_si,ft) = sites(s)%recruitment_rate(ft) * days_per_year / m2_per_ha + + ! Gridcell output and inputs + hio_seeds_out_gc_si_pft(io_si,ft) = sites(s)%seed_out(ft) + hio_seeds_in_gc_si_pft(io_si,ft) = sites(s)%seed_in(ft) + end do + sites(s)%recruitment_rate(:) = 0._r8 + + ! summarize all of the mortality fluxes by PFT + do ft = 1, numpft + do i_scls = 1,nlevsclass + i_scpf = (ft-1)*nlevsclass + i_scls + + hio_mortality_si_pft(io_si,ft) = hio_mortality_si_pft(io_si,ft) + & + hio_m1_si_scpf(io_si,i_scpf) + & + hio_m2_si_scpf(io_si,i_scpf) + & + hio_m3_si_scpf(io_si,i_scpf) + & + hio_m4_si_scpf(io_si,i_scpf) + & + hio_m5_si_scpf(io_si,i_scpf) + & + hio_m6_si_scpf(io_si,i_scpf) + & + hio_m7_si_scpf(io_si,i_scpf) + & + hio_m8_si_scpf(io_si,i_scpf) + & + hio_m9_si_scpf(io_si,i_scpf) + & + hio_m10_si_scpf(io_si,i_scpf) + + if(hlm_use_tree_damage .eq. itrue) then + hio_mortality_si_pft(io_si, ft) = hio_mortality_si_pft(io_si,ft) + & + this%hvars(ih_m11_si_scpf)%r82d(io_si,i_scpf) + end if + + end do + end do + + ! ------------------------------------------------------------------------------ + ! Some carbon only litter diagnostics (legacy) + ! ------------------------------------------------------------------------------ + + flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) + + + + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) + + + + + + cpatch => cpatch%younger + end do + + ! ------------------------------------------------------------------------------ + ! Diagnostics discretized by element type + ! ------------------------------------------------------------------------------ + + hio_cwd_elcwd(io_si,:) = 0._r8 + + do el = 1, num_elements + + flux_diags => sites(s)%flux_diags(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_cwd_ag_elem(io_si,el) = 0._r8 + hio_cwd_bg_elem(io_si,el) = 0._r8 + hio_fines_ag_elem(io_si,el) = 0._r8 + hio_fines_bg_elem(io_si,el) = 0._r8 + + hio_seed_bank_elem(io_si,el) = 0._r8 + hio_seed_germ_elem(io_si,el) = 0._r8 + hio_seed_decay_elem(io_si,el) = 0._r8 + hio_seeds_in_local_elem(io_si,el) = 0._r8 + hio_seed_in_extern_elem(io_si,el) = 0._r8 + hio_litter_out_elem(io_si,el) = 0._r8 - hio_m1_si_scls(io_si,scls) = hio_m1_si_scls(io_si,scls) + ccohort%bmort*ccohort%n / m2_per_ha - hio_m2_si_scls(io_si,scls) = hio_m2_si_scls(io_si,scls) + ccohort%hmort*ccohort%n / m2_per_ha - hio_m3_si_scls(io_si,scls) = hio_m3_si_scls(io_si,scls) + ccohort%cmort*ccohort%n / m2_per_ha - hio_m7_si_scls(io_si,scls) = hio_m7_si_scls(io_si,scls) + & - (ccohort%lmort_direct+ccohort%lmort_collateral+ccohort%lmort_infra) * ccohort%n / m2_per_ha - hio_m8_si_scls(io_si,scls) = hio_m8_si_scls(io_si,scls) + & - ccohort%frmort*ccohort%n / m2_per_ha - hio_m9_si_scls(io_si,scls) = hio_m9_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha + ! Plant multi-element states and fluxes + ! Zero states, and set the fluxes + if(element_list(el).eq.carbon12_element)then + this%hvars(ih_totvegc_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_leafc_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_fnrtc_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_sapwc_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_storec_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_reproc_scpf)%r82d(io_si,:) = 0._r8 - ! Examine secondary forest mortality and mortality rates - if(cpatch%land_use_label .eq. secondaryland) then - if (hlm_use_cohort_age_tracking .eq.itrue) then - hio_m10_sec_si_scls(io_si,scls) = hio_m10_sec_si_scls(io_si,scls) + & - ccohort%asmort*ccohort%n / m2_per_ha - end if + elseif(element_list(el).eq.nitrogen_element)then - hio_m1_sec_si_scls(io_si,scls) = hio_m1_sec_si_scls(io_si,scls) + ccohort%bmort*ccohort%n / m2_per_ha - hio_m2_sec_si_scls(io_si,scls) = hio_m2_sec_si_scls(io_si,scls) + ccohort%hmort*ccohort%n / m2_per_ha - hio_m3_sec_si_scls(io_si,scls) = hio_m3_sec_si_scls(io_si,scls) + ccohort%cmort*ccohort%n / m2_per_ha - hio_m7_sec_si_scls(io_si,scls) = hio_m7_sec_si_scls(io_si,scls) + & - (ccohort%lmort_direct+ccohort%lmort_collateral+ccohort%lmort_infra) * ccohort%n / m2_per_ha - hio_m8_sec_si_scls(io_si,scls) = hio_m8_sec_si_scls(io_si,scls) + & - ccohort%frmort*ccohort%n / m2_per_ha - hio_m9_sec_si_scls(io_si,scls) = hio_m9_sec_si_scls(io_si,scls) + ccohort%smort*ccohort%n / m2_per_ha - end if + this%hvars(ih_totvegn_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_leafn_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_fnrtn_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_sapwn_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_storen_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_repron_scpf)%r82d(io_si,:) = 0._r8 - !C13 discrimination - if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then - hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & - (ccohort%c13disc_acc * ccohort%gpp_acc_hold)) / (gpp_cached + ccohort%gpp_acc_hold) - else - hio_c13disc_si_scpf(io_si,scpf) = 0.0_r8 - endif + elseif(element_list(el).eq.phosphorus_element)then + this%hvars(ih_totvegp_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_leafp_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_fnrtp_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_sapwp_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_storep_scpf)%r82d(io_si,:) = 0._r8 + this%hvars(ih_reprop_scpf)%r82d(io_si,:) = 0._r8 - ! number density [/m2] - hio_nplant_si_scpf(io_si,scpf) = hio_nplant_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha - ! number density along the cohort age dimension - if (hlm_use_cohort_age_tracking .eq.itrue) then - hio_nplant_si_capf(io_si,capf) = hio_nplant_si_capf(io_si,capf) + ccohort%n / m2_per_ha - hio_nplant_si_cacls(io_si,cacls) = hio_nplant_si_cacls(io_si,cacls)+ccohort%n / m2_per_ha - end if - ! damage variables - cohort level - if(hlm_use_tree_damage .eq. itrue) then - - icdpf = get_cdamagesizepft_class_index(ccohort%dbh, ccohort%crowndamage, ccohort%pft) - - this%hvars(ih_mortality_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_mortality_si_cdpf)%r82d(io_si,icdpf) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & - ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year / m2_per_ha - - ! crown damage by size by pft - this%hvars(ih_nplant_si_cdpf)%r82d(io_si, icdpf) = & - this%hvars(ih_nplant_si_cdpf)%r82d(io_si, icdpf) + ccohort%n / m2_per_ha - this%hvars(ih_m3_si_cdpf)%r82d(io_si, icdpf) = & - this%hvars(ih_m3_si_cdpf)%r82d(io_si, icdpf) + & - ccohort%cmort * ccohort%n / m2_per_ha - - ! mortality - this%hvars(ih_m11_si_scpf)%r82d(io_si,scpf) = & - this%hvars(ih_m11_si_scpf)%r82d(io_si,scpf) + & - ccohort%dgmort*ccohort%n / m2_per_ha - this%hvars(ih_m11_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_m11_si_cdpf)%r82d(io_si,icdpf) + & - ccohort%dgmort*ccohort%n / m2_per_ha - - this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_ddbh_si_cdpf)%r82d(io_si,icdpf) + & - ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm - - end if - - ! Carbon only metrics - sapw_m = ccohort%prt%GetState(sapw_organ, carbon12_element) - struct_m = ccohort%prt%GetState(struct_organ, carbon12_element) - leaf_m = ccohort%prt%GetState(leaf_organ, carbon12_element) - fnrt_m = ccohort%prt%GetState(fnrt_organ, carbon12_element) - store_m = ccohort%prt%GetState(store_organ, carbon12_element) - repro_m = ccohort%prt%GetState(repro_organ, carbon12_element) - alive_m = leaf_m + fnrt_m + sapw_m - total_m = alive_m + store_m + struct_m - - hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_mortality_carbonflux_si_pft(io_si,ccohort%pft) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * & - total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * total_m * & - ccohort%n * ha_per_m2 - - - hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) + & - ccohort%hmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 - - hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) + & - ccohort%cmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 - - ! Aboveground mortality - hio_abg_mortality_cflux_si_scpf(io_si,scpf) = hio_abg_mortality_cflux_si_scpf(io_si,scpf) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * & - ( (sapw_m + struct_m + store_m ) * prt_params%allom_agb_frac(ccohort%pft) + & - leaf_m ) * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ( (sapw_m + struct_m + store_m ) * prt_params%allom_agb_frac(ccohort%pft) + & - leaf_m ) * ccohort%n * ha_per_m2 - - ! Aboveground woody productivity - hio_abg_productivity_cflux_si_scpf(io_si,scpf) = hio_abg_productivity_cflux_si_scpf(io_si,scpf) + & - ( (sapw_m_net_alloc + struct_m_net_alloc + store_m_net_alloc) * prt_params%allom_agb_frac(ccohort%pft) + & - leaf_m_net_alloc ) * n_perm2 / & - days_per_year / sec_per_day - - - ! number density by size and biomass - hio_agb_si_scls(io_si,scls) = hio_agb_si_scls(io_si,scls) + & - total_m * ccohort%n * prt_params%allom_agb_frac(ccohort%pft) * AREA_INV - - hio_agb_si_scpf(io_si,scpf) = hio_agb_si_scpf(io_si,scpf) + & - total_m * ccohort%n * prt_params%allom_agb_frac(ccohort%pft) * AREA_INV - - hio_biomass_si_scls(io_si,scls) = hio_biomass_si_scls(io_si,scls) + & - total_m * ccohort%n * AREA_INV - - ! update size-class x patch-age related quantities - - iscag = get_sizeage_class_index(ccohort%dbh,cpatch%age) - - hio_nplant_si_scag(io_si,iscag) = hio_nplant_si_scag(io_si,iscag) + ccohort%n / m2_per_ha - - hio_nplant_si_scls(io_si,scls) = hio_nplant_si_scls(io_si,scls) + ccohort%n / m2_per_ha - - - ! update size, age, and PFT - indexed quantities - iscagpft = get_sizeagepft_class_index(ccohort%dbh,cpatch%age,ccohort%pft) - - hio_nplant_si_scagpft(io_si,iscagpft) = hio_nplant_si_scagpft(io_si,iscagpft) + ccohort%n / m2_per_ha - - ! update age and PFT - indexed quantities - iagepft = get_agepft_class_index(cpatch%age,ccohort%pft) - - hio_npp_si_agepft(io_si,iagepft) = hio_npp_si_agepft(io_si,iagepft) + & - ccohort%n * ccohort%npp_acc_hold * AREA_INV / days_per_year / sec_per_day - - hio_biomass_si_agepft(io_si,iagepft) = hio_biomass_si_agepft(io_si,iagepft) + & - total_m * ccohort%n * AREA_INV - - ! update SCPF/SCLS- and canopy/subcanopy- partitioned quantities - canlayer: if (ccohort%canopy_layer .eq. 1) then - hio_nplant_canopy_si_scag(io_si,iscag) = hio_nplant_canopy_si_scag(io_si,iscag) + ccohort%n / m2_per_ha - hio_mortality_canopy_si_scag(io_si,iscag) = hio_mortality_canopy_si_scag(io_si,iscag) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha - hio_ddbh_canopy_si_scag(io_si,iscag) = hio_ddbh_canopy_si_scag(io_si,iscag) + & - ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha - hio_bstor_canopy_si_scpf(io_si,scpf) = hio_bstor_canopy_si_scpf(io_si,scpf) + & - store_m * ccohort%n / m2_per_ha - hio_bleaf_canopy_si_scpf(io_si,scpf) = hio_bleaf_canopy_si_scpf(io_si,scpf) + & - leaf_m * ccohort%n / m2_per_ha - hio_lai_canopy_si_scpf(io_si,scpf) = hio_lai_canopy_si_scpf(io_si,scpf) + & - ccohort%treelai*ccohort%c_area * AREA_INV - - !hio_mortality_canopy_si_scpf(io_si,scpf) = hio_mortality_canopy_si_scpf(io_si,scpf)+ & - ! (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ! ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n - - hio_mortality_canopy_si_scpf(io_si,scpf) = hio_mortality_canopy_si_scpf(io_si,scpf)+ & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & - ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year / m2_per_ha - - hio_m3_mortality_canopy_si_scpf(io_si,scpf) = hio_m3_mortality_canopy_si_scpf(io_si,scpf) + & - ccohort%cmort * ccohort%n / m2_per_ha - - hio_nplant_canopy_si_scpf(io_si,scpf) = hio_nplant_canopy_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha - hio_nplant_canopy_si_scls(io_si,scls) = hio_nplant_canopy_si_scls(io_si,scls) + ccohort%n / m2_per_ha - hio_lai_canopy_si_scls(io_si,scls) = hio_lai_canopy_si_scls(io_si,scls) + & - ccohort%treelai*ccohort%c_area * AREA_INV - hio_sai_canopy_si_scls(io_si,scls) = hio_sai_canopy_si_scls(io_si,scls) + & - ccohort%treesai*ccohort%c_area * AREA_INV - hio_trimming_canopy_si_scls(io_si,scls) = hio_trimming_canopy_si_scls(io_si,scls) + & - ccohort%n * ccohort%canopy_trim / m2_per_ha - hio_crown_area_canopy_si_scls(io_si,scls) = hio_crown_area_canopy_si_scls(io_si,scls) + & - ccohort%c_area / m2_per_ha - hio_gpp_canopy_si_scpf(io_si,scpf) = hio_gpp_canopy_si_scpf(io_si,scpf) + & - n_perm2*ccohort%gpp_acc_hold / days_per_year / sec_per_day - hio_ar_canopy_si_scpf(io_si,scpf) = hio_ar_canopy_si_scpf(io_si,scpf) + & - n_perm2*ccohort%resp_acc_hold / days_per_year / sec_per_day - ! growth increment - hio_ddbh_canopy_si_scpf(io_si,scpf) = hio_ddbh_canopy_si_scpf(io_si,scpf) + & - ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha - hio_ddbh_canopy_si_scls(io_si,scls) = hio_ddbh_canopy_si_scls(io_si,scls) + & - ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha - - ! sum of all mortality - hio_mortality_canopy_si_scls(io_si,scls) = hio_mortality_canopy_si_scls(io_si,scls) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year / m2_per_ha - - hio_m3_mortality_canopy_si_scls(io_si,scls) = hio_m3_mortality_canopy_si_scls(io_si,scls) + & - ccohort%cmort * ccohort%n / m2_per_ha - - hio_carbon_balance_canopy_si_scls(io_si,scls) = hio_carbon_balance_canopy_si_scls(io_si,scls) + & - ccohort%n * ccohort%npp_acc_hold / m2_per_ha / days_per_year / sec_per_day - - ! damage variables - canopy - if(hlm_use_tree_damage .eq. itrue) then - - ! carbon starvation mortality in the canopy by size x damage x pft - this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_m3_mortality_canopy_si_cdpf)%r82d(io_si,icdpf)+& - ccohort%cmort * ccohort%n / m2_per_ha - - ! damage mortality in the canopy by size x damage x pft - this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_m11_mortality_canopy_si_cdpf)%r82d(io_si,icdpf)+& - ccohort%dgmort * ccohort%n / m2_per_ha - - this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf)+ & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + ccohort%smort + & - ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year / m2_per_ha - - ! nplants by damage - this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_nplant_canopy_si_cdpf)%r82d(io_si,icdpf) + & - ccohort%n / m2_per_ha - - ! growth rate by damage x size x pft in the canopy - this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_ddbh_canopy_si_cdpf)%r82d(io_si,icdpf) + & - ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm - - end if ! end if damage - - - hio_leaf_md_canopy_si_scls(io_si,scls) = hio_leaf_md_canopy_si_scls(io_si,scls) + & - leaf_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_root_md_canopy_si_scls(io_si,scls) = hio_root_md_canopy_si_scls(io_si,scls) + & - fnrt_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_bsw_md_canopy_si_scls(io_si,scls) = hio_bsw_md_canopy_si_scls(io_si,scls) + & - sapw_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_bstore_md_canopy_si_scls(io_si,scls) = hio_bstore_md_canopy_si_scls(io_si,scls) + & - store_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day - 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 - - 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 - hio_npp_fnrt_canopy_si_scls(io_si,scls) = hio_npp_fnrt_canopy_si_scls(io_si,scls) + & - fnrt_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_npp_sapw_canopy_si_scls(io_si,scls) = hio_npp_sapw_canopy_si_scls(io_si,scls) + & - sapw_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_npp_dead_canopy_si_scls(io_si,scls) = hio_npp_dead_canopy_si_scls(io_si,scls) + & - struct_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_npp_seed_canopy_si_scls(io_si,scls) = hio_npp_seed_canopy_si_scls(io_si,scls) + & - repro_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_npp_stor_canopy_si_scls(io_si,scls) = hio_npp_stor_canopy_si_scls(io_si,scls) + & - store_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - - hio_yesterdaycanopylevel_canopy_si_scls(io_si,scls) = & - hio_yesterdaycanopylevel_canopy_si_scls(io_si,scls) + & - ccohort%canopy_layer_yesterday * ccohort%n / m2_per_ha - - - else canlayer - hio_nplant_understory_si_scag(io_si,iscag) = hio_nplant_understory_si_scag(io_si,iscag) + ccohort%n / m2_per_ha - hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha - hio_ddbh_understory_si_scag(io_si,iscag) = hio_ddbh_understory_si_scag(io_si,iscag) + & - ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha - hio_bstor_understory_si_scpf(io_si,scpf) = hio_bstor_understory_si_scpf(io_si,scpf) + & - store_m * ccohort%n / m2_per_ha - hio_bleaf_understory_si_scpf(io_si,scpf) = hio_bleaf_understory_si_scpf(io_si,scpf) + & - leaf_m * ccohort%n / m2_per_ha - - hio_lai_understory_si_scpf(io_si,scpf) = hio_lai_understory_si_scpf(io_si,scpf) + & - ccohort%treelai*ccohort%c_area * AREA_INV - - !hio_mortality_understory_si_scpf(io_si,scpf) = hio_mortality_understory_si_scpf(io_si,scpf)+ & - ! (ccohort%bmort + ccohort%hmort + ccohort%cmort + - ! ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n - - hio_mortality_understory_si_scpf(io_si,scpf) = hio_mortality_understory_si_scpf(io_si,scpf)+ & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year / m2_per_ha - - hio_m3_mortality_understory_si_scpf(io_si,scpf) = hio_m3_mortality_understory_si_scpf(io_si,scpf) + & - ccohort%cmort * ccohort%n / m2_per_ha - - if(cpatch%land_use_label .eq. secondaryland) then - hio_mortality_canopy_secondary_si_scls(io_si,scls) = hio_mortality_canopy_secondary_si_scls(io_si,scls) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort) * ccohort%n / m2_per_ha + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year / m2_per_ha - end if - - hio_nplant_understory_si_scpf(io_si,scpf) = hio_nplant_understory_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha - hio_nplant_understory_si_scls(io_si,scls) = hio_nplant_understory_si_scls(io_si,scls) + ccohort%n / m2_per_ha - hio_lai_understory_si_scls(io_si,scls) = hio_lai_understory_si_scls(io_si,scls) + & - ccohort%treelai*ccohort%c_area * AREA_INV - hio_sai_understory_si_scls(io_si,scls) = hio_sai_understory_si_scls(io_si,scls) + & - ccohort%treelai*ccohort%c_area * AREA_INV - hio_trimming_understory_si_scls(io_si,scls) = hio_trimming_understory_si_scls(io_si,scls) + & - ccohort%n * ccohort%canopy_trim / m2_per_ha - hio_crown_area_understory_si_scls(io_si,scls) = hio_crown_area_understory_si_scls(io_si,scls) + & - ccohort%c_area / m2_per_ha - hio_gpp_understory_si_scpf(io_si,scpf) = hio_gpp_understory_si_scpf(io_si,scpf) + & - n_perm2*ccohort%gpp_acc_hold / days_per_year / sec_per_day - hio_ar_understory_si_scpf(io_si,scpf) = hio_ar_understory_si_scpf(io_si,scpf) + & - n_perm2*ccohort%resp_acc_hold / days_per_year / sec_per_day - - ! growth increment - hio_ddbh_understory_si_scpf(io_si,scpf) = hio_ddbh_understory_si_scpf(io_si,scpf) + & - ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha - hio_ddbh_understory_si_scls(io_si,scls) = hio_ddbh_understory_si_scls(io_si,scls) + & - ccohort%ddbhdt*ccohort%n * m_per_cm / m2_per_ha - - ! sum of all mortality - hio_mortality_understory_si_scls(io_si,scls) = hio_mortality_understory_si_scls(io_si,scls) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + & - ccohort%frmort + ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year / m2_per_ha - - hio_m3_mortality_understory_si_scls(io_si,scls) = hio_m3_mortality_understory_si_scls(io_si,scls) + & - ccohort%cmort * ccohort%n / m2_per_ha - - - - hio_carbon_balance_understory_si_scls(io_si,scls) = hio_carbon_balance_understory_si_scls(io_si,scls) + & - ccohort%npp_acc_hold * ccohort%n / m2_per_ha / days_per_year / sec_per_day - - ! damage variables - understory - if(hlm_use_tree_damage .eq. itrue) then - - ! carbon mortality in the understory by damage x size x pft - this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_m3_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & - ccohort%cmort * ccohort%n / m2_per_ha - - ! damage in the understory by damage x size x pft - this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_m11_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & - ccohort%dgmort * ccohort%n / m2_per_ha - - ! total mortality of understory cohorts by damage x size x pft - this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & - (ccohort%bmort + ccohort%hmort + ccohort%cmort + ccohort%frmort + & - ccohort%smort + ccohort%asmort + ccohort%dgmort) * ccohort%n / m2_per_ha + & - (ccohort%lmort_direct + ccohort%lmort_collateral + ccohort%lmort_infra) * & - ccohort%n * sec_per_day * days_per_year / m2_per_ha - - this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_nplant_understory_si_cdpf)%r82d(io_si,icdpf) + & - ccohort%n / m2_per_ha - - ! growth rate by size x damage x pft - understory - this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_ddbh_understory_si_cdpf)%r82d(io_si,icdpf) + & - ccohort%ddbhdt*ccohort%n / m2_per_ha * m_per_cm - - end if ! end if damage - - hio_leaf_md_understory_si_scls(io_si,scls) = hio_leaf_md_understory_si_scls(io_si,scls) + & - leaf_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_root_md_understory_si_scls(io_si,scls) = hio_root_md_understory_si_scls(io_si,scls) + & - fnrt_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_bsw_md_understory_si_scls(io_si,scls) = hio_bsw_md_understory_si_scls(io_si,scls) + & - sapw_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_bstore_md_understory_si_scls(io_si,scls) = hio_bstore_md_understory_si_scls(io_si,scls) + & - store_m_turnover * ccohort%n / m2_per_ha / days_per_year / sec_per_day - 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 - - 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 - hio_npp_fnrt_understory_si_scls(io_si,scls) = hio_npp_fnrt_understory_si_scls(io_si,scls) + & - fnrt_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_npp_sapw_understory_si_scls(io_si,scls) = hio_npp_sapw_understory_si_scls(io_si,scls) + & - sapw_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_npp_dead_understory_si_scls(io_si,scls) = hio_npp_dead_understory_si_scls(io_si,scls) + & - struct_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_npp_seed_understory_si_scls(io_si,scls) = hio_npp_seed_understory_si_scls(io_si,scls) + & - repro_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - hio_npp_stor_understory_si_scls(io_si,scls) = hio_npp_stor_understory_si_scls(io_si,scls) + & - store_m_net_alloc * ccohort%n / m2_per_ha / days_per_year / sec_per_day - - hio_yesterdaycanopylevel_understory_si_scls(io_si,scls) = & - hio_yesterdaycanopylevel_understory_si_scls(io_si,scls) + & - ccohort%canopy_layer_yesterday * ccohort%n / m2_per_ha - endif canlayer - ! - ! - ccohort%canopy_layer_yesterday = real(ccohort%canopy_layer, r8) - ! - ! growth flux of individuals into a given bin - ! track the actual growth here, the virtual growth from fusion lower down - if ( (scls - ccohort%size_class_lasttimestep ) .gt. 0) then - do i_scls = ccohort%size_class_lasttimestep + 1, scls - i_scpf = (ccohort%pft-1)*nlevsclass+i_scls - hio_growthflux_si_scpf(io_si,i_scpf) = hio_growthflux_si_scpf(io_si,i_scpf) + & - ccohort%n * days_per_year / m2_per_ha - end do - end if - ccohort%size_class_lasttimestep = scls - - end associate - else notnew ! i.e. cohort%isnew - ! - ! if cohort is new, track its growth flux into the first size bin - i_scpf = (ccohort%pft-1)*nlevsclass+1 - hio_growthflux_si_scpf(io_si,i_scpf) = & - hio_growthflux_si_scpf(io_si,i_scpf) + ccohort%n * & - days_per_year / m2_per_ha - ccohort%size_class_lasttimestep = 1 - - end if notnew - - ! resolve some canopy area profiles, both total and of occupied leaves - ican = ccohort%canopy_layer - ! - hio_crownarea_cl(io_si, ican) = hio_crownarea_cl(io_si, ican) + ccohort%c_area / AREA - ! - do ileaf=1,ccohort%nv - cnlf_indx = ileaf + (ican-1) * nlevleaf - hio_crownarea_si_cnlf(io_si, cnlf_indx) = hio_crownarea_si_cnlf(io_si, cnlf_indx) + & - ccohort%c_area / AREA - end do - - ccohort => ccohort%taller - enddo cohortloop ! cohort loop + end if + + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) + + litt => cpatch%litter(el) + + area_frac = cpatch%area * AREA_INV + + ! Sum up all output fluxes (fragmentation) + hio_litter_out_elem(io_si,el) = hio_litter_out_elem(io_si,el) + & + (sum(litt%leaf_fines_frag(:)) + & + sum(litt%root_fines_frag(:,:)) + & + sum(litt%ag_cwd_frag(:)) + & + sum(litt%bg_cwd_frag(:,:)) + & + sum(litt%seed_decay(:)) + & + sum(litt%seed_germ_decay(:))) * cpatch%area / m2_per_ha / sec_per_day + hio_seed_bank_elem(io_si,el) = hio_seed_bank_elem(io_si,el) + & + sum(litt%seed(:)) * cpatch%area / m2_per_ha + hio_seed_germ_elem(io_si,el) = hio_seed_germ_elem(io_si,el) + & + sum(litt%seed_germ(:)) * cpatch%area / m2_per_ha + + hio_seed_decay_elem(io_si,el) = hio_seed_decay_elem(io_si,el) + & + sum(litt%seed_decay(:) + litt%seed_germ_decay(:) ) * & + cpatch%area / m2_per_ha / sec_per_day + + hio_seeds_in_local_elem(io_si,el) = hio_seeds_in_local_elem(io_si,el) + & + sum(litt%seed_in_local(:)) * cpatch%area / m2_per_ha / sec_per_day + + hio_seed_in_extern_elem(io_si,el) = hio_seed_in_extern_elem(io_si,el) + & + sum(litt%seed_in_extern(:)) * cpatch%area / m2_per_ha / sec_per_day + + ! Litter State Variables + hio_cwd_ag_elem(io_si,el) = hio_cwd_ag_elem(io_si,el) + & + sum(litt%ag_cwd(:)) * cpatch%area / m2_per_ha + + hio_cwd_bg_elem(io_si,el) = hio_cwd_bg_elem(io_si,el) + & + sum(litt%bg_cwd(:,:)) * cpatch%area / m2_per_ha + + hio_fines_ag_elem(io_si,el) = hio_fines_ag_elem(io_si,el) + & + sum(litt%leaf_fines(:)) * cpatch%area / m2_per_ha + + hio_fines_bg_elem(io_si,el) = hio_fines_bg_elem(io_si,el) + & + sum(litt%root_fines(:,:)) * cpatch%area / m2_per_ha + + do i_cwd=1,ncwd + elcwd = (el-1)*ncwd+i_cwd + hio_cwd_elcwd(io_si,elcwd) = hio_cwd_elcwd(io_si,elcwd) + & + (litt%ag_cwd(i_cwd) + sum(litt%bg_cwd(i_cwd,:))) * & + cpatch%area / m2_per_ha + + end do + + ! Load Mass States + ccohort => cpatch%tallest + do while(associated(ccohort)) + + sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) + struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) + leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) + fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) + store_m = ccohort%prt%GetState(store_organ, element_list(el)) + repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) + total_m = sapw_m+struct_m+leaf_m+fnrt_m+store_m+repro_m + + + i_scpf = ccohort%size_by_pft_class + + if(element_list(el).eq.carbon12_element)then + this%hvars(ih_totvegc_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_totvegc_scpf)%r82d(io_si,i_scpf) + & + total_m * ccohort%n / m2_per_ha + this%hvars(ih_leafc_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_leafc_scpf)%r82d(io_si,i_scpf) + & + leaf_m * ccohort%n / m2_per_ha + this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) + & + fnrt_m * ccohort%n / m2_per_ha + this%hvars(ih_sapwc_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_sapwc_scpf)%r82d(io_si,i_scpf) + & + sapw_m * ccohort%n / m2_per_ha + this%hvars(ih_storec_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storec_scpf)%r82d(io_si,i_scpf) + & + store_m * ccohort%n / m2_per_ha + this%hvars(ih_reproc_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_reproc_scpf)%r82d(io_si,i_scpf) + & + repro_m * ccohort%n / m2_per_ha + elseif(element_list(el).eq.nitrogen_element)then + + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) + + this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) + & + total_m * ccohort%n / m2_per_ha + this%hvars(ih_leafn_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_leafn_scpf)%r82d(io_si,i_scpf) + & + leaf_m * ccohort%n / m2_per_ha + this%hvars(ih_fnrtn_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_fnrtn_scpf)%r82d(io_si,i_scpf) + & + fnrt_m * ccohort%n / m2_per_ha + this%hvars(ih_sapwn_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_sapwn_scpf)%r82d(io_si,i_scpf) + & + sapw_m * ccohort%n / m2_per_ha + this%hvars(ih_storen_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storen_scpf)%r82d(io_si,i_scpf) + & + store_m * ccohort%n / m2_per_ha + this%hvars(ih_repron_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_repron_scpf)%r82d(io_si,i_scpf) + & + repro_m * ccohort%n / m2_per_ha + + elseif(element_list(el).eq.phosphorus_element)then + + store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) + + this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) + & + total_m * ccohort%n / m2_per_ha + this%hvars(ih_leafp_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_leafp_scpf)%r82d(io_si,i_scpf) + & + leaf_m * ccohort%n / m2_per_ha + this%hvars(ih_fnrtp_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_fnrtp_scpf)%r82d(io_si,i_scpf) + & + fnrt_m * ccohort%n / m2_per_ha + this%hvars(ih_sapwp_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_sapwp_scpf)%r82d(io_si,i_scpf) + & + sapw_m * ccohort%n / m2_per_ha + this%hvars(ih_storep_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_storep_scpf)%r82d(io_si,i_scpf) + & + store_m * ccohort%n / m2_per_ha + this%hvars(ih_reprop_scpf)%r82d(io_si,i_scpf) = & + this%hvars(ih_reprop_scpf)%r82d(io_si,i_scpf) + & + repro_m * ccohort%n / m2_per_ha + + end if + + ccohort => ccohort%shorter + end do ! end cohort loop + + cpatch => cpatch%younger + end do ! end patch loop + + end do ! end element loop + + + ! Normalize storage fractions and L2FR + + + + do ft = 1, numpft + do i_scls = 1,nlevsclass + i_scpf = (ft-1)*nlevsclass + i_scls + + if( this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then + this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + storec_canopy_scpf(i_scpf) / & + this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) + end if + if( this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf)>nearzero ) then + this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) = & + storec_understory_scpf(i_scpf) / & + this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) + end if + + end do + end do + + do el = 1, num_elements + + if(element_list(el).eq.nitrogen_element)then + + do ft = 1, numpft + do i_scls = 1,nlevsclass + i_scpf = (ft-1)*nlevsclass + i_scls + + if( this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then + this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + storen_canopy_scpf(i_scpf) / & + this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) + end if + if( this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf)>nearzero ) then + this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) = & + storen_understory_scpf(i_scpf) / & + this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) + end if + + end do + end do + elseif(element_list(el).eq.phosphorus_element)then + + do ft = 1, numpft + do i_scls = 1,nlevsclass + i_scpf = (ft-1)*nlevsclass + i_scls + + if( this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then + this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) = & + storep_canopy_scpf(i_scpf) / & + this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) + end if + if( this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf)>nearzero ) then + this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) = & + storep_understory_scpf(i_scpf) / & + this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) + end if + + end do + end do + end if + end do + + ! pass demotion rates and associated carbon fluxes to history + do i_scls = 1,nlevsclass + hio_demotion_rate_si_scls(io_si,i_scls) = sites(s)%demotion_rate(i_scls) * days_per_year / m2_per_ha + hio_promotion_rate_si_scls(io_si,i_scls) = sites(s)%promotion_rate(i_scls) * days_per_year / m2_per_ha + end do + ! + + ! + + ! add the site-level disturbance-associated cwd and litter input fluxes to thir respective flux fields + + 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 - do ilyr = 1,sites(s)%nlevsoil - hio_fragmentation_scaler_sl(io_si,ilyr) = hio_fragmentation_scaler_sl(io_si,ilyr) + cpatch%fragmentation_scaler(ilyr) * cpatch%area * AREA_INV - end do - - do i_fuel = 1,nfsc + 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 - i_agefuel = get_agefuel_class_index(cpatch%age,i_fuel) - hio_fuel_amount_age_fuel(io_si,i_agefuel) = hio_fuel_amount_age_fuel(io_si,i_agefuel) + & - cpatch%fuel_frac(i_fuel) * cpatch%sum_fuel * cpatch%area * AREA_INV + end do - hio_litter_moisture_si_fuel(io_si, i_fuel) = hio_litter_moisture_si_fuel(io_si, i_fuel) + & - cpatch%litter_moisture(i_fuel) * cpatch%area * AREA_INV + enddo siteloop ! site loop - hio_fuel_amount_si_fuel(io_si, i_fuel) = hio_fuel_amount_si_fuel(io_si, i_fuel) + & - cpatch%fuel_frac(i_fuel) * cpatch%sum_fuel * cpatch%area * AREA_INV - - hio_burnt_frac_litter_si_fuel(io_si, i_fuel) = hio_burnt_frac_litter_si_fuel(io_si, i_fuel) + & - cpatch%burnt_frac_litter(i_fuel) * cpatch%frac_burnt * cpatch%area * AREA_INV - end do - - - - - ! Update Litter Flux Variables - - litt_c => cpatch%litter(element_pos(carbon12_element)) - - - do i_cwd = 1, ncwd - - hio_cwd_ag_si_cwdsc(io_si, i_cwd) = hio_cwd_ag_si_cwdsc(io_si, i_cwd) + & - litt_c%ag_cwd(i_cwd)*cpatch%area * AREA_INV - hio_cwd_bg_si_cwdsc(io_si, i_cwd) = hio_cwd_bg_si_cwdsc(io_si, i_cwd) + & - sum(litt_c%bg_cwd(i_cwd,:)) * cpatch%area * AREA_INV - - hio_cwd_ag_out_si_cwdsc(io_si, i_cwd) = hio_cwd_ag_out_si_cwdsc(io_si, i_cwd) + & - litt_c%ag_cwd_frag(i_cwd)*cpatch%area * AREA_INV / & - days_per_year / sec_per_day + end associate + end associate + end associate - hio_cwd_bg_out_si_cwdsc(io_si, i_cwd) = hio_cwd_bg_out_si_cwdsc(io_si, i_cwd) + & - sum(litt_c%bg_cwd_frag(i_cwd,:)) * cpatch%area * AREA_INV / & - days_per_year / sec_per_day + return + end subroutine update_history_dyn2 - end do + ! =============================================================================================== - ipa = ipa + 1 - cpatch => cpatch%younger - end do patchloop !patch loop + subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) + ! --------------------------------------------------------------------------------- + ! This is the call to update the history IO arrays that are expected to only change + ! at the model time-step frequency. + ! This is the general routine that will call the single or multi-dimensional + ! routines if they are called for by the user + ! --------------------------------------------------------------------------------- + ! + ! Arguments + class(fates_history_interface_type) :: this + integer , intent(in) :: nc ! clump index + integer , intent(in) :: nsites + type(ed_site_type) , intent(inout), target :: sites(nsites) + type(bc_in_type) , intent(in) :: bc_in(nsites) + type(bc_out_type) , intent(in) :: bc_out(nsites) + real(r8) , intent(in) :: dt_tstep - - - ! divide so-far-just-summed but to-be-averaged patch-age-class - ! variables by patch-age-class area to get mean values - do ipa2 = 1, nlevage - if (hio_area_si_age(io_si, ipa2) .gt. nearzero) then - hio_lai_si_age(io_si, ipa2) = hio_lai_si_age(io_si, ipa2) / (hio_area_si_age(io_si, ipa2)*AREA) - hio_ncl_si_age(io_si, ipa2) = hio_ncl_si_age(io_si, ipa2) / (hio_area_si_age(io_si, ipa2)*AREA) - do ft = 1, numpft - iagepft = ipa2 + (ft-1) * nlevage - hio_scorch_height_si_agepft(io_si, iagepft) = & - hio_scorch_height_si_agepft(io_si, iagepft) / (hio_area_si_age(io_si, ipa2)*AREA) - enddo - else - hio_lai_si_age(io_si, ipa2) = 0._r8 - hio_ncl_si_age(io_si, ipa2) = 0._r8 - endif - end do - - - - ! pass the cohort termination mortality as a flux to the history, and then reset the termination mortality buffer - ! note there are various ways of reporting the total mortality, so pass to these as well - do ft = 1, numpft - do i_scls = 1,nlevsclass - i_scpf = (ft-1)*nlevsclass + i_scls - ! - ! termination mortality. sum of canopy and understory indices - hio_m6_si_scpf(io_si,i_scpf) = (sites(s)%term_nindivs_canopy(i_scls,ft) + & - sites(s)%term_nindivs_ustory(i_scls,ft)) * & - days_per_year / m2_per_ha - - hio_m6_si_scls(io_si,i_scls) = hio_m6_si_scls(io_si,i_scls) + & - (sites(s)%term_nindivs_canopy(i_scls,ft) + & - sites(s)%term_nindivs_ustory(i_scls,ft)) * & - days_per_year / m2_per_ha - ! - ! add termination mortality to canopy and understory mortality - hio_mortality_canopy_si_scls(io_si,i_scls) = hio_mortality_canopy_si_scls(io_si,i_scls) + & - sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha - - hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & - sites(s)%term_nindivs_ustory(i_scls,ft) * days_per_year / m2_per_ha - - hio_mortality_canopy_si_scpf(io_si,i_scpf) = hio_mortality_canopy_si_scpf(io_si,i_scpf) + & - sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha - - hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & - sites(s)%term_nindivs_ustory(i_scls,ft) * days_per_year / m2_per_ha - - ! - ! imort on its own - hio_m4_si_scpf(io_si,i_scpf) = sites(s)%imort_rate(i_scls, ft) / m2_per_ha - hio_m4_si_scls(io_si,i_scls) = hio_m4_si_scls(io_si,i_scls) + sites(s)%imort_rate(i_scls, ft) / m2_per_ha - ! - ! add imort to other mortality terms. consider imort as understory mortality even if it happens in - ! cohorts that may have been promoted as part of the patch creation, and use the pre-calculated site-level - ! values to avoid biasing the results by the dramatically-reduced number densities in cohorts that are subject to imort - hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & - sites(s)%imort_rate(i_scls, ft) / m2_per_ha - hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & - sites(s)%imort_rate(i_scls, ft) / m2_per_ha - ! - iscag = i_scls ! since imort is by definition something that only happens in newly disturbed patches, treat as such - hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & - sites(s)%imort_rate(i_scls, ft) / m2_per_ha - - ! fire mortality from the site-level diagnostic rates - hio_m5_si_scpf(io_si,i_scpf) = (sites(s)%fmort_rate_canopy(i_scls, ft) + & - sites(s)%fmort_rate_ustory(i_scls, ft)) / m2_per_ha - hio_m5_si_scls(io_si,i_scls) = hio_m5_si_scls(io_si,i_scls) + & - (sites(s)%fmort_rate_canopy(i_scls, ft) + & - sites(s)%fmort_rate_ustory(i_scls, ft)) / m2_per_ha - ! - hio_crownfiremort_si_scpf(io_si,i_scpf) = sites(s)%fmort_rate_crown(i_scls, ft) / m2_per_ha - hio_cambialfiremort_si_scpf(io_si,i_scpf) = sites(s)%fmort_rate_cambial(i_scls, ft) / m2_per_ha - ! - ! fire components of overall canopy and understory mortality - hio_mortality_canopy_si_scpf(io_si,i_scpf) = hio_mortality_canopy_si_scpf(io_si,i_scpf) + & - sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha - hio_mortality_canopy_si_scls(io_si,i_scls) = hio_mortality_canopy_si_scls(io_si,i_scls) + & - sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha - - ! Shijie: Think about how to add later? - !if ( cpatch%land_use_label .eq. secondaryland ) then - ! hio_mortality_canopy_secondary_si_scls(io_si,i_scls) = hio_mortality_canopy_secondary_si_scls(io_si,i_scls) + & - ! sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha - !end if - - ! the fire mortality rates for each layer are total dead, since the usable - ! output will then normalize by the counts, we are allowed to sum over layers - hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & - sites(s)%fmort_rate_ustory(i_scls, ft) / m2_per_ha - - hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & - sites(s)%fmort_rate_ustory(i_scls, ft) / m2_per_ha - - ! - ! for scag variables, also treat as happening in the newly-disurbed patch - - hio_mortality_canopy_si_scag(io_si,iscag) = hio_mortality_canopy_si_scag(io_si,iscag) + & - sites(s)%fmort_rate_canopy(i_scls, ft) / m2_per_ha - hio_mortality_understory_si_scag(io_si,iscag) = hio_mortality_understory_si_scag(io_si,iscag) + & - sites(s)%fmort_rate_ustory(i_scls, ft) / m2_per_ha - - ! while in this loop, pass the fusion-induced growth rate flux to history - hio_growthflux_fusion_si_scpf(io_si,i_scpf) = hio_growthflux_fusion_si_scpf(io_si,i_scpf) + & - sites(s)%growthflux_fusion(i_scls, ft) * days_per_year / m2_per_ha - - end do - end do - - - - do ft = 1, numpft - hio_mortality_carbonflux_si_pft(io_si,ft) = hio_mortality_carbonflux_si_pft(io_si,ft) + & - (sites(s)%fmort_carbonflux_canopy(ft) + & - sites(s)%fmort_carbonflux_ustory(ft) ) / g_per_kg + & - sites(s)%imort_carbonflux(ft) + & - sites(s)%term_carbonflux_ustory(ft) * days_per_sec * ha_per_m2 + & - sites(s)%term_carbonflux_canopy(ft) * days_per_sec * ha_per_m2 - - hio_firemortality_carbonflux_si_pft(io_si,ft) = sites(s)%fmort_carbonflux_canopy(ft) / g_per_kg - end do - - ! add imort and fmort to aboveground woody mortality - do ft = 1, numpft - do i_scls = 1,nlevsclass - i_scpf = (ft-1)*nlevsclass + i_scls - hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) = hio_abg_mortality_cflux_si_scpf(io_si,i_scpf) + & - (sites(s)%fmort_abg_flux(i_scls,ft) / g_per_kg ) + & - sites(s)%imort_abg_flux(i_scls,ft) + & - (sites(s)%term_abg_flux(i_scls,ft) * days_per_sec * ha_per_m2 ) - end do - end do - - - if(hlm_use_tree_damage .eq. itrue) then - - do ft = 1, numpft - do icdam = 1, nlevdamage - do i_scls = 1,nlevsclass - - icdsc = (icdam-1)*nlevsclass + i_scls - icdpf = (icdam-1)*nlevsclass + i_scls + & - (ft-1) * nlevsclass * nlevdamage - - this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) = & - this%hvars(ih_mortality_si_cdpf)%r82d(io_si, icdpf) + & - ( (sites(s)%term_nindivs_canopy_damage(icdam, i_scls, ft) * days_per_year) + & - (sites(s)%term_nindivs_ustory_damage(icdam, i_scls, ft) * days_per_year) + & - sites(s)%imort_rate_damage(icdam, i_scls, ft) + & - sites(s)%fmort_rate_canopy_damage(icdam, i_scls, ft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, ft) ) / m2_per_ha - - this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_mortality_canopy_si_cdpf)%r82d(io_si,icdpf) + & - ( sites(s)%term_nindivs_canopy_damage(icdam,i_scls,ft) * days_per_year + & - sites(s)%fmort_rate_canopy_damage(icdam, i_scls, ft) )/ m2_per_ha - - this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) = & - this%hvars(ih_mortality_understory_si_cdpf)%r82d(io_si,icdpf) + & - ( sites(s)%term_nindivs_ustory_damage(icdam, i_scls,ft) * days_per_year + & - sites(s)%imort_rate_damage(icdam, i_scls, ft) + & - sites(s)%fmort_rate_ustory_damage(icdam, i_scls, ft) )/ m2_per_ha - - end do - end do - end do - end if - - sites(s)%term_nindivs_canopy(:,:) = 0._r8 - sites(s)%term_nindivs_ustory(:,:) = 0._r8 - sites(s)%imort_carbonflux(:) = 0._r8 - sites(s)%imort_rate(:,:) = 0._r8 - sites(s)%fmort_rate_canopy(:,:) = 0._r8 - sites(s)%fmort_rate_ustory(:,:) = 0._r8 - sites(s)%fmort_carbonflux_canopy(:) = 0._r8 - sites(s)%fmort_carbonflux_ustory(:) = 0._r8 - sites(s)%fmort_rate_cambial(:,:) = 0._r8 - sites(s)%fmort_rate_crown(:,:) = 0._r8 - sites(s)%growthflux_fusion(:,:) = 0._r8 - sites(s)%fmort_abg_flux(:,:) = 0._r8 - sites(s)%imort_abg_flux(:,:) = 0._r8 - sites(s)%term_abg_flux(:,:) = 0._r8 - - sites(s)%imort_rate_damage(:,:,:) = 0.0_r8 - sites(s)%term_nindivs_canopy_damage(:,:,:) = 0.0_r8 - sites(s)%term_nindivs_ustory_damage(:,:,:) = 0.0_r8 - sites(s)%imort_cflux_damage(:,:) = 0._r8 - sites(s)%term_cflux_canopy_damage(:,:) = 0._r8 - sites(s)%term_cflux_ustory_damage(:,:) = 0._r8 - sites(s)%fmort_rate_canopy_damage(:,:,:) = 0._r8 - sites(s)%fmort_rate_ustory_damage(:,:,:) = 0._r8 - sites(s)%fmort_cflux_canopy_damage(:,:) = 0._r8 - sites(s)%fmort_cflux_ustory_damage(:,:) = 0._r8 - sites(s)%crownarea_canopy_damage = 0._r8 - sites(s)%crownarea_ustory_damage = 0._r8 - - ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer - do ft = 1, numpft - ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer - hio_recruitment_si_pft(io_si,ft) = sites(s)%recruitment_rate(ft) * days_per_year / m2_per_ha - - ! Gridcell output and inputs - hio_seeds_out_gc_si_pft(io_si,ft) = sites(s)%seed_out(ft) - hio_seeds_in_gc_si_pft(io_si,ft) = sites(s)%seed_in(ft) - end do - sites(s)%recruitment_rate(:) = 0._r8 - - ! summarize all of the mortality fluxes by PFT - do ft = 1, numpft - do i_scls = 1,nlevsclass - i_scpf = (ft-1)*nlevsclass + i_scls - - hio_mortality_si_pft(io_si,ft) = hio_mortality_si_pft(io_si,ft) + & - hio_m1_si_scpf(io_si,i_scpf) + & - hio_m2_si_scpf(io_si,i_scpf) + & - hio_m3_si_scpf(io_si,i_scpf) + & - hio_m4_si_scpf(io_si,i_scpf) + & - hio_m5_si_scpf(io_si,i_scpf) + & - hio_m6_si_scpf(io_si,i_scpf) + & - hio_m7_si_scpf(io_si,i_scpf) + & - hio_m8_si_scpf(io_si,i_scpf) + & - hio_m9_si_scpf(io_si,i_scpf) + & - hio_m10_si_scpf(io_si,i_scpf) - - if(hlm_use_tree_damage .eq. itrue) then - hio_mortality_si_pft(io_si, ft) = hio_mortality_si_pft(io_si,ft) + & - this%hvars(ih_m11_si_scpf)%r82d(io_si,i_scpf) - end if - - end do - end do - - ! ------------------------------------------------------------------------------ - ! Some carbon only litter diagnostics (legacy) - ! ------------------------------------------------------------------------------ - - flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) - - - - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - - - - - - cpatch => cpatch%younger - end do - - ! ------------------------------------------------------------------------------ - ! Diagnostics discretized by element type - ! ------------------------------------------------------------------------------ - - hio_cwd_elcwd(io_si,:) = 0._r8 - - do el = 1, num_elements - - flux_diags => sites(s)%flux_diags(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_cwd_ag_elem(io_si,el) = 0._r8 - hio_cwd_bg_elem(io_si,el) = 0._r8 - hio_fines_ag_elem(io_si,el) = 0._r8 - hio_fines_bg_elem(io_si,el) = 0._r8 - - hio_seed_bank_elem(io_si,el) = 0._r8 - hio_seed_germ_elem(io_si,el) = 0._r8 - hio_seed_decay_elem(io_si,el) = 0._r8 - hio_seeds_in_local_elem(io_si,el) = 0._r8 - hio_seed_in_extern_elem(io_si,el) = 0._r8 - hio_litter_out_elem(io_si,el) = 0._r8 - - ! Plant multi-element states and fluxes - ! Zero states, and set the fluxes - if(element_list(el).eq.carbon12_element)then - this%hvars(ih_totvegc_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_leafc_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_fnrtc_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_sapwc_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_storec_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_reproc_scpf)%r82d(io_si,:) = 0._r8 - - elseif(element_list(el).eq.nitrogen_element)then - - this%hvars(ih_totvegn_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_leafn_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_fnrtn_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_sapwn_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_storen_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_repron_scpf)%r82d(io_si,:) = 0._r8 - - elseif(element_list(el).eq.phosphorus_element)then - this%hvars(ih_totvegp_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_leafp_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_fnrtp_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_sapwp_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_storep_scpf)%r82d(io_si,:) = 0._r8 - this%hvars(ih_reprop_scpf)%r82d(io_si,:) = 0._r8 - - - - end if - - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - - litt => cpatch%litter(el) - - area_frac = cpatch%area * AREA_INV - - ! Sum up all output fluxes (fragmentation) - hio_litter_out_elem(io_si,el) = hio_litter_out_elem(io_si,el) + & - (sum(litt%leaf_fines_frag(:)) + & - sum(litt%root_fines_frag(:,:)) + & - sum(litt%ag_cwd_frag(:)) + & - sum(litt%bg_cwd_frag(:,:)) + & - sum(litt%seed_decay(:)) + & - sum(litt%seed_germ_decay(:))) * cpatch%area / m2_per_ha / sec_per_day - - hio_seed_bank_elem(io_si,el) = hio_seed_bank_elem(io_si,el) + & - sum(litt%seed(:)) * cpatch%area / m2_per_ha - - hio_seed_germ_elem(io_si,el) = hio_seed_germ_elem(io_si,el) + & - sum(litt%seed_germ(:)) * cpatch%area / m2_per_ha - - hio_seed_decay_elem(io_si,el) = hio_seed_decay_elem(io_si,el) + & - sum(litt%seed_decay(:) + litt%seed_germ_decay(:) ) * & - cpatch%area / m2_per_ha / sec_per_day - - hio_seeds_in_local_elem(io_si,el) = hio_seeds_in_local_elem(io_si,el) + & - sum(litt%seed_in_local(:)) * cpatch%area / m2_per_ha / sec_per_day - - hio_seed_in_extern_elem(io_si,el) = hio_seed_in_extern_elem(io_si,el) + & - sum(litt%seed_in_extern(:)) * cpatch%area / m2_per_ha / sec_per_day - - ! Litter State Variables - hio_cwd_ag_elem(io_si,el) = hio_cwd_ag_elem(io_si,el) + & - sum(litt%ag_cwd(:)) * cpatch%area / m2_per_ha - - hio_cwd_bg_elem(io_si,el) = hio_cwd_bg_elem(io_si,el) + & - sum(litt%bg_cwd(:,:)) * cpatch%area / m2_per_ha - - hio_fines_ag_elem(io_si,el) = hio_fines_ag_elem(io_si,el) + & - sum(litt%leaf_fines(:)) * cpatch%area / m2_per_ha - - hio_fines_bg_elem(io_si,el) = hio_fines_bg_elem(io_si,el) + & - sum(litt%root_fines(:,:)) * cpatch%area / m2_per_ha - - do i_cwd=1,ncwd - elcwd = (el-1)*ncwd+i_cwd - hio_cwd_elcwd(io_si,elcwd) = hio_cwd_elcwd(io_si,elcwd) + & - (litt%ag_cwd(i_cwd) + sum(litt%bg_cwd(i_cwd,:))) * & - cpatch%area / m2_per_ha - - end do - - ! Load Mass States - ccohort => cpatch%tallest - do while(associated(ccohort)) - - sapw_m = ccohort%prt%GetState(sapw_organ, element_list(el)) - struct_m = ccohort%prt%GetState(struct_organ, element_list(el)) - leaf_m = ccohort%prt%GetState(leaf_organ, element_list(el)) - fnrt_m = ccohort%prt%GetState(fnrt_organ, element_list(el)) - store_m = ccohort%prt%GetState(store_organ, element_list(el)) - repro_m = ccohort%prt%GetState(repro_organ, element_list(el)) - total_m = sapw_m+struct_m+leaf_m+fnrt_m+store_m+repro_m - - - i_scpf = ccohort%size_by_pft_class - - if(element_list(el).eq.carbon12_element)then - this%hvars(ih_totvegc_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_totvegc_scpf)%r82d(io_si,i_scpf) + & - total_m * ccohort%n / m2_per_ha - this%hvars(ih_leafc_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_leafc_scpf)%r82d(io_si,i_scpf) + & - leaf_m * ccohort%n / m2_per_ha - this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_fnrtc_scpf)%r82d(io_si,i_scpf) + & - fnrt_m * ccohort%n / m2_per_ha - this%hvars(ih_sapwc_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_sapwc_scpf)%r82d(io_si,i_scpf) + & - sapw_m * ccohort%n / m2_per_ha - this%hvars(ih_storec_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storec_scpf)%r82d(io_si,i_scpf) + & - store_m * ccohort%n / m2_per_ha - this%hvars(ih_reproc_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_reproc_scpf)%r82d(io_si,i_scpf) + & - repro_m * ccohort%n / m2_per_ha - elseif(element_list(el).eq.nitrogen_element)then - - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) - - this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_totvegn_scpf)%r82d(io_si,i_scpf) + & - total_m * ccohort%n / m2_per_ha - this%hvars(ih_leafn_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_leafn_scpf)%r82d(io_si,i_scpf) + & - leaf_m * ccohort%n / m2_per_ha - this%hvars(ih_fnrtn_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_fnrtn_scpf)%r82d(io_si,i_scpf) + & - fnrt_m * ccohort%n / m2_per_ha - this%hvars(ih_sapwn_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_sapwn_scpf)%r82d(io_si,i_scpf) + & - sapw_m * ccohort%n / m2_per_ha - this%hvars(ih_storen_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storen_scpf)%r82d(io_si,i_scpf) + & - store_m * ccohort%n / m2_per_ha - this%hvars(ih_repron_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_repron_scpf)%r82d(io_si,i_scpf) + & - repro_m * ccohort%n / m2_per_ha - - elseif(element_list(el).eq.phosphorus_element)then - - store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) - - this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_totvegp_scpf)%r82d(io_si,i_scpf) + & - total_m * ccohort%n / m2_per_ha - this%hvars(ih_leafp_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_leafp_scpf)%r82d(io_si,i_scpf) + & - leaf_m * ccohort%n / m2_per_ha - this%hvars(ih_fnrtp_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_fnrtp_scpf)%r82d(io_si,i_scpf) + & - fnrt_m * ccohort%n / m2_per_ha - this%hvars(ih_sapwp_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_sapwp_scpf)%r82d(io_si,i_scpf) + & - sapw_m * ccohort%n / m2_per_ha - this%hvars(ih_storep_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_storep_scpf)%r82d(io_si,i_scpf) + & - store_m * ccohort%n / m2_per_ha - this%hvars(ih_reprop_scpf)%r82d(io_si,i_scpf) = & - this%hvars(ih_reprop_scpf)%r82d(io_si,i_scpf) + & - repro_m * ccohort%n / m2_per_ha - - end if - - ccohort => ccohort%shorter - end do ! end cohort loop - - cpatch => cpatch%younger - end do ! end patch loop - - end do ! end element loop - - - ! Normalize storage fractions and L2FR - - - - do ft = 1, numpft - do i_scls = 1,nlevsclass - i_scpf = (ft-1)*nlevsclass + i_scls - - if( this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then - this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - storec_canopy_scpf(i_scpf) / & - this%hvars(ih_storectfrac_canopy_scpf)%r82d(io_si,i_scpf) - end if - if( this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf)>nearzero ) then - this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) = & - storec_understory_scpf(i_scpf) / & - this%hvars(ih_storectfrac_ustory_scpf)%r82d(io_si,i_scpf) - end if - - end do - end do - - do el = 1, num_elements - - if(element_list(el).eq.nitrogen_element)then - - do ft = 1, numpft - do i_scls = 1,nlevsclass - i_scpf = (ft-1)*nlevsclass + i_scls - - if( this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then - this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - storen_canopy_scpf(i_scpf) / & - this%hvars(ih_storentfrac_canopy_scpf)%r82d(io_si,i_scpf) - end if - if( this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf)>nearzero ) then - this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) = & - storen_understory_scpf(i_scpf) / & - this%hvars(ih_storentfrac_understory_scpf)%r82d(io_si,i_scpf) - end if - - end do - end do - elseif(element_list(el).eq.phosphorus_element)then - - do ft = 1, numpft - do i_scls = 1,nlevsclass - i_scpf = (ft-1)*nlevsclass + i_scls - - if( this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf)>nearzero ) then - this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) = & - storep_canopy_scpf(i_scpf) / & - this%hvars(ih_storeptfrac_canopy_scpf)%r82d(io_si,i_scpf) - end if - if( this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf)>nearzero ) then - this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) = & - storep_understory_scpf(i_scpf) / & - this%hvars(ih_storeptfrac_understory_scpf)%r82d(io_si,i_scpf) - end if - - end do - end do - end if - end do - - ! pass demotion rates and associated carbon fluxes to history - do i_scls = 1,nlevsclass - hio_demotion_rate_si_scls(io_si,i_scls) = sites(s)%demotion_rate(i_scls) * days_per_year / m2_per_ha - hio_promotion_rate_si_scls(io_si,i_scls) = sites(s)%promotion_rate(i_scls) * days_per_year / m2_per_ha - end do - ! - - ! - - ! add the site-level disturbance-associated cwd and litter input fluxes to thir respective flux fields - - 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 - - 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 - - end do - - enddo siteloop ! site loop - - end associate - end associate -end associate - -return -end subroutine update_history_dyn2 - - ! =============================================================================================== - -subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) - - ! --------------------------------------------------------------------------------- - ! This is the call to update the history IO arrays that are expected to only change - ! at the model time-step frequency. - ! This is the general routine that will call the single or multi-dimensional - ! routines if they are called for by the user - ! --------------------------------------------------------------------------------- + if(hlm_hist_level_hifrq>0) then + call update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) + if(hlm_hist_level_hifrq>1) then + call update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) + end if + end if - if(hlm_hist_level_hifrq>0) then - call update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) - if(hlm_hist_level_hifrq>1) then - call update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) - end if - end if - - return -end subroutine update_history_hifrq + return + end subroutine update_history_hifrq subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) @@ -4810,12 +4856,12 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) integer :: age_class ! class age index real(r8) :: site_area_veg_inv ! inverse canopy area of the site (1/m2) real(r8) :: site_area_rad_inv ! inverse canopy area of site for only - ! patches that called the solver + ! patches that called the solver real(r8) :: dt_tstep_inv ! inverse timestep (1/sec) real(r8) :: n_perm2 ! number of plants per square meter real(r8) :: sum_area_rad ! sum of patch canopy areas real(r8),allocatable :: age_area_rad(:) - + type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort @@ -4823,7 +4869,7 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) ! This routine is only called for hlm_hist_level_hifrq >= 1 if(hlm_hist_level_hifrq<1) return - + associate( hio_gpp_si => this%hvars(ih_gpp_si)%r81d, & hio_gpp_secondary_si => this%hvars(ih_gpp_secondary_si)%r81d, & hio_npp_si => this%hvars(ih_npp_si)%r81d, & @@ -4853,15 +4899,15 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) ! Flush the relevant history variables - call this%flush_hvars(nc,upfreq_in=2) + call this%flush_hvars(nc,upfreq_in=group_hifr_simple) dt_tstep_inv = 1.0_r8/dt_tstep allocate(age_area_rad(size(ED_val_history_ageclass_bin_edges,1)+1)) - + do_sites: do s = 1,nsites - call this%zero_site_hvars(sites(s), upfreq_in=2) + call this%zero_site_hvars(sites(s), upfreq_in=group_hifr_simple) io_si = sites(s)%h_gid @@ -4886,9 +4932,9 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) end if cpatch => cpatch%younger end do - + sum_area_rad = sum(age_area_rad(:)) - + if_anyrad: if(sum_area_radnearzero ) then age_class = get_age_class_index(cpatch%age) - + hio_vis_rad_err_si(io_si) = hio_vis_rad_err_si(io_si) + & - cpatch%rad_err(ivis)*cpatch%total_canopy_area/sum_area_rad + cpatch%rad_error(ivis)*cpatch%total_canopy_area/sum_area_rad hio_nir_rad_err_si(io_si) = hio_nir_rad_err_si(io_si) + & - cpatch%rad_err(inir)*cpatch%total_canopy_area/sum_area_rad - + cpatch%rad_error(inir)*cpatch%total_canopy_area/sum_area_rad + end if cpatch => cpatch%younger end do end if if_anyrad - + ! Diagnostics that are only relevant if there is vegetation present on this site ! ie, non-zero canopy area @@ -4922,7 +4968,7 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) site_area_veg_inv = site_area_veg_inv + cpatch%total_canopy_area cpatch => cpatch%younger end do !patch loop - + if_veg_area: if(site_area_veg_inv < nearzero) then hio_c_stomata_si(io_si) = hlm_hio_ignore_val @@ -4940,14 +4986,14 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) do while(associated(cpatch)) ipa = ipa + 1 - + hio_c_stomata_si(io_si) = hio_c_stomata_si(io_si) + & cpatch%c_stomata * cpatch%total_canopy_area * mol_per_umol * site_area_veg_inv hio_c_lblayer_si(io_si) = hio_c_lblayer_si(io_si) + & cpatch%c_lblayer * cpatch%total_canopy_area * mol_per_umol * site_area_veg_inv - + ! Only accumulate the instantaneous vegetation temperature for vegetated patches if (cpatch%patchno .ne. 0) then hio_tveg(io_si) = hio_tveg(io_si) + & @@ -4989,7 +5035,7 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) if(cpatch%land_use_label .eq. secondaryland) then hio_npp_secondary_si(io_si) = hio_npp_secondary_si(io_si) + & ccohort%npp_tstep * n_perm2 * dt_tstep_inv - + hio_gpp_secondary_si(io_si) = hio_gpp_secondary_si(io_si) + & ccohort%gpp_tstep * n_perm2 * dt_tstep_inv @@ -5037,20 +5083,20 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) end if if_notnew ccohort => ccohort%taller end do - + cpatch => cpatch%younger end do end if if_veg_area end do do_sites deallocate(age_area_rad) - + end associate return end subroutine update_history_hifrq1 ! =============================================================================================== - + subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) ! --------------------------------------------------------------------------------- @@ -5089,63 +5135,63 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) real(r8) :: clllpf_area ! area footprint (m2) for the current cl x ll x pft bin real(r8) :: clll_area ! area footprint (m2) for the cl x ll bin (ie adds up pfts in parallel) real(r8) :: cl_area ! total weight of all ll x pft bins in the canopy layer - + type(fates_patch_type),pointer :: cpatch type(fates_cohort_type),pointer :: ccohort real(r8) :: dt_tstep_inv ! Time step in frequency units (/s) ! This routine is only called for hlm_hist_level_hifrq >= 1 if(hlm_hist_level_hifrq<2) return - + associate( hio_ar_si_scpf => this%hvars(ih_ar_si_scpf)%r82d, & - hio_ar_grow_si_scpf => this%hvars(ih_ar_grow_si_scpf)%r82d, & - hio_ar_maint_si_scpf => this%hvars(ih_ar_maint_si_scpf)%r82d, & - hio_ar_agsapm_si_scpf => this%hvars(ih_ar_agsapm_si_scpf)%r82d, & - hio_ar_darkm_si_scpf => this%hvars(ih_ar_darkm_si_scpf)%r82d, & - hio_ar_crootm_si_scpf => this%hvars(ih_ar_crootm_si_scpf)%r82d, & - hio_ar_frootm_si_scpf => this%hvars(ih_ar_frootm_si_scpf)%r82d, & - hio_rdark_canopy_si_scls => this%hvars(ih_rdark_canopy_si_scls)%r82d, & - hio_livestem_mr_canopy_si_scls => this%hvars(ih_livestem_mr_canopy_si_scls)%r82d, & - hio_livecroot_mr_canopy_si_scls => this%hvars(ih_livecroot_mr_canopy_si_scls)%r82d, & - hio_froot_mr_canopy_si_scls => this%hvars(ih_froot_mr_canopy_si_scls)%r82d, & - hio_resp_g_canopy_si_scls => this%hvars(ih_resp_g_canopy_si_scls)%r82d, & - hio_resp_m_canopy_si_scls => this%hvars(ih_resp_m_canopy_si_scls)%r82d, & - hio_rdark_understory_si_scls => this%hvars(ih_rdark_understory_si_scls)%r82d, & - hio_livestem_mr_understory_si_scls => this%hvars(ih_livestem_mr_understory_si_scls)%r82d, & - hio_livecroot_mr_understory_si_scls => this%hvars(ih_livecroot_mr_understory_si_scls)%r82d, & - hio_froot_mr_understory_si_scls => this%hvars(ih_froot_mr_understory_si_scls)%r82d, & - hio_resp_g_understory_si_scls => this%hvars(ih_resp_g_understory_si_scls)%r82d, & - hio_resp_m_understory_si_scls => this%hvars(ih_resp_m_understory_si_scls)%r82d, & - hio_gpp_si_age => this%hvars(ih_gpp_si_age)%r82d, & - hio_npp_si_age => this%hvars(ih_npp_si_age)%r82d, & - hio_c_stomata_si_age => this%hvars(ih_c_stomata_si_age)%r82d, & - hio_c_lblayer_si_age => this%hvars(ih_c_lblayer_si_age)%r82d, & - hio_parsun_z_si_cnlf => this%hvars(ih_parsun_z_si_cnlf)%r82d, & - hio_parsha_z_si_cnlf => this%hvars(ih_parsha_z_si_cnlf)%r82d, & - hio_ts_net_uptake_si_cnlf => this%hvars(ih_ts_net_uptake_si_cnlf)%r82d, & - hio_parsun_z_si_cnlfpft => this%hvars(ih_parsun_z_si_cnlfpft)%r82d, & - hio_parsha_z_si_cnlfpft => this%hvars(ih_parsha_z_si_cnlfpft)%r82d, & - hio_laisun_z_si_cnlf => this%hvars(ih_laisun_z_si_cnlf)%r82d, & - hio_laisha_z_si_cnlf => this%hvars(ih_laisha_z_si_cnlf)%r82d, & - hio_laisun_clllpf => this%hvars(ih_laisun_clllpf)%r82d, & - hio_laisha_clllpf => this%hvars(ih_laisha_clllpf)%r82d, & - hio_crownfrac_clllpf => this%hvars(ih_crownfrac_clllpf)%r82d, & - hio_parprof_dir_si_cnlf => this%hvars(ih_parprof_dir_si_cnlf)%r82d, & - hio_parprof_dif_si_cnlf => this%hvars(ih_parprof_dif_si_cnlf)%r82d, & - hio_parprof_dir_si_cnlfpft => this%hvars(ih_parprof_dir_si_cnlfpft)%r82d, & - hio_parprof_dif_si_cnlfpft => this%hvars(ih_parprof_dif_si_cnlfpft)%r82d, & - hio_parsun_si_can => this%hvars(ih_parsun_si_can)%r82d, & - hio_parsha_si_can => this%hvars(ih_parsha_si_can)%r82d, & - hio_laisun_si_can => this%hvars(ih_laisun_si_can)%r82d, & - hio_laisha_si_can => this%hvars(ih_laisha_si_can)%r82d ) - + hio_ar_grow_si_scpf => this%hvars(ih_ar_grow_si_scpf)%r82d, & + hio_ar_maint_si_scpf => this%hvars(ih_ar_maint_si_scpf)%r82d, & + hio_ar_agsapm_si_scpf => this%hvars(ih_ar_agsapm_si_scpf)%r82d, & + hio_ar_darkm_si_scpf => this%hvars(ih_ar_darkm_si_scpf)%r82d, & + hio_ar_crootm_si_scpf => this%hvars(ih_ar_crootm_si_scpf)%r82d, & + hio_ar_frootm_si_scpf => this%hvars(ih_ar_frootm_si_scpf)%r82d, & + hio_rdark_canopy_si_scls => this%hvars(ih_rdark_canopy_si_scls)%r82d, & + hio_livestem_mr_canopy_si_scls => this%hvars(ih_livestem_mr_canopy_si_scls)%r82d, & + hio_livecroot_mr_canopy_si_scls => this%hvars(ih_livecroot_mr_canopy_si_scls)%r82d, & + hio_froot_mr_canopy_si_scls => this%hvars(ih_froot_mr_canopy_si_scls)%r82d, & + hio_resp_g_canopy_si_scls => this%hvars(ih_resp_g_canopy_si_scls)%r82d, & + hio_resp_m_canopy_si_scls => this%hvars(ih_resp_m_canopy_si_scls)%r82d, & + hio_rdark_understory_si_scls => this%hvars(ih_rdark_understory_si_scls)%r82d, & + hio_livestem_mr_understory_si_scls => this%hvars(ih_livestem_mr_understory_si_scls)%r82d, & + hio_livecroot_mr_understory_si_scls => this%hvars(ih_livecroot_mr_understory_si_scls)%r82d, & + hio_froot_mr_understory_si_scls => this%hvars(ih_froot_mr_understory_si_scls)%r82d, & + hio_resp_g_understory_si_scls => this%hvars(ih_resp_g_understory_si_scls)%r82d, & + hio_resp_m_understory_si_scls => this%hvars(ih_resp_m_understory_si_scls)%r82d, & + hio_gpp_si_age => this%hvars(ih_gpp_si_age)%r82d, & + hio_npp_si_age => this%hvars(ih_npp_si_age)%r82d, & + hio_c_stomata_si_age => this%hvars(ih_c_stomata_si_age)%r82d, & + hio_c_lblayer_si_age => this%hvars(ih_c_lblayer_si_age)%r82d, & + hio_parsun_z_si_cnlf => this%hvars(ih_parsun_z_si_cnlf)%r82d, & + hio_parsha_z_si_cnlf => this%hvars(ih_parsha_z_si_cnlf)%r82d, & + hio_ts_net_uptake_si_cnlf => this%hvars(ih_ts_net_uptake_si_cnlf)%r82d, & + hio_parsun_z_si_cnlfpft => this%hvars(ih_parsun_z_si_cnlfpft)%r82d, & + hio_parsha_z_si_cnlfpft => this%hvars(ih_parsha_z_si_cnlfpft)%r82d, & + hio_laisun_z_si_cnlf => this%hvars(ih_laisun_z_si_cnlf)%r82d, & + hio_laisha_z_si_cnlf => this%hvars(ih_laisha_z_si_cnlf)%r82d, & + hio_laisun_clllpf => this%hvars(ih_laisun_clllpf)%r82d, & + hio_laisha_clllpf => this%hvars(ih_laisha_clllpf)%r82d, & + hio_crownfrac_clllpf => this%hvars(ih_crownfrac_clllpf)%r82d, & + hio_parprof_dir_si_cnlf => this%hvars(ih_parprof_dir_si_cnlf)%r82d, & + hio_parprof_dif_si_cnlf => this%hvars(ih_parprof_dif_si_cnlf)%r82d, & + hio_parprof_dir_si_cnlfpft => this%hvars(ih_parprof_dir_si_cnlfpft)%r82d, & + hio_parprof_dif_si_cnlfpft => this%hvars(ih_parprof_dif_si_cnlfpft)%r82d, & + hio_parsun_si_can => this%hvars(ih_parsun_si_can)%r82d, & + hio_parsha_si_can => this%hvars(ih_parsha_si_can)%r82d, & + hio_laisun_si_can => this%hvars(ih_laisun_si_can)%r82d, & + hio_laisha_si_can => this%hvars(ih_laisha_si_can)%r82d ) + ! Flush the relevant history variables - call this%flush_hvars(nc,upfreq_in=upfreq_hifr_multi) + call this%flush_hvars(nc,upfreq_in=group_hifr_complx) dt_tstep_inv = 1.0_r8/dt_tstep do_sites: do s = 1,nsites - + site_area_veg_inv = 0._r8 cpatch => sites(s)%oldest_patch do while(associated(cpatch)) @@ -5161,25 +5207,25 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) io_si = sites(s)%h_gid ipa = 0 - + patch_area_by_age(1:nlevage) = 0._r8 canopy_area_by_age(1:nlevage) = 0._r8 - - call this%zero_site_hvars(sites(s), upfreq_in=upfreq_hifr_multi) - + + call this%zero_site_hvars(sites(s), upfreq_in=group_hifr_complx) + cpatch => sites(s)%oldest_patch do while(associated(cpatch)) ipa = ipa + 1 - + patch_area_by_age(cpatch%age_class) = & patch_area_by_age(cpatch%age_class) + cpatch%area canopy_area_by_age(cpatch%age_class) = & canopy_area_by_age(cpatch%age_class) + cpatch%total_canopy_area - - + + ! Canopy resitance terms hio_c_stomata_si_age(io_si,cpatch%age_class) = & hio_c_stomata_si_age(io_si,cpatch%age_class) + & @@ -5189,93 +5235,93 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_c_lblayer_si_age(io_si,cpatch%age_class) + & cpatch%c_lblayer * cpatch%total_canopy_area * mol_per_umol - ccohort => cpatch%shortest - do while(associated(ccohort)) + ccohort => cpatch%shortest + do while(associated(ccohort)) n_perm2 = ccohort%n * AREA_INV if ( .not. ccohort%isnew ) then - npp = ccohort%npp_tstep - resp_g = ccohort%resp_g_tstep - aresp = ccohort%resp_tstep + npp = ccohort%npp_tstep + resp_g = ccohort%resp_g_tstep + aresp = ccohort%resp_tstep ! Calculate index for the scpf class associate( scpf => ccohort%size_by_pft_class, & - scls => ccohort%size_class ) - - ! Total AR (kgC/m2/s) = (kgC/plant/step) / (s/step) * (plant/m2) - hio_ar_si_scpf(io_si,scpf) = hio_ar_si_scpf(io_si,scpf) + & - (ccohort%resp_tstep*dt_tstep_inv) * n_perm2 - - ! Growth AR (kgC/m2/s) - hio_ar_grow_si_scpf(io_si,scpf) = hio_ar_grow_si_scpf(io_si,scpf) + & - (resp_g*dt_tstep_inv) * n_perm2 - - ! Maint AR (kgC/m2/s) - hio_ar_maint_si_scpf(io_si,scpf) = hio_ar_maint_si_scpf(io_si,scpf) + & - (ccohort%resp_m*dt_tstep_inv) * n_perm2 - - ! Maintenance AR partition variables are stored as rates (kgC/plant/s) - ! (kgC/m2/s) = (kgC/plant/s) * (plant/m2) - hio_ar_agsapm_si_scpf(io_si,scpf) = hio_ar_agsapm_si_scpf(io_si,scpf) + & - ccohort%livestem_mr * n_perm2 - - ! (kgC/m2/s) = (kgC/plant/s) * (plant/m2) - hio_ar_darkm_si_scpf(io_si,scpf) = hio_ar_darkm_si_scpf(io_si,scpf) + & - ccohort%rdark * n_perm2 - - ! (kgC/m2/s) = (kgC/plant/s) * (plant/m2) - hio_ar_crootm_si_scpf(io_si,scpf) = hio_ar_crootm_si_scpf(io_si,scpf) + & - ccohort%livecroot_mr * n_perm2 - - ! (kgC/m2/s) = (kgC/plant/s) * (plant/m2) - hio_ar_frootm_si_scpf(io_si,scpf) = hio_ar_frootm_si_scpf(io_si,scpf) + & - ccohort%froot_mr * n_perm2 - - ! accumulate fluxes per patch age bin - hio_gpp_si_age(io_si,cpatch%age_class) = hio_gpp_si_age(io_si,cpatch%age_class) & - + ccohort%gpp_tstep * ccohort%n * dt_tstep_inv - - hio_npp_si_age(io_si,cpatch%age_class) = hio_npp_si_age(io_si,cpatch%age_class) & - + npp * ccohort%n * dt_tstep_inv - - ! accumulate fluxes on canopy- and understory- separated fluxes - if (ccohort%canopy_layer .eq. 1) then - - ! size-resolved respiration fluxes are in kg C / m2 / s - hio_rdark_canopy_si_scls(io_si,scls) = hio_rdark_canopy_si_scls(io_si,scls) + & - ccohort%rdark * ccohort%n * ha_per_m2 - hio_livestem_mr_canopy_si_scls(io_si,scls) = hio_livestem_mr_canopy_si_scls(io_si,scls) + & - ccohort%livestem_mr * ccohort%n * ha_per_m2 - hio_livecroot_mr_canopy_si_scls(io_si,scls) = hio_livecroot_mr_canopy_si_scls(io_si,scls) + & - ccohort%livecroot_mr * ccohort%n * ha_per_m2 - hio_froot_mr_canopy_si_scls(io_si,scls) = hio_froot_mr_canopy_si_scls(io_si,scls) + & - ccohort%froot_mr * ccohort%n * ha_per_m2 - hio_resp_g_canopy_si_scls(io_si,scls) = hio_resp_g_canopy_si_scls(io_si,scls) + & - resp_g * ccohort%n * dt_tstep_inv * ha_per_m2 - hio_resp_m_canopy_si_scls(io_si,scls) = hio_resp_m_canopy_si_scls(io_si,scls) + & - ccohort%resp_m * ccohort%n * dt_tstep_inv * ha_per_m2 - else - - ! size-resolved respiration fluxes are in kg C / m2 / s - hio_rdark_understory_si_scls(io_si,scls) = hio_rdark_understory_si_scls(io_si,scls) + & - ccohort%rdark * ccohort%n * ha_per_m2 - hio_livestem_mr_understory_si_scls(io_si,scls) = hio_livestem_mr_understory_si_scls(io_si,scls) + & - ccohort%livestem_mr * ccohort%n * ha_per_m2 - hio_livecroot_mr_understory_si_scls(io_si,scls) = hio_livecroot_mr_understory_si_scls(io_si,scls) + & - ccohort%livecroot_mr * ccohort%n * ha_per_m2 - hio_froot_mr_understory_si_scls(io_si,scls) = hio_froot_mr_understory_si_scls(io_si,scls) + & - ccohort%froot_mr * ccohort%n * ha_per_m2 - hio_resp_g_understory_si_scls(io_si,scls) = hio_resp_g_understory_si_scls(io_si,scls) + & - resp_g * ccohort%n * dt_tstep_inv * ha_per_m2 - hio_resp_m_understory_si_scls(io_si,scls) = hio_resp_m_understory_si_scls(io_si,scls) + & - ccohort%resp_m * ccohort%n * dt_tstep_inv * ha_per_m2 - endif - end associate + scls => ccohort%size_class ) + + ! Total AR (kgC/m2/s) = (kgC/plant/step) / (s/step) * (plant/m2) + hio_ar_si_scpf(io_si,scpf) = hio_ar_si_scpf(io_si,scpf) + & + (ccohort%resp_tstep*dt_tstep_inv) * n_perm2 + + ! Growth AR (kgC/m2/s) + hio_ar_grow_si_scpf(io_si,scpf) = hio_ar_grow_si_scpf(io_si,scpf) + & + (resp_g*dt_tstep_inv) * n_perm2 + + ! Maint AR (kgC/m2/s) + hio_ar_maint_si_scpf(io_si,scpf) = hio_ar_maint_si_scpf(io_si,scpf) + & + (ccohort%resp_m*dt_tstep_inv) * n_perm2 + + ! Maintenance AR partition variables are stored as rates (kgC/plant/s) + ! (kgC/m2/s) = (kgC/plant/s) * (plant/m2) + hio_ar_agsapm_si_scpf(io_si,scpf) = hio_ar_agsapm_si_scpf(io_si,scpf) + & + ccohort%livestem_mr * n_perm2 + + ! (kgC/m2/s) = (kgC/plant/s) * (plant/m2) + hio_ar_darkm_si_scpf(io_si,scpf) = hio_ar_darkm_si_scpf(io_si,scpf) + & + ccohort%rdark * n_perm2 + + ! (kgC/m2/s) = (kgC/plant/s) * (plant/m2) + hio_ar_crootm_si_scpf(io_si,scpf) = hio_ar_crootm_si_scpf(io_si,scpf) + & + ccohort%livecroot_mr * n_perm2 + + ! (kgC/m2/s) = (kgC/plant/s) * (plant/m2) + hio_ar_frootm_si_scpf(io_si,scpf) = hio_ar_frootm_si_scpf(io_si,scpf) + & + ccohort%froot_mr * n_perm2 + + ! accumulate fluxes per patch age bin + hio_gpp_si_age(io_si,cpatch%age_class) = hio_gpp_si_age(io_si,cpatch%age_class) & + + ccohort%gpp_tstep * ccohort%n * dt_tstep_inv + + hio_npp_si_age(io_si,cpatch%age_class) = hio_npp_si_age(io_si,cpatch%age_class) & + + npp * ccohort%n * dt_tstep_inv + + ! accumulate fluxes on canopy- and understory- separated fluxes + if (ccohort%canopy_layer .eq. 1) then + + ! size-resolved respiration fluxes are in kg C / m2 / s + hio_rdark_canopy_si_scls(io_si,scls) = hio_rdark_canopy_si_scls(io_si,scls) + & + ccohort%rdark * ccohort%n * ha_per_m2 + hio_livestem_mr_canopy_si_scls(io_si,scls) = hio_livestem_mr_canopy_si_scls(io_si,scls) + & + ccohort%livestem_mr * ccohort%n * ha_per_m2 + hio_livecroot_mr_canopy_si_scls(io_si,scls) = hio_livecroot_mr_canopy_si_scls(io_si,scls) + & + ccohort%livecroot_mr * ccohort%n * ha_per_m2 + hio_froot_mr_canopy_si_scls(io_si,scls) = hio_froot_mr_canopy_si_scls(io_si,scls) + & + ccohort%froot_mr * ccohort%n * ha_per_m2 + hio_resp_g_canopy_si_scls(io_si,scls) = hio_resp_g_canopy_si_scls(io_si,scls) + & + resp_g * ccohort%n * dt_tstep_inv * ha_per_m2 + hio_resp_m_canopy_si_scls(io_si,scls) = hio_resp_m_canopy_si_scls(io_si,scls) + & + ccohort%resp_m * ccohort%n * dt_tstep_inv * ha_per_m2 + else + + ! size-resolved respiration fluxes are in kg C / m2 / s + hio_rdark_understory_si_scls(io_si,scls) = hio_rdark_understory_si_scls(io_si,scls) + & + ccohort%rdark * ccohort%n * ha_per_m2 + hio_livestem_mr_understory_si_scls(io_si,scls) = hio_livestem_mr_understory_si_scls(io_si,scls) + & + ccohort%livestem_mr * ccohort%n * ha_per_m2 + hio_livecroot_mr_understory_si_scls(io_si,scls) = hio_livecroot_mr_understory_si_scls(io_si,scls) + & + ccohort%livecroot_mr * ccohort%n * ha_per_m2 + hio_froot_mr_understory_si_scls(io_si,scls) = hio_froot_mr_understory_si_scls(io_si,scls) + & + ccohort%froot_mr * ccohort%n * ha_per_m2 + hio_resp_g_understory_si_scls(io_si,scls) = hio_resp_g_understory_si_scls(io_si,scls) + & + resp_g * ccohort%n * dt_tstep_inv * ha_per_m2 + hio_resp_m_understory_si_scls(io_si,scls) = hio_resp_m_understory_si_scls(io_si,scls) + & + ccohort%resp_m * ccohort%n * dt_tstep_inv * ha_per_m2 + endif + end associate endif - !!! canopy leaf carbon balance +!!! canopy leaf carbon balance ican = ccohort%canopy_layer do ileaf=1,ccohort%nv cnlf_indx = ileaf + (ican-1) * nlevleaf @@ -5289,7 +5335,7 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) ! summarize radiation profiles through the canopy ! -------------------------------------------------------------------- - + do_pft1: do ipft=1,numpft do_canlev1: do ican=1,cpatch%ncl_p do_leaflev1: do ileaf=1,cpatch%ncan(ican,ipft) @@ -5313,63 +5359,63 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) cpatch%ed_parsha_z(ican,ipft,ileaf) * clllpf_area ! elai_profile is the m2 of leaf inside the m2 of bin. - + hio_laisun_clllpf(io_si, clllpf_indx) = hio_laisun_clllpf(io_si, clllpf_indx) + & cpatch%elai_profile(ican,ipft,ileaf)*cpatch%f_sun(ican,ipft,ileaf)*clllpf_area - + hio_laisha_clllpf(io_si,clllpf_indx) = hio_laisha_clllpf(io_si,clllpf_indx) + & cpatch%elai_profile(ican,ipft,ileaf)*(1._r8-cpatch%f_sun(ican,ipft,ileaf))*clllpf_area - + hio_parprof_dir_si_cnlfpft(io_si,clllpf_indx) = hio_parprof_dir_si_cnlfpft(io_si,clllpf_indx) + & cpatch%parprof_pft_dir_z(ican,ipft,ileaf) * clllpf_area - + hio_parprof_dif_si_cnlfpft(io_si,clllpf_indx) = hio_parprof_dif_si_cnlfpft(io_si,clllpf_indx) + & cpatch%parprof_pft_dif_z(ican,ipft,ileaf) * clllpf_area - + ! The fractional area of Canopy layer and PFTs can be used ! do upscale the CLLLPF properties hio_crownfrac_clllpf(io_si,clllpf_indx) = hio_crownfrac_clllpf(io_si,clllpf_indx) + & clllpf_area - + ! Canopy by leaf layer (mean across pfts) level diagnostics ! ---------------------------------------------------------------------------- hio_parprof_dir_si_cnlf(io_si,cnlf_indx) = hio_parprof_dir_si_cnlf(io_si,cnlf_indx) + & cpatch%parprof_pft_dir_z(ican,ipft,ileaf) * clllpf_area - + hio_parprof_dif_si_cnlf(io_si,cnlf_indx) = hio_parprof_dif_si_cnlf(io_si,cnlf_indx) + & cpatch%parprof_pft_dif_z(ican,ipft,ileaf) * clllpf_area - + hio_parsun_z_si_cnlf(io_si,cnlf_indx) = hio_parsun_z_si_cnlf(io_si,cnlf_indx) + & cpatch%ed_parsun_z(ican,ipft,ileaf) * clllpf_area - + hio_parsha_z_si_cnlf(io_si,cnlf_indx) = hio_parsha_z_si_cnlf(io_si,cnlf_indx) + & cpatch%ed_parsha_z(ican,ipft,ileaf) * clllpf_area - + hio_laisun_z_si_cnlf(io_si,cnlf_indx) = hio_laisun_z_si_cnlf(io_si,cnlf_indx) + & cpatch%f_sun(ican,ipft,ileaf)*clllpf_area - + hio_laisha_z_si_cnlf(io_si,cnlf_indx) = hio_laisha_z_si_cnlf(io_si,cnlf_indx) + & (1._r8-cpatch%f_sun(ican,ipft,ileaf))*clllpf_area ! Canopy mean diagnostics ! -------------------------------------------------------------- - + hio_parsun_si_can(io_si,ican) = hio_parsun_si_can(io_si,ican) + & cpatch%ed_parsun_z(ican,ipft,ileaf) * clllpf_area hio_parsha_si_can(io_si,ican) = hio_parsha_si_can(io_si,ican) + & cpatch%ed_parsha_z(ican,ipft,ileaf) * clllpf_area - + hio_laisun_si_can(io_si,ican) = hio_laisun_si_can(io_si,ican) + & cpatch%f_sun(ican,ipft,ileaf)*cpatch%elai_profile(ican,ipft,ileaf) * clllpf_area hio_laisha_si_can(io_si,ican) = hio_laisha_si_can(io_si,ican) + & (1._r8-cpatch%f_sun(ican,ipft,ileaf))*cpatch%elai_profile(ican,ipft,ileaf) * clllpf_area - + end do do_leaflev1 end do do_canlev1 end do do_pft1 - + cpatch => cpatch%younger end do !patch loop @@ -5384,7 +5430,7 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) clll_area = 0._r8 do_ipft2: do ipft = 1,numpft - + clllpf_indx = ileaf + (ican-1) * nlevleaf + (ipft-1) * nlevleaf * nclmax if( hio_crownfrac_clllpf(io_si,clllpf_indx)0) then + + if_hifrq0: if(hlm_hist_level_hifrq>0) then + + ! Flush the relevant history variables + call this%flush_hvars(nc,upfreq_in=group_hydr_simple) associate( hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d, & hio_rootwgt_soilvwc_si => this%hvars(ih_rootwgt_soilvwc_si)%r81d, & @@ -5588,326 +5627,303 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) hio_h2oveg_si => this%hvars(ih_h2oveg_si)%r81d ) do s = 1,nsites - - call this%zero_site_hvars(sites(s),upfreq_in=4) - + + call this%zero_site_hvars(sites(s),upfreq_in=group_hydr_simple) + site_hydr => sites(s)%si_hydr nlevrhiz = site_hydr%nlevrhiz nlevsoil = bc_in(s)%nlevsoil io_si = sites(s)%h_gid - + hio_h2oveg_si(io_si) = site_hydr%h2oveg hio_h2oveg_hydro_err_si(io_si) = site_hydr%h2oveg_hydro_err hio_rootuptake_si(io_si) = sum(site_hydr%rootuptake_sl,dim=1) - ! Get column means of some soil diagnostics, these are weighted - ! by the amount of fine-root surface area in each layer - ! -------------------------------------------------------------------- + ! Get column means of some soil diagnostics, these are weighted + ! by the amount of fine-root surface area in each layer + ! -------------------------------------------------------------------- - mean_soil_vwc = 0._r8 - mean_soil_matpot = 0._r8 - mean_soil_vwcsat = 0._r8 - areaweight = 0._r8 + mean_soil_vwc = 0._r8 + mean_soil_matpot = 0._r8 + mean_soil_vwcsat = 0._r8 + areaweight = 0._r8 - do j=1,nlevrhiz + do j=1,nlevrhiz - j_t = site_hydr%map_r2s(j,1) ! top soil layer matching rhiz layer - j_b = site_hydr%map_r2s(j,2) ! bottom soil layer matching rhiz layer + j_t = site_hydr%map_r2s(j,1) ! top soil layer matching rhiz layer + j_b = site_hydr%map_r2s(j,2) ! bottom soil layer matching rhiz layer - do j_bc = j_t,j_b - - vwc = bc_in(s)%h2o_liqvol_sl(j_bc) - psi = site_hydr%wrf_soil(j)%p%psi_from_th(vwc) ! MLO: Any reason for not using smp_sl? - ! cap capillary pressure - ! psi = max(-1e5_r8,psi) Removing cap as that is inconstistent - ! with model internals and physics. Should - ! implement caps inside the functions - ! if desired. (RGK 12-2021) - vwc_sat = bc_in(s)%watsat_sl(j_bc) - depth_frac = bc_in(s)%dz_sisl(j_bc)/site_hydr%dz_rhiz(j) - - ! If there are any roots, we use root weighting - if(sum(site_hydr%l_aroot_layer(:),dim=1) > nearzero) then - layer_areaweight = site_hydr%l_aroot_layer(j)*depth_frac*pi_const*site_hydr%rs1(j)**2.0 - - ! If there are no roots, we use depth weighting - else - layer_areaweight = bc_in(s)%dz_sisl(j_bc) - endif - - areaweight = areaweight + layer_areaweight - mean_soil_vwc = mean_soil_vwc + vwc*layer_areaweight - mean_soil_vwcsat = mean_soil_vwcsat + vwc_sat*layer_areaweight - mean_soil_matpot = mean_soil_matpot + psi*layer_areaweight + do j_bc = j_t,j_b + vwc = bc_in(s)%h2o_liqvol_sl(j_bc) + psi = site_hydr%wrf_soil(j)%p%psi_from_th(vwc) ! MLO: Any reason for not using smp_sl? + ! cap capillary pressure + ! psi = max(-1e5_r8,psi) Removing cap as that is inconstistent + ! with model internals and physics. Should + ! implement caps inside the functions + ! if desired. (RGK 12-2021) + vwc_sat = bc_in(s)%watsat_sl(j_bc) + depth_frac = bc_in(s)%dz_sisl(j_bc)/site_hydr%dz_rhiz(j) + + ! If there are any roots, we use root weighting + if(sum(site_hydr%l_aroot_layer(:),dim=1) > nearzero) then + layer_areaweight = site_hydr%l_aroot_layer(j)*depth_frac*pi_const*site_hydr%rs1(j)**2.0 + + ! If there are no roots, we use depth weighting + else + layer_areaweight = bc_in(s)%dz_sisl(j_bc) + endif + + areaweight = areaweight + layer_areaweight + mean_soil_vwc = mean_soil_vwc + vwc*layer_areaweight + mean_soil_vwcsat = mean_soil_vwcsat + vwc_sat*layer_areaweight + mean_soil_matpot = mean_soil_matpot + psi*layer_areaweight + + end do end do + + hio_rootwgt_soilvwc_si(io_si) = mean_soil_vwc/areaweight + hio_rootwgt_soilvwcsat_si(io_si) = mean_soil_vwcsat/areaweight + hio_rootwgt_soilmatpot_si(io_si) = mean_soil_matpot/areaweight * pa_per_mpa + end do + end associate + end if if_hifrq0 + + if_hifrq1: if(hlm_hist_level_hifrq>1) then + + associate( hio_errh2o_scpf => this%hvars(ih_errh2o_scpf)%r82d, & + hio_tran_scpf => this%hvars(ih_tran_scpf)%r82d, & + hio_sapflow_scpf => this%hvars(ih_sapflow_scpf)%r82d, & + hio_iterh1_scpf => this%hvars(ih_iterh1_scpf)%r82d, & + hio_iterh2_scpf => this%hvars(ih_iterh2_scpf)%r82d, & + hio_ath_scpf => this%hvars(ih_ath_scpf)%r82d, & + hio_tth_scpf => this%hvars(ih_tth_scpf)%r82d, & + hio_sth_scpf => this%hvars(ih_sth_scpf)%r82d, & + hio_lth_scpf => this%hvars(ih_lth_scpf)%r82d, & + hio_awp_scpf => this%hvars(ih_awp_scpf)%r82d, & + hio_twp_scpf => this%hvars(ih_twp_scpf)%r82d, & + hio_swp_scpf => this%hvars(ih_swp_scpf)%r82d, & + hio_lwp_scpf => this%hvars(ih_lwp_scpf)%r82d, & + hio_aflc_scpf => this%hvars(ih_aflc_scpf)%r82d, & + hio_tflc_scpf => this%hvars(ih_tflc_scpf)%r82d, & + hio_sflc_scpf => this%hvars(ih_sflc_scpf)%r82d, & + hio_lflc_scpf => this%hvars(ih_lflc_scpf)%r82d, & + hio_btran_scpf => this%hvars(ih_btran_scpf)%r82d, & + + hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & + hio_nplant_si_capf => this%hvars(ih_nplant_si_capf)%r82d, & + hio_soilmatpot_sl => this%hvars(ih_soilmatpot_sl)%r82d, & + hio_soilvwc_sl => this%hvars(ih_soilvwc_sl)%r82d, & + hio_soilvwcsat_sl => this%hvars(ih_soilvwcsat_sl)%r82d, & + hio_rootuptake_sl => this%hvars(ih_rootuptake_sl)%r82d, & + hio_rootuptake0_scpf => this%hvars(ih_rootuptake0_scpf)%r82d, & + hio_rootuptake10_scpf => this%hvars(ih_rootuptake10_scpf)%r82d, & + hio_rootuptake50_scpf => this%hvars(ih_rootuptake50_scpf)%r82d, & + hio_rootuptake100_scpf => this%hvars(ih_rootuptake100_scpf)%r82d ) + + call this%flush_hvars(nc,upfreq_in=group_hydr_complx) - - hio_rootwgt_soilvwc_si(io_si) = mean_soil_vwc/areaweight - hio_rootwgt_soilvwcsat_si(io_si) = mean_soil_vwcsat/areaweight - hio_rootwgt_soilmatpot_si(io_si) = mean_soil_matpot/areaweight * pa_per_mpa - - end do - end associate + do s = 1,nsites + + site_hydr => sites(s)%si_hydr + nlevrhiz = site_hydr%nlevrhiz + nlevsoil = bc_in(s)%nlevsoil + io_si = sites(s)%h_gid - !! if_hifrq1: if(hlm_hist_level_hifrq>1) then - - associate( hio_errh2o_scpf => this%hvars(ih_errh2o_scpf)%r82d, & - hio_tran_scpf => this%hvars(ih_tran_scpf)%r82d, & - hio_sapflow_scpf => this%hvars(ih_sapflow_scpf)%r82d, & - hio_iterh1_scpf => this%hvars(ih_iterh1_scpf)%r82d, & - hio_iterh2_scpf => this%hvars(ih_iterh2_scpf)%r82d, & - hio_ath_scpf => this%hvars(ih_ath_scpf)%r82d, & - hio_tth_scpf => this%hvars(ih_tth_scpf)%r82d, & - hio_sth_scpf => this%hvars(ih_sth_scpf)%r82d, & - hio_lth_scpf => this%hvars(ih_lth_scpf)%r82d, & - hio_awp_scpf => this%hvars(ih_awp_scpf)%r82d, & - hio_twp_scpf => this%hvars(ih_twp_scpf)%r82d, & - hio_swp_scpf => this%hvars(ih_swp_scpf)%r82d, & - hio_lwp_scpf => this%hvars(ih_lwp_scpf)%r82d, & - hio_aflc_scpf => this%hvars(ih_aflc_scpf)%r82d, & - hio_tflc_scpf => this%hvars(ih_tflc_scpf)%r82d, & - hio_sflc_scpf => this%hvars(ih_sflc_scpf)%r82d, & - hio_lflc_scpf => this%hvars(ih_lflc_scpf)%r82d, & - hio_btran_scpf => this%hvars(ih_btran_scpf)%r82d, & - - hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & - hio_nplant_si_capf => this%hvars(ih_nplant_si_capf)%r82d, & - hio_soilmatpot_sl => this%hvars(ih_soilmatpot_sl)%r82d, & - hio_soilvwc_sl => this%hvars(ih_soilvwc_sl)%r82d, & - hio_soilvwcsat_sl => this%hvars(ih_soilvwcsat_sl)%r82d, & - hio_rootuptake_sl => this%hvars(ih_rootuptake_sl)%r82d, & - hio_rootuptake0_scpf => this%hvars(ih_rootuptake0_scpf)%r82d, & - hio_rootuptake10_scpf => this%hvars(ih_rootuptake10_scpf)%r82d, & - hio_rootuptake50_scpf => this%hvars(ih_rootuptake50_scpf)%r82d, & - hio_rootuptake100_scpf => this%hvars(ih_rootuptake100_scpf)%r82d ) - - if(print_iterations) then - do iscpf = 1,iterh2_nhist - iterh2_histx(iscpf) = iterh2_dx*real(iscpf-1,r8) - end do - end if + call this%zero_site_hvars(sites(s),upfreq_in=group_hydr_complx) - do s = 1,nsites - - site_hydr => sites(s)%si_hydr - nlevrhiz = site_hydr%nlevrhiz - nlevsoil = bc_in(s)%nlevsoil - io_si = sites(s)%h_gid - - hio_rootuptake_sl(io_si,1:nlevsoil) = site_hydr%rootuptake_sl(1:nlevsoil) - - ! Get column means of some soil diagnostics, these are weighted - ! by the amount of fine-root surface area in each layer - ! -------------------------------------------------------------------- - - mean_soil_vwc = 0._r8 - mean_soil_matpot = 0._r8 - mean_soil_vwcsat = 0._r8 - areaweight = 0._r8 - - do j=1,nlevrhiz - - j_t = site_hydr%map_r2s(j,1) ! top soil layer matching rhiz layer - j_b = site_hydr%map_r2s(j,2) ! bottom soil layer matching rhiz layer - - do j_bc = j_t,j_b - - vwc = bc_in(s)%h2o_liqvol_sl(j_bc) - psi = site_hydr%wrf_soil(j)%p%psi_from_th(vwc) ! MLO: Any reason for not using smp_sl? - ! cap capillary pressure - ! psi = max(-1e5_r8,psi) Removing cap as that is inconstistent - ! with model internals and physics. Should - ! implement caps inside the functions - ! if desired. (RGK 12-2021) - vwc_sat = bc_in(s)%watsat_sl(j_bc) - depth_frac = bc_in(s)%dz_sisl(j_bc)/site_hydr%dz_rhiz(j) - - ! If there are any roots, we use root weighting - if(sum(site_hydr%l_aroot_layer(:),dim=1) > nearzero) then - layer_areaweight = site_hydr%l_aroot_layer(j)*depth_frac*pi_const*site_hydr%rs1(j)**2.0 - - ! If there are no roots, we use depth weighting - else - layer_areaweight = bc_in(s)%dz_sisl(j_bc) - endif - - areaweight = areaweight + layer_areaweight - mean_soil_vwc = mean_soil_vwc + vwc*layer_areaweight - mean_soil_vwcsat = mean_soil_vwcsat + vwc_sat*layer_areaweight - mean_soil_matpot = mean_soil_matpot + psi*layer_areaweight - - hio_soilmatpot_sl(io_si,j_bc) = psi * pa_per_mpa - hio_soilvwc_sl(io_si,j_bc) = vwc - hio_soilvwcsat_sl(io_si,j_bc) = vwc_sat - - end do - end do + hio_rootuptake_sl(io_si,1:nlevsoil) = site_hydr%rootuptake_sl(1:nlevsoil) - ! Normalization counters - nplant_scpf(:) = 0._r8 - ncohort_scpf(:) = 0._r8 - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - ccohort => cpatch%shortest - do while(associated(ccohort)) - if ( .not. ccohort%isnew ) then - ! Calculate index for the scpf class - iscpf = ccohort%size_by_pft_class - nplant_scpf(iscpf) = nplant_scpf(iscpf) + ccohort%n - ncohort_scpf(iscpf) = ncohort_scpf(iscpf) + 1._r8 - end if - ccohort => ccohort%taller - enddo ! cohort loop - cpatch => cpatch%younger - end do !patch loop - - ! Generate a histogram of the the iteration counts - if(print_iterations) then - iterh2_histy(:) = 0._r8 - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - ccohort => cpatch%shortest - do while(associated(ccohort)) - ccohort_hydr => ccohort%co_hydr - ix = count((iterh2_histx(:)-0.00001_r8) < ccohort_hydr%iterh2 ) - iterh2_histy(ix) = iterh2_histy(ix) + 1 - ccohort => ccohort%taller - enddo ! cohort loop - cpatch => cpatch%younger - end do !patch loop - end if + ! Get column means of some soil diagnostics, these are weighted + ! by the amount of fine-root surface area in each layer + ! -------------------------------------------------------------------- + + mean_soil_vwc = 0._r8 + mean_soil_matpot = 0._r8 + mean_soil_vwcsat = 0._r8 + areaweight = 0._r8 + + do j=1,nlevrhiz + + j_t = site_hydr%map_r2s(j,1) ! top soil layer matching rhiz layer + j_b = site_hydr%map_r2s(j,2) ! bottom soil layer matching rhiz layer + + do j_bc = j_t,j_b + + vwc = bc_in(s)%h2o_liqvol_sl(j_bc) + psi = site_hydr%wrf_soil(j)%p%psi_from_th(vwc) ! MLO: Any reason for not using smp_sl? + ! cap capillary pressure + ! psi = max(-1e5_r8,psi) Removing cap as that is inconstistent + ! with model internals and physics. Should + ! implement caps inside the functions + ! if desired. (RGK 12-2021) + vwc_sat = bc_in(s)%watsat_sl(j_bc) + depth_frac = bc_in(s)%dz_sisl(j_bc)/site_hydr%dz_rhiz(j) + + ! If there are any roots, we use root weighting + if(sum(site_hydr%l_aroot_layer(:),dim=1) > nearzero) then + layer_areaweight = site_hydr%l_aroot_layer(j)*depth_frac*pi_const*site_hydr%rs1(j)**2.0 + + ! If there are no roots, we use depth weighting + else + layer_areaweight = bc_in(s)%dz_sisl(j_bc) + endif + + areaweight = areaweight + layer_areaweight + mean_soil_vwc = mean_soil_vwc + vwc*layer_areaweight + mean_soil_vwcsat = mean_soil_vwcsat + vwc_sat*layer_areaweight + mean_soil_matpot = mean_soil_matpot + psi*layer_areaweight + + hio_soilmatpot_sl(io_si,j_bc) = psi * pa_per_mpa + hio_soilvwc_sl(io_si,j_bc) = vwc + hio_soilvwcsat_sl(io_si,j_bc) = vwc_sat + + end do + end do - do ipft = 1, numpft - do iscls = 1,nlevsclass - iscpf = (ipft-1)*nlevsclass + iscls - hio_sapflow_scpf(io_si,iscpf) = site_hydr%sapflow_scpf(iscls, ipft) * ha_per_m2 - hio_rootuptake0_scpf(io_si,iscpf) = site_hydr%rootuptake0_scpf(iscls,ipft) * ha_per_m2 - hio_rootuptake10_scpf(io_si,iscpf) = site_hydr%rootuptake10_scpf(iscls,ipft) * ha_per_m2 - hio_rootuptake50_scpf(io_si,iscpf) = site_hydr%rootuptake50_scpf(iscls,ipft) * ha_per_m2 - hio_rootuptake100_scpf(io_si,iscpf) = site_hydr%rootuptake100_scpf(iscls,ipft) * ha_per_m2 - hio_iterh1_scpf(io_si,iscpf) = 0._r8 - hio_iterh2_scpf(io_si,iscpf) = 0._r8 - end do + ! Normalization counters + nplant_scpf(:) = 0._r8 + ncohort_scpf(:) = 0._r8 + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) + ccohort => cpatch%shortest + do while(associated(ccohort)) + if ( .not. ccohort%isnew ) then + ! Calculate index for the scpf class + iscpf = ccohort%size_by_pft_class + nplant_scpf(iscpf) = nplant_scpf(iscpf) + ccohort%n + ncohort_scpf(iscpf) = ncohort_scpf(iscpf) + 1._r8 + end if + ccohort => ccohort%taller + enddo ! cohort loop + cpatch => cpatch%younger + end do !patch loop + + do ipft = 1, numpft + do iscls = 1,nlevsclass + iscpf = (ipft-1)*nlevsclass + iscls + hio_sapflow_scpf(io_si,iscpf) = site_hydr%sapflow_scpf(iscls, ipft) * ha_per_m2 + hio_rootuptake0_scpf(io_si,iscpf) = site_hydr%rootuptake0_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake10_scpf(io_si,iscpf) = site_hydr%rootuptake10_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake50_scpf(io_si,iscpf) = site_hydr%rootuptake50_scpf(iscls,ipft) * ha_per_m2 + hio_rootuptake100_scpf(io_si,iscpf) = site_hydr%rootuptake100_scpf(iscls,ipft) * ha_per_m2 + hio_iterh1_scpf(io_si,iscpf) = 0._r8 + hio_iterh2_scpf(io_si,iscpf) = 0._r8 end do + end do - ipa = 0 - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) + ipa = 0 + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) - ccohort => cpatch%shortest - do while(associated(ccohort)) + ccohort => cpatch%shortest + do while(associated(ccohort)) - ccohort_hydr => ccohort%co_hydr + ccohort_hydr => ccohort%co_hydr - if ( .not. ccohort%isnew ) then + if ( .not. ccohort%isnew ) then - ! Calculate index for the scpf class - iscpf = ccohort%size_by_pft_class + ! Calculate index for the scpf class + iscpf = ccohort%size_by_pft_class - ! scale up cohort fluxes to their sites - number_fraction_rate = (ccohort%n / nplant_scpf(iscpf)) * per_dt_tstep + ! scale up cohort fluxes to their sites + number_fraction_rate = (ccohort%n / nplant_scpf(iscpf)) * per_dt_tstep - ! scale cohorts to mean quantity - number_fraction = (ccohort%n / nplant_scpf(iscpf)) + ! scale cohorts to mean quantity + number_fraction = (ccohort%n / nplant_scpf(iscpf)) - hio_errh2o_scpf(io_si,iscpf) = hio_errh2o_scpf(io_si,iscpf) + & - ccohort_hydr%errh2o * number_fraction_rate ! [kg/indiv/s] + hio_errh2o_scpf(io_si,iscpf) = hio_errh2o_scpf(io_si,iscpf) + & + ccohort_hydr%errh2o * number_fraction_rate ! [kg/indiv/s] - hio_tran_scpf(io_si,iscpf) = hio_tran_scpf(io_si,iscpf) + & - (ccohort_hydr%qtop) * number_fraction_rate ! [kg/indiv/s] + hio_tran_scpf(io_si,iscpf) = hio_tran_scpf(io_si,iscpf) + & + (ccohort_hydr%qtop) * number_fraction_rate ! [kg/indiv/s] - hio_iterh1_scpf(io_si,iscpf) = hio_iterh1_scpf(io_si,iscpf) + & - ccohort_hydr%iterh1/ncohort_scpf(iscpf) + hio_iterh1_scpf(io_si,iscpf) = hio_iterh1_scpf(io_si,iscpf) + & + ccohort_hydr%iterh1/ncohort_scpf(iscpf) - hio_iterh2_scpf(io_si,iscpf) = hio_iterh2_scpf(io_si,iscpf) + & - ccohort_hydr%iterh2/ncohort_scpf(iscpf) + hio_iterh2_scpf(io_si,iscpf) = hio_iterh2_scpf(io_si,iscpf) + & + ccohort_hydr%iterh2/ncohort_scpf(iscpf) - mean_aroot = sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & - sum(ccohort_hydr%v_aroot_layer(:)) + mean_aroot = sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & + sum(ccohort_hydr%v_aroot_layer(:)) - hio_ath_scpf(io_si,iscpf) = hio_ath_scpf(io_si,iscpf) + & - mean_aroot * number_fraction ! [m3 m-3] + hio_ath_scpf(io_si,iscpf) = hio_ath_scpf(io_si,iscpf) + & + mean_aroot * number_fraction ! [m3 m-3] - hio_tth_scpf(io_si,iscpf) = hio_tth_scpf(io_si,iscpf) + & - ccohort_hydr%th_troot * number_fraction ! [m3 m-3] + hio_tth_scpf(io_si,iscpf) = hio_tth_scpf(io_si,iscpf) + & + ccohort_hydr%th_troot * number_fraction ! [m3 m-3] - hio_sth_scpf(io_si,iscpf) = hio_sth_scpf(io_si,iscpf) + & - ccohort_hydr%th_ag(2) * number_fraction ! [m3 m-3] + hio_sth_scpf(io_si,iscpf) = hio_sth_scpf(io_si,iscpf) + & + ccohort_hydr%th_ag(2) * number_fraction ! [m3 m-3] - hio_lth_scpf(io_si,iscpf) = hio_lth_scpf(io_si,iscpf) + & - ccohort_hydr%th_ag(1) * number_fraction ! [m3 m-3] + hio_lth_scpf(io_si,iscpf) = hio_lth_scpf(io_si,iscpf) + & + ccohort_hydr%th_ag(1) * number_fraction ! [m3 m-3] - mean_aroot = sum(ccohort_hydr%psi_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & - sum(ccohort_hydr%v_aroot_layer(:)) + mean_aroot = sum(ccohort_hydr%psi_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & + sum(ccohort_hydr%v_aroot_layer(:)) - hio_awp_scpf(io_si,iscpf) = hio_awp_scpf(io_si,iscpf) + & - mean_aroot * number_fraction * pa_per_mpa ! [Pa] + hio_awp_scpf(io_si,iscpf) = hio_awp_scpf(io_si,iscpf) + & + mean_aroot * number_fraction * pa_per_mpa ! [Pa] - hio_twp_scpf(io_si,iscpf) = hio_twp_scpf(io_si,iscpf) + & - ccohort_hydr%psi_troot * number_fraction * pa_per_mpa ! [Pa] + hio_twp_scpf(io_si,iscpf) = hio_twp_scpf(io_si,iscpf) + & + ccohort_hydr%psi_troot * number_fraction * pa_per_mpa ! [Pa] - hio_swp_scpf(io_si,iscpf) = hio_swp_scpf(io_si,iscpf) + & - ccohort_hydr%psi_ag(2) * number_fraction * pa_per_mpa ! [Pa] + hio_swp_scpf(io_si,iscpf) = hio_swp_scpf(io_si,iscpf) + & + ccohort_hydr%psi_ag(2) * number_fraction * pa_per_mpa ! [Pa] - hio_lwp_scpf(io_si,iscpf) = hio_lwp_scpf(io_si,iscpf) + & - ccohort_hydr%psi_ag(1) * number_fraction * pa_per_mpa ! [Pa] + hio_lwp_scpf(io_si,iscpf) = hio_lwp_scpf(io_si,iscpf) + & + ccohort_hydr%psi_ag(1) * number_fraction * pa_per_mpa ! [Pa] - mean_aroot = sum(ccohort_hydr%ftc_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & - sum(ccohort_hydr%v_aroot_layer(:)) - hio_aflc_scpf(io_si,iscpf) = hio_aflc_scpf(io_si,iscpf) + & - mean_aroot * number_fraction + mean_aroot = sum(ccohort_hydr%ftc_aroot(:)*ccohort_hydr%v_aroot_layer(:)) / & + sum(ccohort_hydr%v_aroot_layer(:)) + hio_aflc_scpf(io_si,iscpf) = hio_aflc_scpf(io_si,iscpf) + & + mean_aroot * number_fraction - hio_tflc_scpf(io_si,iscpf) = hio_tflc_scpf(io_si,iscpf) + & - ccohort_hydr%ftc_troot * number_fraction + hio_tflc_scpf(io_si,iscpf) = hio_tflc_scpf(io_si,iscpf) + & + ccohort_hydr%ftc_troot * number_fraction - hio_sflc_scpf(io_si,iscpf) = hio_sflc_scpf(io_si,iscpf) + & - ccohort_hydr%ftc_ag(2) * number_fraction + hio_sflc_scpf(io_si,iscpf) = hio_sflc_scpf(io_si,iscpf) + & + ccohort_hydr%ftc_ag(2) * number_fraction - hio_lflc_scpf(io_si,iscpf) = hio_lflc_scpf(io_si,iscpf) + & - ccohort_hydr%ftc_ag(1) * number_fraction + hio_lflc_scpf(io_si,iscpf) = hio_lflc_scpf(io_si,iscpf) + & + ccohort_hydr%ftc_ag(1) * number_fraction - hio_btran_scpf(io_si,iscpf) = hio_btran_scpf(io_si,iscpf) + & - ccohort_hydr%btran * number_fraction ! [-] + hio_btran_scpf(io_si,iscpf) = hio_btran_scpf(io_si,iscpf) + & + ccohort_hydr%btran * number_fraction ! [-] - endif + endif - ccohort => ccohort%taller - enddo ! cohort loop - ipa = ipa + 1 - cpatch => cpatch%younger - end do !patch loop - - if((hlm_use_ed_st3.eq.ifalse) ) then - do iscpf=1,nlevsclass*numpft - if ((abs(hio_nplant_si_scpf(io_si, iscpf)-(nplant_scpf(iscpf)*ha_per_m2)) > 1.0E-8_r8) .and. & - (hio_nplant_si_scpf(io_si, iscpf) .ne. hlm_hio_ignore_val)) then - write(fates_log(),*) 'numpft:',numpft - write(fates_log(),*) 'nlevsclass:',nlevsclass - write(fates_log(),*) 'scpf:',iscpf - write(fates_log(),*) 'io_si:',io_si - write(fates_log(),*) 'hio_nplant_si_scpf:',hio_nplant_si_scpf(io_si, iscpf) - write(fates_log(),*) 'nplant_scpf:',nplant_scpf(iscpf) - write(fates_log(),*) 'nplant check on hio_nplant_si_scpf fails during hydraulics history updates' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end do - end if - - end do - end associate + ccohort => ccohort%taller + enddo ! cohort loop + ipa = ipa + 1 + cpatch => cpatch%younger + end do !patch loop + + if((hlm_use_ed_st3.eq.ifalse) ) then + do iscpf=1,nlevsclass*numpft + if ((abs(hio_nplant_si_scpf(io_si, iscpf)-(nplant_scpf(iscpf)*ha_per_m2)) > 1.0E-8_r8) .and. & + (hio_nplant_si_scpf(io_si, iscpf) .ne. hlm_hio_ignore_val)) then + write(fates_log(),*) 'numpft:',numpft + write(fates_log(),*) 'nlevsclass:',nlevsclass + write(fates_log(),*) 'scpf:',iscpf + write(fates_log(),*) 'io_si:',io_si + write(fates_log(),*) 'hio_nplant_si_scpf:',hio_nplant_si_scpf(io_si, iscpf) + write(fates_log(),*) 'nplant_scpf:',nplant_scpf(iscpf) + write(fates_log(),*) 'nplant check on hio_nplant_si_scpf fails during hydraulics history updates' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end do + end if - if(print_iterations) then - write(fmt_char,'(I2)') iterh2_nhist - write(fates_log(),fmt='(A,'//fmt_char//'I5)') 'Solves: ',int(iterh2_histy(:)) - end if + end do + end associate + + end if if_hifrq1 - !!end if if_hifrq1 - !!end if if_hifrq0 end subroutine update_history_hydraulics - + ! ==================================================================================== integer function num_history_vars(this) @@ -5927,17 +5943,17 @@ subroutine initialize_history_vars(this) class(fates_history_interface_type), intent(inout) :: this - ! Determine how many of the history IO variables registered in FATES - ! are going to be allocated - call this%define_history_vars(initialize_variables=.false.) + ! Determine how many of the history IO variables registered in FATES + ! are going to be allocated + call this%define_history_vars(initialize_variables=.false.) - ! Allocate the list of history output variable objects - allocate(this%hvars(this%num_history_vars())) + ! Allocate the list of history output variable objects + allocate(this%hvars(this%num_history_vars())) - ! construct the object that defines all of the IO variables - call this%define_history_vars(initialize_variables=.true.) + ! construct the object that defines all of the IO variables + call this%define_history_vars(initialize_variables=.true.) - end subroutine initialize_history_vars + end subroutine initialize_history_vars ! ==================================================================================== @@ -5974,7 +5990,7 @@ subroutine define_history_vars(this, initialize_variables) use FatesIOVariableKindMod, only : site_size_r8, site_pft_r8, site_age_r8 use FatesIOVariableKindMod, only : site_coage_pft_r8, site_coage_r8 use FatesIOVariableKindMod, only : site_height_r8, site_agefuel_r8 - use FatesInterfaceTypesMod , only : hlm_use_planthydro + use FatesInterfaceTypesMod, only : hlm_use_planthydro use FatesIOVariableKindMod, only : site_fuel_r8, site_cwdsc_r8, site_scag_r8 use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 @@ -6009,7 +6025,7 @@ subroutine define_history_vars(this, initialize_variables) ! soil layer (site_soil_r8) : SL ! cohort size (site_size_r8) : SZ ! cohort crown damage (site_cd_r8) : CD - + ! Multiple dimensions should have multiple two-code suffixes: ! cohort age x pft (site_cooage_r8) : ACPF ! patch age x fuel class (site_agefuel_r8) : APFC @@ -6024,3177 +6040,3179 @@ subroutine define_history_vars(this, initialize_variables) ! cohort size x crown damage (site_cdsc_r8) : SZCD ! cohort size x crown damage x pft (site_cdpf_r8) : CDPF + print*,hlm_hist_level_dynam,hlm_hist_level_hifrq + stop if_dyn0: if(hlm_hist_level_dynam>0) then - ! Site level counting variables call this%set_history_var(vname='FATES_NPATCHES', units='', & - long='total number of patches per site', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_npatches_si) - + long='total number of patches per site', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_npatches_si) + call this%set_history_var(vname='FATES_NCOHORTS', units='', & long='total number of cohorts per site', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index=ih_ncohorts_si) - + call this%set_history_var(vname='FATES_NPATCHES_SECONDARY', units='', & long='total number of patches per site', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index=ih_npatches_sec_si) - call this%set_history_var(vname='FATES_NCOHORTS_SECONDARY', units='', & - long='total number of cohorts per site', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_ncohorts_sec_si) - - ! Patch variables - call this%set_history_var(vname='FATES_TRIMMING', units='1', & - long='degree to which canopy expansion is limited by leaf economics (0-1)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_trimming_si) - - call this%set_history_var(vname='FATES_AREA_PLANTS', units='m2 m-2', & - long='area occupied by all plants per m2 land area', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index=ih_area_plant_si) - - call this%set_history_var(vname='FATES_AREA_TREES', units='m2 m-2', & - long='area occupied by woody plants per m2 land area', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_area_trees_si) - - call this%set_history_var(vname='FATES_FRACTION', units='m2 m-2', & - long='total gridcell fraction which FATES is running over', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fates_fraction_si, flush_to_zero=.true.) - - call this%set_history_var(vname='FATES_BA_WEIGHTED_HEIGHT', units='m', & - long='basal area-weighted mean height of woody plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_ba_weighted_height_si) - - call this%set_history_var(vname='FATES_CA_WEIGHTED_HEIGHT', units='m', & - long='crown area-weighted mean height of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_ca_weighted_height_si) - - call this%set_history_var(vname='FATES_COLD_STATUS', units='', & - long='site-level cold status, 0=not cold-dec, 1=too cold for leaves, 2=not too cold', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_site_cstatus_si) - - call this%set_history_var(vname='FATES_GDD', units='degree_Celsius', & - long='site-level growing degree days', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index=ih_gdd_si) - - call this%set_history_var(vname='FATES_NCHILLDAYS', units = 'days', & - long='site-level number of chill days', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_site_nchilldays_si) - - call this%set_history_var(vname='FATES_NCOLDDAYS', units = 'days', & - long='site-level number of cold days', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_site_ncolddays_si) - - call this%set_history_var(vname='FATES_DAYSINCE_COLDLEAFOFF', & - units='days', long='site-level days elapsed since cold leaf drop', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_cleafoff_si) - - call this%set_history_var(vname='FATES_DAYSINCE_COLDLEAFON', & - units='days', long='site-level days elapsed since cold leaf flush', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_cleafon_si) - - call this%set_history_var(vname='FATES_CANOPY_SPREAD', units='', & - long='scaling factor (0-1) between tree basal area and canopy area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_canopy_spread_si) - - call this%set_history_var(vname='FATES_LAI', units='m2 m-2', & - long='leaf area index per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_lai_si) - - call this%set_history_var(vname='FATES_LAI_SECONDARY', units='m2 m-2', & - long='leaf area index per m2 land area, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_lai_secondary_si) - - call this%set_history_var(vname='FATES_PATCHAREA_LU', units='m2 m-2', & - long='patch area by land use type', use_default='active', & - avgflag='A', vtype=site_landuse_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index=ih_area_si_landuse) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_MATRIX_LULU', units='m2 m-2 yr-1', & - long='disturbance rates by land use type x land use type matrix', use_default='active', & - avgflag='A', vtype=site_lulu_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index=ih_disturbance_rate_si_lulu) - - ! Secondary forest area and age diagnostics - - call this%set_history_var(vname='FATES_SECONDARY_FOREST_FRACTION', & - units='m2 m-2', long='secondary forest fraction', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fraction_secondary_forest_si) - - call this%set_history_var(vname='FATES_WOOD_PRODUCT', units='kg m-2', & - long='total wood product from logging in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_woodproduct_si) - - call this%set_history_var(vname='FATES_SECONDARY_FOREST_VEGC', & - units='kg m-2', & - long='biomass on secondary lands in kg carbon per m2 land area (mult by FATES_SECONDARY_FOREST_FRACTION to get per secondary forest area)', & - use_default='active', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_biomass_secondary_forest_si) - ! Fire Variables - - call this%set_history_var(vname='FATES_NESTEROV_INDEX', units='', & - long='nesterov fire danger index', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nesterov_fire_danger_si) - - call this%set_history_var(vname='FATES_IGNITIONS', & - units='m-2 s-1', & - long='number of successful fire ignitions per m2 land area per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_nignitions_si) - - call this%set_history_var(vname='FATES_FDI', units='1', & - long='Fire Danger Index (probability that an ignition will lead to a fire)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_fdi_si) - - call this%set_history_var(vname='FATES_ROS', units='m s-1', & - long='fire rate of spread in meters per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_spitfire_ros_si) - - call this%set_history_var(vname='FATES_EFFECT_WSPEED', units='m s-1', & - long ='effective wind speed for fire spread in meters per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_effect_wspeed_si) - - call this%set_history_var(vname='FATES_FUELCONSUMED', units='kg m-2', & - long ='total fuel consumed in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_tfc_ros_si) - - call this%set_history_var(vname='FATES_FIRE_INTENSITY', & - units='J m-1 s-1', & - long='spitfire surface fireline intensity in J per m per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_intensity_si) - - call this%set_history_var(vname='FATES_FIRE_INTENSITY_BURNFRAC', & - units='J m-1 s-1', & - long='product of surface fire intensity and burned area fraction -- divide by FATES_BURNFRAC to get area-weighted mean intensity', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_intensity_area_product_si) - - call this%set_history_var(vname='FATES_BURNFRAC', units='s-1', & - long='burned area fraction per second', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_area_si) - - call this%set_history_var(vname='FATES_FUEL_MEF', units='m3 m-3', & - long='fuel moisture of extinction (volumetric)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_fire_fuel_mef_si) - - call this%set_history_var(vname='FATES_FUEL_BULKD', & - units='kg m-3', long='fuel bulk density in kg per m3', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_fuel_bulkd_si ) - - call this%set_history_var(vname='FATES_FUEL_EFF_MOIST', units='m3 m-3', & - long='spitfire fuel moisture (volumetric)', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fire_fuel_eff_moist_si) - - call this%set_history_var(vname='FATES_FUEL_SAV', units='m-1', & - long='spitfire fuel surface area to volume ratio', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_fuel_sav_si) - - call this%set_history_var(vname='FATES_FUEL_AMOUNT', units='kg m-2', & - long='total ground fuel related to FATES_ROS (omits 1000hr fuels) in kg C per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_sum_fuel_si) - ! Litter Variables - - call this%set_history_var(vname='FATES_LITTER_IN', units='kg m-2 s-1', & - long='litter flux in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_in_si) - - call this%set_history_var(vname='FATES_LITTER_OUT', units='kg m-2 s-1', & - long='litter flux out in kg carbon (exudation, fragmentation, seed decay)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_out_si) - - call this%set_history_var(vname='FATES_SEED_BANK', units='kg m-2', & - long='total seed mass of all PFTs in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seed_bank_si) - - call this%set_history_var(vname='FATES_UNGERM_SEED_BANK', units='kg m-2', & - long='ungerminated seed mass of all PFTs in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_ungerm_seed_bank_si) - - call this%set_history_var(vname='FATES_SEEDLING_POOL', units='kg m-2', & - long='total seedling (ie germinated seeds) mass of all PFTs in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seedling_pool_si) - - call this%set_history_var(vname='FATES_SEEDS_IN', units='kg m-2 s-1', & - long='seed production rate in kg carbon per m2 second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seeds_in_si) - - call this%set_history_var(vname='FATES_SEEDS_IN_LOCAL', units='kg m-2 s-1', & - long='local seed production rate in kg carbon per m2 second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seeds_in_local_si) - - call this%set_history_var(vname='FATES_STOREC', units='kg m-2', & - long='total biomass in live plant storage in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_storec_si) - - call this%set_history_var(vname='FATES_STOREC_TF', units='kg kg-1', & - long='Storage C fraction of target', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_si ) - - call this%set_history_var(vname='FATES_VEGC', units='kg m-2', & - long='total biomass in live plants in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_totvegc_si) - - call this%set_history_var(vname='FATES_SAPWOODC', units='kg m-2', & - long='total biomass in live plant sapwood in kg carbon per m2', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_sapwc_si) - - call this%set_history_var(vname='FATES_LEAFC', units='kg m-2', & - long='total biomass in live plant leaves in kg carbon per m2', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_leafc_si) - - call this%set_history_var(vname='FATES_FROOTC', units='kg m-2', & - long='total biomass in live plant fine roots in kg carbon per m2', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fnrtc_si) - - call this%set_history_var(vname='FATES_REPROC', units='kg m-2', & - long='total biomass in live plant reproductive tissues in kg carbon per m2', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_reproc_si) - - ! Output specific to the chemical species dynamics used (parteh) - select case(hlm_parteh_mode) - case (prt_cnp_flex_allom_hyp) - - call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for target allometry', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) - - call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & - long='ammonium uptake rate by plants in kg NH4 per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_nh4uptake_si) - - call this%set_history_var(vname='FATES_NO3UPTAKE', units='kg m-2 s-1', & - long='nitrate uptake rate by plants in kg NO3 per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_no3uptake_si) - - call this%set_history_var(vname='FATES_NEFFLUX', units='kg m-2 s-1', & - long='nitrogen effluxed from plant in kg N per m2 per second (unused)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, 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=5, 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', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_nfix_si) - - end select - - nitrogen_active_if0: if(any(element_list(:)==nitrogen_element)) then - call this%set_history_var(vname='FATES_STOREN', units='kg m-2', & - long='total nitrogen in live plant storage', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_storen_si) - - call this%set_history_var(vname='FATES_STOREN_TF', units='1', & - long='storage N fraction of target', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storentfrac_si) - - call this%set_history_var(vname='FATES_VEGN', units='kg m-2', & - long='total nitrogen in live plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_totvegn_si) - - call this%set_history_var(vname='FATES_SAPWOODN', units='kg m-2', & - long='total nitrogen in live plant sapwood', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_sapwn_si) - - call this%set_history_var(vname='FATES_LEAFN', units='kg m-2', & - long='total nitrogen in live plant leaves', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_leafn_si) - - call this%set_history_var(vname='FATES_FROOTN', units='kg m-2', & - long='total nitrogen in live plant fine-roots', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fnrtn_si) - - call this%set_history_var(vname='FATES_REPRON', units='kg m-2', & - long='total nitrogen in live plant reproductive tissues', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_repron_si) - end if nitrogen_active_if0 - - phosphorus_active_if0: if(any(element_list(:)==phosphorus_element)) then - call this%set_history_var(vname='FATES_STOREP', units='kg m-2', & - long='total phosphorus in live plant storage', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_storep_si) - - call this%set_history_var(vname='FATES_STOREP_TF', units='1', & - long='storage P fraction of target', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, & - index = ih_storeptfrac_si) - - call this%set_history_var(vname='FATES_VEGP', units='kg m-2', & - long='total phosphorus in live plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_totvegp_si) - - call this%set_history_var(vname='FATES_SAPWOODP', units='kg m-2', & - long='Total phosphorus in live plant sapwood', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sapwp_si) - - call this%set_history_var(vname='FATES_LEAFP', units='kg m-2', & - long='total phosphorus in live plant leaves', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_leafp_si) - - call this%set_history_var(vname='FATES_FROOTP', units='kg m-2', & - long='total phosphorus in live plant fine roots', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fnrtp_si) - - call this%set_history_var(vname='FATES_REPROP', units='kg m-2', & - long='total phosphorus in live plant reproductive tissues', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_reprop_si) - - call this%set_history_var(vname='FATES_PUPTAKE', units='kg m-2 s-1', & - long='mineralized phosphorus uptake rate of plants in kg P per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_puptake_si) - - call this%set_history_var(vname='FATES_PEFFLUX', units='kg m-2 s-1', & - long='phosphorus effluxed from plant in kg P per m2 per second (unused)', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, 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=5, 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', & - long='structural biomass in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_bdead_si) - - call this%set_history_var(vname='FATES_NONSTRUCTC', units='kg m-2', & - long='non-structural biomass (sapwood + leaf + fineroot) in kg carbon per m2', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_balive_si) - - call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND', units='kg m-2', & - long='aboveground biomass in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_agb_si) - - call this%set_history_var(vname='FATES_CANOPY_VEGC', units='kg m-2', & - long='biomass of canopy plants in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_canopy_biomass_si) - - call this%set_history_var(vname='FATES_USTORY_VEGC', units='kg m-2', & - long='biomass of understory plants in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_understory_biomass_si) - - ! disturbance rates - - call this%set_history_var(vname='FATES_PRIMARY_PATCHFUSION_ERR', & - units='m2 m-2 yr-1', & - long='error in total primary lands associated with patch fusion', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_primaryland_fusion_error_si) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_FIRE', & - units='m2 m-2 yr-1', long='disturbance rate from fire', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_disturbance_rate_si) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_LOGGING', & - units='m2 m-2 yr-1', long='disturbance rate from logging', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_logging_disturbance_rate_si) - - call this%set_history_var(vname='FATES_DISTURBANCE_RATE_TREEFALL', & - units='m2 m-2 yr-1', long='disturbance rate from treefall', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fall_disturbance_rate_si) - - call this%set_history_var(vname='FATES_HARVEST_CARBON_FLUX', & - units='kg m-2 yr-1', & - long='harvest carbon flux in kg carbon per m2 per year', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_harvest_carbonflux_si) - - call this%set_history_var(vname='FATES_TVEG24', units='degree_Celsius', & - long='fates 24-hr running mean vegetation temperature by site', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) - - call this%set_history_var(vname='FATES_TLONGTERM', units='degree_Celsius', & - long='fates 30-year running mean vegetation temperature by site', & - use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_tlongterm_si ) - - call this%set_history_var(vname='FATES_TGROWTH', units='degree_Celsius', & - long='fates long-term running mean vegetation temperature by site', & - use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_tgrowth_si ) - - call this%set_history_var(vname='FATES_HARVEST_DEBT', units='kg C', & - long='Accumulated carbon failed to be harvested', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) - - call this%set_history_var(vname='FATES_HARVEST_DEBT_SEC', units='kg C', & - long='Accumulated carbon failed to be harvested from secondary patches', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) - - call this%set_history_var(vname='FATES_EXCESS_RESP', units='kg m-2 s-1', & - long='respiration of un-allocatable carbon gain', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & - index = ih_excess_resp_si) - ! slow carbon fluxes associated with mortality from or transfer betweeen canopy and understory + call this%set_history_var(vname='FATES_NCOHORTS_SECONDARY', units='', & + long='total number of cohorts per site', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_ncohorts_sec_si) + + ! Patch variables + call this%set_history_var(vname='FATES_TRIMMING', units='1', & + long='degree to which canopy expansion is limited by leaf economics (0-1)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_trimming_si) + + call this%set_history_var(vname='FATES_AREA_PLANTS', units='m2 m-2', & + long='area occupied by all plants per m2 land area', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & + initialize=initialize_variables, index=ih_area_plant_si) + + call this%set_history_var(vname='FATES_AREA_TREES', units='m2 m-2', & + long='area occupied by woody plants per m2 land area', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_area_trees_si) - call this%set_history_var(vname='FATES_DEMOTION_CARBONFLUX', & - units = 'kg m-2 s-1', & - long='demotion-associated biomass carbon flux from canopy to understory in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_demotion_carbonflux_si) - - call this%set_history_var(vname='FATES_PROMOTION_CARBONFLUX', & - units = 'kg m-2 s-1', & - long='promotion-associated biomass carbon flux from understory to canopy in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_promotion_carbonflux_si) - - call this%set_history_var(vname='FATES_MORTALITY_CFLUX_CANOPY', & - units = 'kg m-2 s-1', & - long='flux of biomass carbon from live to dead pools from mortality of canopy plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_canopy_mortality_carbonflux_si) - - call this%set_history_var(vname='FATES_MORTALITY_CFLUX_USTORY', & - units = 'kg m-2 s-1', & - long='flux of biomass carbon from live to dead pools from mortality of understory plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_understory_mortality_carbonflux_si) - - call this%set_history_var(vname='MORTALITY_CROWNAREA_CANOPY', & - units = 'm2/ha/year', & - long='Crown area of canopy trees that died', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_canopy_mortality_crownarea_si ) - - call this%set_history_var(vname='MORTALITY_CROWNAREA_UNDERSTORY', & - units = 'm2/ha/year', & - long='Crown aera of understory trees that died', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_understory_mortality_crownarea_si ) - - call this%set_history_var(vname='FATES_FIRE_CLOSS', units='kg m-2 s-1', & - long='carbon loss to atmosphere from fire in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_c_to_atm_si) - - call this%set_history_var(vname='FATES_CBALANCE_ERROR', & - units='kg s-1', & - long='total carbon error in kg carbon per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, 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', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_leaf_si) - - call this%set_history_var(vname='FATES_SEED_ALLOC', units='kg m-2 s-1', & - long='allocation to seeds in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_seed_si) - - call this%set_history_var(vname='FATES_STEM_ALLOC', units='kg m-2 s-1', & - long='allocation to stem in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stem_si) - - call this%set_history_var(vname='FATES_FROOT_ALLOC', units='kg m-2 s-1', & - long='allocation to fine roots in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_froot_si) - - call this%set_history_var(vname='FATES_CROOT_ALLOC', units='kg m-2 s-1', & - long='allocation to coarse roots in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_croot_si) - - call this%set_history_var(vname='FATES_STORE_ALLOC', units='kg m-2 s-1', & - long='allocation to storage tissues in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stor_si) - - hydro_active_if: if(hlm_use_planthydro.eq.itrue) then - call this%set_history_var(vname='FATES_VEGH2O_DEAD', units = 'kg m-2', & - long='cumulative water stored in dead biomass due to mortality', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_dead_si) - - call this%set_history_var(vname='FATES_VEGH2O_RECRUIT', & - units = 'kg m-2', long='amount of water in new recruits', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_recruit_si) - - call this%set_history_var(vname='FATES_VEGH2O_GROWTURN_ERR', & - units = 'kg m-2', & - long='cumulative net borrowed (+) or lost (-) from water storage due to combined growth & turnover', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_growturn_err_si) - end if hydro_active_if + call this%set_history_var(vname='FATES_FRACTION', units='m2 m-2', & + long='total gridcell fraction which FATES is running over', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_fates_fraction_si, flush_to_zero=.true.) - !HERE - - if_dyn1: if(hlm_hist_level_dynam>1) then - - call this%set_history_var(vname='FATES_VEGC_PF', units='kg m-2', & - long='total PFT-level biomass in kg of carbon per land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_biomass_si_pft) - - call this%set_history_var(vname='FATES_VEGC_SE_PF', units='kg m-2', & - long='total PFT-level biomass in kg of carbon per land area, secondary patches', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_biomass_sec_si_pft) - - call this%set_history_var(vname='FATES_LEAFC_PF', units='kg m-2', & - long='total PFT-level leaf biomass in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_leafbiomass_si_pft) - - call this%set_history_var(vname='FATES_STOREC_PF', units='kg m-2', & - long='total PFT-level stored biomass in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_storebiomass_si_pft) - - call this%set_history_var(vname='FATES_CROWNAREA_PF', units='m2 m-2', & - long='total PFT-level crown area per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_crownarea_si_pft) - - call this%set_history_var(vname='FATES_CANOPYCROWNAREA_PF', & - units='m2 m-2', long='total PFT-level canopy-layer crown area per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_canopycrownarea_si_pft) - - call this%set_history_var(vname='FATES_GPP_PF', units='kg m-2 s-1', & - long='total PFT-level GPP in kg carbon per m2 land area per second', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_gpp_si_pft) - - call this%set_history_var(vname='FATES_NPP_PF', units='kg m-2 s-1', & - long='total PFT-level NPP in kg carbon per m2 land area per second', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_npp_si_pft) - - call this%set_history_var(vname='FATES_GPP_SE_PF', units='kg m-2 s-1', & - long='total PFT-level GPP in kg carbon per m2 land area per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_gpp_sec_si_pft) - - call this%set_history_var(vname='FATES_NPP_SE_PF', units='kg m-2 s-1', & - long='total PFT-level NPP in kg carbon per m2 land area per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_npp_sec_si_pft) - - call this%set_history_var(vname='FATES_NPLANT_PF', units='m-2', & - long='total PFT-level number of individuals per m2 land area', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nindivs_si_pft) - - call this%set_history_var(vname='FATES_NPLANT_SEC_PF', units='m-2', & - long='total PFT-level number of individuals per m2 land area, secondary patches', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nindivs_sec_si_pft) - - call this%set_history_var(vname='FATES_RECRUITMENT_PF', & - units='m-2 yr-1', & - long='PFT-level recruitment rate in number of individuals per m2 land area per year', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_recruitment_si_pft) - - call this%set_history_var(vname='FATES_SEEDS_IN_GRIDCELL_PF', & - units='kg', & - long='Site-level seed mass input from neighboring gridcells per pft', & - use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_seeds_in_gc_si_pft) - - call this%set_history_var(vname='FATES_SEEDS_OUT_GRIDCELL_PF', & - units='kg', & - long='Site-level seed mass output to neighboring gridcells per pft', & - use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_seeds_out_gc_si_pft) - - call this%set_history_var(vname='FATES_MORTALITY_PF', units='m-2 yr-1', & - long='PFT-level mortality rate in number of individuals per m2 land area per year', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_mortality_si_pft) - - !MLO - Drought-deciduous phenology variables are now defined for each PFT. - call this%set_history_var(vname='FATES_DROUGHT_STATUS_PF', & - units='', & - long='PFT-level drought status, <2 too dry for leaves, >=2 not too dry', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_site_dstatus_si_pft) - - call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFOFF_PF', & - units='days', long='PFT-level days elapsed since drought leaf drop', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_dleafoff_si_pft) - - call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFON_PF', & - units='days', & - long='PFT-level days elapsed since drought leaf flush', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_dleafon_si_pft) - - call this%set_history_var(vname='FATES_MEANLIQVOL_DROUGHTPHEN_PF', & - units='m3 m-3', & - long='PFT-level mean liquid water volume for drought phenolgy', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_meanliqvol_si_pft) - - call this%set_history_var(vname='FATES_MEANSMP_DROUGHTPHEN_PF', & - units='Pa', & - long='PFT-level mean soil matric potential for drought phenology', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_meansmp_si_pft) - - call this%set_history_var(vname='FATES_ELONG_FACTOR_PF', & - units='1', & - long='PFT-level mean elongation factor (partial flushing/abscission)', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_elong_factor_si_pft) - - nocomp_if: if (hlm_use_nocomp .eq. itrue) then - call this%set_history_var(vname='FATES_NOCOMP_NPATCHES_PF', units='', & - long='number of patches per PFT (nocomp-mode-only)', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nocomp_pftnpatches_si_pft) + call this%set_history_var(vname='FATES_BA_WEIGHTED_HEIGHT', units='m', & + long='basal area-weighted mean height of woody plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_ba_weighted_height_si) - call this%set_history_var(vname='FATES_NOCOMP_PATCHAREA_PF', units='m2 m-2',& - long='total patch area allowed per PFT (nocomp-mode-only)', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nocomp_pftpatchfraction_si_pft) + call this%set_history_var(vname='FATES_CA_WEIGHTED_HEIGHT', units='m', & + long='crown area-weighted mean height of canopy plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_ca_weighted_height_si) - call this%set_history_var(vname='FATES_NOCOMP_BURNEDAREA_PF', units='s-1', & - long='total burned area of PFT-labeled patch area (nocomp-mode-only)',& - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_nocomp_pftburnedarea_si_pft) - endif nocomp_if - - ! patch age class variables - call this%set_history_var(vname='FATES_PATCHAREA_AP', units='m2 m-2', & - long='patch area by age bin per m2 land area', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index=ih_area_si_age) - - call this%set_history_var(vname='FATES_LAI_AP', units='m2 m-2', & - long='leaf area index by age bin per m2 land area', & - use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_lai_si_age) - - - - call this%set_history_var(vname='FATES_CANOPYAREA_AP', units='m2 m-2', & - long='canopy area by age bin per m2 land area', use_default='active', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index=ih_canopy_area_si_age) - - call this%set_history_var(vname='FATES_NCL_AP', units='', & - long='number of canopy levels by age bin', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_ncl_si_age) - - call this%set_history_var(vname='FATES_NPATCH_AP', units='', & - long='number of patches by age bin', use_default='inactive', & - avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_npatches_si_age) - - if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled - tempstring = 'active' - else - tempstring = 'inactive' - endif + call this%set_history_var(vname='FATES_COLD_STATUS', units='', & + long='site-level cold status, 0=not cold-dec, 1=too cold for leaves, 2=not too cold', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_site_cstatus_si) - call this%set_history_var(vname='FATES_ZSTAR_AP', units='m', & - long='product of zstar and patch area by age bin (divide by FATES_PATCHAREA_AP to get mean zstar)', & - use_default=trim(tempstring), avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_zstar_si_age) - - call this%set_history_var(vname='FATES_CANOPYAREA_HT', units='m2 m-2', & - long='canopy area height distribution', & - use_default='active', avgflag='A', vtype=site_height_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_canopy_height_dist_si_height) - - call this%set_history_var(vname='FATES_LEAFAREA_HT', units='m2 m-2', & - long='leaf area height distribution', use_default='active', & - avgflag='A', vtype=site_height_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_leaf_height_dist_si_height) - - call this%set_history_var(vname='FATES_VEGC_AP', units='kg m-2', & - long='total biomass within a given patch age bin in kg carbon per m2 land area', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_biomass_si_age) - - call this%set_history_var(vname='FATES_SECONDAREA_ANTHRODIST_AP', & - units='m2 m-2', & - long='secondary forest patch area age distribution since anthropgenic disturbance', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_agesince_anthrodist_si_age) - - call this%set_history_var(vname='FATES_SECONDAREA_DIST_AP', & - units='m2 m-2', & - long='secondary forest patch area age distribution since any kind of disturbance', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_secondarylands_area_si_age) - - call this%set_history_var(vname='FATES_FRAGMENTATION_SCALER_SL', units='', & - long='factor (0-1) by which litter/cwd fragmentation proceeds relative to max rate by soil layer', & - use_default='active', avgflag='A', vtype=site_soil_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fragmentation_scaler_sl) - - call this%set_history_var(vname='FATES_FUEL_MOISTURE_FC', units='m3 m-3', & - long='spitfire fuel class-level fuel moisture (volumetric)', & - use_default='active', avgflag='A', vtype=site_fuel_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_moisture_si_fuel) - - call this%set_history_var(vname='FATES_FUEL_AMOUNT_FC', units='kg m-2', & - long='spitfire fuel-class level fuel amount in kg carbon per m2 land area', & - use_default='active', avgflag='A', vtype=site_fuel_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fuel_amount_si_fuel) - - call this%set_history_var(vname='FATES_FUEL_AMOUNT_APFC', units='kg m-2', & - long='spitfire fuel quantity in each age x fuel class in kg carbon per m2 land area', & - use_default='inactive', avgflag='A', vtype=site_agefuel_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fuel_amount_age_fuel) - - call this%set_history_var(vname='FATES_BURNFRAC_AP', units='s-1', & - long='spitfire fraction area burnt (per second) by patch age', & - use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_area_burnt_si_age) - - call this%set_history_var(vname='FATES_FIRE_INTENSITY_BURNFRAC_AP', & - units='J m-1 s-1', & - long='product of fire intensity and burned fraction, resolved by patch age (so divide by FATES_BURNFRAC_AP to get burned-area-weighted-average intensity)', & - use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_intensity_si_age) - - call this%set_history_var(vname='FATES_FUEL_AMOUNT_AP', units='kg m-2', & - long='spitfire ground fuel (kg carbon per m2) related to FATES_ROS (omits 1000hr fuels) within each patch age bin (divide by FATES_PATCHAREA_AP to get fuel per unit area of that-age patch)', & - use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fire_sum_fuel_si_age) - - call this%set_history_var(vname='FATES_FUEL_BURNT_BURNFRAC_FC', units='1', & - long='product of fraction (0-1) of fuel burnt and burnt fraction (divide by FATES_BURNFRAC to get burned-area-weighted mean fraction fuel burnt)', & - use_default='active', avgflag='A', vtype=site_fuel_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_burnt_frac_litter_si_fuel) - - call this%set_history_var(vname='FATES_LITTER_IN_EL', units='kg m-2 s-1', & - long='litter flux in in kg element per m2 per second', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_in_elem) - - call this%set_history_var(vname='FATES_LITTER_OUT_EL', units='kg m-2 s-1', & - long='litter flux out (exudation, fragmentation and seed decay) in kg element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_litter_out_elem) - - call this%set_history_var(vname='FATES_SEED_BANK_EL', units='kg m-2', & - long='element-level total seed mass of all PFTs in kg element per m2', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seed_bank_elem) - - call this%set_history_var(vname='FATES_SEEDS_IN_LOCAL_EL', & - units='kg m-2 s-1', & - long='within-site, element-level seed production rate in kg element per m2 per second', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seeds_in_local_elem) - - call this%set_history_var(vname='FATES_SEEDS_IN_EXTERN_EL', & - units='kg m-2 s-1', long='external seed influx rate in kg element per m2 per second', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seeds_in_extern_elem) - - call this%set_history_var(vname='FATES_SEED_GERM_EL', units='kg m-2', & - long='element-level total germinated seed mass of all PFTs in kg element per m2', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seed_germ_elem) - - call this%set_history_var(vname='FATES_SEED_DECAY_EL', units='kg m-2 s-1', & - long='seed mass decay (germinated and un-germinated) in kg element per m2 per second', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_seed_decay_elem) - - ! SITE LEVEL CARBON STATE VARIABLES - - call this%set_history_var(vname='FATES_STOREC_TF_USTORY_SZPF', units='kg kg-1', & - long='Storage C fraction of target by size x pft, in the understory', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_ustory_scpf ) - - - call this%set_history_var(vname='FATES_STOREC_TF_CANOPY_SZPF', units='kg kg-1', & - long='Storage C fraction of target by size x pft, in the canopy', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_canopy_scpf ) - - + call this%set_history_var(vname='FATES_GDD', units='degree_Celsius', & + long='site-level growing degree days', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, index=ih_gdd_si) - - call this%set_history_var(vname='FATES_FROOTC_SL', units='kg m-3', & - long='Total carbon in live plant fine-roots over depth', use_default='active', & - avgflag='A', vtype=site_soil_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_sl ) + call this%set_history_var(vname='FATES_NCHILLDAYS', units = 'days', & + long='site-level number of chill days', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_site_nchilldays_si) - + call this%set_history_var(vname='FATES_NCOLDDAYS', units = 'days', & + long='site-level number of cold days', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_site_ncolddays_si) + + call this%set_history_var(vname='FATES_DAYSINCE_COLDLEAFOFF', & + units='days', long='site-level days elapsed since cold leaf drop', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_cleafoff_si) + + call this%set_history_var(vname='FATES_DAYSINCE_COLDLEAFON', & + units='days', long='site-level days elapsed since cold leaf flush', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_cleafon_si) + + call this%set_history_var(vname='FATES_CANOPY_SPREAD', units='', & + long='scaling factor (0-1) between tree basal area and canopy area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_canopy_spread_si) + + call this%set_history_var(vname='FATES_LAI', units='m2 m-2', & + long='leaf area index per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_lai_si) + + call this%set_history_var(vname='FATES_LAI_SECONDARY', units='m2 m-2', & + long='leaf area index per m2 land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_lai_secondary_si) + + call this%set_history_var(vname='FATES_PATCHAREA_LU', units='m2 m-2', & + long='patch area by land use type', use_default='active', & + avgflag='A', vtype=site_landuse_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & + initialize=initialize_variables, index=ih_area_si_landuse) + + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_MATRIX_LULU', units='m2 m-2 yr-1', & + long='disturbance rates by land use type x land use type matrix', use_default='active', & + avgflag='A', vtype=site_lulu_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & + initialize=initialize_variables, index=ih_disturbance_rate_si_lulu) + + ! Secondary forest area and age diagnostics + + call this%set_history_var(vname='FATES_SECONDARY_FOREST_FRACTION', & + units='m2 m-2', long='secondary forest fraction', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_fraction_secondary_forest_si) + + call this%set_history_var(vname='FATES_WOOD_PRODUCT', units='kg m-2', & + long='total wood product from logging in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_woodproduct_si) + + call this%set_history_var(vname='FATES_SECONDARY_FOREST_VEGC', & + units='kg m-2', & + long='biomass on secondary lands in kg carbon per m2 land area (mult by FATES_SECONDARY_FOREST_FRACTION to get per secondary forest area)', & + use_default='active', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_biomass_secondary_forest_si) + ! Fire Variables + + call this%set_history_var(vname='FATES_NESTEROV_INDEX', units='', & + long='nesterov fire danger index', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_nesterov_fire_danger_si) + + call this%set_history_var(vname='FATES_IGNITIONS', & + units='m-2 s-1', & + long='number of successful fire ignitions per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_fire_nignitions_si) + + call this%set_history_var(vname='FATES_FDI', units='1', & + long='Fire Danger Index (probability that an ignition will lead to a fire)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_fire_fdi_si) + + call this%set_history_var(vname='FATES_ROS', units='m s-1', & + long='fire rate of spread in meters per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_spitfire_ros_si) + + call this%set_history_var(vname='FATES_EFFECT_WSPEED', units='m s-1', & + long ='effective wind speed for fire spread in meters per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_effect_wspeed_si) + + call this%set_history_var(vname='FATES_FUELCONSUMED', units='kg m-2', & + long ='total fuel consumed in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_tfc_ros_si) + + call this%set_history_var(vname='FATES_FIRE_INTENSITY', & + units='J m-1 s-1', & + long='spitfire surface fireline intensity in J per m per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_fire_intensity_si) + + call this%set_history_var(vname='FATES_FIRE_INTENSITY_BURNFRAC', & + units='J m-1 s-1', & + long='product of surface fire intensity and burned area fraction -- divide by FATES_BURNFRAC to get area-weighted mean intensity', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_fire_intensity_area_product_si) + + call this%set_history_var(vname='FATES_BURNFRAC', units='s-1', & + long='burned area fraction per second', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_fire_area_si) + + call this%set_history_var(vname='FATES_FUEL_MEF', units='m3 m-3', & + long='fuel moisture of extinction (volumetric)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_fire_fuel_mef_si) + + call this%set_history_var(vname='FATES_FUEL_BULKD', & + units='kg m-3', long='fuel bulk density in kg per m3', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_fuel_bulkd_si ) + + call this%set_history_var(vname='FATES_FUEL_EFF_MOIST', units='m3 m-3', & + long='spitfire fuel moisture (volumetric)', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & + initialize=initialize_variables, index = ih_fire_fuel_eff_moist_si) + + call this%set_history_var(vname='FATES_FUEL_SAV', units='m-1', & + long='spitfire fuel surface area to volume ratio', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_fuel_sav_si) + + call this%set_history_var(vname='FATES_FUEL_AMOUNT', units='kg m-2', & + long='total ground fuel related to FATES_ROS (omits 1000hr fuels) in kg C per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_sum_fuel_si) + ! Litter Variables + + call this%set_history_var(vname='FATES_LITTER_IN', units='kg m-2 s-1', & + long='litter flux in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_in_si) + + call this%set_history_var(vname='FATES_LITTER_OUT', units='kg m-2 s-1', & + long='litter flux out in kg carbon (exudation, fragmentation, seed decay)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_out_si) + + call this%set_history_var(vname='FATES_SEED_BANK', units='kg m-2', & + long='total seed mass of all PFTs in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_seed_bank_si) + + call this%set_history_var(vname='FATES_UNGERM_SEED_BANK', units='kg m-2', & + long='ungerminated seed mass of all PFTs in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_ungerm_seed_bank_si) + + call this%set_history_var(vname='FATES_SEEDLING_POOL', units='kg m-2', & + long='total seedling (ie germinated seeds) mass of all PFTs in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_seedling_pool_si) + + call this%set_history_var(vname='FATES_SEEDS_IN', units='kg m-2 s-1', & + long='seed production rate in kg carbon per m2 second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_seeds_in_si) + + call this%set_history_var(vname='FATES_SEEDS_IN_LOCAL', units='kg m-2 s-1', & + long='local seed production rate in kg carbon per m2 second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_seeds_in_local_si) + + call this%set_history_var(vname='FATES_STOREC', units='kg m-2', & + long='total biomass in live plant storage in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_storec_si) + + call this%set_history_var(vname='FATES_STOREC_TF', units='kg kg-1', & + long='Storage C fraction of target', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & + ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_si ) + + call this%set_history_var(vname='FATES_VEGC', units='kg m-2', & + long='total biomass in live plants in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_totvegc_si) + + call this%set_history_var(vname='FATES_SAPWOODC', units='kg m-2', & + long='total biomass in live plant sapwood in kg carbon per m2', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_sapwc_si) + + call this%set_history_var(vname='FATES_LEAFC', units='kg m-2', & + long='total biomass in live plant leaves in kg carbon per m2', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_leafc_si) + + call this%set_history_var(vname='FATES_FROOTC', units='kg m-2', & + long='total biomass in live plant fine roots in kg carbon per m2', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_fnrtc_si) + + call this%set_history_var(vname='FATES_REPROC', units='kg m-2', & + long='total biomass in live plant reproductive tissues in kg carbon per m2', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_reproc_si) + + ! Output specific to the chemical species dynamics used (parteh) + select case(hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) + + call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for target allometry', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) + + call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & + long='ammonium uptake rate by plants in kg NH4 per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_nh4uptake_si) + + call this%set_history_var(vname='FATES_NO3UPTAKE', units='kg m-2 s-1', & + long='nitrate uptake rate by plants in kg NO3 per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_no3uptake_si) + + call this%set_history_var(vname='FATES_NEFFLUX', units='kg m-2 s-1', & + long='nitrogen effluxed from plant in kg N per m2 per second (unused)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, 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=5, 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', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_nfix_si) + + end select + + nitrogen_active_if0: if(any(element_list(:)==nitrogen_element)) then + call this%set_history_var(vname='FATES_STOREN', units='kg m-2', & + long='total nitrogen in live plant storage', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_storen_si) + + call this%set_history_var(vname='FATES_STOREN_TF', units='1', & + long='storage N fraction of target', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_storentfrac_si) + + call this%set_history_var(vname='FATES_VEGN', units='kg m-2', & + long='total nitrogen in live plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_totvegn_si) + + call this%set_history_var(vname='FATES_SAPWOODN', units='kg m-2', & + long='total nitrogen in live plant sapwood', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_sapwn_si) + + call this%set_history_var(vname='FATES_LEAFN', units='kg m-2', & + long='total nitrogen in live plant leaves', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_leafn_si) + + call this%set_history_var(vname='FATES_FROOTN', units='kg m-2', & + long='total nitrogen in live plant fine-roots', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fnrtn_si) + + call this%set_history_var(vname='FATES_REPRON', units='kg m-2', & + long='total nitrogen in live plant reproductive tissues', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_repron_si) + end if nitrogen_active_if0 + + phosphorus_active_if0: if(any(element_list(:)==phosphorus_element)) then + call this%set_history_var(vname='FATES_STOREP', units='kg m-2', & + long='total phosphorus in live plant storage', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_storep_si) + + call this%set_history_var(vname='FATES_STOREP_TF', units='1', & + long='storage P fraction of target', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, & + index = ih_storeptfrac_si) + + call this%set_history_var(vname='FATES_VEGP', units='kg m-2', & + long='total phosphorus in live plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_totvegp_si) + + call this%set_history_var(vname='FATES_SAPWOODP', units='kg m-2', & + long='Total phosphorus in live plant sapwood', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_sapwp_si) + + call this%set_history_var(vname='FATES_LEAFP', units='kg m-2', & + long='total phosphorus in live plant leaves', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_leafp_si) + + call this%set_history_var(vname='FATES_FROOTP', units='kg m-2', & + long='total phosphorus in live plant fine roots', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fnrtp_si) + + call this%set_history_var(vname='FATES_REPROP', units='kg m-2', & + long='total phosphorus in live plant reproductive tissues', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_reprop_si) + + call this%set_history_var(vname='FATES_PUPTAKE', units='kg m-2 s-1', & + long='mineralized phosphorus uptake rate of plants in kg P per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_puptake_si) + + call this%set_history_var(vname='FATES_PEFFLUX', units='kg m-2 s-1', & + long='phosphorus effluxed from plant in kg P per m2 per second (unused)', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, 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=5, 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', & + long='structural biomass in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_bdead_si) + call this%set_history_var(vname='FATES_NONSTRUCTC', units='kg m-2', & + long='non-structural biomass (sapwood + leaf + fineroot) in kg carbon per m2', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_balive_si) - - ! Output specific to the chemical species dynamics used (parteh) - select case(hlm_parteh_mode) - case (prt_cnp_flex_allom_hyp) - - call this%set_history_var(vname='FATES_L2FR_CANOPY_REC_PF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for recruits (canopy)', & - use_default='active', & - avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) + call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND', units='kg m-2', & + long='aboveground biomass in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_agb_si) - call this%set_history_var(vname='FATES_L2FR_USTORY_REC_PF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for recruits (understory)', & - use_default='active', & - avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) - - !call this%set_history_var(vname='FATES_L2FR_CLSZPF', units='kg kg-1', & - ! long='The leaf to fineroot biomass multiplier for target allometry', & - ! use_default='inactive', & - ! avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=1, & - ! ivar=ivar, initialize=initialize_variables, index = ih_l2fr_clscpf) - - call this%set_history_var(vname='FATES_NH4UPTAKE_SZPF', & - units='kg m-2 s-1', & - long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_nh4uptake_scpf) - - call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & - units='kg m-2 s-1', & - long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_no3uptake_scpf) - - call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & - long='nitrogen efflux, root to soil, 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=5, 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=5, 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, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & - initialize=initialize_variables, index = ih_nfix_scpf) - - end select - - nitrogen_active_if1: if(any(element_list(:)==nitrogen_element)) then - - call this%set_history_var(vname='FATES_VEGN_SZPF', units='kg m-2', & - long='total (live) vegetation nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_totvegn_scpf) - - call this%set_history_var(vname='FATES_LEAFN_SZPF', units='kg m-2', & - long='leaf nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_leafn_scpf) - - call this%set_history_var(vname='FATES_FROOTN_SZPF', units='kg m-2', & - long='fine-root nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fnrtn_scpf) - - call this%set_history_var(vname='FATES_SAPWOODN_SZPF', units='kg m-2', & - long='sapwood nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sapwn_scpf) - - call this%set_history_var(vname='FATES_STOREN_SZPF', units='kg m-2', & - long='storage nitrogen mass by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storen_scpf) - - call this%set_history_var(vname='FATES_STOREN_TF_CANOPY_SZPF', & - units='1', & - long='storage nitrogen fraction (0-1) of target, in canopy, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storentfrac_canopy_scpf) - - call this%set_history_var(vname='FATES_STOREN_TF_USTORY_SZPF', & - units='1', & - long='storage nitrogen fraction (0-1) of target, in understory, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_storentfrac_understory_scpf) - - call this%set_history_var(vname='FATES_REPRON_SZPF', units='kg m-2', & - long='reproductive nitrogen mass (on plant) by size-class x pft in kg N per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_repron_scpf) - - end if nitrogen_active_if1 - - phosphorus_active_if1: if(any(element_list(:)==phosphorus_element)) then - - call this%set_history_var(vname='FATES_VEGP_SZPF', units='kg m-2', & - long='total (live) vegetation phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_totvegp_scpf) - - call this%set_history_var(vname='FATES_LEAFP_SZPF', units='kg m-2', & - long='leaf phosphorus mass by size-class x pft', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_leafp_scpf ) - - call this%set_history_var(vname='FATES_FROOTP_SZPF', units='kg m-2', & - long='fine-root phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fnrtp_scpf) - - call this%set_history_var(vname='FATES_SAPWOODP_SZPF', units='kg m-2', & - long='sapwood phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sapwp_scpf) - - call this%set_history_var(vname='FATES_STOREP_SZPF', units='kg m-2', & - long='storage phosphorus mass by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storep_scpf) - - call this%set_history_var(vname='FATES_STOREP_TF_CANOPY_SZPF', & - units='1', & - long='storage phosphorus fraction (0-1) of target, in canopy, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_storeptfrac_canopy_scpf) - - call this%set_history_var(vname='FATES_STOREP_TF_USTORY_SZPF', & - units='1', & - long='storage phosphorus fraction (0-1) of target, in understory, by size-class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_storeptfrac_understory_scpf) - - call this%set_history_var(vname='FATES_REPROP_SZPF', units='kg m-2', & - long='reproductive phosphorus mass (on plant) by size-class x pft in kg P per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_reprop_scpf) - - call this%set_history_var(vname='FATES_PUPTAKE_SZPF', & - units='kg m-2 s-1', & - long='phosphorus uptake rate by plants, 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=5, ivar=ivar, & - initialize=initialize_variables, index = ih_puptake_scpf) - - call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & - units='kg m-2 s-1', & - long='phosphorus efflux, root to soil, 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=5, 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=5, 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', & - long='area fraction of the total ground occupied by each canopy-leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_crownarea_si_cnlf) - - call this%set_history_var(vname='FATES_CROWNAREA_CL', units='m2 m-2', & - long='area fraction of the canopy footprint occupied by each canopy-leaf layer', use_default='active', & - avgflag='A', vtype=site_can_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_crownarea_cl) + call this%set_history_var(vname='FATES_CANOPY_VEGC', units='kg m-2', & + long='biomass of canopy plants in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_canopy_biomass_si) - - call this%set_history_var(vname='FATES_MORTALITY_CFLUX_PF', units='kg m-2 s-1', & - long='PFT-level flux of biomass carbon from live to dead pool from mortality', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_mortality_carbonflux_si_pft) - - call this%set_history_var(vname='FATES_MORTALITY_FIRE_CFLUX_PF', units='kg m-2 s-1', & - long='PFT-level flux of biomass carbon from live to dead pool from fire mortality', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_firemortality_carbonflux_si_pft) - - call this%set_history_var(vname='FATES_MORTALITY_HYDRO_CFLUX_PF', units='kg m-2 s-1', & - long='PFT-level flux of biomass carbon from live to dead pool from hydraulic failure mortality', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_hydraulicmortality_carbonflux_si_pft) - - call this%set_history_var(vname='FATES_MORTALITY_CSTARV_CFLUX_PF', units='kg m-2 s-1', & - long='PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality', & - use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_cstarvmortality_carbonflux_si_pft) - - call this%set_history_var(vname='FATES_ABOVEGROUND_MORT_SZPF', units='kg m-2 s-1', & - long='Aboveground flux of carbon from AGB to necromass due to mortality', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_abg_mortality_cflux_si_scpf) - - call this%set_history_var(vname='FATES_ABOVEGROUND_PROD_SZPF', units='kg m-2 s-1', & - long='Aboveground carbon productivity', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index=ih_abg_productivity_cflux_si_scpf) - ! size class by age dimensioned variables - - call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & - long='number of plants per m2 in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_si_scag) - - call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZAP', units = 'm-2', & - long='number of plants per m2 in canopy in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_canopy_si_scag) - - call this%set_history_var(vname='FATES_NPLANT_USTORY_SZAP', & - units = 'm-2', & - long='number of plants per m2 in understory in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_understory_si_scag) - - call this%set_history_var(vname='FATES_DDBH_CANOPY_SZAP', & - units = 'm m-2 yr-1', & - long='growth rate of canopy plants in meters DBH per m2 per year in canopy in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_canopy_si_scag) - - call this%set_history_var(vname='FATES_DDBH_USTORY_SZAP', & - units = 'm m-2 yr-1', & - long='growth rate of understory plants in meters DBH per m2 per year in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_understory_si_scag) - - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZAP', & - units = 'm-2 yr-1', & - long='mortality rate of canopy plants in number of plants per m2 per year in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_canopy_si_scag) - - call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZAP', & - units = 'm-2 yr-1', & - long='mortality rate of understory plants in number of plants per m2 per year in each size x age class', & - use_default='inactive', avgflag='A', vtype=site_scag_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_understory_si_scag) - - ! size x age x pft dimensioned - - call this%set_history_var(vname='FATES_NPLANT_SZAPPF',units = 'm-2', & - long='number of plants per m2 in each size x age x pft class', & - use_default='inactive', avgflag='A', vtype=site_scagpft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_si_scagpft) - - ! age x pft dimensioned - call this%set_history_var(vname='FATES_NPP_APPF',units = 'kg m-2 s-1', & - long='NPP per PFT in each age bin in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_agepft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_si_agepft) - - call this%set_history_var(vname='FATES_VEGC_APPF',units = 'kg m-2', & - long='biomass per PFT in each age bin in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_agepft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_biomass_si_agepft) - - call this%set_history_var(vname='FATES_SCORCH_HEIGHT_APPF',units = 'm', & - long='SPITFIRE flame Scorch Height (calculated per PFT in each patch age bin)', & - use_default='inactive', avgflag='A', vtype=site_agepft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_scorch_height_si_agepft) - - - ! Carbon Flux (grid dimension x scpf) (THESE ARE DEFAULT INACTIVE!!! - ! (BECAUSE THEY TAKE UP SPACE!!! - ! =================================================================================== - - call this%set_history_var(vname='FATES_GPP_SZPF', units='kg m-2 s-1', & - long='gross primary production by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_gpp_si_scpf) - - call this%set_history_var(vname='FATES_GPP_CANOPY_SZPF', & - units='kg m-2 s-1', & - long='gross primary production of canopy plants by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_gpp_canopy_si_scpf) - - call this%set_history_var(vname='FATES_AUTORESP_CANOPY_SZPF', & - units='kg m-2 s-1', & - long='autotrophic respiration of canopy plants by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_canopy_si_scpf) - - call this%set_history_var(vname='FATES_GPP_USTORY_SZPF', & - units='kg m-2 s-1', & - long='gross primary production of understory plants by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_gpp_understory_si_scpf) - - call this%set_history_var(vname='FATES_AUTORESP_USTORY_SZPF', & - units='kg m-2 s-1', & - long='autotrophic respiration of understory plants by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_understory_si_scpf) - - call this%set_history_var(vname='FATES_NPP_SZPF', units='kg m-2 s-1', & - long='total net primary production by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_totl_si_scpf) - - call this%set_history_var(vname='FATES_LEAF_ALLOC_SZPF', units='kg m-2 s-1', & - long='allocation to leaves by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_leaf_si_scpf) - - call this%set_history_var(vname='FATES_SEED_ALLOC_SZPF', units='kg m-2 s-1', & - long='allocation to seeds by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_seed_si_scpf) - - call this%set_history_var(vname='FATES_FROOT_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to fine roots by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_npp_fnrt_si_scpf) - - call this%set_history_var(vname='FATES_BGSAPWOOD_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to below-ground sapwood by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_bgsw_si_scpf) - - call this%set_history_var(vname='FATES_BGSTRUCT_ALLOC_SZPF', units='kg m-2 s-1', & - long='allocation to below-ground structural (deadwood) by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_bgdw_si_scpf) - - call this%set_history_var(vname='FATES_AGSAPWOOD_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to above-ground sapwood by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_agsw_si_scpf) - - call this%set_history_var(vname = 'FATES_AGSTRUCT_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to above-ground structural (deadwood) by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_agdw_si_scpf) - - call this%set_history_var(vname = 'FATES_STORE_ALLOC_SZPF', & - units='kg m-2 s-1', & - long='allocation to storage C by pft/size in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stor_si_scpf) - - call this%set_history_var(vname='FATES_DDBH_SZPF', units = 'm m-2 yr-1', & - long='diameter growth increment by pft/size', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_ddbh_si_scpf) - - call this%set_history_var(vname='FATES_GROWTHFLUX_SZPF', & - units = 'm-2 yr-1', & - long='flux of individuals into a given size class bin via growth and recruitment', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_growthflux_si_scpf) - - call this%set_history_var(vname='FATES_GROWTHFLUX_FUSION_SZPF', & - units = 'm-2 yr-1', & - long='flux of individuals into a given size class bin via fusion', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_growthflux_fusion_si_scpf) - - call this%set_history_var(vname='FATES_DDBH_CANOPY_SZPF', & - units = 'm m-2 yr-1', & - long='diameter growth increment by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_canopy_si_scpf) - - call this%set_history_var(vname='FATES_DDBH_USTORY_SZPF', & - units = 'm m-2 yr-1', & - long='diameter growth increment by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_understory_si_scpf) - - call this%set_history_var(vname='FATES_BASALAREA_SZPF', units = 'm2 m-2', & - long='basal area by pft/size', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_ba_si_scpf) - - call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND_SZPF', & - units = 'kg m-2', & - long='aboveground biomass by pft/size in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_agb_si_scpf) - - call this%set_history_var(vname='FATES_NPLANT_SZPF', units = 'm-2', & - long='stem number density by pft/size', use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_nplant_si_scpf) - - call this%set_history_var(vname='FATES_NPLANT_ACPF', units = 'm-2', & - long='stem number density by pft and age class', & - use_default='inactive', avgflag='A', vtype=site_coage_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_nplant_si_capf) - - call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SZPF', & - units = 'm-2 yr-1', & - long='background mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m1_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SZPF', & - units = 'm-2 yr-1', & - long='hydraulic mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m2_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZPF', & - units = 'm-2 yr-1', & - long='carbon starvation mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZPF', & - units = 'm-2 yr-1', & - long='impact mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m4_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_FIRE_SZPF', & - units = 'm-2 yr-1', & - long='fire mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m5_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_CROWNSCORCH_SZPF', & - units = 'm-2 yr-1', & - long='fire mortality from crown scorch by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_crownfiremort_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_CAMBIALBURN_SZPF', & - units = 'm-2 yr-1', & - long='fire mortality from cambial burn by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cambialfiremort_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZPF', & - units = 'm-2 yr-1', & - long='termination mortality by pft/size in number pf plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m6_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZPF', & - units = 'm-2 yr-1', & - long='logging mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_m7_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SZPF', & - units = 'm-2 yr-1', & - long='freezing mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m8_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SZPF', & - units = 'm-2 yr-1', & - long='senescence mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m9_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SZPF', & - units = 'm-2 yr-1', & - long='age senescence mortality by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype =site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_m10_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_ACPF', & - units='m-2 yr-1', & - long='age senescence mortality by pft/cohort age in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype =site_coage_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index =ih_m10_si_capf) - - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZPF', & - units = 'm-2 yr-1', & - long='total mortality of canopy plants by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_canopy_si_scpf) - - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZPF', & - units = 'N/ha/yr', & - long='C starvation mortality of canopy plants by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scpf ) - - call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZPF', & - units = 'N/ha/yr', & - long='C starvation mortality of understory plants by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_mortality_understory_si_scpf ) + call this%set_history_var(vname='FATES_USTORY_VEGC', units='kg m-2', & + long='biomass of understory plants in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_understory_biomass_si) - - call this%set_history_var(vname='FATES_C13DISC_SZPF', units = 'per mil', & - long='C13 discrimination by pft/size',use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_c13disc_si_scpf) - - call this%set_history_var(vname='FATES_STOREC_CANOPY_SZPF', units = 'kg m-2', & - long='biomass in storage pools of canopy plants by pft/size in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bstor_canopy_si_scpf) - - call this%set_history_var(vname='FATES_LEAFC_CANOPY_SZPF', & - units = 'kg m-2', & - long='biomass in leaves of canopy plants by pft/size in kg carbon per m2', & - use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, & - index = ih_bleaf_canopy_si_scpf) - - call this%set_history_var(vname='FATES_LAI_CANOPY_SZPF', & - units = 'm2 m-2', & - long='Leaf area index (LAI) of canopy plants by pft/size', & - use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, & - index = ih_lai_canopy_si_scpf ) - - call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZPF', units = 'm-2', & - long='number of canopy plants by size/pft per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_canopy_si_scpf) - - call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZPF', & - units = 'm-2 yr-1', & - long='total mortality of understory plants by pft/size in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_mortality_understory_si_scpf) - - call this%set_history_var(vname='FATES_STOREC_USTORY_SZPF', & - units = 'kg m-2', & - long='biomass in storage pools of understory plants by pft/size in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bstor_understory_si_scpf) - - call this%set_history_var(vname='FATES_LEAFC_USTORY_SZPF', & - units = 'kg m-2', & - long='biomass in leaves of understory plants by pft/size in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bleaf_understory_si_scpf) - - call this%set_history_var(vname='FATES_LAI_USTORY_SZPF', & - units = 'm2 m-2', & - long='Leaf area index (LAI) of understory plants by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_lai_understory_si_scpf ) - - call this%set_history_var(vname='FATES_NPLANT_USTORY_SZPF', & - units = 'm-2', & - long='density of understory plants by pft/size in number of plants per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_understory_si_scpf) - - call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_DC', units='kg m-2', & - long='debris class-level aboveground coarse woody debris stocks in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_ag_si_cwdsc) - - call this%set_history_var(vname='FATES_CWD_BELOWGROUND_DC', units='kg m-2', & - long='debris class-level belowground coarse woody debris stocks in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_bg_si_cwdsc) - - call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_IN_DC', & - units='kg m-2 s-1', & - long='debris class-level aboveground coarse woody debris input in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_ag_in_si_cwdsc) - - call this%set_history_var(vname='FATES_CWD_BELOWGROUND_IN_DC', & - units='kg m-2 s-1', & - long='debris class-level belowground coarse woody debris input in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_bg_in_si_cwdsc) - - call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_OUT_DC', & - units='kg m-2 s-1', & - long='debris class-level aboveground coarse woody debris output in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_ag_out_si_cwdsc) - - call this%set_history_var(vname='FATES_CWD_BELOWGROUND_OUT_DC', & - units='kg m-2 s-1', & - long='debris class-level belowground coarse woody debris output in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_bg_out_si_cwdsc) - - - ! size-class only variables - - call this%set_history_var(vname='FATES_DDBH_CANOPY_SZ', & - units = 'm m-2 yr-1', long='diameter growth increment by size of canopy plants', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_canopy_si_scls) - - call this%set_history_var(vname='FATES_DDBH_USTORY_SZ', & - units = 'm m-2 yr-1', long='diameter growth increment by size of understory plants', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_ddbh_understory_si_scls) - - call this%set_history_var(vname='FATES_YESTCANLEV_CANOPY_SZ', & - units = 'm-2', & - long='yesterdays canopy level for canopy plants by size class in number of plants per m2', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_yesterdaycanopylevel_canopy_si_scls) - - call this%set_history_var(vname='FATES_YESTCANLEV_USTORY_SZ', & - units = 'm-2', & - long='yesterdays canopy level for understory plants by size class in number of plants per m2', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_yesterdaycanopylevel_understory_si_scls) - - call this%set_history_var(vname='FATES_BASALAREA_SZ', units = 'm2 m-2', & - long='basal area by size class', use_default='active', & - avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_ba_si_scls) - - call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND_SZ', & - units = 'kg m-2', & - long='aboveground biomass by size class in kg carbon per m2', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_agb_si_scls) - - call this%set_history_var(vname='FATES_VEGC_SZ', units = 'kg m-2', & - long='total biomass by size class in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_biomass_si_scls) - - call this%set_history_var(vname='FATES_DEMOTION_RATE_SZ', & - units = 'm-2 yr-1', & - long='demotion rate from canopy to understory by size class in number of plants per m2 per year', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_demotion_rate_si_scls) - - call this%set_history_var(vname='FATES_PROMOTION_RATE_SZ', & - units = 'm-2 yr-1', & - long='promotion rate from understory to canopy by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_promotion_rate_si_scls) - - call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZ', & - units = 'm-2', & - long='number of canopy plants per m2 by size class', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_canopy_si_scls) - - call this%set_history_var(vname='FATES_LAI_CANOPY_SZ', units = 'm2 m-2', & - long='leaf area index (LAI) of canopy plants by size class', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_lai_canopy_si_scls) - - call this%set_history_var(vname='FATES_SAI_CANOPY_SZ', units = 'm2 m-2', & - long='stem area index (SAI) of canopy plants by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sai_canopy_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZ', & - units = 'm-2 yr-1', & - long='total mortality of canopy trees by size class in number of plants per m2', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_canopy_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SE_SZ', & - units = 'm-2 yr-1', & - long='total mortality of canopy trees by size class in number of plants per m2, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_mortality_canopy_secondary_si_scls) - - call this%set_history_var(vname='FATES_NPLANT_USTORY_SZ', & - units = 'm-2', & - long='number of understory plants per m2 by size class', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_understory_si_scls) - - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZ', & - units = 'N/ha/yr', & - long='C starvation mortality of canopy plants by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scls ) - - call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZ', & - units = 'N/ha/yr', & - long='C starvation mortality of understory plants by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_mortality_understory_si_scls ) - - call this%set_history_var(vname='FATES_LAI_USTORY_SZ', & - units = 'm2 m-2', & - long='leaf area index (LAI) of understory plants by size class', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_lai_understory_si_scls) - - call this%set_history_var(vname='FATES_SAI_USTORY_SZ', & - units = 'm2 m-2', & - long='stem area index (SAI) of understory plants by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_sai_understory_si_scls) - - call this%set_history_var(vname='FATES_NPLANT_SZ', units = 'm-2', & - long='number of plants per m2 by size class', use_default='active', & - avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', upfreq=1, & - ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_scls) - - call this%set_history_var(vname='FATES_NPLANT_AC', units = 'm-2', & - long='number of plants per m2 by cohort age class', & - use_default='active', avgflag='A', vtype=site_coage_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_nplant_si_cacls) - - call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SZ', & - units = 'm-2 yr-1', & - long='background mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m1_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SZ', & - units = 'm-2 yr-1', & - long='hydraulic mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m2_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZ', & - units = 'm-2 yr-1', & - long='carbon starvation mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SE_SZ', & - units = 'm-2 yr-1', & - long='background mortality by size in number of plants per m2 per year, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m1_sec_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SE_SZ', & - units = 'm-2 yr-1', & - long='hydraulic mortality by size in number of plants per m2 per year, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m2_sec_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SE_SZ', & - units = 'm-2 yr-1', & - long='carbon starvation mortality by size in number of plants per m2 per year, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m3_sec_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZ', & - units = 'm-2 yr-1', & - long='impact mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m4_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_FIRE_SZ', & - units = 'm-2 yr-1', & - long='fire mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m5_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZ', & - units = 'm-2 yr-1', & - long='termination mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m6_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZ', & - units = 'm-2 yr-1', & - long='logging mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m7_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SZ', & - units = 'm-2 yr-1', & - long='freezing mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m8_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SZ', & - units = 'm-2 yr-1', & - long='senescence mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m9_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SZ', & - units = 'm-2 yr-1', & - long='age senescence mortality by size in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m10_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_AC', & - units = 'm-2 yr-1', & - long='age senescence mortality by cohort age in number of plants per m2 per year', & - use_default='active', avgflag='A', vtype=site_coage_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m10_si_cacls) - - call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SE_SZ', & - units = 'm-2 yr-1', & - long='logging mortality by size in number of plants per m2 per event, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m7_sec_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SE_SZ', & - units = 'm-2 event-1', & - long='freezing mortality by size in number of plants per m2 per event, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m8_sec_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SE_SZ', & - units = 'm-2 yr-1', & - long='senescence mortality by size in number of plants per m2 per event, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m9_sec_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SE_SZ', & - units = 'm-2 yr-1', & - long='age senescence mortality by size in number of plants per m2 per year, secondary patches', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_m10_sec_si_scls) - - call this%set_history_var(vname='FATES_NPP_CANOPY_SZ', units = 'kg m-2 s-1', & - long='NPP of canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_carbon_balance_canopy_si_scls) - - call this%set_history_var(vname='FATES_NPP_USTORY_SZ', units = 'kg m-2 s-1', & - long='NPP of understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_carbon_balance_understory_si_scls) - - call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZ', & - units = 'm-2 yr-1', & - long='total mortality of understory trees by size class in individuals per m2 per year', & - use_default='active', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_mortality_understory_si_scls) - - call this%set_history_var(vname='FATES_TRIMMING_CANOPY_SZ', units = 'm-2', & - long='trimming term of canopy plants weighted by plant density, by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_trimming_canopy_si_scls) - - call this%set_history_var(vname='FATES_TRIMMING_USTORY_SZ', & - units = 'm-2', & - long='trimming term of understory plants weighted by plant density, by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_trimming_understory_si_scls) - - call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_SZ', units = 'm2 m-2', & - long='total crown area of canopy plants by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_crown_area_canopy_si_scls) - - call this%set_history_var(vname='FATES_CROWNAREA_USTORY_SZ', units = 'm2 m-2', & - long='total crown area of understory plants by size class', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_crown_area_understory_si_scls) - - call this%set_history_var(vname='FATES_LEAFCTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='leaf turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_leaf_md_canopy_si_scls) - - call this%set_history_var(vname='FATES_FROOTCTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='fine root turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_root_md_canopy_si_scls) - - call this%set_history_var(vname='FATES_STORECTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='storage turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bstore_md_canopy_si_scls) - - call this%set_history_var(vname='FATES_STRUCTCTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='structural C turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bdead_md_canopy_si_scls) - - call this%set_history_var(vname='FATES_SAPWOODCTURN_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='sapwood turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bsw_md_canopy_si_scls) - - call this%set_history_var(vname='FATES_SEED_PROD_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='seed production of canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_seed_prod_canopy_si_scls) - - call this%set_history_var(vname='FATES_LEAF_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to leaves for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_leaf_canopy_si_scls) - - call this%set_history_var(vname='FATES_FROOT_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to fine root C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_fnrt_canopy_si_scls) - - call this%set_history_var(vname='FATES_SAPWOOD_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to sapwood C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_sapw_canopy_si_scls) - - call this%set_history_var(vname='FATES_STRUCT_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to structural C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_dead_canopy_si_scls) - - call this%set_history_var(vname='FATES_SEED_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to reproductive C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_seed_canopy_si_scls) - - call this%set_history_var(vname='FATES_STORE_ALLOC_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to storage C for canopy plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stor_canopy_si_scls) - - call this%set_history_var(vname='FATES_LEAFCTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='leaf turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_leaf_md_understory_si_scls) - - call this%set_history_var(vname='FATES_FROOTCTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='fine root turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_root_md_understory_si_scls) - - call this%set_history_var(vname='FATES_STORECTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='storage C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_bstore_md_understory_si_scls) - - call this%set_history_var(vname='FATES_STRUCTCTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='structural C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_bdead_md_understory_si_scls) - - call this%set_history_var(vname='FATES_SAPWOODCTURN_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='sapwood C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_bsw_md_understory_si_scls) - - call this%set_history_var(vname='FATES_SEED_PROD_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='seed production of understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, & - index = ih_seed_prod_understory_si_scls) - - call this%set_history_var(vname='FATES_LEAF_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to leaves for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_leaf_understory_si_scls) - - call this%set_history_var(vname='FATES_FROOT_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to fine roots for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_fnrt_understory_si_scls) - - call this%set_history_var(vname='FATES_SAPWOOD_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to sapwood C for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_sapw_understory_si_scls) - - call this%set_history_var(vname='FATES_STRUCT_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to structural C for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_dead_understory_si_scls) - - call this%set_history_var(vname='FATES_SEED_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to reproductive C for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_seed_understory_si_scls) - - call this%set_history_var(vname='FATES_STORE_ALLOC_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='allocation to storage C for understory plants by size class in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_stor_understory_si_scls) - - ! CROWN DAMAGE VARIABLES - if_crowndamage: if(hlm_use_tree_damage .eq. itrue) then - - call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 m-2 yr-1', & - long='crownarea lost to damage each year', use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) - - call this%set_history_var(vname='FATES_CROWNAREA_USTORY_CD', units = 'm2 m-2 yr-1', & - long='crownarea lost to damage each year', use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) - - call this%set_history_var(vname='FATES_NPLANT_CDPF', units = 'm-2', & - long='N. plants per damage x size x pft class', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdpf ) - - call this%set_history_var(vname='FATES_NPLANT_CANOPY_CDPF', units = 'm-2', & - long='N. plants per damage x size x pft class', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdpf ) - - call this%set_history_var(vname='FATES_NPLANT_USTORY_CDPF', units = 'm-2', & - long='N. plants in the understory per damage x size x pft class', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdpf ) - - call this%set_history_var(vname='FATES_M3_CDPF', units = 'm-2 yr-1', & - long='carbon starvation mortality by damaage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdpf ) - - call this%set_history_var(vname='FATES_M11_SZPF', units = 'm-2 yr-1', & - long='damage mortality by pft/size',use_default='inactive', & - avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scpf ) - - call this%set_history_var(vname='FATES_M11_CDPF', units = 'm-2 yr-1', & - long='damage mortality by damaage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdpf ) - - call this%set_history_var(vname='FATES_MORTALITY_CDPF', units = 'm-2 yr-1', & - long='mortality by damage class by size by pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdpf ) - - call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & - long='C starvation mortality of canopy plants by damage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdpf ) - - call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & - long='C starvation mortality of understory plants by pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdpf ) - - call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & - long='damage mortality of canopy plants by damage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdpf ) - - call this%set_history_var(vname='FATES_M11_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & - long='damage mortality of understory plants by pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdpf ) - - call this%set_history_var(vname='FATES_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & - long='mortality of canopy plants by damage/pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_cdpf ) - - call this%set_history_var(vname='FATES_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & - long='mortality of understory plants by pft/size', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_cdpf ) - - call this%set_history_var(vname='FATES_DDBH_CDPF', units = 'm m-2 yr-1', & - long='ddbh annual increment growth by damage x size pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdpf ) - - call this%set_history_var(vname='FATES_DDBH_CANOPY_CDPF', units = 'm m-2 yr-1', & - long='ddbh annual canopy increment growth by damage x size pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_canopy_si_cdpf ) - - call this%set_history_var(vname='FATES_DDBH_USTORY_CDPF', units = 'm m-2 yr-1', & - long='ddbh annual understory increment growth by damage x size pft', use_default='inactive', & - avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_understory_si_cdpf ) - - end if if_crowndamage - - - call this%set_history_var(vname='FATES_FIRE_FLUX_EL', units='kg m-2 s-1', & - long='loss to atmosphere from fire by element in kg element per m2 per s', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_burn_flux_elem) - + ! disturbance rates - call this%set_history_var(vname='FATES_ERROR_EL', units='kg s-1', & - long='total mass-balance error in kg per second by element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_err_fates_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, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fines_ag_elem) - - call this%set_history_var(vname='FATES_LITTER_BG_FINE_EL', units='kg m-2', & - long='mass of belowground litter in fines (fineroots) by element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_fines_bg_elem) - - call this%set_history_var(vname='FATES_LITTER_BG_CWD_EL', units='kg m-2', & - long='mass of belowground litter in coarse woody debris (coarse roots) by element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_bg_elem) - - call this%set_history_var(vname='FATES_LITTER_AG_CWD_EL', units='kg m-2', & - long='mass of aboveground litter in coarse woody debris (trunks/branches/twigs) by element', & - use_default='active', avgflag='A', vtype=site_elem_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_ag_elem) - - call this%set_history_var(vname='FATES_LITTER_CWD_ELDC', units='kg m-2', & - long='total mass of litter in coarse woody debris by element and coarse woody debris size', & - use_default='active', avgflag='A', vtype=site_elcwd_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & - initialize=initialize_variables, index = ih_cwd_elcwd) - - ! Mass states C/N/P SCPF dimensions - ! CARBON - call this%set_history_var(vname='FATES_VEGC_SZPF', units='kg m-2', & - long='total vegetation biomass in live plants by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_totvegc_scpf) - - call this%set_history_var(vname='FATES_LEAFC_SZPF', units='kg m-2', & - long='leaf carbon mass by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_leafc_scpf) - - call this%set_history_var(vname='FATES_FROOTC_SZPF', units='kg m-2', & - long='fine-root carbon mass by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_fnrtc_scpf) - - call this%set_history_var(vname='FATES_SAPWOODC_SZPF', units='kg m-2', & - long='sapwood carbon mass by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_sapwc_scpf) - - call this%set_history_var(vname='FATES_STOREC_SZPF', units='kg m-2', & - long='storage carbon mass by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_storec_scpf) - - call this%set_history_var(vname='FATES_REPROC_SZPF', units='kg m-2', & - long='reproductive carbon mass (on plant) by size-class x pft in kg carbon per m2', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, initialize=initialize_variables, & - index = ih_reproc_scpf) - - - - end if if_dyn1 -end if if_dyn0 - -!HERE - + call this%set_history_var(vname='FATES_PRIMARY_PATCHFUSION_ERR', & + units='m2 m-2 yr-1', & + long='error in total primary lands associated with patch fusion', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_primaryland_fusion_error_si) -!! if_hifrq0: if(hlm_hist_level_hifrq>0) then + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_FIRE', & + units='m2 m-2 yr-1', long='disturbance rate from fire', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_disturbance_rate_si) - ! Canopy Resistance + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_LOGGING', & + units='m2 m-2 yr-1', long='disturbance rate from logging', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_logging_disturbance_rate_si) - call this%set_history_var(vname='FATES_STOMATAL_COND', & - units='mol m-2 s-1', long='mean stomatal conductance', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_c_stomata_si) + call this%set_history_var(vname='FATES_DISTURBANCE_RATE_TREEFALL', & + units='m2 m-2 yr-1', long='disturbance rate from treefall', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fall_disturbance_rate_si) - call this%set_history_var(vname='FATES_LBLAYER_COND', units='mol m-2 s-1', & - long='mean leaf boundary layer conductance', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_c_lblayer_si) + call this%set_history_var(vname='FATES_HARVEST_CARBON_FLUX', & + units='kg m-2 yr-1', & + long='harvest carbon flux in kg carbon per m2 per year', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_harvest_carbonflux_si) - ! Temperature + call this%set_history_var(vname='FATES_TVEG24', units='degree_Celsius', & + long='fates 24-hr running mean vegetation temperature by site', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) + + call this%set_history_var(vname='FATES_TLONGTERM', units='degree_Celsius', & + long='fates 30-year running mean vegetation temperature by site', & + use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_tlongterm_si ) + + call this%set_history_var(vname='FATES_TGROWTH', units='degree_Celsius', & + long='fates long-term running mean vegetation temperature by site', & + use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_tgrowth_si ) + + call this%set_history_var(vname='FATES_HARVEST_DEBT', units='kg C', & + long='Accumulated carbon failed to be harvested', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) + + call this%set_history_var(vname='FATES_HARVEST_DEBT_SEC', units='kg C', & + long='Accumulated carbon failed to be harvested from secondary patches', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) + + call this%set_history_var(vname='FATES_EXCESS_RESP', units='kg m-2 s-1', & + long='respiration of un-allocatable carbon gain', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=5, ivar=ivar, initialize=initialize_variables, & + index = ih_excess_resp_si) + ! slow carbon fluxes associated with mortality from or transfer betweeen canopy and understory - call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & - long='fates instantaneous mean vegetation temperature by site', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) + call this%set_history_var(vname='FATES_DEMOTION_CARBONFLUX', & + units = 'kg m-2 s-1', & + long='demotion-associated biomass carbon flux from canopy to understory in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_demotion_carbonflux_si) - call this%set_history_var(vname='FATES_VIS_RAD_ERROR', units='-', & - long='mean two-stream solver error for VIS', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_vis_rad_err_si) - - call this%set_history_var(vname='FATES_NIR_RAD_ERROR', units='-', & - long='mean two-stream solver error for NIR', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_nir_rad_err_si) - - call this%set_history_var(vname='FATES_AR', units='gC/m^2/s', & - long='autotrophic respiration', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_aresp_si ) - ! Ecosystem Carbon Fluxes (updated rapidly, upfreq=2) - - call this%set_history_var(vname='FATES_NPP', units='kg m-2 s-1', & - long='net primary production in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_si) - - call this%set_history_var(vname='FATES_NPP_SECONDARY', units='kg m-2 s-1', & - long='net primary production in kg carbon per m2 per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_npp_secondary_si) - - call this%set_history_var(vname='FATES_GPP', units='kg m-2 s-1', & - long='gross primary production in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_si) - - call this%set_history_var(vname='FATES_GPP_SECONDARY', units='kg m-2 s-1', & - long='gross primary production in kg carbon per m2 per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_gpp_secondary_si) - - call this%set_history_var(vname='FATES_AUTORESP', units='kg m-2 s-1', & - long='autotrophic respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_si) - - call this%set_history_var(vname='FATES_AUTORESP_SECONDARY', units='kg m-2 s-1', & - long='autotrophic respiration in kg carbon per m2 per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_aresp_secondary_si) - - call this%set_history_var(vname='FATES_GROWTH_RESP', units='kg m-2 s-1', & - long='growth respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_growth_resp_si) - - call this%set_history_var(vname='FATES_GROWTH_RESP_SECONDARY', units='kg m-2 s-1', & - long='growth respiration in kg carbon per m2 per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_growth_resp_secondary_si) - - call this%set_history_var(vname='FATES_MAINT_RESP', units='kg m-2 s-1', & - long='maintenance respiration in kg carbon per m2 land area per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_maint_resp_si) - - call this%set_history_var(vname='FATES_MAINT_RESP_UNREDUCED', units='kg m-2 s-1', & - long='diagnostic maintenance respiration if the low-carbon-storage reduction is ignored', & - use_default='unactive', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_maint_resp_unreduced_si) - - call this%set_history_var(vname='FATES_MAINT_RESP_SECONDARY', units='kg m-2 s-1', & - long='maintenance respiration in kg carbon per m2 land area per second, secondary patches', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_maint_resp_secondary_si) - - call this%set_history_var(vname='FATES_AR_CANOPY', units='gC/m^2/s', & - long='autotrophic respiration of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ar_canopy_si ) - - call this%set_history_var(vname='FATES_AR_UNDERSTORY', units='gC/m^2/s', & - long='autotrophic respiration of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=2, & - ivar=ivar, initialize=initialize_variables, index = ih_ar_understory_si ) - - ! fast fluxes separated canopy/understory - call this%set_history_var(vname='FATES_GPP_CANOPY', units='kg m-2 s-1', & - long='gross primary production of canopy plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_gpp_canopy_si) - - call this%set_history_var(vname='FATES_AUTORESP_CANOPY', & - units='kg m-2 s-1', & - long='autotrophic respiration of canopy plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_ar_canopy_si) - - call this%set_history_var(vname='FATES_GPP_USTORY', & - units='kg m-2 s-1', & - long='gross primary production of understory plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_gpp_understory_si) - - call this%set_history_var(vname='FATES_AUTORESP_USTORY', & - units='kg m-2 s-1', & - long='autotrophic respiration of understory plants in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_ar_understory_si) - - - - call this%set_history_var(vname='FATES_LEAFMAINTAR', & - units = 'kg m-2 s-1', & - long='leaf maintenance autotrophic respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_leaf_mr_si) - - call this%set_history_var(vname='FATES_FROOTMAINTAR', & - units = 'kg m-2 s-1', & - long='fine root maintenance autotrophic respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_froot_mr_si) - - call this%set_history_var(vname='FATES_CROOTMAINTAR', & - units = 'kg m-2 s-1', & - long='live coarse root maintenance autotrophic respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_livecroot_mr_si) - - call this%set_history_var(vname='FATES_LSTEMMAINTAR', & - units = 'kg m-2 s-1', & - long='live stem maintenance autotrophic respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_livestem_mr_si) - - call this%set_history_var(vname='FATES_NEP', units='kg m-2 s-1', & - long='net ecosystem production in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, & - index = ih_nep_si) - - call this%set_history_var(vname='FATES_HET_RESP', units='kg m-2 s-1', & - long='heterotrophic respiration in kg carbon per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=2, ivar=ivar, initialize=initialize_variables, index = ih_hr_si) - - hydro_active_if0: if(hlm_use_planthydro.eq.itrue) then - call this%set_history_var(vname='FATES_SAPFLOW', units='kg m-2 s-1', & - long='areal sap flow rate in kg per m2 per second', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, & - index = ih_sapflow_si) - call this%set_history_var(vname='FATES_ROOTWGT_SOILVWC', units='m3 m-3', & - long='soil volumetric water content, weighted by root area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, & - index = ih_rootwgt_soilvwc_si) - - call this%set_history_var(vname='FATES_ROOTWGT_SOILVWCSAT', & - units='m3 m-3', & - long='soil saturated volumetric water content, weighted by root area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, & - index = ih_rootwgt_soilvwcsat_si) - - call this%set_history_var(vname='FATES_ROOTWGT_SOILMATPOT', units='Pa', & - long='soil matric potential, weighted by root area', & - use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, & - index = ih_rootwgt_soilmatpot_si) - - call this%set_history_var(vname='FATES_ROOTUPTAKE', units='kg m-2 s-1', & - long='root water uptake rate', use_default='active', avgflag='A', & - vtype=site_r8, hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_rootuptake_si) - - - call this%set_history_var(vname='FATES_VEGH2O', units = 'kg m-2', & - long='water stored inside vegetation tissues (leaf, stem, roots)', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_si) - - call this%set_history_var(vname='FATES_VEGH2O_HYDRO_ERR', & - units = 'kg m-2', & - long='cumulative net borrowed (+) from plant_stored_h2o due to plant hydrodynamics', & - use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_h2oveg_hydro_err_si) - end if hydro_active_if0 + call this%set_history_var(vname='FATES_PROMOTION_CARBONFLUX', & + units = 'kg m-2 s-1', & + long='promotion-associated biomass carbon flux from understory to canopy in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_promotion_carbonflux_si) - !HERE - -!! if_hifrq1: if(hlm_hist_level_hifrq>1) then - - ! This next group are multidimensional variables that are updated - ! over the short timestep. We turn off these variables when we want - ! to save time (and some space) + call this%set_history_var(vname='FATES_MORTALITY_CFLUX_CANOPY', & + units = 'kg m-2 s-1', & + long='flux of biomass carbon from live to dead pools from mortality of canopy plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_canopy_mortality_carbonflux_si) + call this%set_history_var(vname='FATES_MORTALITY_CFLUX_USTORY', & + units = 'kg m-2 s-1', & + long='flux of biomass carbon from live to dead pools from mortality of understory plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_understory_mortality_carbonflux_si) + + call this%set_history_var(vname='MORTALITY_CROWNAREA_CANOPY', & + units = 'm2/ha/year', & + long='Crown area of canopy trees that died', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_canopy_mortality_crownarea_si ) + + call this%set_history_var(vname='MORTALITY_CROWNAREA_UNDERSTORY', & + units = 'm2/ha/year', & + long='Crown aera of understory trees that died', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_understory_mortality_crownarea_si ) + + call this%set_history_var(vname='FATES_FIRE_CLOSS', units='kg m-2 s-1', & + long='carbon loss to atmosphere from fire in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_c_to_atm_si) + + call this%set_history_var(vname='FATES_CBALANCE_ERROR', & + units='kg s-1', & + long='total carbon error in kg carbon per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, 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', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_leaf_si) + + call this%set_history_var(vname='FATES_SEED_ALLOC', units='kg m-2 s-1', & + long='allocation to seeds in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_seed_si) + + call this%set_history_var(vname='FATES_STEM_ALLOC', units='kg m-2 s-1', & + long='allocation to stem in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stem_si) + + call this%set_history_var(vname='FATES_FROOT_ALLOC', units='kg m-2 s-1', & + long='allocation to fine roots in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_froot_si) + + call this%set_history_var(vname='FATES_CROOT_ALLOC', units='kg m-2 s-1', & + long='allocation to coarse roots in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_croot_si) + + call this%set_history_var(vname='FATES_STORE_ALLOC', units='kg m-2 s-1', & + long='allocation to storage tissues in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stor_si) + + hydro_active_if: if(hlm_use_planthydro.eq.itrue) then + call this%set_history_var(vname='FATES_VEGH2O_DEAD', units = 'kg m-2', & + long='cumulative water stored in dead biomass due to mortality', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_dead_si) + + call this%set_history_var(vname='FATES_VEGH2O_RECRUIT', & + units = 'kg m-2', long='amount of water in new recruits', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_recruit_si) + + call this%set_history_var(vname='FATES_VEGH2O_GROWTURN_ERR', & + units = 'kg m-2', & + long='cumulative net borrowed (+) or lost (-) from water storage due to combined growth & turnover', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=1, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_growturn_err_si) + end if hydro_active_if + + !HERE + + if_dyn1: if(hlm_hist_level_dynam>1) then + + call this%set_history_var(vname='FATES_VEGC_PF', units='kg m-2', & + long='total PFT-level biomass in kg of carbon per land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_biomass_si_pft) + + call this%set_history_var(vname='FATES_VEGC_SE_PF', units='kg m-2', & + long='total PFT-level biomass in kg of carbon per land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_biomass_sec_si_pft) + + call this%set_history_var(vname='FATES_LEAFC_PF', units='kg m-2', & + long='total PFT-level leaf biomass in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_leafbiomass_si_pft) + + call this%set_history_var(vname='FATES_STOREC_PF', units='kg m-2', & + long='total PFT-level stored biomass in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_storebiomass_si_pft) + + call this%set_history_var(vname='FATES_CROWNAREA_PF', units='m2 m-2', & + long='total PFT-level crown area per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_crownarea_si_pft) + + call this%set_history_var(vname='FATES_CANOPYCROWNAREA_PF', & + units='m2 m-2', long='total PFT-level canopy-layer crown area per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_canopycrownarea_si_pft) + + call this%set_history_var(vname='FATES_GPP_PF', units='kg m-2 s-1', & + long='total PFT-level GPP in kg carbon per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_gpp_si_pft) + + call this%set_history_var(vname='FATES_NPP_PF', units='kg m-2 s-1', & + long='total PFT-level NPP in kg carbon per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_npp_si_pft) + + call this%set_history_var(vname='FATES_GPP_SE_PF', units='kg m-2 s-1', & + long='total PFT-level GPP in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_gpp_sec_si_pft) + + call this%set_history_var(vname='FATES_NPP_SE_PF', units='kg m-2 s-1', & + long='total PFT-level NPP in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_npp_sec_si_pft) + + call this%set_history_var(vname='FATES_NPLANT_PF', units='m-2', & + long='total PFT-level number of individuals per m2 land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_nindivs_si_pft) + + call this%set_history_var(vname='FATES_NPLANT_SEC_PF', units='m-2', & + long='total PFT-level number of individuals per m2 land area, secondary patches', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_nindivs_sec_si_pft) + + call this%set_history_var(vname='FATES_RECRUITMENT_PF', & + units='m-2 yr-1', & + long='PFT-level recruitment rate in number of individuals per m2 land area per year', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_recruitment_si_pft) + + call this%set_history_var(vname='FATES_SEEDS_IN_GRIDCELL_PF', & + units='kg', & + long='Site-level seed mass input from neighboring gridcells per pft', & + use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_seeds_in_gc_si_pft) + + call this%set_history_var(vname='FATES_SEEDS_OUT_GRIDCELL_PF', & + units='kg', & + long='Site-level seed mass output to neighboring gridcells per pft', & + use_default='inactive', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_seeds_out_gc_si_pft) + + call this%set_history_var(vname='FATES_MORTALITY_PF', units='m-2 yr-1', & + long='PFT-level mortality rate in number of individuals per m2 land area per year', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_mortality_si_pft) + + !MLO - Drought-deciduous phenology variables are now defined for each PFT. + call this%set_history_var(vname='FATES_DROUGHT_STATUS_PF', & + units='', & + long='PFT-level drought status, <2 too dry for leaves, >=2 not too dry', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_site_dstatus_si_pft) + + call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFOFF_PF', & + units='days', long='PFT-level days elapsed since drought leaf drop', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_dleafoff_si_pft) + + call this%set_history_var(vname='FATES_DAYSINCE_DROUGHTLEAFON_PF', & + units='days', & + long='PFT-level days elapsed since drought leaf flush', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_dleafon_si_pft) + + call this%set_history_var(vname='FATES_MEANLIQVOL_DROUGHTPHEN_PF', & + units='m3 m-3', & + long='PFT-level mean liquid water volume for drought phenolgy', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_meanliqvol_si_pft) + + call this%set_history_var(vname='FATES_MEANSMP_DROUGHTPHEN_PF', & + units='Pa', & + long='PFT-level mean soil matric potential for drought phenology', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_meansmp_si_pft) + + call this%set_history_var(vname='FATES_ELONG_FACTOR_PF', & + units='1', & + long='PFT-level mean elongation factor (partial flushing/abscission)', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_elong_factor_si_pft) + + nocomp_if: if (hlm_use_nocomp .eq. itrue) then + call this%set_history_var(vname='FATES_NOCOMP_NPATCHES_PF', units='', & + long='number of patches per PFT (nocomp-mode-only)', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_nocomp_pftnpatches_si_pft) + + call this%set_history_var(vname='FATES_NOCOMP_PATCHAREA_PF', units='m2 m-2',& + long='total patch area allowed per PFT (nocomp-mode-only)', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_nocomp_pftpatchfraction_si_pft) + + call this%set_history_var(vname='FATES_NOCOMP_BURNEDAREA_PF', units='s-1', & + long='total burned area of PFT-labeled patch area (nocomp-mode-only)',& + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_nocomp_pftburnedarea_si_pft) + endif nocomp_if + + ! patch age class variables + call this%set_history_var(vname='FATES_PATCHAREA_AP', units='m2 m-2', & + long='patch area by age bin per m2 land area', use_default='active', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index=ih_area_si_age) + + call this%set_history_var(vname='FATES_LAI_AP', units='m2 m-2', & + long='leaf area index by age bin per m2 land area', & + use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_lai_si_age) + + + + call this%set_history_var(vname='FATES_CANOPYAREA_AP', units='m2 m-2', & + long='canopy area by age bin per m2 land area', use_default='active', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index=ih_canopy_area_si_age) + + call this%set_history_var(vname='FATES_NCL_AP', units='', & + long='number of canopy levels by age bin', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_ncl_si_age) + + call this%set_history_var(vname='FATES_NPATCH_AP', units='', & + long='number of patches by age bin', use_default='inactive', & + avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_npatches_si_age) + + if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled + tempstring = 'active' + else + tempstring = 'inactive' + endif + + call this%set_history_var(vname='FATES_ZSTAR_AP', units='m', & + long='product of zstar and patch area by age bin (divide by FATES_PATCHAREA_AP to get mean zstar)', & + use_default=trim(tempstring), avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_zstar_si_age) + + call this%set_history_var(vname='FATES_CANOPYAREA_HT', units='m2 m-2', & + long='canopy area height distribution', & + use_default='active', avgflag='A', vtype=site_height_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_canopy_height_dist_si_height) + + call this%set_history_var(vname='FATES_LEAFAREA_HT', units='m2 m-2', & + long='leaf area height distribution', use_default='active', & + avgflag='A', vtype=site_height_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_leaf_height_dist_si_height) + + call this%set_history_var(vname='FATES_VEGC_AP', units='kg m-2', & + long='total biomass within a given patch age bin in kg carbon per m2 land area', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_biomass_si_age) + + call this%set_history_var(vname='FATES_SECONDAREA_ANTHRODIST_AP', & + units='m2 m-2', & + long='secondary forest patch area age distribution since anthropgenic disturbance', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_agesince_anthrodist_si_age) + + call this%set_history_var(vname='FATES_SECONDAREA_DIST_AP', & + units='m2 m-2', & + long='secondary forest patch area age distribution since any kind of disturbance', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_secondarylands_area_si_age) + + call this%set_history_var(vname='FATES_FRAGMENTATION_SCALER_SL', units='', & + long='factor (0-1) by which litter/cwd fragmentation proceeds relative to max rate by soil layer', & + use_default='active', avgflag='A', vtype=site_soil_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_fragmentation_scaler_sl) + + call this%set_history_var(vname='FATES_FUEL_MOISTURE_FC', units='m3 m-3', & + long='spitfire fuel class-level fuel moisture (volumetric)', & + use_default='active', avgflag='A', vtype=site_fuel_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_moisture_si_fuel) + + call this%set_history_var(vname='FATES_FUEL_AMOUNT_FC', units='kg m-2', & + long='spitfire fuel-class level fuel amount in kg carbon per m2 land area', & + use_default='active', avgflag='A', vtype=site_fuel_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_fuel_amount_si_fuel) + + call this%set_history_var(vname='FATES_FUEL_AMOUNT_APFC', units='kg m-2', & + long='spitfire fuel quantity in each age x fuel class in kg carbon per m2 land area', & + use_default='inactive', avgflag='A', vtype=site_agefuel_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_fuel_amount_age_fuel) + + call this%set_history_var(vname='FATES_BURNFRAC_AP', units='s-1', & + long='spitfire fraction area burnt (per second) by patch age', & + use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_area_burnt_si_age) + + call this%set_history_var(vname='FATES_FIRE_INTENSITY_BURNFRAC_AP', & + units='J m-1 s-1', & + long='product of fire intensity and burned fraction, resolved by patch age (so divide by FATES_BURNFRAC_AP to get burned-area-weighted-average intensity)', & + use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_intensity_si_age) + + call this%set_history_var(vname='FATES_FUEL_AMOUNT_AP', units='kg m-2', & + long='spitfire ground fuel (kg carbon per m2) related to FATES_ROS (omits 1000hr fuels) within each patch age bin (divide by FATES_PATCHAREA_AP to get fuel per unit area of that-age patch)', & + use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_fire_sum_fuel_si_age) + + call this%set_history_var(vname='FATES_FUEL_BURNT_BURNFRAC_FC', units='1', & + long='product of fraction (0-1) of fuel burnt and burnt fraction (divide by FATES_BURNFRAC to get burned-area-weighted mean fraction fuel burnt)', & + use_default='active', avgflag='A', vtype=site_fuel_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_burnt_frac_litter_si_fuel) + + call this%set_history_var(vname='FATES_LITTER_IN_EL', units='kg m-2 s-1', & + long='litter flux in in kg element per m2 per second', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_in_elem) + + call this%set_history_var(vname='FATES_LITTER_OUT_EL', units='kg m-2 s-1', & + long='litter flux out (exudation, fragmentation and seed decay) in kg element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_litter_out_elem) + + call this%set_history_var(vname='FATES_SEED_BANK_EL', units='kg m-2', & + long='element-level total seed mass of all PFTs in kg element per m2', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_seed_bank_elem) + + call this%set_history_var(vname='FATES_SEEDS_IN_LOCAL_EL', & + units='kg m-2 s-1', & + long='within-site, element-level seed production rate in kg element per m2 per second', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_seeds_in_local_elem) + + call this%set_history_var(vname='FATES_SEEDS_IN_EXTERN_EL', & + units='kg m-2 s-1', long='external seed influx rate in kg element per m2 per second', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_seeds_in_extern_elem) + + call this%set_history_var(vname='FATES_SEED_GERM_EL', units='kg m-2', & + long='element-level total germinated seed mass of all PFTs in kg element per m2', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_seed_germ_elem) + + call this%set_history_var(vname='FATES_SEED_DECAY_EL', units='kg m-2 s-1', & + long='seed mass decay (germinated and un-germinated) in kg element per m2 per second', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_seed_decay_elem) + + ! SITE LEVEL CARBON STATE VARIABLES + + call this%set_history_var(vname='FATES_STOREC_TF_USTORY_SZPF', units='kg kg-1', & + long='Storage C fraction of target by size x pft, in the understory', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_ustory_scpf ) + + + call this%set_history_var(vname='FATES_STOREC_TF_CANOPY_SZPF', units='kg kg-1', & + long='Storage C fraction of target by size x pft, in the canopy', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_canopy_scpf ) + + + + + call this%set_history_var(vname='FATES_FROOTC_SL', units='kg m-3', & + long='Total carbon in live plant fine-roots over depth', use_default='active', & + avgflag='A', vtype=site_soil_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_sl ) + + + + + + ! Output specific to the chemical species dynamics used (parteh) + select case(hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) + + call this%set_history_var(vname='FATES_L2FR_CANOPY_REC_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (canopy)', & + use_default='active', & + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) + + call this%set_history_var(vname='FATES_L2FR_USTORY_REC_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (understory)', & + use_default='active', & + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) + + !call this%set_history_var(vname='FATES_L2FR_CLSZPF', units='kg kg-1', & + ! long='The leaf to fineroot biomass multiplier for target allometry', & + ! use_default='inactive', & + ! avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ! ivar=ivar, initialize=initialize_variables, index = ih_l2fr_clscpf) + + call this%set_history_var(vname='FATES_NH4UPTAKE_SZPF', & + units='kg m-2 s-1', & + long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_nh4uptake_scpf) + + call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & + units='kg m-2 s-1', & + long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_no3uptake_scpf) + + call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & + long='nitrogen efflux, root to soil, 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=5, 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=5, 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, & + hlms='CLM:ALM', upfreq=5, ivar=ivar, & + initialize=initialize_variables, index = ih_nfix_scpf) + + end select + + nitrogen_active_if1: if(any(element_list(:)==nitrogen_element)) then + + call this%set_history_var(vname='FATES_VEGN_SZPF', units='kg m-2', & + long='total (live) vegetation nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_totvegn_scpf) + + call this%set_history_var(vname='FATES_LEAFN_SZPF', units='kg m-2', & + long='leaf nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_leafn_scpf) + + call this%set_history_var(vname='FATES_FROOTN_SZPF', units='kg m-2', & + long='fine-root nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_fnrtn_scpf) + + call this%set_history_var(vname='FATES_SAPWOODN_SZPF', units='kg m-2', & + long='sapwood nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_sapwn_scpf) + + call this%set_history_var(vname='FATES_STOREN_SZPF', units='kg m-2', & + long='storage nitrogen mass by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_storen_scpf) + + call this%set_history_var(vname='FATES_STOREN_TF_CANOPY_SZPF', & + units='1', & + long='storage nitrogen fraction (0-1) of target, in canopy, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_storentfrac_canopy_scpf) + + call this%set_history_var(vname='FATES_STOREN_TF_USTORY_SZPF', & + units='1', & + long='storage nitrogen fraction (0-1) of target, in understory, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_storentfrac_understory_scpf) + + call this%set_history_var(vname='FATES_REPRON_SZPF', units='kg m-2', & + long='reproductive nitrogen mass (on plant) by size-class x pft in kg N per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_repron_scpf) + + end if nitrogen_active_if1 + + phosphorus_active_if1: if(any(element_list(:)==phosphorus_element)) then + + call this%set_history_var(vname='FATES_VEGP_SZPF', units='kg m-2', & + long='total (live) vegetation phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_totvegp_scpf) + + call this%set_history_var(vname='FATES_LEAFP_SZPF', units='kg m-2', & + long='leaf phosphorus mass by size-class x pft', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_leafp_scpf ) + + call this%set_history_var(vname='FATES_FROOTP_SZPF', units='kg m-2', & + long='fine-root phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_fnrtp_scpf) + + call this%set_history_var(vname='FATES_SAPWOODP_SZPF', units='kg m-2', & + long='sapwood phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_sapwp_scpf) + + call this%set_history_var(vname='FATES_STOREP_SZPF', units='kg m-2', & + long='storage phosphorus mass by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_storep_scpf) + + call this%set_history_var(vname='FATES_STOREP_TF_CANOPY_SZPF', & + units='1', & + long='storage phosphorus fraction (0-1) of target, in canopy, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_storeptfrac_canopy_scpf) + + call this%set_history_var(vname='FATES_STOREP_TF_USTORY_SZPF', & + units='1', & + long='storage phosphorus fraction (0-1) of target, in understory, by size-class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_storeptfrac_understory_scpf) + + call this%set_history_var(vname='FATES_REPROP_SZPF', units='kg m-2', & + long='reproductive phosphorus mass (on plant) by size-class x pft in kg P per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_reprop_scpf) + + call this%set_history_var(vname='FATES_PUPTAKE_SZPF', & + units='kg m-2 s-1', & + long='phosphorus uptake rate by plants, 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=5, ivar=ivar, & + initialize=initialize_variables, index = ih_puptake_scpf) + + call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & + units='kg m-2 s-1', & + long='phosphorus efflux, root to soil, 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=5, 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=5, 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', & + long='area fraction of the total ground occupied by each canopy-leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_crownarea_si_cnlf) + + call this%set_history_var(vname='FATES_CROWNAREA_CL', units='m2 m-2', & + long='area fraction of the canopy footprint occupied by each canopy-leaf layer', use_default='active', & + avgflag='A', vtype=site_can_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_crownarea_cl) + + + call this%set_history_var(vname='FATES_MORTALITY_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_mortality_carbonflux_si_pft) + + call this%set_history_var(vname='FATES_MORTALITY_FIRE_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from fire mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_firemortality_carbonflux_si_pft) + + call this%set_history_var(vname='FATES_MORTALITY_HYDRO_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from hydraulic failure mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_hydraulicmortality_carbonflux_si_pft) + + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_cstarvmortality_carbonflux_si_pft) + + call this%set_history_var(vname='FATES_ABOVEGROUND_MORT_SZPF', units='kg m-2 s-1', & + long='Aboveground flux of carbon from AGB to necromass due to mortality', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_abg_mortality_cflux_si_scpf) + + call this%set_history_var(vname='FATES_ABOVEGROUND_PROD_SZPF', units='kg m-2 s-1', & + long='Aboveground carbon productivity', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_abg_productivity_cflux_si_scpf) + ! size class by age dimensioned variables + + call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & + long='number of plants per m2 in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_si_scag) + + call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZAP', units = 'm-2', & + long='number of plants per m2 in canopy in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_canopy_si_scag) + + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZAP', & + units = 'm-2', & + long='number of plants per m2 in understory in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_understory_si_scag) + + call this%set_history_var(vname='FATES_DDBH_CANOPY_SZAP', & + units = 'm m-2 yr-1', & + long='growth rate of canopy plants in meters DBH per m2 per year in canopy in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_canopy_si_scag) + + call this%set_history_var(vname='FATES_DDBH_USTORY_SZAP', & + units = 'm m-2 yr-1', & + long='growth rate of understory plants in meters DBH per m2 per year in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_understory_si_scag) + + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZAP', & + units = 'm-2 yr-1', & + long='mortality rate of canopy plants in number of plants per m2 per year in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_canopy_si_scag) + + call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZAP', & + units = 'm-2 yr-1', & + long='mortality rate of understory plants in number of plants per m2 per year in each size x age class', & + use_default='inactive', avgflag='A', vtype=site_scag_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_understory_si_scag) + + ! size x age x pft dimensioned + + call this%set_history_var(vname='FATES_NPLANT_SZAPPF',units = 'm-2', & + long='number of plants per m2 in each size x age x pft class', & + use_default='inactive', avgflag='A', vtype=site_scagpft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_si_scagpft) + + ! age x pft dimensioned + call this%set_history_var(vname='FATES_NPP_APPF',units = 'kg m-2 s-1', & + long='NPP per PFT in each age bin in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_agepft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_si_agepft) + + call this%set_history_var(vname='FATES_VEGC_APPF',units = 'kg m-2', & + long='biomass per PFT in each age bin in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_agepft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_biomass_si_agepft) + + call this%set_history_var(vname='FATES_SCORCH_HEIGHT_APPF',units = 'm', & + long='SPITFIRE flame Scorch Height (calculated per PFT in each patch age bin)', & + use_default='inactive', avgflag='A', vtype=site_agepft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_scorch_height_si_agepft) + + + ! Carbon Flux (grid dimension x scpf) (THESE ARE DEFAULT INACTIVE!!! + ! (BECAUSE THEY TAKE UP SPACE!!! + ! =================================================================================== + + call this%set_history_var(vname='FATES_GPP_SZPF', units='kg m-2 s-1', & + long='gross primary production by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_gpp_si_scpf) + + call this%set_history_var(vname='FATES_GPP_CANOPY_SZPF', & + units='kg m-2 s-1', & + long='gross primary production of canopy plants by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_gpp_canopy_si_scpf) + + call this%set_history_var(vname='FATES_AUTORESP_CANOPY_SZPF', & + units='kg m-2 s-1', & + long='autotrophic respiration of canopy plants by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_canopy_si_scpf) + + call this%set_history_var(vname='FATES_GPP_USTORY_SZPF', & + units='kg m-2 s-1', & + long='gross primary production of understory plants by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_gpp_understory_si_scpf) + + call this%set_history_var(vname='FATES_AUTORESP_USTORY_SZPF', & + units='kg m-2 s-1', & + long='autotrophic respiration of understory plants by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_understory_si_scpf) + + call this%set_history_var(vname='FATES_NPP_SZPF', units='kg m-2 s-1', & + long='total net primary production by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_totl_si_scpf) + + call this%set_history_var(vname='FATES_LEAF_ALLOC_SZPF', units='kg m-2 s-1', & + long='allocation to leaves by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_leaf_si_scpf) + + call this%set_history_var(vname='FATES_SEED_ALLOC_SZPF', units='kg m-2 s-1', & + long='allocation to seeds by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_seed_si_scpf) + + call this%set_history_var(vname='FATES_FROOT_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to fine roots by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_npp_fnrt_si_scpf) + + call this%set_history_var(vname='FATES_BGSAPWOOD_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to below-ground sapwood by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_bgsw_si_scpf) + + call this%set_history_var(vname='FATES_BGSTRUCT_ALLOC_SZPF', units='kg m-2 s-1', & + long='allocation to below-ground structural (deadwood) by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_bgdw_si_scpf) + + call this%set_history_var(vname='FATES_AGSAPWOOD_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to above-ground sapwood by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_agsw_si_scpf) + + call this%set_history_var(vname = 'FATES_AGSTRUCT_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to above-ground structural (deadwood) by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_agdw_si_scpf) + + call this%set_history_var(vname = 'FATES_STORE_ALLOC_SZPF', & + units='kg m-2 s-1', & + long='allocation to storage C by pft/size in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stor_si_scpf) + + call this%set_history_var(vname='FATES_DDBH_SZPF', units = 'm m-2 yr-1', & + long='diameter growth increment by pft/size', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_ddbh_si_scpf) + + call this%set_history_var(vname='FATES_GROWTHFLUX_SZPF', & + units = 'm-2 yr-1', & + long='flux of individuals into a given size class bin via growth and recruitment', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_growthflux_si_scpf) + + call this%set_history_var(vname='FATES_GROWTHFLUX_FUSION_SZPF', & + units = 'm-2 yr-1', & + long='flux of individuals into a given size class bin via fusion', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_growthflux_fusion_si_scpf) + + call this%set_history_var(vname='FATES_DDBH_CANOPY_SZPF', & + units = 'm m-2 yr-1', & + long='diameter growth increment by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_canopy_si_scpf) + + call this%set_history_var(vname='FATES_DDBH_USTORY_SZPF', & + units = 'm m-2 yr-1', & + long='diameter growth increment by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_understory_si_scpf) + + call this%set_history_var(vname='FATES_BASALAREA_SZPF', units = 'm2 m-2', & + long='basal area by pft/size', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_ba_si_scpf) + + call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND_SZPF', & + units = 'kg m-2', & + long='aboveground biomass by pft/size in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_agb_si_scpf) + + call this%set_history_var(vname='FATES_NPLANT_SZPF', units = 'm-2', & + long='stem number density by pft/size', use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_nplant_si_scpf) + + call this%set_history_var(vname='FATES_NPLANT_ACPF', units = 'm-2', & + long='stem number density by pft and age class', & + use_default='inactive', avgflag='A', vtype=site_coage_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_nplant_si_capf) + + call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SZPF', & + units = 'm-2 yr-1', & + long='background mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m1_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SZPF', & + units = 'm-2 yr-1', & + long='hydraulic mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m2_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZPF', & + units = 'm-2 yr-1', & + long='carbon starvation mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZPF', & + units = 'm-2 yr-1', & + long='impact mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m4_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_FIRE_SZPF', & + units = 'm-2 yr-1', & + long='fire mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m5_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_CROWNSCORCH_SZPF', & + units = 'm-2 yr-1', & + long='fire mortality from crown scorch by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_crownfiremort_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_CAMBIALBURN_SZPF', & + units = 'm-2 yr-1', & + long='fire mortality from cambial burn by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cambialfiremort_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZPF', & + units = 'm-2 yr-1', & + long='termination mortality by pft/size in number pf plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m6_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZPF', & + units = 'm-2 yr-1', & + long='logging mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_m7_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SZPF', & + units = 'm-2 yr-1', & + long='freezing mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m8_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SZPF', & + units = 'm-2 yr-1', & + long='senescence mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m9_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SZPF', & + units = 'm-2 yr-1', & + long='age senescence mortality by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype =site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_m10_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_ACPF', & + units='m-2 yr-1', & + long='age senescence mortality by pft/cohort age in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype =site_coage_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index =ih_m10_si_capf) + + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZPF', & + units = 'm-2 yr-1', & + long='total mortality of canopy plants by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_canopy_si_scpf) + + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZPF', & + units = 'N/ha/yr', & + long='C starvation mortality of canopy plants by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scpf ) + + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZPF', & + units = 'N/ha/yr', & + long='C starvation mortality of understory plants by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_understory_si_scpf ) + + + call this%set_history_var(vname='FATES_C13DISC_SZPF', units = 'per mil', & + long='C13 discrimination by pft/size',use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_c13disc_si_scpf) + + call this%set_history_var(vname='FATES_STOREC_CANOPY_SZPF', units = 'kg m-2', & + long='biomass in storage pools of canopy plants by pft/size in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_bstor_canopy_si_scpf) + + call this%set_history_var(vname='FATES_LEAFC_CANOPY_SZPF', & + units = 'kg m-2', & + long='biomass in leaves of canopy plants by pft/size in kg carbon per m2', & + use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, & + index = ih_bleaf_canopy_si_scpf) + + call this%set_history_var(vname='FATES_LAI_CANOPY_SZPF', & + units = 'm2 m-2', & + long='Leaf area index (LAI) of canopy plants by pft/size', & + use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, & + index = ih_lai_canopy_si_scpf ) + + call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZPF', units = 'm-2', & + long='number of canopy plants by size/pft per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_canopy_si_scpf) + + call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZPF', & + units = 'm-2 yr-1', & + long='total mortality of understory plants by pft/size in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_mortality_understory_si_scpf) + + call this%set_history_var(vname='FATES_STOREC_USTORY_SZPF', & + units = 'kg m-2', & + long='biomass in storage pools of understory plants by pft/size in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_bstor_understory_si_scpf) + + call this%set_history_var(vname='FATES_LEAFC_USTORY_SZPF', & + units = 'kg m-2', & + long='biomass in leaves of understory plants by pft/size in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_bleaf_understory_si_scpf) + + call this%set_history_var(vname='FATES_LAI_USTORY_SZPF', & + units = 'm2 m-2', & + long='Leaf area index (LAI) of understory plants by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_lai_understory_si_scpf ) + + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZPF', & + units = 'm-2', & + long='density of understory plants by pft/size in number of plants per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_understory_si_scpf) + + call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_DC', units='kg m-2', & + long='debris class-level aboveground coarse woody debris stocks in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_ag_si_cwdsc) + + call this%set_history_var(vname='FATES_CWD_BELOWGROUND_DC', units='kg m-2', & + long='debris class-level belowground coarse woody debris stocks in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_bg_si_cwdsc) + + call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_IN_DC', & + units='kg m-2 s-1', & + long='debris class-level aboveground coarse woody debris input in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_ag_in_si_cwdsc) + + call this%set_history_var(vname='FATES_CWD_BELOWGROUND_IN_DC', & + units='kg m-2 s-1', & + long='debris class-level belowground coarse woody debris input in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_bg_in_si_cwdsc) + + call this%set_history_var(vname='FATES_CWD_ABOVEGROUND_OUT_DC', & + units='kg m-2 s-1', & + long='debris class-level aboveground coarse woody debris output in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_ag_out_si_cwdsc) + + call this%set_history_var(vname='FATES_CWD_BELOWGROUND_OUT_DC', & + units='kg m-2 s-1', & + long='debris class-level belowground coarse woody debris output in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_cwdsc_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_bg_out_si_cwdsc) + + + ! size-class only variables + + call this%set_history_var(vname='FATES_DDBH_CANOPY_SZ', & + units = 'm m-2 yr-1', long='diameter growth increment by size of canopy plants', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_canopy_si_scls) + + call this%set_history_var(vname='FATES_DDBH_USTORY_SZ', & + units = 'm m-2 yr-1', long='diameter growth increment by size of understory plants', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ddbh_understory_si_scls) + + call this%set_history_var(vname='FATES_YESTCANLEV_CANOPY_SZ', & + units = 'm-2', & + long='yesterdays canopy level for canopy plants by size class in number of plants per m2', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_yesterdaycanopylevel_canopy_si_scls) + + call this%set_history_var(vname='FATES_YESTCANLEV_USTORY_SZ', & + units = 'm-2', & + long='yesterdays canopy level for understory plants by size class in number of plants per m2', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_yesterdaycanopylevel_understory_si_scls) + + call this%set_history_var(vname='FATES_BASALAREA_SZ', units = 'm2 m-2', & + long='basal area by size class', use_default='active', & + avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_ba_si_scls) + + call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND_SZ', & + units = 'kg m-2', & + long='aboveground biomass by size class in kg carbon per m2', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_agb_si_scls) + + call this%set_history_var(vname='FATES_VEGC_SZ', units = 'kg m-2', & + long='total biomass by size class in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_biomass_si_scls) + + call this%set_history_var(vname='FATES_DEMOTION_RATE_SZ', & + units = 'm-2 yr-1', & + long='demotion rate from canopy to understory by size class in number of plants per m2 per year', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_demotion_rate_si_scls) + + call this%set_history_var(vname='FATES_PROMOTION_RATE_SZ', & + units = 'm-2 yr-1', & + long='promotion rate from understory to canopy by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_promotion_rate_si_scls) + + call this%set_history_var(vname='FATES_NPLANT_CANOPY_SZ', & + units = 'm-2', & + long='number of canopy plants per m2 by size class', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_canopy_si_scls) + + call this%set_history_var(vname='FATES_LAI_CANOPY_SZ', units = 'm2 m-2', & + long='leaf area index (LAI) of canopy plants by size class', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_lai_canopy_si_scls) + + call this%set_history_var(vname='FATES_SAI_CANOPY_SZ', units = 'm2 m-2', & + long='stem area index (SAI) of canopy plants by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_sai_canopy_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SZ', & + units = 'm-2 yr-1', & + long='total mortality of canopy trees by size class in number of plants per m2', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_canopy_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_SE_SZ', & + units = 'm-2 yr-1', & + long='total mortality of canopy trees by size class in number of plants per m2, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_mortality_canopy_secondary_si_scls) + + call this%set_history_var(vname='FATES_NPLANT_USTORY_SZ', & + units = 'm-2', & + long='number of understory plants per m2 by size class', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_understory_si_scls) + + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZ', & + units = 'N/ha/yr', & + long='C starvation mortality of canopy plants by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scls ) + + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZ', & + units = 'N/ha/yr', & + long='C starvation mortality of understory plants by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_mortality_understory_si_scls ) + + call this%set_history_var(vname='FATES_LAI_USTORY_SZ', & + units = 'm2 m-2', & + long='leaf area index (LAI) of understory plants by size class', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_lai_understory_si_scls) + + call this%set_history_var(vname='FATES_SAI_USTORY_SZ', & + units = 'm2 m-2', & + long='stem area index (SAI) of understory plants by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_sai_understory_si_scls) + + call this%set_history_var(vname='FATES_NPLANT_SZ', units = 'm-2', & + long='number of plants per m2 by size class', use_default='active', & + avgflag='A', vtype=site_size_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_scls) + + call this%set_history_var(vname='FATES_NPLANT_AC', units = 'm-2', & + long='number of plants per m2 by cohort age class', & + use_default='active', avgflag='A', vtype=site_coage_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_nplant_si_cacls) + + call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SZ', & + units = 'm-2 yr-1', & + long='background mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m1_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SZ', & + units = 'm-2 yr-1', & + long='hydraulic mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m2_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZ', & + units = 'm-2 yr-1', & + long='carbon starvation mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_BACKGROUND_SE_SZ', & + units = 'm-2 yr-1', & + long='background mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m1_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_HYDRAULIC_SE_SZ', & + units = 'm-2 yr-1', & + long='hydraulic mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m2_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SE_SZ', & + units = 'm-2 yr-1', & + long='carbon starvation mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m3_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_IMPACT_SZ', & + units = 'm-2 yr-1', & + long='impact mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m4_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_FIRE_SZ', & + units = 'm-2 yr-1', & + long='fire mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m5_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZ', & + units = 'm-2 yr-1', & + long='termination mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m6_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SZ', & + units = 'm-2 yr-1', & + long='logging mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m7_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SZ', & + units = 'm-2 yr-1', & + long='freezing mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m8_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SZ', & + units = 'm-2 yr-1', & + long='senescence mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m9_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SZ', & + units = 'm-2 yr-1', & + long='age senescence mortality by size in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m10_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_AC', & + units = 'm-2 yr-1', & + long='age senescence mortality by cohort age in number of plants per m2 per year', & + use_default='active', avgflag='A', vtype=site_coage_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m10_si_cacls) + + call this%set_history_var(vname='FATES_MORTALITY_LOGGING_SE_SZ', & + units = 'm-2 yr-1', & + long='logging mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m7_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_FREEZING_SE_SZ', & + units = 'm-2 event-1', & + long='freezing mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m8_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_SENESCENCE_SE_SZ', & + units = 'm-2 yr-1', & + long='senescence mortality by size in number of plants per m2 per event, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m9_sec_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_AGESCEN_SE_SZ', & + units = 'm-2 yr-1', & + long='age senescence mortality by size in number of plants per m2 per year, secondary patches', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_m10_sec_si_scls) + + call this%set_history_var(vname='FATES_NPP_CANOPY_SZ', units = 'kg m-2 s-1', & + long='NPP of canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_carbon_balance_canopy_si_scls) + + call this%set_history_var(vname='FATES_NPP_USTORY_SZ', units = 'kg m-2 s-1', & + long='NPP of understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_carbon_balance_understory_si_scls) + + call this%set_history_var(vname='FATES_MORTALITY_USTORY_SZ', & + units = 'm-2 yr-1', & + long='total mortality of understory trees by size class in individuals per m2 per year', & + use_default='active', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_mortality_understory_si_scls) + + call this%set_history_var(vname='FATES_TRIMMING_CANOPY_SZ', units = 'm-2', & + long='trimming term of canopy plants weighted by plant density, by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_trimming_canopy_si_scls) + + call this%set_history_var(vname='FATES_TRIMMING_USTORY_SZ', & + units = 'm-2', & + long='trimming term of understory plants weighted by plant density, by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_trimming_understory_si_scls) + + call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_SZ', units = 'm2 m-2', & + long='total crown area of canopy plants by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_crown_area_canopy_si_scls) + + call this%set_history_var(vname='FATES_CROWNAREA_USTORY_SZ', units = 'm2 m-2', & + long='total crown area of understory plants by size class', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_crown_area_understory_si_scls) + + call this%set_history_var(vname='FATES_LEAFCTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='leaf turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_leaf_md_canopy_si_scls) + + call this%set_history_var(vname='FATES_FROOTCTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='fine root turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_root_md_canopy_si_scls) + + call this%set_history_var(vname='FATES_STORECTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='storage turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_bstore_md_canopy_si_scls) + + call this%set_history_var(vname='FATES_STRUCTCTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='structural C turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_bdead_md_canopy_si_scls) + + call this%set_history_var(vname='FATES_SAPWOODCTURN_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='sapwood turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_bsw_md_canopy_si_scls) + + call this%set_history_var(vname='FATES_SEED_PROD_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='seed production of canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_seed_prod_canopy_si_scls) + + call this%set_history_var(vname='FATES_LEAF_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to leaves for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_leaf_canopy_si_scls) + + call this%set_history_var(vname='FATES_FROOT_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to fine root C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_fnrt_canopy_si_scls) + + call this%set_history_var(vname='FATES_SAPWOOD_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to sapwood C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_sapw_canopy_si_scls) + + call this%set_history_var(vname='FATES_STRUCT_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to structural C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_dead_canopy_si_scls) + + call this%set_history_var(vname='FATES_SEED_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to reproductive C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_seed_canopy_si_scls) + + call this%set_history_var(vname='FATES_STORE_ALLOC_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to storage C for canopy plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stor_canopy_si_scls) + + call this%set_history_var(vname='FATES_LEAFCTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='leaf turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_leaf_md_understory_si_scls) + + call this%set_history_var(vname='FATES_FROOTCTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='fine root turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_root_md_understory_si_scls) + + call this%set_history_var(vname='FATES_STORECTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='storage C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_bstore_md_understory_si_scls) + + call this%set_history_var(vname='FATES_STRUCTCTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='structural C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_bdead_md_understory_si_scls) + + call this%set_history_var(vname='FATES_SAPWOODCTURN_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='sapwood C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_bsw_md_understory_si_scls) + + call this%set_history_var(vname='FATES_SEED_PROD_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='seed production of understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_seed_prod_understory_si_scls) + + call this%set_history_var(vname='FATES_LEAF_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to leaves for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_leaf_understory_si_scls) + + call this%set_history_var(vname='FATES_FROOT_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to fine roots for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_fnrt_understory_si_scls) + + call this%set_history_var(vname='FATES_SAPWOOD_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to sapwood C for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_sapw_understory_si_scls) + + call this%set_history_var(vname='FATES_STRUCT_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to structural C for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_dead_understory_si_scls) + + call this%set_history_var(vname='FATES_SEED_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to reproductive C for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_seed_understory_si_scls) + + call this%set_history_var(vname='FATES_STORE_ALLOC_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='allocation to storage C for understory plants by size class in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_stor_understory_si_scls) + + ! CROWN DAMAGE VARIABLES + if_crowndamage: if(hlm_use_tree_damage .eq. itrue) then + + call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 m-2 yr-1', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) + + call this%set_history_var(vname='FATES_CROWNAREA_USTORY_CD', units = 'm2 m-2 yr-1', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) + + call this%set_history_var(vname='FATES_NPLANT_CDPF', units = 'm-2', & + long='N. plants per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_nplant_si_cdpf ) + + call this%set_history_var(vname='FATES_NPLANT_CANOPY_CDPF', units = 'm-2', & + long='N. plants per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_nplant_canopy_si_cdpf ) + + call this%set_history_var(vname='FATES_NPLANT_USTORY_CDPF', units = 'm-2', & + long='N. plants in the understory per damage x size x pft class', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_nplant_understory_si_cdpf ) + + call this%set_history_var(vname='FATES_M3_CDPF', units = 'm-2 yr-1', & + long='carbon starvation mortality by damaage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_m3_si_cdpf ) + + call this%set_history_var(vname='FATES_M11_SZPF', units = 'm-2 yr-1', & + long='damage mortality by pft/size',use_default='inactive', & + avgflag='A', vtype =site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_scpf ) + + call this%set_history_var(vname='FATES_M11_CDPF', units = 'm-2 yr-1', & + long='damage mortality by damaage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_m11_si_cdpf ) + + call this%set_history_var(vname='FATES_MORTALITY_CDPF', units = 'm-2 yr-1', & + long='mortality by damage class by size by pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_mortality_si_cdpf ) + + call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & + long='C starvation mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_canopy_si_cdpf ) + + call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & + long='C starvation mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_m3_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='FATES_M11_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & + long='damage mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_canopy_si_cdpf ) + + call this%set_history_var(vname='FATES_M11_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & + long='damage mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_m11_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='FATES_MORTALITY_CANOPY_CDPF', units = 'm-2 yr-1', & + long='mortality of canopy plants by damage/pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_mortality_canopy_si_cdpf ) + + call this%set_history_var(vname='FATES_MORTALITY_USTORY_CDPF', units = 'm-2 yr-1', & + long='mortality of understory plants by pft/size', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_mortality_understory_si_cdpf ) + + call this%set_history_var(vname='FATES_DDBH_CDPF', units = 'm m-2 yr-1', & + long='ddbh annual increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_si_cdpf ) + + call this%set_history_var(vname='FATES_DDBH_CANOPY_CDPF', units = 'm m-2 yr-1', & + long='ddbh annual canopy increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_canopy_si_cdpf ) + + call this%set_history_var(vname='FATES_DDBH_USTORY_CDPF', units = 'm m-2 yr-1', & + long='ddbh annual understory increment growth by damage x size pft', use_default='inactive', & + avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_ddbh_understory_si_cdpf ) + + end if if_crowndamage + + + call this%set_history_var(vname='FATES_FIRE_FLUX_EL', units='kg m-2 s-1', & + long='loss to atmosphere from fire by element in kg element per m2 per s', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_burn_flux_elem) + + + call this%set_history_var(vname='FATES_ERROR_EL', units='kg s-1', & + long='total mass-balance error in kg per second by element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_err_fates_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, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_fines_ag_elem) + + call this%set_history_var(vname='FATES_LITTER_BG_FINE_EL', units='kg m-2', & + long='mass of belowground litter in fines (fineroots) by element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_fines_bg_elem) + + call this%set_history_var(vname='FATES_LITTER_BG_CWD_EL', units='kg m-2', & + long='mass of belowground litter in coarse woody debris (coarse roots) by element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_bg_elem) + + call this%set_history_var(vname='FATES_LITTER_AG_CWD_EL', units='kg m-2', & + long='mass of aboveground litter in coarse woody debris (trunks/branches/twigs) by element', & + use_default='active', avgflag='A', vtype=site_elem_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_ag_elem) + + call this%set_history_var(vname='FATES_LITTER_CWD_ELDC', units='kg m-2', & + long='total mass of litter in coarse woody debris by element and coarse woody debris size', & + use_default='active', avgflag='A', vtype=site_elcwd_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_cwd_elcwd) + + ! Mass states C/N/P SCPF dimensions + ! CARBON + call this%set_history_var(vname='FATES_VEGC_SZPF', units='kg m-2', & + long='total vegetation biomass in live plants by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_totvegc_scpf) + + call this%set_history_var(vname='FATES_LEAFC_SZPF', units='kg m-2', & + long='leaf carbon mass by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_leafc_scpf) + + call this%set_history_var(vname='FATES_FROOTC_SZPF', units='kg m-2', & + long='fine-root carbon mass by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_fnrtc_scpf) + + call this%set_history_var(vname='FATES_SAPWOODC_SZPF', units='kg m-2', & + long='sapwood carbon mass by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_sapwc_scpf) + + call this%set_history_var(vname='FATES_STOREC_SZPF', units='kg m-2', & + long='storage carbon mass by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_storec_scpf) + + call this%set_history_var(vname='FATES_REPROC_SZPF', units='kg m-2', & + long='reproductive carbon mass (on plant) by size-class x pft in kg carbon per m2', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_reproc_scpf) + + + + end if if_dyn1 + end if if_dyn0 - call this%set_history_var(vname='FATES_NPP_AP', units='kg m-2 s-1', & - long='net primary productivity by age bin in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_npp_si_age) + !HERE - call this%set_history_var(vname='FATES_GPP_AP', units='kg m-2 s-1', & - long='gross primary productivity by age bin in kg carbon per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_gpp_si_age) - call this%set_history_var(vname='FATES_RDARK_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='dark respiration for understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_rdark_understory_si_scls) + if_hifrq0: if(hlm_hist_level_hifrq>0) then - call this%set_history_var(vname='FATES_LSTEMMAINTAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='live stem maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_livestem_mr_understory_si_scls) + ! Canopy Resistance - call this%set_history_var(vname='FATES_CROOTMAINTAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='live coarse root maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_livecroot_mr_understory_si_scls) + call this%set_history_var(vname='FATES_STOMATAL_COND', & + units='mol m-2 s-1', long='mean stomatal conductance', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_c_stomata_si) - call this%set_history_var(vname='FATES_FROOTMAINTAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='fine root maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_froot_mr_understory_si_scls) + call this%set_history_var(vname='FATES_LBLAYER_COND', units='mol m-2 s-1', & + long='mean leaf boundary layer conductance', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & + ivar=ivar, initialize=initialize_variables, index = ih_c_lblayer_si) - call this%set_history_var(vname='FATES_GROWAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='growth autotrophic respiration of understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_resp_g_understory_si_scls) + ! Temperature - call this%set_history_var(vname='FATES_MAINTAR_USTORY_SZ', & - units = 'kg m-2 s-1', & - long='maintenance autotrophic respiration of understory plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', & - upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_resp_m_understory_si_scls) + call this%set_history_var(vname='FATES_TVEG', units='degree_Celsius', & + long='fates instantaneous mean vegetation temperature by site', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & + ivar=ivar, initialize=initialize_variables, index = ih_tveg_si ) + + call this%set_history_var(vname='FATES_VIS_RAD_ERROR', units='-', & + long='mean two-stream solver error for VIS', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & + ivar=ivar, initialize=initialize_variables, index = ih_vis_rad_err_si) + + call this%set_history_var(vname='FATES_NIR_RAD_ERROR', units='-', & + long='mean two-stream solver error for NIR', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & + ivar=ivar, initialize=initialize_variables, index = ih_nir_rad_err_si) + + call this%set_history_var(vname='FATES_AR', units='gC/m^2/s', & + long='autotrophic respiration', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & + ivar=ivar, initialize=initialize_variables, index = ih_aresp_si ) + ! Ecosystem Carbon Fluxes (updated rapidly, upfreq=group_hifr_simple) + + call this%set_history_var(vname='FATES_NPP', units='kg m-2 s-1', & + long='net primary production in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, index = ih_npp_si) + + call this%set_history_var(vname='FATES_NPP_SECONDARY', units='kg m-2 s-1', & + long='net primary production in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, index = ih_npp_secondary_si) + + call this%set_history_var(vname='FATES_GPP', units='kg m-2 s-1', & + long='gross primary production in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, index = ih_gpp_si) + + call this%set_history_var(vname='FATES_GPP_SECONDARY', units='kg m-2 s-1', & + long='gross primary production in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, index = ih_gpp_secondary_si) + + call this%set_history_var(vname='FATES_AUTORESP', units='kg m-2 s-1', & + long='autotrophic respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, index = ih_aresp_si) + + call this%set_history_var(vname='FATES_AUTORESP_SECONDARY', units='kg m-2 s-1', & + long='autotrophic respiration in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, index = ih_aresp_secondary_si) + + call this%set_history_var(vname='FATES_GROWTH_RESP', units='kg m-2 s-1', & + long='growth respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_growth_resp_si) + + call this%set_history_var(vname='FATES_GROWTH_RESP_SECONDARY', units='kg m-2 s-1', & + long='growth respiration in kg carbon per m2 per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_growth_resp_secondary_si) + + call this%set_history_var(vname='FATES_MAINT_RESP', units='kg m-2 s-1', & + long='maintenance respiration in kg carbon per m2 land area per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_maint_resp_si) + + call this%set_history_var(vname='FATES_MAINT_RESP_UNREDUCED', units='kg m-2 s-1', & + long='diagnostic maintenance respiration if the low-carbon-storage reduction is ignored', & + use_default='unactive', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_maint_resp_unreduced_si) + + call this%set_history_var(vname='FATES_MAINT_RESP_SECONDARY', units='kg m-2 s-1', & + long='maintenance respiration in kg carbon per m2 land area per second, secondary patches', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_maint_resp_secondary_si) + + call this%set_history_var(vname='FATES_AR_CANOPY', units='gC/m^2/s', & + long='autotrophic respiration of canopy plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & + ivar=ivar, initialize=initialize_variables, index = ih_ar_canopy_si ) + + call this%set_history_var(vname='FATES_AR_UNDERSTORY', units='gC/m^2/s', & + long='autotrophic respiration of understory plants', use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & + ivar=ivar, initialize=initialize_variables, index = ih_ar_understory_si ) + + ! fast fluxes separated canopy/understory + call this%set_history_var(vname='FATES_GPP_CANOPY', units='kg m-2 s-1', & + long='gross primary production of canopy plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_gpp_canopy_si) + + call this%set_history_var(vname='FATES_AUTORESP_CANOPY', & + units='kg m-2 s-1', & + long='autotrophic respiration of canopy plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_ar_canopy_si) - call this%set_history_var(vname='FATES_RDARK_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='dark respiration for canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_rdark_canopy_si_scls) + call this%set_history_var(vname='FATES_GPP_USTORY', & + units='kg m-2 s-1', & + long='gross primary production of understory plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_gpp_understory_si) - call this%set_history_var(vname='FATES_CROOTMAINTAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_livecroot_mr_canopy_si_scls) + call this%set_history_var(vname='FATES_AUTORESP_USTORY', & + units='kg m-2 s-1', & + long='autotrophic respiration of understory plants in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_ar_understory_si) - call this%set_history_var(vname='FATES_FROOTMAINTAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_froot_mr_canopy_si_scls) - - call this%set_history_var(vname='FATES_GROWAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='growth autotrophic respiration of canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_resp_g_canopy_si_scls) - - call this%set_history_var(vname='FATES_MAINTAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='maintenance autotrophic respiration of canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_resp_m_canopy_si_scls) - call this%set_history_var(vname='FATES_LSTEMMAINTAR_CANOPY_SZ', & - units = 'kg m-2 s-1', & - long='live stem maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & - use_default='inactive', avgflag='A', vtype=site_size_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, & - index = ih_livestem_mr_canopy_si_scls) - call this%set_history_var(vname='FATES_AUTORESP_SZPF', & + call this%set_history_var(vname='FATES_LEAFMAINTAR', & units = 'kg m-2 s-1', & - long='total autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_si_scpf) + long='leaf maintenance autotrophic respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_leaf_mr_si) - call this%set_history_var(vname='FATES_GROWAR_SZPF', & + call this%set_history_var(vname='FATES_FROOTMAINTAR', & units = 'kg m-2 s-1', & - long='growth autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_grow_si_scpf) - - call this%set_history_var(vname='FATES_MAINTAR_SZPF', & - units = 'kg m-2 s-1', & - long='maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_maint_si_scpf) - - call this%set_history_var(vname='FATES_RDARK_SZPF', & - units = 'kg m-2 s-1', & - long='dark portion of maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_darkm_si_scpf) + long='fine root maintenance autotrophic respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_froot_mr_si) - call this%set_history_var(vname='FATES_AGSAPMAINTAR_SZPF', & + call this%set_history_var(vname='FATES_CROOTMAINTAR', & units = 'kg m-2 s-1', & - long='above-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_agsapm_si_scpf) + long='live coarse root maintenance autotrophic respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_livecroot_mr_si) - call this%set_history_var(vname='FATES_BGSAPMAINTAR_SZPF', & + call this%set_history_var(vname='FATES_LSTEMMAINTAR', & units = 'kg m-2 s-1', & - long='below-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_crootm_si_scpf) + long='live stem maintenance autotrophic respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_livestem_mr_si) + + call this%set_history_var(vname='FATES_NEP', units='kg m-2 s-1', & + long='net ecosystem production in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_nep_si) + + call this%set_history_var(vname='FATES_HET_RESP', units='kg m-2 s-1', & + long='heterotrophic respiration in kg carbon per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, index = ih_hr_si) + + hydro_active_if0: if(hlm_use_planthydro.eq.itrue) then + call this%set_history_var(vname='FATES_SAPFLOW', units='kg m-2 s-1', & + long='areal sap flow rate in kg per m2 per second', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hydr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_sapflow_si) + call this%set_history_var(vname='FATES_ROOTWGT_SOILVWC', units='m3 m-3', & + long='soil volumetric water content, weighted by root area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hydr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_rootwgt_soilvwc_si) + + call this%set_history_var(vname='FATES_ROOTWGT_SOILVWCSAT', & + units='m3 m-3', & + long='soil saturated volumetric water content, weighted by root area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hydr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_rootwgt_soilvwcsat_si) + + call this%set_history_var(vname='FATES_ROOTWGT_SOILMATPOT', units='Pa', & + long='soil matric potential, weighted by root area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_hydr_simple, ivar=ivar, initialize=initialize_variables, & + index = ih_rootwgt_soilmatpot_si) + + call this%set_history_var(vname='FATES_ROOTUPTAKE', units='kg m-2 s-1', & + long='root water uptake rate', use_default='active', avgflag='A', & + vtype=site_r8, hlms='CLM:ALM', upfreq=group_hydr_simple, ivar=ivar, & + initialize=initialize_variables, index = ih_rootuptake_si) + + + call this%set_history_var(vname='FATES_VEGH2O', units = 'kg m-2', & + long='water stored inside vegetation tissues (leaf, stem, roots)', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=group_hydr_simple, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_si) + + call this%set_history_var(vname='FATES_VEGH2O_HYDRO_ERR', & + units = 'kg m-2', & + long='cumulative net borrowed (+) from plant_stored_h2o due to plant hydrodynamics', & + use_default='inactive', avgflag='A', vtype=site_r8, & + hlms='CLM:ALM', upfreq=group_hydr_simple, ivar=ivar, & + initialize=initialize_variables, index = ih_h2oveg_hydro_err_si) + end if hydro_active_if0 + + !HERE + + if_hifrq1: if(hlm_hist_level_hifrq>1) then + + ! This next group are multidimensional variables that are updated + ! over the short timestep. We turn off these variables when we want + ! to save time (and some space) + + call this%set_history_var(vname='FATES_NPP_AP', units='kg m-2 s-1', & + long='net primary productivity by age bin in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_npp_si_age) + + call this%set_history_var(vname='FATES_GPP_AP', units='kg m-2 s-1', & + long='gross primary productivity by age bin in kg carbon per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_gpp_si_age) + + call this%set_history_var(vname='FATES_RDARK_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='dark respiration for understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_rdark_understory_si_scls) + + call this%set_history_var(vname='FATES_LSTEMMAINTAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='live stem maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_livestem_mr_understory_si_scls) + + call this%set_history_var(vname='FATES_CROOTMAINTAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='live coarse root maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_livecroot_mr_understory_si_scls) + + call this%set_history_var(vname='FATES_FROOTMAINTAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='fine root maintenance autotrophic respiration for understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_froot_mr_understory_si_scls) + + call this%set_history_var(vname='FATES_GROWAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='growth autotrophic respiration of understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_resp_g_understory_si_scls) + + call this%set_history_var(vname='FATES_MAINTAR_USTORY_SZ', & + units = 'kg m-2 s-1', & + long='maintenance autotrophic respiration of understory plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', & + upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_resp_m_understory_si_scls) + + call this%set_history_var(vname='FATES_RDARK_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='dark respiration for canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_rdark_canopy_si_scls) + + call this%set_history_var(vname='FATES_CROOTMAINTAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_livecroot_mr_canopy_si_scls) + + call this%set_history_var(vname='FATES_FROOTMAINTAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_froot_mr_canopy_si_scls) + + call this%set_history_var(vname='FATES_GROWAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='growth autotrophic respiration of canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_resp_g_canopy_si_scls) + + call this%set_history_var(vname='FATES_MAINTAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='maintenance autotrophic respiration of canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_resp_m_canopy_si_scls) + + call this%set_history_var(vname='FATES_LSTEMMAINTAR_CANOPY_SZ', & + units = 'kg m-2 s-1', & + long='live stem maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second by size', & + use_default='inactive', avgflag='A', vtype=site_size_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, & + index = ih_livestem_mr_canopy_si_scls) + + call this%set_history_var(vname='FATES_AUTORESP_SZPF', & + units = 'kg m-2 s-1', & + long='total autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_si_scpf) + + call this%set_history_var(vname='FATES_GROWAR_SZPF', & + units = 'kg m-2 s-1', & + long='growth autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_grow_si_scpf) + + call this%set_history_var(vname='FATES_MAINTAR_SZPF', & + units = 'kg m-2 s-1', & + long='maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_maint_si_scpf) + + call this%set_history_var(vname='FATES_RDARK_SZPF', & + units = 'kg m-2 s-1', & + long='dark portion of maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_darkm_si_scpf) + + call this%set_history_var(vname='FATES_AGSAPMAINTAR_SZPF', & + units = 'kg m-2 s-1', & + long='above-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_agsapm_si_scpf) + + call this%set_history_var(vname='FATES_BGSAPMAINTAR_SZPF', & + units = 'kg m-2 s-1', & + long='below-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_crootm_si_scpf) + + call this%set_history_var(vname='FATES_FROOTMAINTAR_SZPF', & + units = 'kg m-2 s-1', & + long='fine root maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ar_frootm_si_scpf) + + call this%set_history_var(vname='FATES_PARSUN_CLLL', units='W m-2', & + long='PAR absorbed in the sun by each canopy and leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_parsun_z_si_cnlf) + + call this%set_history_var(vname='FATES_PARSHA_CLLL', units='W m-2', & + long='PAR absorbed in the shade by each canopy and leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_parsha_z_si_cnlf) + + call this%set_history_var(vname='FATES_PARSUN_CLLLPF', units='W m-2', & + long='PAR absorbed in the sun by each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_parsun_z_si_cnlfpft) + + call this%set_history_var(vname='FATES_PARSHA_CLLLPF', units='W m-2', & + long='PAR absorbed in the shade by each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_parsha_z_si_cnlfpft) + + call this%set_history_var(vname='FATES_PARSUN_CL', units='W m-2', & + long='PAR absorbed by sunlit leaves in each canopy layer', & + use_default='inactive', avgflag='A', vtype=site_can_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_parsun_si_can ) + + call this%set_history_var(vname='FATES_PARSHA_CL', units='W m-2', & + long='PAR absorbed by shaded leaves in each canopy layer', & + use_default='inactive', avgflag='A', vtype=site_can_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_parsha_si_can) + + call this%set_history_var(vname='FATES_LAISUN_CLLL', units='m2 m-2', & + long='LAI in the sun by each canopy and leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_laisun_z_si_cnlf) + + call this%set_history_var(vname='FATES_LAISHA_CLLL', units='m2 m-2', & + long='LAI in the shade by each canopy and leaf layer', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_laisha_z_si_cnlf) + + call this%set_history_var(vname='FATES_LAISUN_CLLLPF', units='m2 m-2', & + long='Sunlit leaf area by each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_laisun_clllpf) + + call this%set_history_var(vname='FATES_LAISHA_CLLLPF', units='m2 m-2', & + long='Shaded leaf area by each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_laisha_clllpf) + + call this%set_history_var(vname='FATES_PARPROF_DIR_CLLLPF', units='W m-2', & + long='radiative profile of direct PAR through each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_parprof_dir_si_cnlfpft) + + call this%set_history_var(vname='FATES_PARPROF_DIF_CLLLPF', units='W m-2', & + long='radiative profile of diffuse PAR through each canopy, leaf, and PFT', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_parprof_dif_si_cnlfpft) + + call this%set_history_var(vname='FATES_LAISUN_CL', units='m2 m-2', & + long='LAI of sunlit leaves by canopy layer', & + use_default='inactive', avgflag='A', vtype=site_can_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_laisun_si_can) + + call this%set_history_var(vname='FATES_LAISHA_CL', units='m2 m-2', & + long='LAI of shaded leaves by canopy layer', & + use_default='inactive', avgflag='A', vtype=site_can_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_laisha_si_can) + + call this%set_history_var(vname='FATES_PARPROF_DIR_CLLL', units='W m-2', & + long='radiative profile of direct PAR through each canopy and leaf layer (averaged across PFTs)', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_parprof_dir_si_cnlf) + + call this%set_history_var(vname='FATES_PARPROF_DIF_CLLL', units='W m-2', & + long='radiative profile of diffuse PAR through each canopy and leaf layer (averaged across PFTs)', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_parprof_dif_si_cnlf) + + ! canopy-resolved fluxes and structure + + call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLL', & + units='kg m-2 s-1', & + long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & + use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_ts_net_uptake_si_cnlf) + + call this%set_history_var(vname='FATES_CROWNFRAC_CLLLPF', units='m2 m-2', & + long='area fraction of the canopy footprint occupied by each canopy-leaf-pft layer', & + use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_crownfrac_clllpf) + + call this%set_history_var(vname='FATES_LBLAYER_COND_AP', & + units='mol m-2 s-1', & + long='mean leaf boundary layer conductance - by patch age', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_c_lblayer_si_age) + + ! Canopy resistance + call this%set_history_var(vname='FATES_STOMATAL_COND_AP', & + units='mol m-2 s-1', long='mean stomatal conductance - by patch age', & + use_default='inactive', avgflag='A', vtype=site_age_r8, & + hlms='CLM:ALM', upfreq=group_hifr_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_c_stomata_si_age) + + ! PLANT HYDRAULICS + + hydro_active_if1: if(hlm_use_planthydro.eq.itrue) then + + call this%set_history_var(vname='FATES_ERRH2O_SZPF', units='kg s-1', & + long='mean individual water balance error in kg per individual per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_errh2o_scpf) + + call this%set_history_var(vname='FATES_TRAN_SZPF', units='kg s-1', & + long='mean individual transpiration rate in kg per individual per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_tran_scpf) + + call this%set_history_var(vname='FATES_SAPFLOW_SZPF', units='kg m-2 s-1', & + long='areal sap flow rate dimensioned by size x pft in kg per m2 per second', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_sapflow_scpf) + + + call this%set_history_var(vname='FATES_ITERH1_SZPF', units='count indiv-1 step-1', & + long='water balance error iteration diagnostic 1', & + use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_hydr_complx, ivar=ivar, initialize=initialize_variables, index = ih_iterh1_scpf ) + + call this%set_history_var(vname='FATES_ITERH2_SZPF', units='count indiv-1 step-1', & + long='water balance error iteration diagnostic 2', & + use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_hydr_complx, ivar=ivar, initialize=initialize_variables, index = ih_iterh2_scpf ) + + call this%set_history_var(vname='FATES_ABSROOT_H2O_SZPF', & + units='m3 m-3', & + long='absorbing volumetric root water content by size class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_ath_scpf) + + call this%set_history_var(vname='FATES_TRANSROOT_H2O_SZPF', & + units='m3 m-3', & + long='transporting volumetric root water content by size class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_tth_scpf) + + call this%set_history_var(vname='FATES_STEM_H2O_SZPF', units='m3 m-3', & + long='stem volumetric water content by size class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_sth_scpf) + + call this%set_history_var(vname='FATES_LEAF_H2O_SZPF', units='m3 m-3', & + long='leaf volumetric water content by size class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_lth_scpf) + + call this%set_history_var(vname='FATES_ABSROOT_H2OPOT_SZPF', units='Pa', & + long='absorbing root water potential by size class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_awp_scpf) + + call this%set_history_var(vname='FATES_TRANSROOT_H2OPOT_SZPF', & + units='Pa', long='transporting root water potential by size class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_twp_scpf) + + call this%set_history_var(vname='FATES_STEM_H2OPOT_SZPF', units='Pa', & + long='stem water potential by size class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_swp_scpf) + + call this%set_history_var(vname='FATES_LEAF_H2OPOT_SZPF', units='Pa', & + long='leaf water potential by size class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_lwp_scpf) + + call this%set_history_var(vname='FATES_ABSROOT_CONDFRAC_SZPF', units='1', & + long='absorbing root fraction (0-1) of condutivity by size class x pft', & + use_default='active', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_aflc_scpf) + + call this%set_history_var(vname='FATES_TRANSROOT_CONDFRAC_SZPF', units='1', & + long='transporting root fraction (0-1) of condutivity by size class x pft', & + use_default='active', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_tflc_scpf) + + call this%set_history_var(vname='FATES_STEM_CONDFRAC_SZPF', units='1', & + long='stem water fraction (0-1) of condutivity by size class x pft', & + use_default='active', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_sflc_scpf) + + call this%set_history_var(vname='FATES_LEAF_CONDFRAC_SZPF', units='1', & + long='leaf water fraction (0-1) of condutivity by size class x pft', & + use_default='active', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_lflc_scpf) + + call this%set_history_var(vname='FATES_BTRAN_SZPF', units='1', & + long='mean individual level BTRAN by size class x pft', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_btran_scpf) + + call this%set_history_var(vname='FATES_SOILMATPOT_SL', units='Pa', & + long='soil water matric potenial by soil layer', & + use_default='inactive', avgflag='A', vtype=site_soil_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_soilmatpot_sl) + + call this%set_history_var(vname='FATES_SOILVWC_SL', units='m3 m-3', & + long='soil volumetric water content by soil layer', & + use_default='inactive', avgflag='A', vtype=site_soil_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_soilvwc_sl) + + call this%set_history_var(vname='FATES_SOILVWCSAT_SL', units='m3 m-3', & + long='soil saturated volumetric water content by soil layer', & + use_default='inactive', avgflag='A', vtype=site_soil_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_soilvwcsat_sl) + + call this%set_history_var(vname='FATES_ROOTUPTAKE_SL', & + units='kg m-2 s-1', & + long='root water uptake rate by soil layer', & + use_default='inactive', avgflag='A', vtype=site_soil_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_rootuptake_sl) + + call this%set_history_var(vname='FATES_ROOTUPTAKE0_SZPF', & + units='kg m-2 m-1 s-1', & + long='root water uptake from 0 to to 10 cm depth, by plant size x pft ', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_rootuptake0_scpf) + + call this%set_history_var(vname='FATES_ROOTUPTAKE10_SZPF', & + units='kg m-2 m-1 s-1', & + long='root water uptake from 10 to to 50 cm depth, by plant size x pft ', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_rootuptake10_scpf) + + call this%set_history_var(vname='FATES_ROOTUPTAKE50_SZPF', & + units='kg m-2 m-1 s-1', & + long='root water uptake from 50 to to 100 cm depth, by plant size x pft ', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_rootuptake50_scpf) + + call this%set_history_var(vname='FATES_ROOTUPTAKE100_SZPF', & + units='kg m-2 m-1 s-1', & + long='root water uptake below 100 cm depth, by plant size x pft ', & + use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & + hlms='CLM:ALM', upfreq=group_hydr_complx, ivar=ivar, & + initialize=initialize_variables, index = ih_rootuptake100_scpf) + + end if hydro_active_if1 + + end if if_hifrq1 + + + end if if_hifrq0 - call this%set_history_var(vname='FATES_FROOTMAINTAR_SZPF', & - units = 'kg m-2 s-1', & - long='fine root maintenance autotrophic respiration in kg carbon per m2 per second by pft/size', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_ar_frootm_si_scpf) - - call this%set_history_var(vname='FATES_PARSUN_CLLL', units='W m-2', & - long='PAR absorbed in the sun by each canopy and leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_parsun_z_si_cnlf) - - call this%set_history_var(vname='FATES_PARSHA_CLLL', units='W m-2', & - long='PAR absorbed in the shade by each canopy and leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_parsha_z_si_cnlf) - - call this%set_history_var(vname='FATES_PARSUN_CLLLPF', units='W m-2', & - long='PAR absorbed in the sun by each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parsun_z_si_cnlfpft) - - call this%set_history_var(vname='FATES_PARSHA_CLLLPF', units='W m-2', & - long='PAR absorbed in the shade by each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parsha_z_si_cnlfpft) - - call this%set_history_var(vname='FATES_PARSUN_CL', units='W m-2', & - long='PAR absorbed by sunlit leaves in each canopy layer', & - use_default='inactive', avgflag='A', vtype=site_can_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parsun_si_can ) - - call this%set_history_var(vname='FATES_PARSHA_CL', units='W m-2', & - long='PAR absorbed by shaded leaves in each canopy layer', & - use_default='inactive', avgflag='A', vtype=site_can_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parsha_si_can) - - call this%set_history_var(vname='FATES_LAISUN_CLLL', units='m2 m-2', & - long='LAI in the sun by each canopy and leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisun_z_si_cnlf) - - call this%set_history_var(vname='FATES_LAISHA_CLLL', units='m2 m-2', & - long='LAI in the shade by each canopy and leaf layer', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisha_z_si_cnlf) - - call this%set_history_var(vname='FATES_LAISUN_CLLLPF', units='m2 m-2', & - long='Sunlit leaf area by each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisun_clllpf) - - call this%set_history_var(vname='FATES_LAISHA_CLLLPF', units='m2 m-2', & - long='Shaded leaf area by each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisha_clllpf) - - call this%set_history_var(vname='FATES_PARPROF_DIR_CLLLPF', units='W m-2', & - long='radiative profile of direct PAR through each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parprof_dir_si_cnlfpft) - - call this%set_history_var(vname='FATES_PARPROF_DIF_CLLLPF', units='W m-2', & - long='radiative profile of diffuse PAR through each canopy, leaf, and PFT', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parprof_dif_si_cnlfpft) - - call this%set_history_var(vname='FATES_LAISUN_CL', units='m2 m-2', & - long='LAI of sunlit leaves by canopy layer', & - use_default='inactive', avgflag='A', vtype=site_can_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisun_si_can) - - call this%set_history_var(vname='FATES_LAISHA_CL', units='m2 m-2', & - long='LAI of shaded leaves by canopy layer', & - use_default='inactive', avgflag='A', vtype=site_can_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_laisha_si_can) - - call this%set_history_var(vname='FATES_PARPROF_DIR_CLLL', units='W m-2', & - long='radiative profile of direct PAR through each canopy and leaf layer (averaged across PFTs)', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parprof_dir_si_cnlf) - - call this%set_history_var(vname='FATES_PARPROF_DIF_CLLL', units='W m-2', & - long='radiative profile of diffuse PAR through each canopy and leaf layer (averaged across PFTs)', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_parprof_dif_si_cnlf) - - ! canopy-resolved fluxes and structure - - call this%set_history_var(vname='FATES_NET_C_UPTAKE_CLLL', & - units='kg m-2 s-1', & - long='net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer per unit ground area (i.e. divide by CROWNAREA_CLLL to make per leaf area)', & - use_default='inactive', avgflag='A', vtype=site_cnlf_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_ts_net_uptake_si_cnlf) - - call this%set_history_var(vname='FATES_CROWNFRAC_CLLLPF', units='m2 m-2', & - long='area fraction of the canopy footprint occupied by each canopy-leaf-pft layer', & - use_default='inactive', avgflag='A', vtype=site_cnlfpft_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_crownfrac_clllpf) - - call this%set_history_var(vname='FATES_LBLAYER_COND_AP', & - units='mol m-2 s-1', & - long='mean leaf boundary layer conductance - by patch age', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, & - initialize=initialize_variables, index = ih_c_lblayer_si_age) - - ! Canopy resistance - call this%set_history_var(vname='FATES_STOMATAL_COND_AP', & - units='mol m-2 s-1', long='mean stomatal conductance - by patch age', & - use_default='inactive', avgflag='A', vtype=site_age_r8, & - hlms='CLM:ALM', upfreq=upfreq_hifr_multi, ivar=ivar, initialize=initialize_variables, & - index = ih_c_stomata_si_age) - - ! PLANT HYDRAULICS - - hydro_active_if1: if(hlm_use_planthydro.eq.itrue) then - - call this%set_history_var(vname='FATES_ERRH2O_SZPF', units='kg s-1', & - long='mean individual water balance error in kg per individual per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_errh2o_scpf) - - call this%set_history_var(vname='FATES_TRAN_SZPF', units='kg s-1', & - long='mean individual transpiration rate in kg per individual per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_tran_scpf) - - call this%set_history_var(vname='FATES_SAPFLOW_SZPF', units='kg m-2 s-1', & - long='areal sap flow rate dimensioned by size x pft in kg per m2 per second', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_sapflow_scpf) - - - call this%set_history_var(vname='FATES_ITERH1_SZPF', units='count indiv-1 step-1', & - long='water balance error iteration diagnostic 1', & - use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, index = ih_iterh1_scpf ) - - call this%set_history_var(vname='FATES_ITERH2_SZPF', units='count indiv-1 step-1', & - long='water balance error iteration diagnostic 2', & - use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=4, ivar=ivar, initialize=initialize_variables, index = ih_iterh2_scpf ) - - call this%set_history_var(vname='FATES_ABSROOT_H2O_SZPF', & - units='m3 m-3', & - long='absorbing volumetric root water content by size class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_ath_scpf) - - call this%set_history_var(vname='FATES_TRANSROOT_H2O_SZPF', & - units='m3 m-3', & - long='transporting volumetric root water content by size class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_tth_scpf) - - call this%set_history_var(vname='FATES_STEM_H2O_SZPF', units='m3 m-3', & - long='stem volumetric water content by size class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_sth_scpf) - - call this%set_history_var(vname='FATES_LEAF_H2O_SZPF', units='m3 m-3', & - long='leaf volumetric water content by size class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_lth_scpf) - - call this%set_history_var(vname='FATES_ABSROOT_H2OPOT_SZPF', units='Pa', & - long='absorbing root water potential by size class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_awp_scpf) - - call this%set_history_var(vname='FATES_TRANSROOT_H2OPOT_SZPF', & - units='Pa', long='transporting root water potential by size class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_twp_scpf) - - call this%set_history_var(vname='FATES_STEM_H2OPOT_SZPF', units='Pa', & - long='stem water potential by size class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_swp_scpf) - - call this%set_history_var(vname='FATES_LEAF_H2OPOT_SZPF', units='Pa', & - long='leaf water potential by size class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_lwp_scpf) - - call this%set_history_var(vname='FATES_ABSROOT_CONDFRAC_SZPF', units='1', & - long='absorbing root fraction (0-1) of condutivity by size class x pft', & - use_default='active', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_aflc_scpf) - - call this%set_history_var(vname='FATES_TRANSROOT_CONDFRAC_SZPF', units='1', & - long='transporting root fraction (0-1) of condutivity by size class x pft', & - use_default='active', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_tflc_scpf) - - call this%set_history_var(vname='FATES_STEM_CONDFRAC_SZPF', units='1', & - long='stem water fraction (0-1) of condutivity by size class x pft', & - use_default='active', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_sflc_scpf) - - call this%set_history_var(vname='FATES_LEAF_CONDFRAC_SZPF', units='1', & - long='leaf water fraction (0-1) of condutivity by size class x pft', & - use_default='active', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_lflc_scpf) - - call this%set_history_var(vname='FATES_BTRAN_SZPF', units='1', & - long='mean individual level BTRAN by size class x pft', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_btran_scpf) - - call this%set_history_var(vname='FATES_SOILMATPOT_SL', units='Pa', & - long='soil water matric potenial by soil layer', & - use_default='inactive', avgflag='A', vtype=site_soil_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_soilmatpot_sl) - - call this%set_history_var(vname='FATES_SOILVWC_SL', units='m3 m-3', & - long='soil volumetric water content by soil layer', & - use_default='inactive', avgflag='A', vtype=site_soil_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_soilvwc_sl) - - call this%set_history_var(vname='FATES_SOILVWCSAT_SL', units='m3 m-3', & - long='soil saturated volumetric water content by soil layer', & - use_default='inactive', avgflag='A', vtype=site_soil_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_soilvwcsat_sl) - - call this%set_history_var(vname='FATES_ROOTUPTAKE_SL', & - units='kg m-2 s-1', & - long='root water uptake rate by soil layer', & - use_default='inactive', avgflag='A', vtype=site_soil_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_rootuptake_sl) - - call this%set_history_var(vname='FATES_ROOTUPTAKE0_SZPF', & - units='kg m-2 m-1 s-1', & - long='root water uptake from 0 to to 10 cm depth, by plant size x pft ', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_rootuptake0_scpf) - - call this%set_history_var(vname='FATES_ROOTUPTAKE10_SZPF', & - units='kg m-2 m-1 s-1', & - long='root water uptake from 10 to to 50 cm depth, by plant size x pft ', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_rootuptake10_scpf) - - call this%set_history_var(vname='FATES_ROOTUPTAKE50_SZPF', & - units='kg m-2 m-1 s-1', & - long='root water uptake from 50 to to 100 cm depth, by plant size x pft ', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_rootuptake50_scpf) - - call this%set_history_var(vname='FATES_ROOTUPTAKE100_SZPF', & - units='kg m-2 m-1 s-1', & - long='root water uptake below 100 cm depth, by plant size x pft ', & - use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=4, ivar=ivar, & - initialize=initialize_variables, index = ih_rootuptake100_scpf) - - end if hydro_active_if1 - -!! end if if_hifrq1 -!!end if if_hifrq0 - ! Must be last thing before return this%num_history_vars_ = ivar - + end subroutine define_history_vars - ! ==================================================================================== - ! DEPRECATED, TRANSITIONAL OR FUTURE CODE SECTION - ! ==================================================================================== - - !subroutine set_fates_hio_str(tag,iotype_name, iostr_val) - -! ! Arguments -! character(len=*), intent(in) :: tag -! character(len=*), optional, intent(in) :: iotype_name -! integer, optional, intent(in) :: iostr_val - -! ! local variables -! logical :: all_set -! integer, parameter :: unset_int = -999 -! real(r8), parameter :: unset_double = -999.9 -! integer :: ityp, idim - -! select case (trim(tag)) -! case('flush_to_unset') -! write(*, *) '' -! write(*, *) 'Flushing FATES IO types prior to transfer from host' -! do ityp=1,ubound(iovar_str, 1) -! iovar_str(ityp)%dimsize = unset_int -! iovar_str(ityp)%active = .false. -! end do - -! case('check_allset') -! do ityp=1,ubound(iovar_str, 1) -! write(*, *) 'Checking to see if ',iovar_str(ityp)%name, ' IO communicators were sent to FATES' -! if(iovar_str(ityp)%active)then -! if(iovar_str(ityp)%offset .eq. unset_int) then -! write(*, *) 'FATES offset information of IO type:', iovar_str(ityp)%name -! write(*, *) 'was never set' -! ! end_run('MESSAGE') -! end if -! do idim=1, iovar_str(ityp)%ndims -! if(iovar_str(ityp)%dimsize(idim) .eq. unset_int) then -! write(*, *) 'FATES dimension information of IO type:', iovar_str(ityp)%name -! write(*, *) 'was never set' -! ! end_run('MESSAGE') -! end if -! end do -! end if -! end do -! write(*, *) 'Checked. All history IO specifications properly sent to FATES.' -! case default - -! ! Must have two arguments if this is not a check or flush -! if(present(iostr_val) .and. present(iotype_name))then -! -! ! Tag in this case is dimsize or offset -! select case (trim(tag)) -! -! case('offset') -! ityp=iotype_index(trim(iotype_name)) -! iovar_str(ityp)%offset = iostr_val -! write(*, *) 'Transfering offset for IOTYPE',iotype_name, ' to FATES' - -! case('dimsize1') -! ityp=iotype_index(trim(iotype_name)) -! iovar_str(ityp)%dimsize(1) = iostr_val -! write(*, *) 'Transfering 1st dimension size for IOTYPE',iotype_name, ' to FATES' - -! case('dimsize2') -! ityp=iotype_index(trim(iotype_name)) -! if(ubound(iovar_str(ityp)%dimsize, 1)==1)then -! write(fates_log(), *) 'Transfering second dimensional bound to unallocated space' -! write(fates_log(), *) 'type:', iotype_name -! ! end_run -! end if -! iovar_str(ityp)%dimsize(2) = iostr_val -! write(*, *) 'Transfering 2nd dimension size for IOTYPE',iotype_name, ' to FATES' - -! case('dimsize3') -! ityp=iotype_index(trim(iotype_name)) -! if(ubound(iovar_str(ityp)%dimsize, 1)<3)then -! write(fates_log(), *) 'Transfering third dimensional bound to unallocated space' -! write(fates_log(), *) 'type:', iotype_name -! ! end_run -! end if -! iovar_str(ityp)%dimsize(3) = iostr_val -! write(*, *) 'Transfering 3rd dimension size for IOTYPE',iotype_name, ' to FATES' - -! case default -! write(*, *) 'IO parameter not recognized:', trim(tag) -! ! end_run -! end select -! else -! write(*, *) 'no value was provided for the tag' -! end if -! -! end select -! return -! end subroutine set_fates_hio_str + ! ==================================================================================== + ! DEPRECATED, TRANSITIONAL OR FUTURE CODE SECTION + ! ==================================================================================== + + !subroutine set_fates_hio_str(tag,iotype_name, iostr_val) + + ! ! Arguments + ! character(len=*), intent(in) :: tag + ! character(len=*), optional, intent(in) :: iotype_name + ! integer, optional, intent(in) :: iostr_val + + ! ! local variables + ! logical :: all_set + ! integer, parameter :: unset_int = -999 + ! real(r8), parameter :: unset_double = -999.9 + ! integer :: ityp, idim + + ! select case (trim(tag)) + ! case('flush_to_unset') + ! write(*, *) '' + ! write(*, *) 'Flushing FATES IO types prior to transfer from host' + ! do ityp=1,ubound(iovar_str, 1) + ! iovar_str(ityp)%dimsize = unset_int + ! iovar_str(ityp)%active = .false. + ! end do + + ! case('check_allset') + ! do ityp=1,ubound(iovar_str, 1) + ! write(*, *) 'Checking to see if ',iovar_str(ityp)%name, ' IO communicators were sent to FATES' + ! if(iovar_str(ityp)%active)then + ! if(iovar_str(ityp)%offset .eq. unset_int) then + ! write(*, *) 'FATES offset information of IO type:', iovar_str(ityp)%name + ! write(*, *) 'was never set' + ! ! end_run('MESSAGE') + ! end if + ! do idim=1, iovar_str(ityp)%ndims + ! if(iovar_str(ityp)%dimsize(idim) .eq. unset_int) then + ! write(*, *) 'FATES dimension information of IO type:', iovar_str(ityp)%name + ! write(*, *) 'was never set' + ! ! end_run('MESSAGE') + ! end if + ! end do + ! end if + ! end do + ! write(*, *) 'Checked. All history IO specifications properly sent to FATES.' + ! case default + + ! ! Must have two arguments if this is not a check or flush + ! if(present(iostr_val) .and. present(iotype_name))then + ! + ! ! Tag in this case is dimsize or offset + ! select case (trim(tag)) + ! + ! case('offset') + ! ityp=iotype_index(trim(iotype_name)) + ! iovar_str(ityp)%offset = iostr_val + ! write(*, *) 'Transfering offset for IOTYPE',iotype_name, ' to FATES' + + ! case('dimsize1') + ! ityp=iotype_index(trim(iotype_name)) + ! iovar_str(ityp)%dimsize(1) = iostr_val + ! write(*, *) 'Transfering 1st dimension size for IOTYPE',iotype_name, ' to FATES' + + ! case('dimsize2') + ! ityp=iotype_index(trim(iotype_name)) + ! if(ubound(iovar_str(ityp)%dimsize, 1)==1)then + ! write(fates_log(), *) 'Transfering second dimensional bound to unallocated space' + ! write(fates_log(), *) 'type:', iotype_name + ! ! end_run + ! end if + ! iovar_str(ityp)%dimsize(2) = iostr_val + ! write(*, *) 'Transfering 2nd dimension size for IOTYPE',iotype_name, ' to FATES' + + ! case('dimsize3') + ! ityp=iotype_index(trim(iotype_name)) + ! if(ubound(iovar_str(ityp)%dimsize, 1)<3)then + ! write(fates_log(), *) 'Transfering third dimensional bound to unallocated space' + ! write(fates_log(), *) 'type:', iotype_name + ! ! end_run + ! end if + ! iovar_str(ityp)%dimsize(3) = iostr_val + ! write(*, *) 'Transfering 3rd dimension size for IOTYPE',iotype_name, ' to FATES' + + ! case default + ! write(*, *) 'IO parameter not recognized:', trim(tag) + ! ! end_run + ! end select + ! else + ! write(*, *) 'no value was provided for the tag' + ! end if + ! + ! end select + ! return + ! end subroutine set_fates_hio_str diff --git a/main/FatesHistoryVariableType.F90 b/main/FatesHistoryVariableType.F90 index 83cbdb8c1c..c2a890355e 100644 --- a/main/FatesHistoryVariableType.F90 +++ b/main/FatesHistoryVariableType.F90 @@ -55,7 +55,7 @@ module FatesHistoryVariableType integer, pointer :: int3d(:,:,:) contains procedure :: Init - procedure :: Flush + procedure :: HFlush procedure, private :: GetBounds end type fates_history_variable_type @@ -283,7 +283,7 @@ subroutine GetBounds(this, thread, dim_bounds, dim_kinds, lb1, ub1, lb2, ub2) end subroutine GetBounds - subroutine Flush(this, thread, dim_bounds, dim_kinds) + subroutine HFlush(this, thread, dim_bounds, dim_kinds) implicit none @@ -357,6 +357,6 @@ subroutine Flush(this, thread, dim_bounds, dim_kinds) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - end subroutine Flush + end subroutine HFlush end module FatesHistoryVariableType diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index 07df7b8270..61e2c93c9d 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -51,6 +51,17 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_elcwd_r8 = 'SI_ELEMCWD_R8' character(*), parameter, public :: site_elage_r8 = 'SI_ELEMAGE_R8' + + ! These are group indices for output variables. We use + ! these groups to do things like zero-ing and initializing + + integer, parameter, public :: group_dyna_simple = 1 + integer, parameter, public :: group_dyna_complx = 2 + integer, parameter, public :: group_hifr_simple = 3 + integer, parameter, public :: group_hifr_complx = 4 + integer, parameter, public :: group_hydr_simple = 5 + integer, parameter, public :: group_hydr_complx = 6 + ! NOTE(RGK, 2016) %active is not used yet. Was intended as a check on the HLM->FATES ! control parameter passing to ensure all active dimension types received all ! dimensioning specifications from the host, but we currently arent using those From e541edb559ca62ed281217b0fdab6b5317f1c0b9 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Fri, 26 Jan 2024 11:21:18 -0800 Subject: [PATCH 080/300] add recruit carbon flux --- main/FatesHistoryInterfaceMod.F90 | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 81bfef2792..243cab5c8b 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -572,6 +572,7 @@ module FatesHistoryInterfaceMod integer :: ih_nindivs_si_pft integer :: ih_nindivs_sec_si_pft integer :: ih_recruitment_si_pft + integer :: ih_recruitment_cflux_si_pft integer :: ih_mortality_si_pft integer :: ih_mortality_carbonflux_si_pft integer :: ih_hydraulicmortality_carbonflux_si_pft @@ -2343,6 +2344,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) hio_nindivs_si_pft => this%hvars(ih_nindivs_si_pft)%r82d, & hio_nindivs_sec_si_pft => this%hvars(ih_nindivs_sec_si_pft)%r82d, & hio_recruitment_si_pft => this%hvars(ih_recruitment_si_pft)%r82d, & + hio_recruitment_cflux_si_pft => this%hvars(ih_recruitment_cflux_si_pft)%r82d, & hio_seeds_out_gc_si_pft => this%hvars(ih_seeds_out_gc_si_pft)%r82d, & hio_seeds_in_gc_si_pft => this%hvars(ih_seeds_in_gc_si_pft)%r82d, & hio_mortality_si_pft => this%hvars(ih_mortality_si_pft)%r82d, & @@ -3030,6 +3032,11 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) (ccohort%n * AREA_INV) * total_m end if + if(ccohort%isnew) then + hio_recruitment_cflux_si_pft(io_si, ft) = hio_recruitment_cflux_si_pft(io_si, ft) + & + (ccohort%n * AREA_INV) * total_m * days_per_year + end if + ! update total biomass per age bin hio_biomass_si_age(io_si,cpatch%age_class) = hio_biomass_si_age(io_si,cpatch%age_class) & + total_m * ccohort%n * AREA_INV @@ -5538,6 +5545,12 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index=ih_biomass_sec_si_pft) + call this%set_history_var(vname='FATES_RECRUITMENT_CFLUX_PF', units='kg m-2 yr-1', & + long='total PFT-level biomass of new recruits in kg of carbon per land area', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=1, ivar=ivar, initialize=initialize_variables, & + index=ih_recruitment_cflux_si_pft) + call this%set_history_var(vname='FATES_LEAFC_PF', units='kg m-2', & long='total PFT-level leaf biomass in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & From a4bb8365dbd6e09c0109e8f9868168d1e310c51d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 26 Jan 2024 14:29:58 -0700 Subject: [PATCH 081/300] updated some upfreq constants for hist density --- main/FatesHistoryInterfaceMod.F90 | 76 +++++++++++++++---------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index b22579fb6c..827a732bca 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3205,7 +3205,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_m8_sec_si_scls => this%hvars(ih_m8_sec_si_scls)%r82d, & hio_m9_sec_si_scls => this%hvars(ih_m9_sec_si_scls)%r82d, & hio_m10_sec_si_scls => this%hvars(ih_m10_sec_si_scls)%r82d, & - hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & + !hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & hio_cwd_elcwd => this%hvars(ih_cwd_elcwd)%r82d, & hio_cwd_ag_elem => this%hvars(ih_cwd_ag_elem)%r82d, & hio_cwd_bg_elem => this%hvars(ih_cwd_bg_elem)%r82d, & @@ -3539,6 +3539,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! Zero states, and set the fluxes if( element_list(el).eq.carbon12_element )then + call bstore_allom(ccohort%dbh,ccohort%pft,ccohort%crowndamage,ccohort%canopy_trim, store_max) + ! Determine the root carbon biomass in kg/m3 ! [kg/m3] = [kg/plant] * [plant/ha] / [m3/ha] * [fraction] / [m] @@ -3787,12 +3789,12 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) end if !C13 discrimination - if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then - hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & - (ccohort%c13disc_acc * ccohort%gpp_acc_hold)) / (gpp_cached + ccohort%gpp_acc_hold) - else - hio_c13disc_si_scpf(io_si,scpf) = 0.0_r8 - endif + !if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then + ! hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & + ! (ccohort%c13disc_acc * ccohort%gpp_acc_hold)) / (gpp_cached + ccohort%gpp_acc_hold) + !else + ! hio_c13disc_si_scpf(io_si,scpf) = 0.0_r8 + !endif ! number density [/m2] hio_nplant_si_scpf(io_si,scpf) = hio_nplant_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha @@ -6049,8 +6051,6 @@ subroutine define_history_vars(this, initialize_variables) ! cohort size x crown damage (site_cdsc_r8) : SZCD ! cohort size x crown damage x pft (site_cdpf_r8) : CDPF - print*,hlm_hist_level_dynam,hlm_hist_level_hifrq - stop if_dyn0: if(hlm_hist_level_dynam>0) then @@ -6377,37 +6377,37 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for target allometry', & use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & long='ammonium uptake rate by plants in kg NH4 per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_nh4uptake_si) call this%set_history_var(vname='FATES_NO3UPTAKE', units='kg m-2 s-1', & long='nitrate uptake rate by plants in kg NO3 per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_no3uptake_si) call this%set_history_var(vname='FATES_NEFFLUX', units='kg m-2 s-1', & long='nitrogen effluxed from plant in kg N per m2 per second (unused)', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_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=5, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_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', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_nfix_si) end select @@ -6415,39 +6415,39 @@ subroutine define_history_vars(this, initialize_variables) nitrogen_active_if0: if(any(element_list(:)==nitrogen_element)) then call this%set_history_var(vname='FATES_STOREN', units='kg m-2', & long='total nitrogen in live plant storage', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_storen_si) call this%set_history_var(vname='FATES_STOREN_TF', units='1', & long='storage N fraction of target', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_storentfrac_si) call this%set_history_var(vname='FATES_VEGN', units='kg m-2', & long='total nitrogen in live plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_totvegn_si) call this%set_history_var(vname='FATES_SAPWOODN', units='kg m-2', & long='total nitrogen in live plant sapwood', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_sapwn_si) call this%set_history_var(vname='FATES_LEAFN', units='kg m-2', & long='total nitrogen in live plant leaves', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_leafn_si) call this%set_history_var(vname='FATES_FROOTN', units='kg m-2', & long='total nitrogen in live plant fine-roots', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_fnrtn_si) call this%set_history_var(vname='FATES_REPRON', units='kg m-2', & long='total nitrogen in live plant reproductive tissues', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_repron_si) end if nitrogen_active_if0 @@ -6455,66 +6455,66 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_STOREP', units='kg m-2', & long='total phosphorus in live plant storage', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_storep_si) call this%set_history_var(vname='FATES_STOREP_TF', units='1', & long='storage P fraction of target', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, & index = ih_storeptfrac_si) call this%set_history_var(vname='FATES_VEGP', units='kg m-2', & long='total phosphorus in live plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_totvegp_si) call this%set_history_var(vname='FATES_SAPWOODP', units='kg m-2', & long='Total phosphorus in live plant sapwood', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, ivar=ivar, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_sapwp_si) call this%set_history_var(vname='FATES_LEAFP', units='kg m-2', & long='total phosphorus in live plant leaves', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_leafp_si) call this%set_history_var(vname='FATES_FROOTP', units='kg m-2', & long='total phosphorus in live plant fine roots', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_fnrtp_si) call this%set_history_var(vname='FATES_REPROP', units='kg m-2', & long='total phosphorus in live plant reproductive tissues', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_reprop_si) call this%set_history_var(vname='FATES_PUPTAKE', units='kg m-2 s-1', & long='mineralized phosphorus uptake rate of plants in kg P per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_puptake_si) call this%set_history_var(vname='FATES_PEFFLUX', units='kg m-2 s-1', & long='phosphorus effluxed from plant in kg P per m2 per second (unused)', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_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=5, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_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', & long='structural biomass in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_bdead_si) call this%set_history_var(vname='FATES_NONSTRUCTC', units='kg m-2', & @@ -7656,11 +7656,11 @@ subroutine define_history_vars(this, initialize_variables) initialize=initialize_variables, index = ih_m3_mortality_understory_si_scpf ) - call this%set_history_var(vname='FATES_C13DISC_SZPF', units = 'per mil', & - long='C13 discrimination by pft/size',use_default='inactive', & - avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & - upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & - index = ih_c13disc_si_scpf) +! call this%set_history_var(vname='FATES_C13DISC_SZPF', units = 'per mil', & +! long='C13 discrimination by pft/size',use_default='inactive', & +! avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & +! upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & +! index = ih_c13disc_si_scpf) call this%set_history_var(vname='FATES_STOREC_CANOPY_SZPF', units = 'kg m-2', & long='biomass in storage pools of canopy plants by pft/size in kg carbon per m2', & From e9e87d1bb4237ccc00033dbda1fc8da4f50629f6 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 26 Jan 2024 16:37:37 -0500 Subject: [PATCH 082/300] upreq updates --- main/FatesHistoryInterfaceMod.F90 | 80 +++++++++++++++---------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 827a732bca..9920aa4839 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -6520,25 +6520,25 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_NONSTRUCTC', units='kg m-2', & long='non-structural biomass (sapwood + leaf + fineroot) in kg carbon per m2', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_balive_si) call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND', units='kg m-2', & long='aboveground biomass in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_agb_si) call this%set_history_var(vname='FATES_CANOPY_VEGC', units='kg m-2', & long='biomass of canopy plants in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_canopy_biomass_si) call this%set_history_var(vname='FATES_USTORY_VEGC', units='kg m-2', & long='biomass of understory plants in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_understory_biomass_si) ! disturbance rates @@ -6547,66 +6547,66 @@ subroutine define_history_vars(this, initialize_variables) units='m2 m-2 yr-1', & long='error in total primary lands associated with patch fusion', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_primaryland_fusion_error_si) call this%set_history_var(vname='FATES_DISTURBANCE_RATE_FIRE', & units='m2 m-2 yr-1', long='disturbance rate from fire', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_fire_disturbance_rate_si) call this%set_history_var(vname='FATES_DISTURBANCE_RATE_LOGGING', & units='m2 m-2 yr-1', long='disturbance rate from logging', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_logging_disturbance_rate_si) call this%set_history_var(vname='FATES_DISTURBANCE_RATE_TREEFALL', & units='m2 m-2 yr-1', long='disturbance rate from treefall', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_fall_disturbance_rate_si) call this%set_history_var(vname='FATES_HARVEST_CARBON_FLUX', & units='kg m-2 yr-1', & long='harvest carbon flux in kg carbon per m2 per year', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_harvest_carbonflux_si) call this%set_history_var(vname='FATES_TVEG24', units='degree_Celsius', & long='fates 24-hr running mean vegetation temperature by site', & use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) call this%set_history_var(vname='FATES_TLONGTERM', units='degree_Celsius', & long='fates 30-year running mean vegetation temperature by site', & use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_tlongterm_si ) call this%set_history_var(vname='FATES_TGROWTH', units='degree_Celsius', & long='fates long-term running mean vegetation temperature by site', & use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_tgrowth_si ) call this%set_history_var(vname='FATES_HARVEST_DEBT', units='kg C', & long='Accumulated carbon failed to be harvested', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) call this%set_history_var(vname='FATES_HARVEST_DEBT_SEC', units='kg C', & long='Accumulated carbon failed to be harvested from secondary patches', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=1, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) call this%set_history_var(vname='FATES_EXCESS_RESP', units='kg m-2 s-1', & long='respiration of un-allocatable carbon gain', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=5, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_excess_resp_si) ! slow carbon fluxes associated with mortality from or transfer betweeen canopy and understory @@ -6614,111 +6614,111 @@ subroutine define_history_vars(this, initialize_variables) units = 'kg m-2 s-1', & long='demotion-associated biomass carbon flux from canopy to understory in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_demotion_carbonflux_si) call this%set_history_var(vname='FATES_PROMOTION_CARBONFLUX', & units = 'kg m-2 s-1', & long='promotion-associated biomass carbon flux from understory to canopy in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_promotion_carbonflux_si) call this%set_history_var(vname='FATES_MORTALITY_CFLUX_CANOPY', & units = 'kg m-2 s-1', & long='flux of biomass carbon from live to dead pools from mortality of canopy plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_canopy_mortality_carbonflux_si) call this%set_history_var(vname='FATES_MORTALITY_CFLUX_USTORY', & units = 'kg m-2 s-1', & long='flux of biomass carbon from live to dead pools from mortality of understory plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_understory_mortality_carbonflux_si) call this%set_history_var(vname='MORTALITY_CROWNAREA_CANOPY', & units = 'm2/ha/year', & long='Crown area of canopy trees that died', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_canopy_mortality_crownarea_si ) call this%set_history_var(vname='MORTALITY_CROWNAREA_UNDERSTORY', & units = 'm2/ha/year', & long='Crown aera of understory trees that died', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_understory_mortality_crownarea_si ) call this%set_history_var(vname='FATES_FIRE_CLOSS', units='kg m-2 s-1', & long='carbon loss to atmosphere from fire in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_fire_c_to_atm_si) call this%set_history_var(vname='FATES_CBALANCE_ERROR', & units='kg s-1', & long='total carbon error in kg carbon per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + 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', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_leaf_si) call this%set_history_var(vname='FATES_SEED_ALLOC', units='kg m-2 s-1', & long='allocation to seeds in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_seed_si) call this%set_history_var(vname='FATES_STEM_ALLOC', units='kg m-2 s-1', & long='allocation to stem in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_stem_si) call this%set_history_var(vname='FATES_FROOT_ALLOC', units='kg m-2 s-1', & long='allocation to fine roots in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_froot_si) call this%set_history_var(vname='FATES_CROOT_ALLOC', units='kg m-2 s-1', & long='allocation to coarse roots in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_croot_si) call this%set_history_var(vname='FATES_STORE_ALLOC', units='kg m-2 s-1', & long='allocation to storage tissues in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=1, ivar=ivar, initialize=initialize_variables, & + group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_stor_si) hydro_active_if: if(hlm_use_planthydro.eq.itrue) then call this%set_history_var(vname='FATES_VEGH2O_DEAD', units = 'kg m-2', & long='cumulative water stored in dead biomass due to mortality', & use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_h2oveg_dead_si) call this%set_history_var(vname='FATES_VEGH2O_RECRUIT', & units = 'kg m-2', long='amount of water in new recruits', & use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_h2oveg_recruit_si) call this%set_history_var(vname='FATES_VEGH2O_GROWTURN_ERR', & units = 'kg m-2', & long='cumulative net borrowed (+) or lost (-) from water storage due to combined growth & turnover', & use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', upfreq=1, ivar=ivar, & + hlms='CLM:ALM', group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_h2oveg_growturn_err_si) end if hydro_active_if @@ -7105,32 +7105,32 @@ subroutine define_history_vars(this, initialize_variables) units='kg m-2 s-1', & long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & + hlms='CLM:ALM', group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_nh4uptake_scpf) call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & units='kg m-2 s-1', & long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & + hlms='CLM:ALM', group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_no3uptake_scpf) call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & long='nitrogen efflux, root to soil, 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=5, ivar=ivar, & + hlms='CLM:ALM', group_dyna_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=5, ivar=ivar, & + hlms='CLM:ALM', group_dyna_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, & - hlms='CLM:ALM', upfreq=5, ivar=ivar, & + hlms='CLM:ALM', group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_nfix_scpf) end select @@ -7246,20 +7246,20 @@ subroutine define_history_vars(this, initialize_variables) units='kg m-2 s-1', & long='phosphorus uptake rate by plants, 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=5, ivar=ivar, & + hlms='CLM:ALM', group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_puptake_scpf) call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & units='kg m-2 s-1', & long='phosphorus efflux, root to soil, 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=5, ivar=ivar, & + hlms='CLM:ALM', group_dyna_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=5, ivar=ivar, & + hlms='CLM:ALM', group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_pdemand_scpf) end if phosphorus_active_if1 From 94ac0a4398cddda9ce5d1b21c03107aad696a19e Mon Sep 17 00:00:00 2001 From: jessica needham Date: Tue, 30 Jan 2024 10:14:46 -0800 Subject: [PATCH 083/300] fix typo --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 1e29f75704..e162ec5419 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2184,7 +2184,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! This code uses the relationship between leaf N and respiration from Atkin et al ! for the top of the canopy, but then scales through the canopy based on a rdark_scaler. ! To assume proportionality with N through the canopy following Lloyd et al. 2010, use the - ! default parameter value of 2.43, which results in the scaling of photosynthesis and respiraiton + ! default parameter value of 2.43, which results in the scaling of photosynthesis and respiration ! being proportional through the canopy. To have a steeper decrease in respiration than photosynthesis ! this number can be smaller. There is some observational evidence for this being the case ! in Lamour et al. 2023. From d56683bcdb7779d6ac05c3ca6a328dfddd5686c4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 31 Jan 2024 12:33:30 -0700 Subject: [PATCH 084/300] fixed some history registration commands --- main/FatesHistoryInterfaceMod.F90 | 78 +++++++++++++++---------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 9920aa4839..8d7e40b1a7 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -6520,25 +6520,25 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_NONSTRUCTC', units='kg m-2', & long='non-structural biomass (sapwood + leaf + fineroot) in kg carbon per m2', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_balive_si) call this%set_history_var(vname='FATES_VEGC_ABOVEGROUND', units='kg m-2', & long='aboveground biomass in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_agb_si) call this%set_history_var(vname='FATES_CANOPY_VEGC', units='kg m-2', & long='biomass of canopy plants in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_canopy_biomass_si) call this%set_history_var(vname='FATES_USTORY_VEGC', units='kg m-2', & long='biomass of understory plants in kg carbon per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_understory_biomass_si) ! disturbance rates @@ -6547,60 +6547,60 @@ subroutine define_history_vars(this, initialize_variables) units='m2 m-2 yr-1', & long='error in total primary lands associated with patch fusion', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_primaryland_fusion_error_si) call this%set_history_var(vname='FATES_DISTURBANCE_RATE_FIRE', & units='m2 m-2 yr-1', long='disturbance rate from fire', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_fire_disturbance_rate_si) call this%set_history_var(vname='FATES_DISTURBANCE_RATE_LOGGING', & units='m2 m-2 yr-1', long='disturbance rate from logging', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_logging_disturbance_rate_si) call this%set_history_var(vname='FATES_DISTURBANCE_RATE_TREEFALL', & units='m2 m-2 yr-1', long='disturbance rate from treefall', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_fall_disturbance_rate_si) call this%set_history_var(vname='FATES_HARVEST_CARBON_FLUX', & units='kg m-2 yr-1', & long='harvest carbon flux in kg carbon per m2 per year', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_harvest_carbonflux_si) call this%set_history_var(vname='FATES_TVEG24', units='degree_Celsius', & long='fates 24-hr running mean vegetation temperature by site', & use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_tveg24_si ) call this%set_history_var(vname='FATES_TLONGTERM', units='degree_Celsius', & long='fates 30-year running mean vegetation temperature by site', & use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_tlongterm_si ) call this%set_history_var(vname='FATES_TGROWTH', units='degree_Celsius', & long='fates long-term running mean vegetation temperature by site', & use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_tgrowth_si ) call this%set_history_var(vname='FATES_HARVEST_DEBT', units='kg C', & long='Accumulated carbon failed to be harvested', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_si ) call this%set_history_var(vname='FATES_HARVEST_DEBT_SEC', units='kg C', & long='Accumulated carbon failed to be harvested from secondary patches', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', group_dyna_simple, & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) call this%set_history_var(vname='FATES_EXCESS_RESP', units='kg m-2 s-1', & @@ -6614,111 +6614,111 @@ subroutine define_history_vars(this, initialize_variables) units = 'kg m-2 s-1', & long='demotion-associated biomass carbon flux from canopy to understory in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_demotion_carbonflux_si) call this%set_history_var(vname='FATES_PROMOTION_CARBONFLUX', & units = 'kg m-2 s-1', & long='promotion-associated biomass carbon flux from understory to canopy in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_promotion_carbonflux_si) call this%set_history_var(vname='FATES_MORTALITY_CFLUX_CANOPY', & units = 'kg m-2 s-1', & long='flux of biomass carbon from live to dead pools from mortality of canopy plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_canopy_mortality_carbonflux_si) call this%set_history_var(vname='FATES_MORTALITY_CFLUX_USTORY', & units = 'kg m-2 s-1', & long='flux of biomass carbon from live to dead pools from mortality of understory plants in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_understory_mortality_carbonflux_si) call this%set_history_var(vname='MORTALITY_CROWNAREA_CANOPY', & units = 'm2/ha/year', & long='Crown area of canopy trees that died', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_canopy_mortality_crownarea_si ) call this%set_history_var(vname='MORTALITY_CROWNAREA_UNDERSTORY', & units = 'm2/ha/year', & long='Crown aera of understory trees that died', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_understory_mortality_crownarea_si ) call this%set_history_var(vname='FATES_FIRE_CLOSS', units='kg m-2 s-1', & long='carbon loss to atmosphere from fire in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_fire_c_to_atm_si) call this%set_history_var(vname='FATES_CBALANCE_ERROR', & units='kg s-1', & long='total carbon error in kg carbon per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=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', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_leaf_si) call this%set_history_var(vname='FATES_SEED_ALLOC', units='kg m-2 s-1', & long='allocation to seeds in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_seed_si) call this%set_history_var(vname='FATES_STEM_ALLOC', units='kg m-2 s-1', & long='allocation to stem in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_stem_si) call this%set_history_var(vname='FATES_FROOT_ALLOC', units='kg m-2 s-1', & long='allocation to fine roots in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_froot_si) call this%set_history_var(vname='FATES_CROOT_ALLOC', units='kg m-2 s-1', & long='allocation to coarse roots in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_croot_si) call this%set_history_var(vname='FATES_STORE_ALLOC', units='kg m-2 s-1', & long='allocation to storage tissues in kg carbon per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_npp_stor_si) hydro_active_if: if(hlm_use_planthydro.eq.itrue) then call this%set_history_var(vname='FATES_VEGH2O_DEAD', units = 'kg m-2', & long='cumulative water stored in dead biomass due to mortality', & use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', group_dyna_simple, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_h2oveg_dead_si) call this%set_history_var(vname='FATES_VEGH2O_RECRUIT', & units = 'kg m-2', long='amount of water in new recruits', & use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', group_dyna_simple, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_h2oveg_recruit_si) call this%set_history_var(vname='FATES_VEGH2O_GROWTURN_ERR', & units = 'kg m-2', & long='cumulative net borrowed (+) or lost (-) from water storage due to combined growth & turnover', & use_default='inactive', avgflag='A', vtype=site_r8, & - hlms='CLM:ALM', group_dyna_simple, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_simple, ivar=ivar, & initialize=initialize_variables, index = ih_h2oveg_growturn_err_si) end if hydro_active_if @@ -7105,32 +7105,32 @@ subroutine define_history_vars(this, initialize_variables) units='kg m-2 s-1', & long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_nh4uptake_scpf) call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & units='kg m-2 s-1', & long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_no3uptake_scpf) call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & long='nitrogen efflux, root to soil, 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', group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_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', group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_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, & - hlms='CLM:ALM', group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_nfix_scpf) end select @@ -7246,20 +7246,20 @@ subroutine define_history_vars(this, initialize_variables) units='kg m-2 s-1', & long='phosphorus uptake rate by plants, 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', group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_puptake_scpf) call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & units='kg m-2 s-1', & long='phosphorus efflux, root to soil, 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', group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_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', group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_pdemand_scpf) end if phosphorus_active_if1 From 494502c817fb4f6c48fbb857f747f9571b25229c Mon Sep 17 00:00:00 2001 From: "[Jennifer Kowalczyk]" <[jenniferkowalczyk@lbl.gov]> Date: Fri, 19 Jan 2024 07:33:13 -0800 Subject: [PATCH 085/300] edit to fix dd restart issue --- biogeophys/FatesPlantHydraulicsMod.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index e38e042252..699045e95b 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -936,6 +936,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) ! we set as our lower cap on leaf volume real(r8), parameter :: min_trim = 0.1_r8 ! The lower cap on trimming function used ! to estimate maximum leaf carbon + real(r8), parameter :: min_efleaf = 0.1_r8 ! Lower cap on leaf elongation factor ccohort_hydr => ccohort%co_hydr ft = ccohort%pft @@ -981,12 +982,11 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) ! Lets also avoid super-low targets that have very low trimming functions call bleaf(ccohort%dbh,ccohort%pft,ccohort%crowndamage, & - max(ccohort%canopy_trim,min_trim),ccohort%efleaf_coh, leaf_c_target) + max(ccohort%canopy_trim,min_trim),max(ccohort%efleaf_coh,min_efleaf), leaf_c_target) + + ccohort_hydr%v_ag(1:n_hypool_leaf) = max(leaf_c,min_leaf_frac*leaf_c_target) * & + prt_params%c2b(ft) / denleaf/ real(n_hypool_leaf,r8) - if( (ccohort%status_coh == leaves_on) .or. ccohort_hydr%is_newly_recruited ) then - ccohort_hydr%v_ag(1:n_hypool_leaf) = max(leaf_c,min_leaf_frac*leaf_c_target) * & - prt_params%c2b(ft) / denleaf/ real(n_hypool_leaf,r8) - end if ! Step sapwood volume ! ----------------------------------------------------------------------------------- From be600081c763756b6a71ed3b3b954b8efa749903 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 1 Feb 2024 19:37:53 -0700 Subject: [PATCH 086/300] fixing term mort changes --- main/FatesHistoryInterfaceMod.F90 | 131 ++++++++++++++++++++++-------- 1 file changed, 97 insertions(+), 34 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 8d7e40b1a7..e61a4b7c08 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -10,6 +10,10 @@ module FatesHistoryInterfaceMod use FatesConstantsMod , only : pi_const use FatesConstantsMod , only : nearzero use FatesConstantsMod , only : t_water_freeze_k_1atm + use FatesConstantsMod , only : n_term_mort_types + 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 FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun use EDParamsMod , only : nclmax, maxpft @@ -618,6 +622,7 @@ module FatesHistoryInterfaceMod integer :: ih_hydraulicmortality_carbonflux_si_pft integer :: ih_cstarvmortality_carbonflux_si_pft integer :: ih_firemortality_carbonflux_si_pft + integer :: ih_cstarvmortality_continuous_carbonflux_si_pft integer :: ih_crownarea_si_pft integer :: ih_canopycrownarea_si_pft integer :: ih_crownarea_si_cnlf @@ -2594,6 +2599,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & sum(sites(s)%fmort_carbonflux_canopy(:)) / g_per_kg + hio_ustory_mortality_carbonflux_si(io_si) = hio_ustory_mortality_carbonflux_si(io_si) + & sum(sites(s)%fmort_carbonflux_ustory(:)) / g_per_kg @@ -2608,10 +2614,10 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! mortality-associated carbon fluxes hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & - sum(sites(s)%term_carbonflux_canopy(:)) * days_per_sec * ha_per_m2 - + sum(sites(s)%term_carbonflux_canopy(:,:)) * days_per_sec * ha_per_m2 + hio_ustory_mortality_carbonflux_si(io_si) = hio_ustory_mortality_carbonflux_si(io_si) + & - sum(sites(s)%term_carbonflux_ustory(:)) * days_per_sec * ha_per_m2 + sum(sites(s)%term_carbonflux_ustory(:,:)) * days_per_sec * ha_per_m2 ! add site level mortality counting to crownarea diagnostic hio_canopy_mortality_crownarea_si(io_si) = hio_canopy_mortality_crownarea_si(io_si) + & @@ -3008,8 +3014,8 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! zero the site-level termination carbon flux variable - sites(s)%term_carbonflux_canopy(:) = 0._r8 - sites(s)%term_carbonflux_ustory(:) = 0._r8 + sites(s)%term_carbonflux_canopy(:,:) = 0._r8 + sites(s)%term_carbonflux_ustory(:,:) = 0._r8 @@ -3064,7 +3070,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) real(r8) :: repro_m_net_alloc ! mass allocated to reproduction [kg/yr] real(r8) :: n_perm2 ! abundance per m2 integer :: ageclass_since_anthrodist ! what is the equivalent age class for - ! time-since-anthropogenic-disturbance of secondary forest + ! time-since-anthropogenic-disturbance of secondary forest real(r8) :: area_frac ! Fraction of area for this patch real(r8) :: frac_canopy_in_bin ! fraction of a leaf's canopy that is within a given height bin real(r8) :: binbottom,bintop ! edges of height bins @@ -3308,7 +3314,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_nplant_si_scag => this%hvars(ih_nplant_si_scag)%r82d, & 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_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) model_day_int = nint(hlm_model_day) @@ -3856,12 +3863,18 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ccohort%n * ha_per_m2 - hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) + & + hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) = & + hio_hydraulicmortality_carbonflux_si_pft(io_si,ccohort%pft) + & ccohort%hmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 - hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) = hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) + & + hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) = & + hio_cstarvmortality_carbonflux_si_pft(io_si,ccohort%pft) + & ccohort%cmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + hio_cstarvmortality_continuous_carbonflux_si_pft(io_si,ccohort%pft) = & + hio_cstarvmortality_continuous_carbonflux_si_pft(io_si,ccohort%pft) + & + ccohort%cmort * total_m * ccohort%n * days_per_sec * years_per_day * ha_per_m2 + ! Aboveground mortality hio_abg_mortality_cflux_si_scpf(io_si,scpf) = hio_abg_mortality_cflux_si_scpf(io_si,scpf) + & (ccohort%bmort + ccohort%hmort + ccohort%cmort + & @@ -4291,32 +4304,77 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! pass the cohort termination mortality as a flux to the history, and then reset the termination mortality buffer ! note there are various ways of reporting the total mortality, so pass to these as well + do i_pft = 1, numpft + hio_cstarvmortality_carbonflux_si_pft(io_si,i_pft) = & + hio_cstarvmortality_carbonflux_si_pft(io_si,i_pft) + & + (sites(s)%term_carbonflux_ustory(i_term_mort_type_cstarv,i_pft) + & + sites(s)%term_carbonflux_canopy(i_term_mort_type_cstarv,i_pft)) * days_per_sec * ha_per_m2 + end do do ft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (ft-1)*nlevsclass + i_scls ! ! termination mortality. sum of canopy and understory indices - hio_m6_si_scpf(io_si,i_scpf) = (sites(s)%term_nindivs_canopy(i_scls,ft) + & - sites(s)%term_nindivs_ustory(i_scls,ft)) * & + + ! move carbon starvation-related termination mortality to the carbon starvation mortality type and only consider + ! the other two types of termination mortality here. + + hio_m6_si_scpf(io_si,i_scpf) = & + (sum(sites(s)%term_nindivs_canopy(i_term_mort_type_canlev:n_term_mort_types,i_scls,ft)) + & + sum(sites(s)%term_nindivs_ustory(i_term_mort_type_canlev:n_term_mort_types,i_scls,ft))) * & days_per_year / m2_per_ha - + hio_m6_si_scls(io_si,i_scls) = hio_m6_si_scls(io_si,i_scls) + & - (sites(s)%term_nindivs_canopy(i_scls,ft) + & - sites(s)%term_nindivs_ustory(i_scls,ft)) * & + (sum(sites(s)%term_nindivs_canopy(i_term_mort_type_canlev:n_term_mort_types,i_scls,ft)) + & + sum(sites(s)%term_nindivs_ustory(i_term_mort_type_canlev:n_term_mort_types,i_scls,ft))) * & + days_per_year / m2_per_ha + ! + ! add the carbon starvation-related termination mortality to the carbon starvation diagnostics + hio_m3_si_scpf(io_si,i_scpf) = hio_m3_si_scpf(io_si,i_scpf) + & + (sites(s)%term_nindivs_canopy(i_term_mort_type_cstarv,i_scls,ft) + & + sites(s)%term_nindivs_ustory(i_term_mort_type_cstarv,i_scls,ft)) * & + days_per_year / m2_per_ha + + hio_m3_si_scls(io_si,i_scls) = hio_m3_si_scls(io_si,i_scls) + & + (sites(s)%term_nindivs_canopy(i_term_mort_type_cstarv,i_scls,ft) + & + sites(s)%term_nindivs_ustory(i_term_mort_type_cstarv,i_scls,ft)) * & + days_per_year / m2_per_ha + + ! add c-starve termination mortality to canopy and understory M3 mortality (N/m^2/yr) + hio_m3_mortality_canopy_si_scpf(io_si,i_scpf) = & + hio_m3_mortality_canopy_si_scpf(io_si,i_scpf) + & + sites(s)%term_nindivs_canopy(i_term_mort_type_cstarv,i_scls,ft) * & + days_per_year / m2_per_ha + + hio_m3_mortality_understory_si_scpf(io_si,i_scpf) = & + hio_m3_mortality_understory_si_scpf(io_si,i_scpf) + & + sites(s)%term_nindivs_ustory(i_term_mort_type_cstarv,i_scls,ft) * & days_per_year / m2_per_ha + + hio_m3_mortality_canopy_si_scls(io_si,i_scls) = & + hio_m3_mortality_canopy_si_scls(io_si,i_scls) + & + sites(s)%term_nindivs_canopy(i_term_mort_type_cstarv,i_scls,ft) * & + days_per_year / m2_per_ha + + hio_m3_mortality_understory_si_scls(io_si,i_scls) = & + hio_m3_mortality_understory_si_scls(io_si,i_scls) + & + sites(s)%term_nindivs_ustory(i_term_mort_type_cstarv,i_scls,ft) * & + days_per_year / m2_per_ha + ! ! add termination mortality to canopy and understory mortality hio_mortality_canopy_si_scls(io_si,i_scls) = hio_mortality_canopy_si_scls(io_si,i_scls) + & - sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha - + sum(sites(s)%term_nindivs_canopy(:,i_scls,ft)) * days_per_year / m2_per_ha + hio_mortality_understory_si_scls(io_si,i_scls) = hio_mortality_understory_si_scls(io_si,i_scls) + & - sites(s)%term_nindivs_ustory(i_scls,ft) * days_per_year / m2_per_ha + sum(sites(s)%term_nindivs_ustory(:,i_scls,ft)) * days_per_year / m2_per_ha hio_mortality_canopy_si_scpf(io_si,i_scpf) = hio_mortality_canopy_si_scpf(io_si,i_scpf) + & - sites(s)%term_nindivs_canopy(i_scls,ft) * days_per_year / m2_per_ha + sum(sites(s)%term_nindivs_canopy(:,i_scls,ft)) * days_per_year / m2_per_ha hio_mortality_understory_si_scpf(io_si,i_scpf) = hio_mortality_understory_si_scpf(io_si,i_scpf) + & - sites(s)%term_nindivs_ustory(i_scls,ft) * days_per_year / m2_per_ha + sum(sites(s)%term_nindivs_ustory(:,i_scls,ft)) * days_per_year / m2_per_ha + ! ! imort on its own @@ -4386,9 +4444,9 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_mortality_carbonflux_si_pft(io_si,ft) = hio_mortality_carbonflux_si_pft(io_si,ft) + & (sites(s)%fmort_carbonflux_canopy(ft) + & sites(s)%fmort_carbonflux_ustory(ft) ) / g_per_kg + & - sites(s)%imort_carbonflux(ft) + & - sites(s)%term_carbonflux_ustory(ft) * days_per_sec * ha_per_m2 + & - sites(s)%term_carbonflux_canopy(ft) * days_per_sec * ha_per_m2 + sites(s)%imort_carbonflux(ft) + & + sum(sites(s)%term_carbonflux_ustory(:,ft)) * days_per_sec * ha_per_m2 + & + sum(sites(s)%term_carbonflux_canopy(:,ft)) * days_per_sec * ha_per_m2 hio_firemortality_carbonflux_si_pft(io_si,ft) = sites(s)%fmort_carbonflux_canopy(ft) / g_per_kg end do @@ -4438,9 +4496,8 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) end do end do end if - - sites(s)%term_nindivs_canopy(:,:) = 0._r8 - sites(s)%term_nindivs_ustory(:,:) = 0._r8 + sites(s)%term_nindivs_canopy(:,:,:) = 0._r8 + sites(s)%term_nindivs_ustory(:,:,:) = 0._r8 sites(s)%imort_carbonflux(:) = 0._r8 sites(s)%imort_rate(:,:) = 0._r8 sites(s)%fmort_rate_canopy(:,:) = 0._r8 @@ -7295,11 +7352,17 @@ subroutine define_history_vars(this, initialize_variables) index=ih_hydraulicmortality_carbonflux_si_pft) call this%set_history_var(vname='FATES_MORTALITY_CSTARV_CFLUX_PF', units='kg m-2 s-1', & - long='PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality', & + long='PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality (both continuous and termination)', & use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & index=ih_cstarvmortality_carbonflux_si_pft) + call this%set_history_var(vname='FATES_MORT_CSTARV_CONT_CFLUX_PF', units='kg m-2 s-1', & + long='PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality (Continuous-only, without termination)', & + use_default='active', avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index=ih_cstarvmortality_continuous_carbonflux_si_pft) + call this%set_history_var(vname='FATES_ABOVEGROUND_MORT_SZPF', units='kg m-2 s-1', & long='Aboveground flux of carbon from AGB to necromass due to mortality', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & @@ -7559,7 +7622,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZPF', & units = 'm-2 yr-1', & - long='carbon starvation mortality by pft/size in number of plants per m2 per year', & + long='carbon starvation mortality by pft/size in number of plants per m2 per year (both continous and termination)', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_m3_si_scpf) @@ -7594,7 +7657,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZPF', & units = 'm-2 yr-1', & - long='termination mortality by pft/size in number pf plants per m2 per year', & + long='termination mortality (excluding C-starvation) by pft/size in number pf plants per m2 per year', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_m6_si_scpf) @@ -7642,14 +7705,14 @@ subroutine define_history_vars(this, initialize_variables) initialize=initialize_variables, index = ih_mortality_canopy_si_scpf) call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZPF', & - units = 'N/ha/yr', & + units = 'm-2 yr-1', & long='C starvation mortality of canopy plants by pft/size', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scpf ) call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZPF', & - units = 'N/ha/yr', & + units = 'm-2 yr-1', & long='C starvation mortality of understory plants by pft/size', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & @@ -7884,14 +7947,14 @@ subroutine define_history_vars(this, initialize_variables) initialize=initialize_variables, index = ih_nplant_understory_si_scls) call this%set_history_var(vname='FATES_M3_MORTALITY_CANOPY_SZ', & - units = 'N/ha/yr', & + units = 'm-2 yr-1', & long='C starvation mortality of canopy plants by size', & use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_m3_mortality_canopy_si_scls ) call this%set_history_var(vname='FATES_M3_MORTALITY_USTORY_SZ', & - units = 'N/ha/yr', & + units = 'm-2 yr-1', & long='C starvation mortality of understory plants by size', & use_default='inactive', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & @@ -7938,7 +8001,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_MORTALITY_CSTARV_SZ', & units = 'm-2 yr-1', & - long='carbon starvation mortality by size in number of plants per m2 per year', & + long='carbon starvation mortality by size in number of plants per m2 per year (both continous and termination)', & use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_m3_si_scls) @@ -7980,7 +8043,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_MORTALITY_TERMINATION_SZ', & units = 'm-2 yr-1', & - long='termination mortality by size in number of plants per m2 per year', & + long='termination mortality (excluding C-starvation) by size in number of plants per m2 per year', & use_default='active', avgflag='A', vtype=site_size_r8, & hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_m6_si_scls) From 1aea1915949946685fbd34ee6c8eadfecae09c3c Mon Sep 17 00:00:00 2001 From: "[Jennifer Kowalczyk]" <[jenniferkowalczyk@lbl.gov]> Date: Fri, 2 Feb 2024 12:06:32 -0800 Subject: [PATCH 087/300] setting efleaf_coh=1 when calculating water storage volume --- biogeophys/FatesPlantHydraulicsMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 699045e95b..fdc506416b 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -936,7 +936,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) ! we set as our lower cap on leaf volume real(r8), parameter :: min_trim = 0.1_r8 ! The lower cap on trimming function used ! to estimate maximum leaf carbon - real(r8), parameter :: min_efleaf = 0.1_r8 ! Lower cap on leaf elongation factor + ccohort_hydr => ccohort%co_hydr ft = ccohort%pft @@ -982,7 +982,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) ! Lets also avoid super-low targets that have very low trimming functions call bleaf(ccohort%dbh,ccohort%pft,ccohort%crowndamage, & - max(ccohort%canopy_trim,min_trim),max(ccohort%efleaf_coh,min_efleaf), leaf_c_target) + max(ccohort%canopy_trim,min_trim),1.0, leaf_c_target) ccohort_hydr%v_ag(1:n_hypool_leaf) = max(leaf_c,min_leaf_frac*leaf_c_target) * & prt_params%c2b(ft) / denleaf/ real(n_hypool_leaf,r8) From 50327691c556b35c0d5ca4027d17889ccb114cb5 Mon Sep 17 00:00:00 2001 From: "[Jennifer Kowalczyk]" <[jenniferkowalczyk@lbl.gov]> Date: Fri, 2 Feb 2024 12:14:36 -0800 Subject: [PATCH 088/300] typo --- biogeophys/FatesPlantHydraulicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index fdc506416b..f8b3e93100 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -982,7 +982,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) ! Lets also avoid super-low targets that have very low trimming functions call bleaf(ccohort%dbh,ccohort%pft,ccohort%crowndamage, & - max(ccohort%canopy_trim,min_trim),1.0, leaf_c_target) + max(ccohort%canopy_trim,min_trim),1.0_r8, leaf_c_target) ccohort_hydr%v_ag(1:n_hypool_leaf) = max(leaf_c,min_leaf_frac*leaf_c_target) * & prt_params%c2b(ft) / denleaf/ real(n_hypool_leaf,r8) From 830c529584325dd42ef4a7fe1318c8f2c70ef570 Mon Sep 17 00:00:00 2001 From: "[Jennifer Kowalczyk]" <[jenniferkowalczyk@lbl.gov]> Date: Fri, 2 Feb 2024 14:01:46 -0800 Subject: [PATCH 089/300] comment --- biogeophys/FatesPlantHydraulicsMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index f8b3e93100..03977fa0ec 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -981,6 +981,7 @@ subroutine UpdatePlantHydrLenVol(ccohort,csite_hydr) ! Get the target, or rather, maximum leaf carrying capacity of plant ! Lets also avoid super-low targets that have very low trimming functions + ! efleaf_coh hard-coded to 1 in the call below to avoid zero leaf volume call bleaf(ccohort%dbh,ccohort%pft,ccohort%crowndamage, & max(ccohort%canopy_trim,min_trim),1.0_r8, leaf_c_target) From 118b411b41e21fa6498431cfc4fc20ee975ccb9f Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 5 Feb 2024 11:56:07 -0500 Subject: [PATCH 090/300] enabling cstarvation mode switch in-code --- main/EDParamsMod.F90 | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 71cc21af73..8d78eec61c 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -430,9 +430,8 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_mort_disturb_frac, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - ! Temporary until we add parameter to file - !call fates_params%RegisterParameter(name=ED_name_mort_cstarvation_model, dimension_shape=dimension_shape_scalar, & - ! dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_mort_cstarvation_model, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=ED_name_comp_excln, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -648,12 +647,10 @@ subroutine FatesReceiveParams(fates_params) call fates_params%RetrieveParameter(name=ED_name_mort_disturb_frac, & data=fates_mortality_disturbance_fraction) - ! Temporary until we add parameter to file - !call fates_params%RetrieveParameter(name=ED_name_mort_cstarvation_model, & - ! data=tmpreal) - ! mort_cstarvation_model = nint(tmpreal) - mort_cstarvation_model = cstarvation_model_lin - + call fates_params%RetrieveParameter(name=ED_name_mort_cstarvation_model, & + data=tmpreal) + mort_cstarvation_model = nint(tmpreal) + call fates_params%RetrieveParameter(name=ED_name_comp_excln, & data=ED_val_comp_excln) From f450fb77eeeedc3cde5ba23cea93f6587aae20e3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 5 Feb 2024 12:53:30 -0500 Subject: [PATCH 091/300] updating parameters for cstarvation and allometry crown depth modes in the xml patch file and cdl --- .../api33.0.0_020524_params_default.cdl | 1741 +++++++++++++++++ .../archive/api33.0.0_020524_patch_params.xml | 70 + parameter_files/fates_params_default.cdl | 9 +- 3 files changed, 1815 insertions(+), 5 deletions(-) create mode 100644 parameter_files/archive/api33.0.0_020524_params_default.cdl create mode 100644 parameter_files/archive/api33.0.0_020524_patch_params.xml diff --git a/parameter_files/archive/api33.0.0_020524_params_default.cdl b/parameter_files/archive/api33.0.0_020524_params_default.cdl new file mode 100644 index 0000000000..99bdaed02e --- /dev/null +++ b/parameter_files/archive/api33.0.0_020524_params_default.cdl @@ -0,0 +1,1741 @@ +netcdf fates_params_default { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; + fates_landuseclass = 5 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + char fates_landuseclass_name(fates_landuseclass, fates_string_length) ; + fates_landuseclass_name:units = "unitless - string" ; + fates_landuseclass_name:long_name = "Name of the land use classes, for variables associated with dimension fates_landuseclass" ; + char fates_litterclass_name(fates_litterclass, fates_string_length) ; + fates_litterclass_name:units = "unitless - string" ; + fates_litterclass_name:long_name = "Name of the litter classes, for variables associated with dimension fates_litterclass" ; + double fates_alloc_organ_priority(fates_plant_organs, fates_pft) ; + fates_alloc_organ_priority:units = "index" ; + fates_alloc_organ_priority:long_name = "Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + double fates_damage_recovery_scalar(fates_pft) ; + fates_damage_recovery_scalar:units = "unitless" ; + fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; + double fates_dev_arbitrary_pft(fates_pft) ; + fates_dev_arbitrary_pft:units = "unknown" ; + fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + double fates_hydro_vg_n_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_n_node:units = "unitless" ; + fates_hydro_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_maintresp_reduction_upthresh(fates_pft) ; + fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; + fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_mort_upthresh_cstarvation(fates_pft) ; + fates_mort_upthresh_cstarvation:units = "unitless" ; + fates_mort_upthresh_cstarvation:long_name = "threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_drought_threshold(fates_pft) ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; + double fates_phen_mindaysoff(fates_pft) ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; + double fates_phen_moist_threshold(fates_pft) ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Flag for stress/drought-deciduous leaf habit. 0 - not stress deciduous; 1 - default drought deciduous (two target states only, fully flushed or fully abscised); 2 - semi-deciduous" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_seed_dispersal_fraction(fates_pft) ; + fates_seed_dispersal_fraction:units = "fraction" ; + fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; + double fates_seed_dispersal_max_dist(fates_pft) ; + fates_seed_dispersal_max_dist:units = "m" ; + fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; + double fates_seed_dispersal_pdf_scale(fates_pft) ; + fates_seed_dispersal_pdf_scale:units = "unitless" ; + fates_seed_dispersal_pdf_scale:long_name = "seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016" ; + double fates_seed_dispersal_pdf_shape(fates_pft) ; + fates_seed_dispersal_pdf_shape:units = "unitless" ; + fates_seed_dispersal_pdf_shape:long_name = "seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_trs_repro_alloc_a(fates_pft) ; + fates_trs_repro_alloc_a:units = "fraction" ; + fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_alloc_b(fates_pft) ; + fates_trs_repro_alloc_b:units = "fraction" ; + fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_frac_seed(fates_pft) ; + fates_trs_repro_frac_seed:units = "fraction" ; + fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; + double fates_trs_seedling_a_emerg(fates_pft) ; + fates_trs_seedling_a_emerg:units = "day -1" ; + fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; + double fates_trs_seedling_b_emerg(fates_pft) ; + fates_trs_seedling_b_emerg:units = "day -1" ; + fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; + double fates_trs_seedling_background_mort(fates_pft) ; + fates_trs_seedling_background_mort:units = "yr-1" ; + fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; + double fates_trs_seedling_h2o_mort_a(fates_pft) ; + fates_trs_seedling_h2o_mort_a:units = "-" ; + fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_b(fates_pft) ; + fates_trs_seedling_h2o_mort_b:units = "-" ; + fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_c(fates_pft) ; + fates_trs_seedling_h2o_mort_c:units = "-" ; + fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_light_mort_a(fates_pft) ; + fates_trs_seedling_light_mort_a:units = "-" ; + fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_mort_b(fates_pft) ; + fates_trs_seedling_light_mort_b:units = "-" ; + fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_rec_a(fates_pft) ; + fates_trs_seedling_light_rec_a:units = "-" ; + fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_light_rec_b(fates_pft) ; + fates_trs_seedling_light_rec_b:units = "-" ; + fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_mdd_crit(fates_pft) ; + fates_trs_seedling_mdd_crit:units = "mm H2O day" ; + fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; + double fates_trs_seedling_par_crit_germ(fates_pft) ; + fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; + fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; + double fates_trs_seedling_psi_crit(fates_pft) ; + fates_trs_seedling_psi_crit:units = "mm H2O" ; + fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; + double fates_trs_seedling_psi_emerg(fates_pft) ; + fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; + fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; + double fates_trs_seedling_root_depth(fates_pft) ; + fates_trs_seedling_root_depth:units = "m" ; + fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + double fates_frag_cwd_frac(fates_NCWD) ; + fates_frag_cwd_frac:units = "fraction" ; + fates_frag_cwd_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_maxpatches_by_landuse(fates_landuseclass) ; + fates_maxpatches_by_landuse:units = "count" ; + fates_maxpatches_by_landuse:long_name = "maximum number of patches per site on each land use type" ; + double fates_canopy_closure_thresh ; + fates_canopy_closure_thresh:units = "unitless" ; + fates_canopy_closure_thresh:long_name = "tree canopy coverage at which crown area allometry changes from savanna to forest value" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + double fates_hydro_solver ; + fates_hydro_solver:units = "unitless" ; + fates_hydro_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard, 3 = 2D Newton (deprecated)" ; + double fates_landuse_logging_coll_under_frac ; + fates_landuse_logging_coll_under_frac:units = "fraction" ; + fates_landuse_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_thome_time ; + fates_leaf_photo_temp_acclim_thome_time:units = "years" ; + fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_rad_model ; + fates_rad_model:units = "unitless" ; + fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; + double fates_regeneration_model ; + fates_regeneration_model:units = "-" ; + fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_trs_seedling2sap_par_timescale ; + fates_trs_seedling2sap_par_timescale:units = "days" ; + fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; + double fates_trs_seedling_emerg_h2o_timescale ; + fates_trs_seedling_emerg_h2o_timescale:units = "days" ; + fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; + double fates_trs_seedling_mdd_timescale ; + fates_trs_seedling_mdd_timescale:units = "days" ; + fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; + double fates_trs_seedling_mort_par_timescale ; + fates_trs_seedling_mort_par_timescale:units = "days" ; + fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_landuseclass_name = + "primaryland", + "secondaryland", + "rangeland", + "pastureland", + "cropland" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + fates_alloc_organ_priority = + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, + 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, + 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, + 0.3381119, 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, + 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, + 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, + -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; + + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_upthresh_cstarvation = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_scale = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_shape = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, + 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; + + fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, + -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; + + fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, + 0.24, 0.24, 0.24, 0.24 ; + + fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, + 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; + + fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371 ; + + fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; + + fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; + + fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; + + fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; + + fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063 ; + + fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, + 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; + + fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, + 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; + + fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, + 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; + + fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, + 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; + + fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7 ; + + fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65 ; + + fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.06, 0.06, 0.06, 0.06 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_maxpatches_by_landuse = 9, 4, 1, 1, 1 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_thome_time = 30 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; + + fates_maxcohort = 100 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindayson = 90 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_rad_model = 1 ; + + fates_regeneration_model = 1 ; + + fates_soil_salinity = 0.4 ; + + fates_trs_seedling2sap_par_timescale = 32 ; + + fates_trs_seedling_emerg_h2o_timescale = 7 ; + + fates_trs_seedling_mdd_timescale = 126 ; + + fates_trs_seedling_mort_par_timescale = 32 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/archive/api33.0.0_020524_patch_params.xml b/parameter_files/archive/api33.0.0_020524_patch_params.xml new file mode 100644 index 0000000000..8beff2ff42 --- /dev/null +++ b/parameter_files/archive/api33.0.0_020524_patch_params.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + archive/api33.0.0_020524_params_default.cdl + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_mort_upthresh_cstarvation + + + fates_mort_upthresh_cstarvation + fates_pft + unitless + threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + + + fates_phen_stress_decid + + + fates_phen_stress_decid + fates_pft + logical flag + Flag for stress/drought-deciduous leaf habit. 0 - not stress deciduous; 1 - default drought deciduous (two target states only, fully flushed or fully abscised); 2 - semi-deciduous + 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 + + + fates_allom_crown_depth_frac + + + fates_allom_dmode + fates_pft + index + crown depth allometry function index + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + + + fates_allom_h2cd1 + fates_pft + variable + Parameter 1 for h2cd allometry (exp(log-intercept) or scaling). If allom_dmode=1; this is the same as former crown_depth_frac parameter + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 + + + fates_allom_h2cd2 + fates_pft + variable + Parameter 2 for h2cd allometry (log-slope or exponent). If allom_dmode=1; this is not needed (as exponent is assumed 1) + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index ea4bbaa27f..b34d9475d1 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -8,12 +8,12 @@ dimensions: fates_history_size_bins = 13 ; fates_hlm_pftno = 14 ; fates_hydr_organs = 4 ; + fates_landuseclass = 5 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; fates_plant_organs = 4 ; fates_string_length = 60 ; - fates_landuseclass = 5 ; variables: double fates_history_ageclass_bin_edges(fates_history_age_bins) ; fates_history_ageclass_bin_edges:units = "yr" ; @@ -113,7 +113,7 @@ variables: fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; double fates_allom_dmode(fates_pft) ; fates_allom_dmode:units = "index" ; - fates_allom_dmode:long_name = "crown depth allometry function index." ; + fates_allom_dmode:long_name = "crown depth allometry function index" ; double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; @@ -1025,8 +1025,7 @@ data: fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_h2cd1 = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; + fates_allom_h2cd1 = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; From c6441863cd5ee683d2754221cd9b50a4a2889611 Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Mon, 5 Feb 2024 10:56:15 -0800 Subject: [PATCH 092/300] Fix crown depth allometry for two stream. Fix documentation typos and added suggested values for the new allometry (thanks JessicaNeedham) --- biogeochem/FatesAllometryMod.F90 | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index e653da6c30..6cccde4422 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1561,6 +1561,14 @@ subroutine dh2blmax_3pwr(d,h,dhdd,p1,p2,p3,slatop,dbh_maxh,c2b,blmax,dblmaxdd) ! blmax -- Plant leaf biomass [ kgC] ! dblmaxdd -- Plant leaf biomass derivative [ kgC/cm] ! + ! ------------------ + ! Suggested first guess for parameters, based on Longo et al. (2020) and + ! corrected to FATES units (first guess based on a very limited leaf area + ! data set). + ! ------------------ + ! p1 = 0.000468 + ! p2 = 0.641 + ! p3 = -1.000 !-------------------------------------------------------------------------- @@ -1957,7 +1965,6 @@ subroutine dh2bagw_3pwr(d,h,dhdd,p1,p2,p3,wood_density,c2b,bagw,dbagwdd) ! p3 -- Parameter 3 (power, or log-slope) [ --] ! wood_density -- Wood density [ g/cm3] ! c2b -- Carbon to biomass multiplier ~ 2 [ kg/kgC] - ! dbh_maxh -- DBH at maximum height [ cm] ! ! ------------------ ! Output arguments @@ -2428,7 +2435,7 @@ subroutine carea_3pwr(dbh,height,ipft,dbh_maxh,spread,dh2bl_p2,dh2bl_ediff, & real(r8) , intent(inout) :: dbh ! Diameter at breast/ref/ height [ cm] real(r8) , intent(inout) :: height ! Height [ m] integer(i4), intent(in) :: ipft ! PFT index - real(r8) , intent(in) :: dbh_maxh ! Minimum DBH at maximum height [ m] + real(r8) , intent(in) :: dbh_maxh ! Minimum DBH at maximum height [ cm] real(r8) , intent(in) :: spread ! site level relative spread score [ 0-1] real(r8) , intent(in) :: dh2bl_p2 ! Exponent for size (bleaf) [ -] real(r8) , intent(in) :: dh2bl_ediff ! Difference in size exponent [ -] @@ -2945,6 +2952,8 @@ subroutine VegAreaLayer(tree_lai,tree_sai,tree_height,iv,nv,pft,snow_depth, & ! [m2 of leaf in bin / m2 crown footprint] real(r8) :: tree_vai ! the in-crown veg area index for the plant + real(r8) :: crown_depth ! crown depth of the plant [m] + real(r8) :: frac_crown_depth ! fraction of the crown depth (relative to plant height) real(r8) :: fraction_exposed ! fraction of the veg media that is above snow real(r8) :: layer_top_height ! Physical height of the layer top relative to ground [m] real(r8) :: layer_bot_height ! Physical height of the layer bottom relative to ground [m] @@ -2957,6 +2966,10 @@ subroutine VegAreaLayer(tree_lai,tree_sai,tree_height,iv,nv,pft,snow_depth, & tree_vai = tree_lai + tree_sai + ! Ratio between crown depth and plant height + call CrownDepth(tree_height,pft,crown_depth) + frac_crown_depth = crown_depth / tree_height + if_any_vai: if(tree_vai>0._r8)then if(iv==0)then @@ -2980,14 +2993,14 @@ subroutine VegAreaLayer(tree_lai,tree_sai,tree_height,iv,nv,pft,snow_depth, & if(layer_height_method .eq. layer_height_const_depth)then if(iv==0)then layer_top_height = tree_height - layer_bot_height = tree_height*(1._r8 - prt_params%crown_depth_frac(pft)) + layer_bot_height = tree_height*(1._r8 - frac_crown_depth) else - layer_top_height = tree_height*(1._r8 - real(iv-1,r8)/real(nv,r8)*prt_params%crown_depth_frac(pft)) - layer_bot_height = tree_height*(1._r8 - real(iv,r8)/real(nv,r8)*prt_params%crown_depth_frac(pft)) + layer_top_height = tree_height*(1._r8 - real(iv-1,r8)/real(nv,r8)*frac_crown_depth) + layer_bot_height = tree_height*(1._r8 - real(iv,r8)/real(nv,r8)*frac_crown_depth) end if else - layer_top_height = tree_height*(1._r8 - prt_params%crown_depth_frac(pft)*vai_top/tree_vai) - layer_bot_height = tree_height*(1._r8 - prt_params%crown_depth_frac(pft)*vai_bot/tree_vai) + layer_top_height = tree_height*(1._r8 - frac_crown_depth*vai_top/tree_vai) + layer_bot_height = tree_height*(1._r8 - frac_crown_depth*vai_bot/tree_vai) end if fraction_exposed = 1._r8 - max(0._r8,(min(1._r8, (snow_depth-layer_bot_height)/(layer_top_height-layer_bot_height)))) From e35f44c73c6dbcb77ad0ccde7f443c233edd6ff5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 6 Feb 2024 13:22:28 -0500 Subject: [PATCH 093/300] Add in parameter file checks and metadata that ECA phosphatase lambda and alpha are incactive --- main/EDPftvarcon.F90 | 24 +++++++++++++++++-- .../archive/api33.0.0_020524_patch_params.xml | 20 ++++++++++++++++ parameter_files/fates_params_default.cdl | 9 ++++--- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 5745141c70..f454a03013 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1845,7 +1845,6 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if - end if end if @@ -1871,7 +1870,25 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if - + + ! We are using a simple phosphatase model right now. There is + ! no critical value (lambda) , and there is no preferential uptake (alpha). + ! Make sure these parameters are both set to 0. + + if ((hlm_phosphorus_spec>0) .and. (trim(hlm_nu_com).eq.'ECA')) then + if (any(abs(EDPftvarcon_inst%eca_lambda_ptase(:)) > nearzero ) ) then + write(fates_log(),*) 'Critical Values for phosphatase in ECA are not' + write(fates_log(),*) 'enabled right now. Please set fates_eca_lambda_ptase = 0' + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + if (any(abs(EDPftvarcon_inst%eca_alpha_ptase(:)) > nearzero ) ) then + write(fates_log(),*) 'There is no preferential plant uptake of P from phosphatase' + write(fates_log(),*) 'enabled right now. Please set fates_eca_alpha_ptase = 0' + write(fates_log(),*) ' Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if case (prt_carbon_allom_hyp) ! No additional checks needed for now. @@ -1915,6 +1932,9 @@ subroutine FatesCheckParams(is_master) end if end if + + + do ipft = 1,npft ! xl must be between -0.4 and 0.6 according to Bonan (2019) doi:10.1017/9781107339217 pg. 238 diff --git a/parameter_files/archive/api33.0.0_020524_patch_params.xml b/parameter_files/archive/api33.0.0_020524_patch_params.xml index 8beff2ff42..d2c6858308 100644 --- a/parameter_files/archive/api33.0.0_020524_patch_params.xml +++ b/parameter_files/archive/api33.0.0_020524_patch_params.xml @@ -66,5 +66,25 @@ Parameter 2 for h2cd allometry (log-slope or exponent). If allom_dmode=1; this is not needed (as exponent is assumed 1) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + + fates_cnp_eca_alpha_ptase + + + fates_cnp_eca_lambda_ptase + + + fates_cnp_eca_alpha_ptase + fates_pft + g/m3 + (INACTIVE, KEEP AT 0) fraction of P from ptase activity sent directly to plant (ECA) + 0,0,0,0,0,0,0,0,0,0,0,0 + + + fates_cnp_eca_lambda_ptase + fates_pft + g/m3 + (INACTIVE, KEEP AT 0) critical value for biochemical production (ECA) + 0,0,0,0,0,0,0,0,0,0,0,0 + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index b34d9475d1..1ecbb13725 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -179,7 +179,7 @@ variables: fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; double fates_cnp_eca_alpha_ptase(fates_pft) ; fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + fates_cnp_eca_alpha_ptase:long_name = "(INACTIVE, KEEP AT 0) fraction of P from ptase activity sent directly to plant (ECA)" ; double fates_cnp_eca_decompmicc(fates_pft) ; fates_cnp_eca_decompmicc:units = "gC/m3" ; fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; @@ -197,7 +197,7 @@ variables: fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; double fates_cnp_eca_lambda_ptase(fates_pft) ; fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + fates_cnp_eca_lambda_ptase:long_name = "(INACTIVE, KEEP AT 0) critical value for biochemical production (ECA)" ; double fates_cnp_eca_vmax_ptase(fates_pft) ; fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; @@ -1062,8 +1062,7 @@ data: fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; + fates_cnp_eca_alpha_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; @@ -1079,7 +1078,7 @@ data: fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_eca_lambda_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; From 8ef1711f8805de40e3a782c1b74c9edf8a8695f0 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 9 Feb 2024 12:45:26 -0700 Subject: [PATCH 094/300] cleaning up l2fr history entries --- main/FatesHistoryInterfaceMod.F90 | 102 +++++++++++------------------- 1 file changed, 37 insertions(+), 65 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index e61a4b7c08..926567b7cb 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2081,7 +2081,6 @@ subroutine update_history_nutrflux(this,csite) integer :: el ! element loop index integer :: ft ! pft loop index real(r8):: uconv ! combined unit conversion factor - real(r8) :: fnrtc_si ! site level fine-root c real(r8) :: fnrt_c ! cohort fine-root c ! Process variables with time-space dimensions only @@ -2089,10 +2088,6 @@ subroutine update_history_nutrflux(this,csite) if_dynam1: if(hlm_hist_level_dynam>0) then - associate(hio_l2fr_si => this%hvars(ih_l2fr_si)%r81d) - - fnrtc_si = 0._r8 - ! history site index io_si = csite%h_gid @@ -2113,11 +2108,6 @@ subroutine update_history_nutrflux(this,csite) fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - hio_l2fr_si(io_si) = hio_l2fr_si(io_si) + ccohort%n*fnrt_c*ccohort%l2fr - - ! These are used for normalizing weighted averages - fnrtc_si = fnrtc_si + ccohort%n*fnrt_c - ! Loop over the different elements. do el = 1, num_elements @@ -2179,13 +2169,6 @@ subroutine update_history_nutrflux(this,csite) cpatch => cpatch%older end do - if(fnrtc_si>nearzero)then - hio_l2fr_si(io_si) = hio_l2fr_si(io_si)/fnrtc_si - else - hio_l2fr_si(io_si) = hlm_hio_ignore_val - end if - - end associate end if if_dynam1 ! Process multiplexed variables @@ -2193,9 +2176,6 @@ subroutine update_history_nutrflux(this,csite) if_dynam2: if(hlm_hist_level_dynam>1) then - associate( & - hio_recl2fr_canopy_pf => this%hvars(ih_recl2fr_canopy_pf)%r82d, & - hio_recl2fr_ustory_pf => this%hvars(ih_recl2fr_ustory_pf)%r82d ) ! history site index io_si = csite%h_gid @@ -2278,12 +2258,6 @@ subroutine update_history_nutrflux(this,csite) cpatch => cpatch%older end do - do ft = 1,numpft - hio_recl2fr_canopy_pf(io_si,ft) = csite%rec_l2fr(ft,1) - hio_recl2fr_ustory_pf(io_si,ft) = csite%rec_l2fr(ft,2) - end do - - end associate end if if_dynam2 return @@ -2418,7 +2392,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) real(r8) :: repro_m_net_alloc ! mass allocated to reproduction [kg/yr] real(r8) :: n_perm2 ! abundance per m2 real(r8) :: area_frac ! Fraction of area for this patch - + associate( hio_npatches_si => this%hvars(ih_npatches_si)%r81d, & hio_npatches_sec_si => this%hvars(ih_npatches_sec_si)%r81d, & hio_ncohorts_si => this%hvars(ih_ncohorts_si)%r81d, & @@ -2759,7 +2733,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) if ( cpatch%land_use_label .eq. secondaryland ) then hio_ncohorts_sec_si(io_si) = hio_ncohorts_sec_si(io_si) + 1._r8 end if - + ! Update biomass components ! Mass pools [kg] elloop: do el = 1, num_elements @@ -2815,6 +2789,13 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) total_m * ccohort%n * AREA_INV endif + if( hlm_parteh_mode == prt_cnp_flex_allom_hyp) then + this%hvars(ih_l2fr_si)%r81d(io_si) = & + this%hvars(ih_l2fr_si)%r81d(io_si) + & + ccohort%l2fr *ccohort%n * fnrt_m / m2_per_ha + end if + + elseif(element_list(el).eq.nitrogen_element)then store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) @@ -3010,16 +2991,18 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) end if end do elloop2 + if(this%hvars(ih_fnrtc_si)%r81d(io_si)>nearzero)then + this%hvars(ih_l2fr_si)%r81d(io_si) = this%hvars(ih_l2fr_si)%r81d(io_si) / & + this%hvars(ih_fnrtc_si)%r81d(io_si) + else + this%hvars(ih_l2fr_si)%r81d(io_si) = hlm_hio_ignore_val + end if - - + ! zero the site-level termination carbon flux variable sites(s)%term_carbonflux_canopy(:,:) = 0._r8 sites(s)%term_carbonflux_ustory(:,:) = 0._r8 - - - end do siteloop end associate @@ -3317,7 +3300,6 @@ 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) - model_day_int = nint(hlm_model_day) ! --------------------------------------------------------------------------------- @@ -4779,11 +4761,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) end do ! end element loop - - ! Normalize storage fractions and L2FR - - - do ft = 1, numpft do i_scls = 1,nlevsclass i_scpf = (ft-1)*nlevsclass + i_scls @@ -4850,9 +4827,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_demotion_rate_si_scls(io_si,i_scls) = sites(s)%demotion_rate(i_scls) * days_per_year / m2_per_ha hio_promotion_rate_si_scls(io_si,i_scls) = sites(s)%promotion_rate(i_scls) * days_per_year / m2_per_ha end do - ! - - ! ! add the site-level disturbance-associated cwd and litter input fluxes to thir respective flux fields @@ -4864,7 +4838,14 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) flux_diags_c%cwd_bg_input(i_cwd) / days_per_year / sec_per_day end do - + + if( hlm_parteh_mode == prt_cnp_flex_allom_hyp) then + do ft = 1,numpft + this%hvars(ih_recl2fr_canopy_pf)%r82d(io_si,ft) = sites(s)%rec_l2fr(ft,1) + this%hvars(ih_recl2fr_ustory_pf)%r82d(io_si,ft) = sites(s)%rec_l2fr(ft,2) + end do + end if + enddo siteloop ! site loop end associate @@ -6428,14 +6409,15 @@ subroutine define_history_vars(this, initialize_variables) index = ih_reproc_si) ! Output specific to the chemical species dynamics used (parteh) - select case(hlm_parteh_mode) - case (prt_cnp_flex_allom_hyp) - + if( hlm_parteh_mode == prt_cnp_flex_allom_hyp) then call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & long='The leaf to fineroot biomass multiplier for target allometry', & use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) + end if + + nitrogen_active_if0: if(any(element_list(:)==nitrogen_element)) then call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & long='ammonium uptake rate by plants in kg NH4 per m2 per second', & @@ -6466,10 +6448,7 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index = ih_nfix_si) - - end select - - nitrogen_active_if0: if(any(element_list(:)==nitrogen_element)) then + call this%set_history_var(vname='FATES_STOREN', units='kg m-2', & long='total nitrogen in live plant storage', use_default='active', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & @@ -7125,23 +7104,16 @@ subroutine define_history_vars(this, initialize_variables) ivar=ivar, initialize=initialize_variables, index = ih_storectfrac_canopy_scpf ) - - call this%set_history_var(vname='FATES_FROOTC_SL', units='kg m-3', & long='Total carbon in live plant fine-roots over depth', use_default='active', & avgflag='A', vtype=site_soil_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & ivar=ivar, initialize=initialize_variables, index = ih_fnrtc_sl ) - - - ! Output specific to the chemical species dynamics used (parteh) - select case(hlm_parteh_mode) - case (prt_cnp_flex_allom_hyp) - - call this%set_history_var(vname='FATES_L2FR_CANOPY_REC_PF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for recruits (canopy)', & + if( hlm_parteh_mode == prt_cnp_flex_allom_hyp) then + call this%set_history_var(vname='FATES_L2FR_CANOPY_REC_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (canopy)', & use_default='active', & avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) @@ -7158,6 +7130,10 @@ subroutine define_history_vars(this, initialize_variables) ! avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & ! ivar=ivar, initialize=initialize_variables, index = ih_l2fr_clscpf) + end if + + nitrogen_active_if1: if(any(element_list(:)==nitrogen_element)) then + call this%set_history_var(vname='FATES_NH4UPTAKE_SZPF', & units='kg m-2 s-1', & long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & @@ -7189,11 +7165,7 @@ subroutine define_history_vars(this, initialize_variables) use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & initialize=initialize_variables, index = ih_nfix_scpf) - - end select - - nitrogen_active_if1: if(any(element_list(:)==nitrogen_element)) then - + call this%set_history_var(vname='FATES_VEGN_SZPF', units='kg m-2', & long='total (live) vegetation nitrogen mass by size-class x pft in kg N per m2', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & From 2fa63533c961449ecbbbd3209adb4229cde35ce7 Mon Sep 17 00:00:00 2001 From: jenniferholm Date: Tue, 13 Feb 2024 21:19:56 -0800 Subject: [PATCH 095/300] adding user switch for turning on and off daylength factor scalingfor photosynthesis parameters --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 31 ++++++++++++++++++++-- main/EDParamsMod.F90 | 13 ++++++++- parameter_files/fates_params_default.cdl | 5 ++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 744e43ec16..1d947d74bb 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -62,6 +62,7 @@ module FATESPlantRespPhotosynthMod use EDParamsMod, only : maintresp_nonleaf_baserate use EDParamsMod, only : stomatal_model use EDParamsMod, only : stomatal_assim_model + use EDParamsMod, only : dayl_switch use EDParamsMod, only : photo_tempsens_model use PRTParametersMod, only : prt_params use EDPftvarcon , only : EDPftvarcon_inst @@ -109,6 +110,10 @@ module FATESPlantRespPhotosynthMod integer, parameter :: medlyn_model = 2 integer, parameter :: ballberry_model = 1 + ! Constants used to define day_length switch for scaling photosynthetic parameters + integer, parameter :: dayl_on = 1 + integer, parameter :: dayl_off = 2 + ! Alternatively, Gross Assimilation can be used to estimate ! leaf co2 partial pressure and therefore conductance. The default ! is to use anet @@ -595,6 +600,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) nscaler, & ! in ft, & ! in bc_in(s)%t_veg_pa(ifp), & ! in + bc_in(s)%dayl_factor_pa(ifp), & ! in currentPatch%tveg_lpa%GetMean(), & ! in lmr_z(iv,ft,cl)) ! out @@ -680,6 +686,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) currentCohort%kp25top, & ! in nscaler, & ! in bc_in(s)%t_veg_pa(ifp), & ! in + bc_in(s)%dayl_factor_pa(ifp), & ! in currentPatch%tveg_lpa%GetMean(), & ! in currentPatch%tveg_longterm%GetMean(),& ! in btran_eff, & ! in @@ -2325,6 +2332,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & nscaler, & ft, & veg_tempk, & + dayl_factor, & tgrowth, & lmr) @@ -2343,6 +2351,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & integer, intent(in) :: ft ! (plant) Functional Type Index real(r8), intent(in) :: nscaler ! Scale for leaf nitrogen profile real(r8), intent(in) :: veg_tempk ! vegetation temperature (degrees K) + real(r8), intent(in) :: dayl_factor ! daylength scaling factor (0-1) real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale (degrees K) real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) @@ -2386,6 +2395,7 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & co2_rcurve_islope25top_ft, & nscaler, & veg_tempk, & + dayl_factor, & t_growth, & t_home, & btran, & @@ -2421,6 +2431,7 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & real(r8), intent(in) :: co2_rcurve_islope25top_ft ! initial slope of CO2 response curve ! (C4 plants) at 25C, canopy top, this pft real(r8), intent(in) :: veg_tempk ! vegetation temperature + real(r8), intent(in) :: dayl_factor ! daylength scaling factor (0-1) real(r8), intent(in) :: t_growth ! T_growth (short-term running mean temperature) (K) real(r8), intent(in) :: t_home ! T_home (long-term running mean temperature) (K) real(r8), intent(in) :: btran ! transpiration wetness factor (0 to 1) @@ -2486,11 +2497,12 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & co2_rcurve_islope = 0._r8 else ! day time + if ( dayl_switch == dayl_on ) then ! Vcmax25top was already calculated to derive the nscaler function - vcmax25 = vcmax25top_ft * nscaler + vcmax25 = vcmax25top_ft * nscaler * dayl_factor select case(photo_tempsens_model) case (photosynth_acclim_model_none) - jmax25 = jmax25top_ft * nscaler + jmax25 = jmax25top_ft * nscaler * dayl_factor case (photosynth_acclim_model_kumarathunge_etal_2019) jmax25 = vcmax25*jvr case default @@ -2498,6 +2510,21 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & call endrun(msg=errMsg(sourcefile, __LINE__)) end select + else if ( dayl_switch == dayl_off ) then + ! Vcmax25top was already calculated to derive the nscaler function + vcmax25 = vcmax25top_ft * nscaler + select case(photo_tempsens_model) + case (photosynth_acclim_model_none) + jmax25 = jmax25top_ft * nscaler + case (photosynth_acclim_model_kumarathunge_etal_2019) + jmax25 = vcmax25*jvr + case default + write (fates_log(),*)'error, incorrect leaf photosynthesis temperature acclimation model specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + end if + co2_rcurve_islope25 = co2_rcurve_islope25top_ft * nscaler ! Adjust for temperature diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 71cc21af73..6eda5d6115 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -77,6 +77,7 @@ module EDParamsMod real(r8),protected, public :: ED_val_patch_fusion_tol ! minimum fraction in difference in profiles between patches real(r8),protected, public :: ED_val_canopy_closure_thresh ! site-level canopy closure point where trees take on forest (narrow) versus savannah (wide) crown allometry integer,protected, public :: stomatal_model ! switch for choosing between stomatal conductance models, 1 for Ball-Berry, 2 for Medlyn + integer,protected, public :: dayl_switch ! switch for turning on or off day length factor scaling for photosynthetic parameters integer,protected, public :: regeneration_model ! Switch for choosing between regeneration models: ! (1) for Fates default ! (2) for the Tree Recruitment Scheme (Hanbury-Brown et al., 2022) @@ -166,6 +167,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_patch_fusion_tol= "fates_patch_fusion_tol" character(len=param_string_length),parameter,public :: ED_name_canopy_closure_thresh= "fates_canopy_closure_thresh" character(len=param_string_length),parameter,public :: ED_name_stomatal_model= "fates_leaf_stomatal_model" + character(len=param_string_length),parameter,public :: ED_name_dayl_switch= "fates_daylength_factor_switch" character(len=param_string_length),parameter,public :: ED_name_regeneration_model= "fates_regeneration_model" character(len=param_string_length),parameter,public :: name_theta_cj_c3 = "fates_leaf_theta_cj_c3" @@ -338,6 +340,7 @@ subroutine FatesParamsInit() ED_val_patch_fusion_tol = nan ED_val_canopy_closure_thresh = nan stomatal_model = -9 + dayl_switch = -9 regeneration_model = -9 stomatal_assim_model = -9 max_cohort_per_patch = -9 @@ -493,6 +496,9 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_stomatal_model, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=ED_name_dayl_switch, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) call fates_params%RegisterParameter(name=ED_name_regeneration_model, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -715,6 +721,10 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) stomatal_model = nint(tmpreal) + call fates_params%RetrieveParameter(name=ED_name_dayl_switch, & + data=tmpreal) + dayl_switch = nint(tmpreal) + call fates_params%RetrieveParameter(name=ED_name_regeneration_model, & data=tmpreal) regeneration_model = nint(tmpreal) @@ -882,7 +892,8 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_cohort_age_fusion_tol = ',ED_val_cohort_age_fusion_tol write(fates_log(),fmt0) 'ED_val_patch_fusion_tol = ',ED_val_patch_fusion_tol write(fates_log(),fmt0) 'ED_val_canopy_closure_thresh = ',ED_val_canopy_closure_thresh - write(fates_log(),fmt0) 'regeneration_model = ',regeneration_model + write(fates_log(),fmt0) 'regeneration_model = ',regeneration_model + write(fates_log(),fmt0) 'dayl_switch = ',dayl_switch write(fates_log(),fmt0) 'stomatal_model = ',stomatal_model write(fates_log(),fmt0) 'stomatal_assim_model = ',stomatal_assim_model write(fates_log(),fmt0) 'hydro_kmax_rsurf1 = ',hydr_kmax_rsurf1 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 99bdaed02e..f664793c47 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -249,6 +249,9 @@ variables: double fates_damage_recovery_scalar(fates_pft) ; fates_damage_recovery_scalar:units = "unitless" ; fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; + double fates_daylength_factor_switch ; + fates_daylength_factor_switch:units = "unitless" ; + fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (2) the day length factor scaling for photosynthetic parameters" ; double fates_dev_arbitrary_pft(fates_pft) ; fates_dev_arbitrary_pft:units = "unknown" ; fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; @@ -1613,6 +1616,8 @@ data: fates_damage_event_code = 1 ; + fates_daylength_factor_switch = 1 ; + fates_dev_arbitrary = _ ; fates_fire_active_crown_fire = 0 ; From 40e5f9313eaa4e42548da4135ff5507407092a5a Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Sat, 17 Feb 2024 15:59:30 -0800 Subject: [PATCH 096/300] bugfix for edge case where all litter is trunk --- fire/SFMainMod.F90 | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index ef245b04f9..7ff02bbc27 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -47,6 +47,7 @@ module SFMainMod use PRTGenericMod, only : SetState use FatesInterfaceTypesMod , only : numpft use FatesAllometryMod, only : CrownDepth + use FatesConstantsMod, only : nearzero implicit none private @@ -295,10 +296,12 @@ subroutine charecteristics_of_fuel ( currentSite ) ! Correct averaging for the fact that we are not using the trunks pool for fire ROS and intensity (5) ! Consumption of fuel in trunk pool does not influence fire ROS or intensity (Pyne 1996) - currentPatch%fuel_bulkd = currentPatch%fuel_bulkd * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) - currentPatch%fuel_sav = currentPatch%fuel_sav * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) - currentPatch%fuel_mef = currentPatch%fuel_mef * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) - currentPatch%fuel_eff_moist = currentPatch%fuel_eff_moist * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) + if ( (1.0_r8-currentPatch%fuel_frac(tr_sf)) .gt. nearzero ) then + currentPatch%fuel_bulkd = currentPatch%fuel_bulkd * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) + currentPatch%fuel_sav = currentPatch%fuel_sav * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) + currentPatch%fuel_mef = currentPatch%fuel_mef * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) + currentPatch%fuel_eff_moist = currentPatch%fuel_eff_moist * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) + endif ! Pass litter moisture into the fuel burning routine (all fuels: twigs,s branch,l branch,trunk,dead leaves,live grass) ! (wo/me term in Thonicke et al. 2010) From 2e8608cfa24fb006eef8b9112eb91d3265e687e4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 22 Feb 2024 16:04:58 -0500 Subject: [PATCH 097/300] Added protections to Campbell Clapp-Hornberger water transfer functions so that it will tolerate incredibly small water contents --- biogeophys/FatesHydroWTFMod.F90 | 43 ++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/biogeophys/FatesHydroWTFMod.F90 b/biogeophys/FatesHydroWTFMod.F90 index 8356b2b165..ea5ac7aba0 100644 --- a/biogeophys/FatesHydroWTFMod.F90 +++ b/biogeophys/FatesHydroWTFMod.F90 @@ -44,6 +44,8 @@ module FatesHydroWTFMod ! elastic-caviation region + real(r8), parameter :: min_psi_cch = -9._r8 ! Minimum psi we are willing to track in cch + ! Generic class that can be extended to describe ! specific water retention functions @@ -146,6 +148,7 @@ module FatesHydroWTFMod ! Water Retention Function type, public, extends(wrf_type) :: wrf_type_cch real(r8) :: th_sat ! Saturation volumetric water content [m3/m3] + real(r8) :: th_res ! Residual volumetric water content [m3/m3] real(r8) :: psi_sat ! Bubbling pressure (potential at saturation) [Mpa] real(r8) :: beta ! Clapp-Hornberger "beta" parameter [-] contains @@ -174,6 +177,7 @@ module FatesHydroWTFMod ! Water Retention Function type, public, extends(wrf_type) :: wrf_type_smooth_cch real(r8) :: th_sat ! Saturation volumetric water content [m3/m3] + real(r8) :: th_res ! Residual volumetric water content [m3/m3] real(r8) :: psi_sat ! Bubbling pressure (potential at saturation) [Mpa] real(r8) :: beta ! Clapp-Hornberger "beta" parameter [-] real(r8) :: scch_pu ! An estimated breakpoint capillary pressure, below which the specified water retention curve is applied. It is also the lower limit when the smoothing function is applied. [Mpa] @@ -710,10 +714,11 @@ subroutine set_wrf_param_cch(this,params_in) this%th_max = max_sf_interp*this%th_sat this%psi_max = this%psi_from_th(this%th_max-tiny(this%th_max)) this%dpsidth_max = this%dpsidth_from_th(this%th_max-tiny(this%th_max)) - this%th_min = fates_unset_r8 - this%psi_min = fates_unset_r8 - this%dpsidth_min = fates_unset_r8 + this%psi_min = min_psi_cch + this%th_min = this%th_from_psi(min_psi_cch+tiny(this%th_max)) + this%dpsidth_min = this%dpsidth_from_th(this%th_min+tiny(this%th_max)) + return end subroutine set_wrf_param_cch @@ -751,8 +756,12 @@ function th_from_psi_cch(this,psi) result(th) if(psi>this%psi_max) then ! Linear range for extreme values th = this%th_max + (psi-this%psi_max)/this%dpsidth_max - else - th = this%th_sat*(psi/this%psi_sat)**(-1.0_r8/this%beta) + else + if(psithis%th_max) then psi = this%psi_max + this%dpsidth_max*(th-max_sf_interp*this%th_sat) - else - psi = this%psi_sat*(th/this%th_sat)**(-this%beta) + else + if(ththis%th_max) then - dpsidth = this%dpsidth_max + dpsidth = this%dpsidth_max else - dpsidth = -this%beta*this%psi_sat/this%th_sat * (th/this%th_sat)**(-this%beta-1._r8) + if(th Date: Thu, 22 Feb 2024 16:23:08 -0500 Subject: [PATCH 098/300] reverting the cap on the smoothed cch function, it already has a protection --- biogeophys/FatesHydroWTFMod.F90 | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/biogeophys/FatesHydroWTFMod.F90 b/biogeophys/FatesHydroWTFMod.F90 index ea5ac7aba0..e1f1a40df2 100644 --- a/biogeophys/FatesHydroWTFMod.F90 +++ b/biogeophys/FatesHydroWTFMod.F90 @@ -148,7 +148,6 @@ module FatesHydroWTFMod ! Water Retention Function type, public, extends(wrf_type) :: wrf_type_cch real(r8) :: th_sat ! Saturation volumetric water content [m3/m3] - real(r8) :: th_res ! Residual volumetric water content [m3/m3] real(r8) :: psi_sat ! Bubbling pressure (potential at saturation) [Mpa] real(r8) :: beta ! Clapp-Hornberger "beta" parameter [-] contains @@ -177,7 +176,6 @@ module FatesHydroWTFMod ! Water Retention Function type, public, extends(wrf_type) :: wrf_type_smooth_cch real(r8) :: th_sat ! Saturation volumetric water content [m3/m3] - real(r8) :: th_res ! Residual volumetric water content [m3/m3] real(r8) :: psi_sat ! Bubbling pressure (potential at saturation) [Mpa] real(r8) :: beta ! Clapp-Hornberger "beta" parameter [-] real(r8) :: scch_pu ! An estimated breakpoint capillary pressure, below which the specified water retention curve is applied. It is also the lower limit when the smoothing function is applied. [Mpa] @@ -932,11 +930,9 @@ subroutine set_wrf_param_smooth_cch(this,params_in) this%th_max = max_sf_interp*this%th_sat this%psi_max = this%psi_from_th(this%th_max-tiny(this%th_max)) this%dpsidth_max = this%dpsidth_from_th(this%th_max-tiny(this%th_max)) - - this%psi_min = min_psi_cch - this%th_min = this%th_from_psi(min_psi_cch+tiny(this%th_max)) - this%dpsidth_min = this%dpsidth_from_th(this%th_min+tiny(this%th_max)) - + this%th_min = fates_unset_r8 + this%psi_min = fates_unset_r8 + this%dpsidth_min = fates_unset_r8 return end subroutine set_wrf_param_smooth_cch @@ -1056,8 +1052,7 @@ function th_from_psi_smooth_cch(this,psi) result(th) sat = 1.d0 endif th = sat * this%th_sat - - + return end function th_from_psi_smooth_cch @@ -1214,7 +1209,7 @@ function dpsidth_from_th_smooth_cch(this,th) result(dpsidth) sat_res = 0._r8 alpha = -1._r8/this%psi_sat lambda = 1._r8/this%beta - + pc = 1._r8 * this%psi_from_th(th) if( pc <= this%scch_pu ) then ! Unsaturated full Brooks-Corey regime. From 6e5b86501b80bd054f4b7cc086adb963bf7428cd Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 22 Feb 2024 10:56:20 -0800 Subject: [PATCH 099/300] further bigfixes to fire edge case in which all fuel is trunk --- fire/SFMainMod.F90 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 7ff02bbc27..54456c9f0d 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -301,6 +301,12 @@ subroutine charecteristics_of_fuel ( currentSite ) currentPatch%fuel_sav = currentPatch%fuel_sav * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) currentPatch%fuel_mef = currentPatch%fuel_mef * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) currentPatch%fuel_eff_moist = currentPatch%fuel_eff_moist * (1.0_r8/(1.0_r8-currentPatch%fuel_frac(tr_sf))) + else + ! somehow the fuel is all trunk. put dummy values from large branches so as not to break things later in code. + currentPatch%fuel_bulkd = SF_val_FBD(lb_sf) + currentPatch%fuel_sav = SF_val_SAV(lb_sf) + currentPatch%fuel_mef = MEF(lb_sf) + currentPatch%fuel_eff_moist = fuel_moisture(lb_sf) endif ! Pass litter moisture into the fuel burning routine (all fuels: twigs,s branch,l branch,trunk,dead leaves,live grass) From d3c13f048eda75f139e8172cd2b3d7520976c2d2 Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Thu, 22 Feb 2024 13:24:17 -0800 Subject: [PATCH 100/300] bugfix to prevent crashes when inserting patch at end of linked list --- biogeochem/EDPatchDynamicsMod.F90 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3bd71249c7..94e04b9ecc 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1438,7 +1438,11 @@ subroutine spawn_patches( currentSite, bc_in) if (fraction_to_keep .le. nearzero) then ! we don't want any patch area with this PFT identity at all anymore. Fuse it into the buffer patch. currentPatch%nocomp_pft_label = 0 - previousPatch => currentPatch%older + if (associated(currentPatch%older)) then + previousPatch => currentPatch%older + else + previousPatch => currentPatch + endif call fuse_2_patches(currentSite, currentPatch, buffer_patch) currentPatch => previousPatch @@ -1470,6 +1474,7 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch%changed_landuse_this_ts = .false. endif end if + currentPatch => currentPatch%younger end do @@ -1559,6 +1564,7 @@ subroutine spawn_patches( currentSite, bc_in) write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' write(fates_log(),*) 'buffer_patch%area', buffer_patch%area write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)), sum(nocomp_pft_area_vector(:)) + write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:)) call endrun(msg=errMsg(sourcefile, __LINE__)) end if else From bb558c6328d6535e8c690b57a495b6ddaa878f0f Mon Sep 17 00:00:00 2001 From: jessica needham Date: Tue, 27 Feb 2024 14:58:05 -0800 Subject: [PATCH 101/300] update param names and add rdark vert scaling 1 param --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 8 +++++--- main/EDPftvarcon.F90 | 24 +++++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index e162ec5419..4855cc910c 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2165,7 +2165,8 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & real(r8) :: lmr25top ! canopy top leaf maint resp rate at 25C for this pft (umol CO2/m**2/s) real(r8) :: rdark_scaler ! negative exponential scaling of rdark real(r8) :: kn ! decay coefficient - real(r8) :: rdark_decay ! determines rate of rdark decay through canopy + real(r8) :: rdark_vert_scaler1 ! determines rate of rdark decay through canopy + real(r8) :: rdark_vert_scaler2 ! determines rate of rdark decay through canopy ! parameter values of r_0 as listed in Atkin et al 2017: (umol CO2/m**2/s) @@ -2179,7 +2180,8 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! r_0 currently put into the EDPftvarcon_inst%dev_arbitrary_pft ! all figs in Atkin et al 2017 stop at zero Celsius so we will assume acclimation is fixed below that r_0 = EDPftvarcon_inst%maintresp_leaf_atkin2017_baserate(ft) - rdark_decay = EDPftvarcon_inst%maintresp_leaf_decay(ft) + rdark_vert_scaler1 = EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff1(ft) + rdark_vert_scaler2 = EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff2(ft) ! This code uses the relationship between leaf N and respiration from Atkin et al ! for the top of the canopy, but then scales through the canopy based on a rdark_scaler. @@ -2189,7 +2191,7 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! this number can be smaller. There is some observational evidence for this being the case ! in Lamour et al. 2023. - kn = exp(0.00963_r8 * vcmax25top - rdark_decay) + kn = exp(rdark_vert_scaler1 * vcmax25top - rdark_vert_scaler2) rdark_scaler = exp(-kn * cumulative_lai) r_t_ref = max(0._r8, rdark_scaler * (r_0 + lmr_r_1 * lnc_top + lmr_r_2 * max(0._r8, (tgrowth - tfrz) )) ) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 9e44cc0218..5962666bcb 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -89,8 +89,10 @@ module EDPftvarcon ! per Atkin et al 2017 real(r8), allocatable :: maintresp_leaf_ryan1991_baserate(:) ! leaf maintenance respiration per Ryan et al 1991 - real(r8), allocatable :: maintresp_leaf_decay(:) ! leaf maintenance respiration decrease through the canopy - ! only with Atkin et al. 2017 + real(r8), allocatable :: maintresp_leaf_vert_scaler_coeff1(:) ! leaf maintenance respiration decrease through the canopy param 1 + ! only with Atkin et al. 2017 respiration model + real(r8), allocatable :: maintresp_leaf_vert_scaler_coeff2(:) ! leaf maintenance respiration decrease through the canopy param 2 + ! only with Atkin et al. 2017 respiraiton model real(r8), allocatable :: bmort(:) real(r8), allocatable :: mort_ip_size_senescence(:) ! inflection point of dbh dependent senescence @@ -471,10 +473,14 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_maintresp_leaf_decay' + name = 'fates_maintresp_leaf_vert_scaler_coeff1' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - + + name = 'fates_maintresp_leaf_vert_scaler_coeff2' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_prescribed_npp_canopy' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -916,10 +922,14 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%maintresp_leaf_ryan1991_baserate) - name = 'fates_maintresp_leaf_decay' + name = 'fates_maintresp_leaf_vert_scaler_coeff1' call fates_params%RetrieveParameterAllocate(name=name, & - data=this%maintresp_leaf_decay) - + data=this%maintresp_leaf_vert_scaler_coeff1) + + name = 'fates_maintresp_leaf_vert_scaler_coeff2' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%maintresp_leaf_vert_scaler_coeff2) + name = 'fates_prescribed_npp_canopy' call fates_params%RetrieveParameterAllocate(name=name, & data=this%prescribed_npp_canopy) From d0a05daa95f236eca039479fafba744c6a23d9d1 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Tue, 27 Feb 2024 15:02:07 -0800 Subject: [PATCH 102/300] update the parameter file --- parameter_files/fates_params_default.cdl | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index f4fb48202e..a762c79e54 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -386,10 +386,13 @@ variables: fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; - fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; - double fates_maintresp_leaf_decay(fates_pft) ; - fates_maintresp_leaf_decay:units = "unitless" ; - fates_maintresp_leaf_decay:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the default value of 2.43." ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_leaf_vert_scaler_coeff1(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff1:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff1:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the default value of 0.00963." ; + double fates_maintresp_leaf_vert_scaler_coeff2(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff2:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the default value of 2.43." ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -1313,7 +1316,10 @@ data: 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06 ; - fates_maintresp_leaf_decay = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, + fates_maintresp_leaf_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; + + fates_maintresp_leaf_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, From 5c8662a73d29e52b8c21f3170c92024887079dfb Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 28 Feb 2024 12:51:03 -0500 Subject: [PATCH 103/300] changed namelist interface name for history dim levels --- main/FatesInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 50588b776d..3c2093fa37 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -1971,13 +1971,13 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_use_inventory_init= ',ival,' to FATES' end if - case('hist_hifrq_dense_level') + case('hist_hifrq_dimlevel') hlm_hist_level_hifrq = ival if (fates_global_verbose()) then write(fates_log(),*) 'Transfering hlm_hist_level_hifrq= ',ival,' to FATES' end if - case('hist_dynam_dense_level') + case('hist_dynam_dimlevel') hlm_hist_level_dynam = ival if (fates_global_verbose()) then write(fates_log(),*) 'Transfering hlm_hist_level_dynam= ',ival,' to FATES' From d37d9733b5970dfe67a0b78f6bd35d6ceb1a623d Mon Sep 17 00:00:00 2001 From: Charles D Koven Date: Sun, 3 Mar 2024 13:38:43 -0800 Subject: [PATCH 104/300] various fixes to edge cases encountered --- biogeochem/EDPatchDynamicsMod.F90 | 89 +++++++++++++++++++++++++------ main/FatesRunningMeanMod.F90 | 3 ++ 2 files changed, 76 insertions(+), 16 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 94e04b9ecc..e610e7c22a 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1508,9 +1508,9 @@ subroutine spawn_patches( currentSite, bc_in) ! newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) ! only bother doing this if the new new patch area needed is greater than some tiny amount - if ( newp_area .gt. rsnbl_math_prec) then + if ( newp_area .gt. rsnbl_math_prec * 0.01_r8) then ! - if (buffer_patch%area - newp_area .gt. rsnbl_math_prec) then + if (buffer_patch%area - newp_area .gt. rsnbl_math_prec * 0.01_r8) then ! split buffer patch in two, keeping the smaller buffer patch to put into new patches allocate(temp_patch) @@ -1553,7 +1553,7 @@ subroutine spawn_patches( currentSite, bc_in) if (buffer_patch_in_linked_list) then buffer_patch => null() else if (buffer_patch%area .lt. rsnbl_math_prec) then - ! here we need to deallocate the buffer patch so that we don't get a memory leak/ + ! here we need to deallocate the buffer patch so that we don't get a memory leak. call buffer_patch%FreeMemory(regeneration_model, numpft) deallocate(buffer_patch, stat=istat, errmsg=smsg) if (istat/=0) then @@ -1565,6 +1565,7 @@ subroutine spawn_patches( currentSite, bc_in) write(fates_log(),*) 'buffer_patch%area', buffer_patch%area write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)), sum(nocomp_pft_area_vector(:)) write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:)) + call endrun(msg=errMsg(sourcefile, __LINE__)) end if else @@ -3214,7 +3215,7 @@ subroutine fuse_2_patches(csite, dp, rp) + rp%age_since_anthro_disturbance * rp%area) * inv_sum_area rp%age_class = get_age_class_index(rp%age) - + do el = 1,num_elements call rp%litter(el)%FuseLitter(rp%area,dp%area,dp%litter(el)) end do @@ -3390,15 +3391,18 @@ subroutine terminate_patches(currentSite, bc_in) type(fates_patch_type), pointer :: olderPatch type(fates_patch_type), pointer :: youngerPatch type(fates_patch_type), pointer :: patchpointer + type(fates_patch_type), pointer :: largest_patch integer, parameter :: max_cycles = 10 ! After 10 loops through ! You should had fused integer :: count_cycles logical :: gotfused logical :: current_patch_is_youngest_lutype integer :: i_landuse, i_pft + integer :: land_use_type_to_remove real(r8) areatot ! variable for checking whether the total patch area is wrong. - real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] + real(r8) :: state_vector_driver(n_landuse_cats) ! [m2/m2] + real(r8) :: state_vector_internal(n_landuse_cats) ! [m2/m2] !--------------------------------------------------------------------- ! Initialize the count cycles @@ -3551,23 +3555,76 @@ subroutine terminate_patches(currentSite, bc_in) write(fates_log(),*) patchpointer%area, patchpointer%nocomp_pft_label, patchpointer%land_use_label patchpointer => patchpointer%older end do - call get_current_landuse_statevector(currentSite, state_vector) - write(fates_log(),*) 'current landuse state vector: ', state_vector - write(fates_log(),*) 'current landuse state vector (not including bare gruond): ', state_vector/(1._r8-currentSite%area_bareground) - call get_luh_statedata(bc_in, state_vector) - write(fates_log(),*) 'driver data landuse state vector: ', state_vector + call get_current_landuse_statevector(currentSite, state_vector_internal) + write(fates_log(),*) 'current landuse state vector: ', state_vector_internal + write(fates_log(),*) 'current landuse state vector (not including bare gruond): ', state_vector_internal/(1._r8-currentSite%area_bareground) + call get_luh_statedata(bc_in, state_vector_driver) + write(fates_log(),*) 'driver data landuse state vector: ', state_vector_driver write(fates_log(),*) 'min_allowed_landuse_fraction: ', currentSite%min_allowed_landuse_fraction write(fates_log(),*) 'landuse_vector_gt_min: ', currentSite%landuse_vector_gt_min do i_landuse = 1, n_landuse_cats write(fates_log(),*) 'trans matrix from: ', i_landuse, currentSite%landuse_transition_matrix(i_landuse,:) end do - call endrun(msg=errMsg(sourcefile, __LINE__)) + + if ( (state_vector_driver(currentPatch%land_use_label) .lt. currentSite%min_allowed_landuse_fraction ) .or. & + (state_vector_internal(currentPatch%land_use_label) .lt. currentSite%min_allowed_landuse_fraction ) ) then + + ! try fusing all of the patches with this land use label into the largest patch on the site. + land_use_type_to_remove = currentPatch%land_use_label + + write(fates_log(),*) 'removing all patches with land use type ',land_use_type_to_remove + + ! first find the largest patch on the site + patchpointer => currentSite%youngest_patch + largest_patch => currentSite%youngest_patch + do while(associated(patchpointer)) + if (patchpointer%area .gt. largest_patch%area .and. patchpointer%nocomp_pft_label .ne. nocomp_bareground) then + largest_patch => patchpointer + endif + patchpointer => patchpointer%older + end do + + ! now go and fuse all patches that have the land use type we are removing into that patch + patchpointer => currentSite%youngest_patch + do while(associated(patchpointer)) + if ( patchpointer%land_use_label .eq. land_use_type_to_remove ) then + + write(fates_log(),*) 'fusing into patch with types, age, and size of:', largest_patch%land_use_label, & + largest_patch%nocomp_pft_label, largest_patch%age, largest_patch%area + + write(fates_log(),*) 'fusing away patch with types, age, and size of:', patchpointer%land_use_label, & + patchpointer%nocomp_pft_label, patchpointer%age, patchpointer%area + + ! reset the categorical properties of the patch and fuse it into the largest patch + patchpointer%land_use_label = largest_patch%land_use_label + patchpointer%nocomp_pft_label = largest_patch%nocomp_pft_label + patchpointer%age_since_anthro_disturbance = largest_patch%age_since_anthro_disturbance + call fuse_2_patches(currentSite, patchpointer, largest_patch) + + ! start over in the loop to make sure we are removing every patch with the targeted land use type + patchpointer => currentSite%youngest_patch + + else + patchpointer => patchpointer%older + endif + end do + + write(fates_log(),*) 'resetting currentSite%landuse_vector_gt_min(i) to .false.' + ! now reset the allowed land use vector element so that we don't make any more such patches unless they exceed the min area + currentSite%landuse_vector_gt_min(land_use_type_to_remove) = .false. + count_cycles = 0 + currentPatch => currentSite%youngest_patch + else + write(fates_log(),*) 'this isnt because the land use was less than allowed' + + call endrun(msg=errMsg(sourcefile, __LINE__)) - ! Note to user. If you DO decide to remove the end-run above this line - ! Make sure that you keep the pointer below this line, or you will get - ! an infinite loop. - currentPatch => currentPatch%older - count_cycles = 0 + ! Note to user. If you DO decide to remove the end-run above this line + ! Make sure that you keep the pointer below this line, or you will get + ! an infinite loop. + currentPatch => currentPatch%older + count_cycles = 0 + endif end if !count cycles enddo ! current patch loop diff --git a/main/FatesRunningMeanMod.F90 b/main/FatesRunningMeanMod.F90 index 7ef7866d62..721030b974 100644 --- a/main/FatesRunningMeanMod.F90 +++ b/main/FatesRunningMeanMod.F90 @@ -328,6 +328,9 @@ subroutine FuseRMean(this,donor,recip_wgt) if (this%c_index .ne. donor%c_index) then write(fates_log(), *) 'trying to fuse two fixed-window averages' write(fates_log(), *) 'that are at different points in the window?' + write(fates_log(), *) 'c_mean', this%c_mean, donor%c_mean + write(fates_log(), *) 'l_mean', this%l_mean, donor%l_mean + write(fates_log(), *) 'c_index', this%c_index, donor%c_index call endrun(msg=errMsg(sourcefile, __LINE__)) end if end if From 743f26497e91c8ad145c5bf2733e2222b5d05a74 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Mon, 4 Mar 2024 20:41:03 -0800 Subject: [PATCH 105/300] add two parameters for vertical scaling of sla and vcmax - placeholders --- parameter_files/fates_params_default.cdl | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index a762c79e54..018d714191 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -392,7 +392,13 @@ variables: fates_maintresp_leaf_vert_scaler_coeff1:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the default value of 0.00963." ; double fates_maintresp_leaf_vert_scaler_coeff2(fates_pft) ; fates_maintresp_leaf_vert_scaler_coeff2:units = "unitless" ; - fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the default value of 2.43." ; + fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the default value of 2.43." ; + double fates_leafn_vert_scaler_coeff1(fates_pft) ; + fates_leafn_vert_scaler_coeff1:units = "unitless" ; + fates_leafn_vert_scaler_coeff1:long_name = "Coefficient one for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010. " ; + double fates_leafn_vert_scaler_coeff2(fates_pft) ; + fates_leafn_vert_scaler_coeff2:units = "unitless" ; + fates_leafn_vert_scaler_coeff2:long_name = "Coefficient two for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010. " ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -1317,9 +1323,15 @@ data: 2.525e-06, 2.525e-06, 2.525e-06 ; fates_maintresp_leaf_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, 0.00963, - 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; fates_maintresp_leaf_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; + + fates_leafn_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; + + fates_leafn_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, From e472084aeeeae88c3fbd6683cef41b80f541e90f Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 7 Mar 2024 12:59:28 -0500 Subject: [PATCH 106/300] Updated solvers --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 206 ++++++--------------- 1 file changed, 61 insertions(+), 145 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 744e43ec16..b77c65097c 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1379,7 +1379,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in aquad = theta_psii bquad = -(qabs + jmax) cquad = qabs * jmax - call quadratic_f (aquad, bquad, cquad, r1, r2) + call QuadraticRoots(aquad, bquad, cquad, r1, r2) je = min(r1,r2) ! Initialize intercellular co2 @@ -1409,7 +1409,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in aquad = theta_cj_c3 bquad = -(ac + aj) cquad = ac * aj - call quadratic_f (aquad, bquad, cquad, r1, r2) + call QuadraticRoots(aquad, bquad, cquad, r1, r2) agross = min(r1,r2) else @@ -1440,13 +1440,13 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in aquad = theta_cj_c4 bquad = -(ac + aj) cquad = ac * aj - call quadratic_f (aquad, bquad, cquad, r1, r2) + call QuadraticRoots(aquad, bquad, cquad, r1, r2) ai = min(r1,r2) aquad = theta_ip bquad = -(ai + ap) cquad = ai * ap - call quadratic_f (aquad, bquad, cquad, r1, r2) + call QuadraticRoots(aquad, bquad, cquad, r1, r2) agross = min(r1,r2) end if @@ -1485,7 +1485,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in (2.0*stomatal_intercept_btran + term * & (1.0 - medlyn_slope(ft)* medlyn_slope(ft) / vpd)) * term - call quadratic_f (aquad, bquad, cquad, r1, r2) + call QuadraticRoots(aquad, bquad, cquad, r1, r2) gs_mol = max(r1,r2) else if ( stomatal_model == ballberry_model ) then !stomatal conductance calculated from Ball et al. (1987) @@ -1494,7 +1494,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in cquad = -gb_mol*(leaf_co2_ppress*stomatal_intercept_btran + & bb_slope(ft)*anet*can_press * ceair/ veg_esat ) - call quadratic_f (aquad, bquad, cquad, r1, r2) + call QuadraticRoots(aquad, bquad, cquad, r1, r2) gs_mol = max(r1,r2) end if @@ -1922,145 +1922,6 @@ end function fth25_f ! ===================================================================================== - subroutine quadratic_f (a, b, c, r1, r2) - ! - ! !DESCRIPTION: - !==============================================================================! - !----------------- Solve quadratic equation for its two roots -----------------! - !==============================================================================! - ! This solution is mostly derived from: - ! Press WH, Teukolsky SA, Vetterling WT, Flannery BP. 1992. Numerical Recipes - ! in Fortran77: The Art of Scientific Computing. 2nd edn. Cambridge - ! University Press, Cambridge UK, ISBN 0-521-43064-X. - ! Available at: http://numerical.recipes/oldverswitcher.html, section 5.6. - ! - ! !REVISION HISTORY: - ! 4/5/10: Adapted from /home/bonan/ecm/psn/An_gs_iterative.f90 by Keith Oleson - ! 7/23/16: Copied over from CLM by Ryan Knox - ! 12/30/23: Instead of issuing errors when a=0, solve the trivial cases too. - ! Check determinant sign, and stop the run when it is negative. - ! - ! !USES: - ! - ! !ARGUMENTS: - real(r8), intent(in) :: a,b,c ! Terms for quadratic equation - real(r8), intent(out) :: r1,r2 ! Roots of quadratic equation - ! - ! !LOCAL VARIABLES: - real(r8) :: discriminant ! Discriminant - real(r8) :: q ! Temporary term for quadratic solution - logical :: a_offzero ! Is a close to zero? - logical :: b_offzero ! Is b close to zero? - logical :: c_offzero ! Is c close to zero? - ! ! Local constants: - real(r8), parameter :: discard = 1.e36_r8 ! Large number for discarding answer - !------------------------------------------------------------------------------ - - ! Save logical tests. - a_offzero = abs(a) > nearzero - b_offzero = abs(b) > nearzero - c_offzero = abs(c) > nearzero - - if (a_offzero .and. ( b_offzero .or. c_offzero ) ) then - ! Quadratic equation with two non-zero solutions (but may be complex solutions) - discriminant = b*b - 4._r8 * a * c - - ! Proceed only when the discriminant is non-negative or only tiny negative - if (discriminant >= - nearzero) then - ! Coerce discriminant to non-negative - discriminant = max(0._r8,discriminant) - - ! Find q as in the numerical recipes. If b or c are non-zero, q cannot - ! be zero, no need for additional checks. - q = - 0.5_r8 * (b + sign(sqrt(discriminant),b)) - r1 = q / a - r2 = c / q - else - ! Negative discriminant, stop the run. - write (fates_log(),'(a)') '---~---' - write (fates_log(),'(a)') ' Fatal error!' - write (fates_log(),'(a)') ' Quadratic equation discriminant is negative.' - write (fates_log(),'(a)') '---~---' - write (fates_log(),'(a,1x,es12.5)') ' a = ',a - write (fates_log(),'(a,1x,es12.5)') ' b = ',b - write (fates_log(),'(a,1x,es12.5)') ' c = ',c - write (fates_log(),'(a,1x,es12.5)') ' discriminant = ',discriminant - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - else if (a_offzero) then - ! b and c are nearly zero. Both roots must be zero. - r1 = 0._r8 - r2 = 0._r8 - else if (b_offzero) then - ! "a" is not zero, not a true quadratic equation. Single root. - r1 = - c / b - r2 = discard - else - ! Both a and b are zero, this really doesn't make any sense and should never - ! happen. If it does, issue an error and stop the run. - write (fates_log(),'(a)') '---~---' - write (fates_log(),'(a)') ' Fatal error!' - write (fates_log(),'(a)') ' This solver expects ''a'' and/or ''b'' to be non-zero.' - write (fates_log(),'(a)') '---~---' - write (fates_log(),'(a,1x,es12.5)') ' a = ',a - write (fates_log(),'(a,1x,es12.5)') ' b = ',b - write (fates_log(),'(a,1x,es12.5)') ' c = ',c - write (fates_log(),'(a)') '---~---' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - return - end subroutine quadratic_f - - ! ==================================================================================== - - subroutine quadratic_fast (a, b, c, r1, r2) - ! - ! !DESCRIPTION: - !==============================================================================! - !----------------- Solve quadratic equation for its two roots -----------------! - ! THIS METHOD SIMPLY REMOVES THE DIV0 CHECK AND ERROR REPORTING ! - !==============================================================================! - ! Solution from Press et al (1986) Numerical Recipes: The Art of Scientific - ! Computing (Cambridge University Press, Cambridge), pp. 145. - ! - ! !REVISION HISTORY: - ! 4/5/10: Adapted from /home/bonan/ecm/psn/An_gs_iterative.f90 by Keith Oleson - ! 7/23/16: Copied over from CLM by Ryan Knox - ! - ! !USES: - ! - ! !ARGUMENTS: - real(r8), intent(in) :: a,b,c ! Terms for quadratic equation - real(r8), intent(out) :: r1,r2 ! Roots of quadratic equation - ! - ! !LOCAL VARIABLES: - real(r8) :: q ! Temporary term for quadratic solution - !------------------------------------------------------------------------------ - - ! if (a == 0._r8) then - ! write (fates_log(),*) 'Quadratic solution error: a = ',a - ! call endrun(msg=errMsg(sourcefile, __LINE__)) - ! end if - - if (b >= 0._r8) then - q = -0.5_r8 * (b + sqrt(b*b - 4._r8*a*c)) - else - q = -0.5_r8 * (b - sqrt(b*b - 4._r8*a*c)) - end if - - r1 = q / a - ! if (q /= 0._r8) then - r2 = c / q - ! else - ! r2 = 1.e36_r8 - ! end if - - end subroutine quadratic_fast - - - ! ==================================================================================== - subroutine UpdateCanopyNCanNRadPresent(currentPatch) ! --------------------------------------------------------------------------------- @@ -2573,4 +2434,59 @@ subroutine lowstorage_maintresp_reduction(frac, pft, maintresp_reduction_factor) end subroutine lowstorage_maintresp_reduction + ! ============================================================================= + + subroutine QuadraticRoots(a,b,c,root1,root2) + + ! This code is based off of routines from the NSWC Mathematics Subroutine Library + ! From the NSWC README (https://github.com/jacobwilliams/nswc) + ! "The NSWC Mathematics Subroutine Library is a collection of Fortran 77 routines + ! specializing in numerical mathematics collected and developed by the U.S. + ! Naval Surface Warfare Center. This software is made available, without cost, + ! to the general scientific community." + ! The F77 code was updated to modern fortran by Jacob Williams: + ! https://jacobwilliams.github.io/polyroots-fortran + ! The FATES adaptation of this aborts if only imaginary roots are generated + + + real(r8),intent(in) :: a , b , c !! coefficients + real(r8),intent(out) :: root1 ! sr !! real part of first root + real(r8),intent(out) :: root2 ! lr !! real part of second root + + real(r8) :: b1, d, e + + if ( a==0.0_r8 ) then + root1 = 0.0_r8 + if ( b/=0.0_r8 ) root1 = -c/b + root2 = 0.0_r8 + elseif ( c/=0.0_r8 ) then + ! compute discriminant avoiding overflow + b1 = b/2.0_r8 + if ( abs(b1)=0.0_r8 ) d = -d + root2 = (-b1+d)/a + root1 = 0.0_r8 + if ( root2/=0.0_r8 ) root1 = (c/root2)/a + endif + else + root1 = 0.0_r8 + root2 = -b/a + endif + + end subroutine QuadraticRoots + end module FATESPlantRespPhotosynthMod From 55bf86477ecbada462d85d520794baa38c18eeb3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 7 Mar 2024 20:09:33 -0700 Subject: [PATCH 107/300] Updates to history density l2fr and damage --- main/FatesHistoryInterfaceMod.F90 | 115 +++++++++++++++--------------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 926567b7cb..5940b9adb7 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -263,11 +263,11 @@ module FatesHistoryInterfaceMod integer :: ih_storeptfrac_canopy_scpf integer :: ih_storeptfrac_understory_scpf - ! These are active if hlm_parteh_mode = prt_cnp_flex_allom_hyp integer :: ih_l2fr_si integer :: ih_l2fr_clscpf integer :: ih_recl2fr_canopy_pf integer :: ih_recl2fr_ustory_pf + integer :: ih_nh4uptake_scpf integer :: ih_no3uptake_scpf integer :: ih_puptake_scpf @@ -2793,9 +2793,12 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) this%hvars(ih_l2fr_si)%r81d(io_si) = & this%hvars(ih_l2fr_si)%r81d(io_si) + & ccohort%l2fr *ccohort%n * fnrt_m / m2_per_ha + else + this%hvars(ih_l2fr_si)%r81d(io_si) = & + this%hvars(ih_l2fr_si)%r81d(io_si) + & + prt_params%allom_l2fr(ft) *ccohort%n * fnrt_m / m2_per_ha end if - elseif(element_list(el).eq.nitrogen_element)then store_max = ccohort%prt%GetNutrientTarget(element_list(el),store_organ,stoich_growth_min) @@ -2991,17 +2994,19 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) end if end do elloop2 + if(this%hvars(ih_fnrtc_si)%r81d(io_si)>nearzero)then this%hvars(ih_l2fr_si)%r81d(io_si) = this%hvars(ih_l2fr_si)%r81d(io_si) / & this%hvars(ih_fnrtc_si)%r81d(io_si) else this%hvars(ih_l2fr_si)%r81d(io_si) = hlm_hio_ignore_val end if - ! zero the site-level termination carbon flux variable sites(s)%term_carbonflux_canopy(:,:) = 0._r8 sites(s)%term_carbonflux_ustory(:,:) = 0._r8 + sites(s)%crownarea_canopy_damage = 0._r8 + sites(s)%crownarea_ustory_damage = 0._r8 end do siteloop @@ -3194,7 +3199,7 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_m8_sec_si_scls => this%hvars(ih_m8_sec_si_scls)%r82d, & hio_m9_sec_si_scls => this%hvars(ih_m9_sec_si_scls)%r82d, & hio_m10_sec_si_scls => this%hvars(ih_m10_sec_si_scls)%r82d, & - !hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & + hio_c13disc_si_scpf => this%hvars(ih_c13disc_si_scpf)%r82d, & hio_cwd_elcwd => this%hvars(ih_cwd_elcwd)%r82d, & hio_cwd_ag_elem => this%hvars(ih_cwd_ag_elem)%r82d, & hio_cwd_bg_elem => this%hvars(ih_cwd_bg_elem)%r82d, & @@ -3778,12 +3783,12 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) end if !C13 discrimination - !if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then - ! hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & - ! (ccohort%c13disc_acc * ccohort%gpp_acc_hold)) / (gpp_cached + ccohort%gpp_acc_hold) - !else - ! hio_c13disc_si_scpf(io_si,scpf) = 0.0_r8 - !endif + if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then + hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & + (ccohort%c13disc_acc * ccohort%gpp_acc_hold)) / (gpp_cached + ccohort%gpp_acc_hold) + else + hio_c13disc_si_scpf(io_si,scpf) = 0.0_r8 + endif ! number density [/m2] hio_nplant_si_scpf(io_si,scpf) = hio_nplant_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha @@ -4503,8 +4508,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) sites(s)%fmort_rate_ustory_damage(:,:,:) = 0._r8 sites(s)%fmort_cflux_canopy_damage(:,:) = 0._r8 sites(s)%fmort_cflux_ustory_damage(:,:) = 0._r8 - sites(s)%crownarea_canopy_damage = 0._r8 - sites(s)%crownarea_ustory_damage = 0._r8 ! pass the recruitment rate as a flux to the history, and then reset the recruitment buffer do ft = 1, numpft @@ -4839,12 +4842,10 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) end do - if( hlm_parteh_mode == prt_cnp_flex_allom_hyp) then - do ft = 1,numpft - this%hvars(ih_recl2fr_canopy_pf)%r82d(io_si,ft) = sites(s)%rec_l2fr(ft,1) - this%hvars(ih_recl2fr_ustory_pf)%r82d(io_si,ft) = sites(s)%rec_l2fr(ft,2) - end do - end if + do ft = 1,numpft + this%hvars(ih_recl2fr_canopy_pf)%r82d(io_si,ft) = sites(s)%rec_l2fr(ft,1) + this%hvars(ih_recl2fr_ustory_pf)%r82d(io_si,ft) = sites(s)%rec_l2fr(ft,2) + end do enddo siteloop ! site loop @@ -6409,13 +6410,11 @@ subroutine define_history_vars(this, initialize_variables) index = ih_reproc_si) ! Output specific to the chemical species dynamics used (parteh) - if( hlm_parteh_mode == prt_cnp_flex_allom_hyp) then - call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for target allometry', & - use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & - ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) - end if + call this%set_history_var(vname='FATES_L2FR', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for target allometry', & + use_default='active', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & + ivar=ivar, initialize=initialize_variables, index = ih_l2fr_si) nitrogen_active_if0: if(any(element_list(:)==nitrogen_element)) then @@ -6758,7 +6757,22 @@ subroutine define_history_vars(this, initialize_variables) initialize=initialize_variables, index = ih_h2oveg_growturn_err_si) end if hydro_active_if - !HERE + if_crowndamage1: if(hlm_use_tree_damage .eq. itrue) then + + call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 m-2 yr-1', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) + + call this%set_history_var(vname='FATES_CROWNAREA_USTORY_CD', units = 'm2 m-2 yr-1', & + long='crownarea lost to damage each year', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) + else + write(fates_log(),*) 'NO TREE DAMAGE?' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if if_crowndamage1 + if_dyn1: if(hlm_hist_level_dynam>1) then @@ -7111,27 +7125,24 @@ subroutine define_history_vars(this, initialize_variables) ! Output specific to the chemical species dynamics used (parteh) - if( hlm_parteh_mode == prt_cnp_flex_allom_hyp) then - call this%set_history_var(vname='FATES_L2FR_CANOPY_REC_PF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for recruits (canopy)', & - use_default='active', & - avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & - ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) - - call this%set_history_var(vname='FATES_L2FR_USTORY_REC_PF', units='kg kg-1', & - long='The leaf to fineroot biomass multiplier for recruits (understory)', & - use_default='active', & - avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & - ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) - + call this%set_history_var(vname='FATES_L2FR_CANOPY_REC_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (canopy)', & + use_default='active', & + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_canopy_pf) + + call this%set_history_var(vname='FATES_L2FR_USTORY_REC_PF', units='kg kg-1', & + long='The leaf to fineroot biomass multiplier for recruits (understory)', & + use_default='active', & + avgflag='A', vtype=site_pft_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & + ivar=ivar, initialize=initialize_variables, index = ih_recl2fr_ustory_pf) + !call this%set_history_var(vname='FATES_L2FR_CLSZPF', units='kg kg-1', & ! long='The leaf to fineroot biomass multiplier for target allometry', & ! use_default='inactive', & ! avgflag='A', vtype=site_clscpf_r8, hlms='CLM:ALM', upfreq=group_dyna_complx, & ! ivar=ivar, initialize=initialize_variables, index = ih_l2fr_clscpf) - end if - nitrogen_active_if1: if(any(element_list(:)==nitrogen_element)) then call this%set_history_var(vname='FATES_NH4UPTAKE_SZPF', & @@ -7691,12 +7702,12 @@ subroutine define_history_vars(this, initialize_variables) initialize=initialize_variables, index = ih_m3_mortality_understory_si_scpf ) -! call this%set_history_var(vname='FATES_C13DISC_SZPF', units = 'per mil', & -! long='C13 discrimination by pft/size',use_default='inactive', & -! avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & -! upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & -! index = ih_c13disc_si_scpf) - + call this%set_history_var(vname='FATES_C13DISC_SZPF', units = 'per mil', & + long='C13 discrimination by pft/size',use_default='inactive', & + avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', & + upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & + index = ih_c13disc_si_scpf) + call this%set_history_var(vname='FATES_STOREC_CANOPY_SZPF', units = 'kg m-2', & long='biomass in storage pools of canopy plants by pft/size in kg carbon per m2', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & @@ -8307,16 +8318,6 @@ subroutine define_history_vars(this, initialize_variables) ! CROWN DAMAGE VARIABLES if_crowndamage: if(hlm_use_tree_damage .eq. itrue) then - call this%set_history_var(vname='FATES_CROWNAREA_CANOPY_CD', units = 'm2 m-2 yr-1', & - long='crownarea lost to damage each year', use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_canopy_damage_si ) - - call this%set_history_var(vname='FATES_CROWNAREA_USTORY_CD', units = 'm2 m-2 yr-1', & - long='crownarea lost to damage each year', use_default='inactive', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) - call this%set_history_var(vname='FATES_NPLANT_CDPF', units = 'm-2', & long='N. plants per damage x size x pft class', use_default='inactive', & avgflag='A', vtype=site_cdpf_r8, hlms='CLM:ALM', & From 6d38fa4f659a091f65c8b2bc6c203dc03f40e386 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 7 Mar 2024 20:47:48 -0700 Subject: [PATCH 108/300] removed test fail --- main/FatesHistoryInterfaceMod.F90 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 5940b9adb7..b7cbc1bfa2 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -6768,9 +6768,7 @@ subroutine define_history_vars(this, initialize_variables) long='crownarea lost to damage each year', use_default='inactive', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, index = ih_crownarea_ustory_damage_si ) - else - write(fates_log(),*) 'NO TREE DAMAGE?' - call endrun(msg=errMsg(sourcefile, __LINE__)) + end if if_crowndamage1 From ddf48a687ddc542990ac0f993732ad97d745d6da Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 8 Mar 2024 11:06:04 -0500 Subject: [PATCH 109/300] Generated and ran unit tests on solve --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 56 +----- .../math_utils/MathUtilsDriver.py | 167 ++++++++++++++++++ functional_unit_testing/math_utils/bld/README | 1 + .../math_utils/build_math_objects.sh | 47 +++++ .../math_utils/f90_src/UnitWrapMod.F90 | 49 +++++ main/FatesUtilsMod.F90 | 69 +++++++- 6 files changed, 331 insertions(+), 58 deletions(-) create mode 100644 functional_unit_testing/math_utils/MathUtilsDriver.py create mode 100644 functional_unit_testing/math_utils/bld/README create mode 100755 functional_unit_testing/math_utils/build_math_objects.sh create mode 100644 functional_unit_testing/math_utils/f90_src/UnitWrapMod.F90 diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index b77c65097c..053323f6a8 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -38,6 +38,7 @@ module FATESPlantRespPhotosynthMod use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : numpft use FatesInterfaceTypesMod, only : nleafage + use FatesUtilsMod, only : QuadraticRoots use EDParamsMod, only : maxpft use EDParamsMod, only : nlevleaf use EDParamsMod, only : nclmax @@ -2434,59 +2435,4 @@ subroutine lowstorage_maintresp_reduction(frac, pft, maintresp_reduction_factor) end subroutine lowstorage_maintresp_reduction - ! ============================================================================= - - subroutine QuadraticRoots(a,b,c,root1,root2) - - ! This code is based off of routines from the NSWC Mathematics Subroutine Library - ! From the NSWC README (https://github.com/jacobwilliams/nswc) - ! "The NSWC Mathematics Subroutine Library is a collection of Fortran 77 routines - ! specializing in numerical mathematics collected and developed by the U.S. - ! Naval Surface Warfare Center. This software is made available, without cost, - ! to the general scientific community." - ! The F77 code was updated to modern fortran by Jacob Williams: - ! https://jacobwilliams.github.io/polyroots-fortran - ! The FATES adaptation of this aborts if only imaginary roots are generated - - - real(r8),intent(in) :: a , b , c !! coefficients - real(r8),intent(out) :: root1 ! sr !! real part of first root - real(r8),intent(out) :: root2 ! lr !! real part of second root - - real(r8) :: b1, d, e - - if ( a==0.0_r8 ) then - root1 = 0.0_r8 - if ( b/=0.0_r8 ) root1 = -c/b - root2 = 0.0_r8 - elseif ( c/=0.0_r8 ) then - ! compute discriminant avoiding overflow - b1 = b/2.0_r8 - if ( abs(b1)=0.0_r8 ) d = -d - root2 = (-b1+d)/a - root1 = 0.0_r8 - if ( root2/=0.0_r8 ) root1 = (c/root2)/a - endif - else - root1 = 0.0_r8 - root2 = -b/a - endif - - end subroutine QuadraticRoots - end module FATESPlantRespPhotosynthMod diff --git a/functional_unit_testing/math_utils/MathUtilsDriver.py b/functional_unit_testing/math_utils/MathUtilsDriver.py new file mode 100644 index 0000000000..35f4d8182e --- /dev/null +++ b/functional_unit_testing/math_utils/MathUtilsDriver.py @@ -0,0 +1,167 @@ +# ======================================================================================= +# +# For usage: $python HydroUTestDriver.py --help +# +# This script runs unit tests on the hydraulics functions. +# +# +# ======================================================================================= + +import matplotlib as mpl +#mpl.use('Agg') +import matplotlib.pyplot as plt +from datetime import datetime +import argparse +#from matplotlib.backends.backend_pdf import PdfPages +import platform +import numpy as np +import os +import sys +import getopt +import code # For development: code.interact(local=dict(globals(), **locals())) +import time +import imp +import ctypes +from ctypes import * +from operator import add + + +#CDLParse = imp.load_source('CDLParse','../shared/py_src/CDLParse.py') +#F90ParamParse = imp.load_source('F90ParamParse','../shared/py_src/F90ParamParse.py') +PyF90Utils = imp.load_source('PyF90Utils','../shared/py_src/PyF90Utils.py') + + +#from CDLParse import CDLParseDims, CDLParseParam, cdl_param_type +#from F90ParamParse import f90_param_type, GetSymbolUsage, GetPFTParmFileSymbols, MakeListUnique + +from PyF90Utils import c8, ci, cchar, c8_arr, ci_arr + +# Load the fortran objects via CTYPES + +f90_unitwrap_obj = ctypes.CDLL('bld/UnitWrapMod.o',mode=ctypes.RTLD_GLOBAL) +f90_constants_obj = ctypes.CDLL('bld/FatesConstantsMod.o',mode=ctypes.RTLD_GLOBAL) +f90_fatesutils_obj = ctypes.CDLL('bld/FatesUtilsMod.o',mode=ctypes.RTLD_GLOBAL) + +# Alias the F90 functions, specify the return type +# ----------------------------------------------------------------------------------- + +neighbor_dist = f90_fatesutils_obj.__fatesutilsmod_MOD_getneighbordistance +#quadratic_f = f90_fatesutils_obj.__fatesutilsmod_MOD_quadratic_f +quadratic_roots = f90_fatesutils_obj.__fatesutilsmod_MOD_quadraticroots + +# Some constants +rwcft = [1.0,0.958,0.958,0.958] +rwccap = [1.0,0.947,0.947,0.947] +pm_leaf = 1 +pm_stem = 2 +pm_troot = 3 +pm_aroot = 4 +pm_rhiz = 5 + +# These parameters are matched with the indices in FATES-HYDRO +vg_type = 1 +cch_type = 2 +tfs_type = 3 + +isoil1 = 0 # Top soil layer parameters (@BCI) +isoil2 = 1 # Bottom soil layer parameters + +# Constants for rhizosphere +watsat = [0.567, 0.444] +sucsat = [159.659, 256.094] +bsw = [6.408, 9.27] + +unconstrained = True + + +# ======================================================================================== +# ======================================================================================== +# Main +# ======================================================================================== +# ======================================================================================== + +def main(argv): + + # First check to make sure python 2.7 is being used + version = platform.python_version() + verlist = version.split('.') + + #if( not ((verlist[0] == '2') & (verlist[1] == '7') & (int(verlist[2])>=15) ) ): + # print("The PARTEH driver mus be run with python 2.7") + # print(" with tertiary version >=15.") + # print(" your version is {}".format(version)) + # print(" exiting...") + # sys.exit(2) + + # Read in the arguments + # ======================================================================================= + + # parser = argparse.ArgumentParser(description='Parse command line arguments to this script.') + # parser.add_argument('--cdl-file', dest='cdlfile', type=str, \ + # help="Input CDL filename. Required.", required=True) + # args = parser.parse_args() + + # Set number of analysis points + + # y = ax2 + bx + c + + a = [1,1,5,1.5] + b = [-2,7,10,3.2] + c = [1,12,3,1.1] + + cd_r1 = c_double(-9.0) + cd_r2 = c_double(-9.0) + + r1 = np.zeros([2,1]) + r2 = np.zeros([2,1]) + + for ic in range(len(a)): + + #iret = quadratic_f(c8(a[ic]),c8(b[ic]),c8(c[ic]),byref(cd_r1),byref(cd_r2)) + r1[0] = cd_r1.value + r2[0] = cd_r2.value + + iret = quadratic_roots(c8(a[ic]),c8(b[ic]),c8(c[ic]),byref(cd_r1),byref(cd_r2)) + r1[1] = cd_r1.value + r2[1] = cd_r2.value + + print(a[ic],b[ic],c[ic]) + print(r1) + print(r2) + + #PlotQuadAndRoots(a[ic],b[ic],c[ic],r1,r2) + + +def PlotQuadAndRoots(a,b,c,d,r1,r2): + + fig, axs = plt.subplots(ncols=1,nrows=1,figsize=(8,8)) + ax1s = axs.reshape(-1) + ic=0 + + npts = 1000 + + for i in range(npts): + print(i) + + + +# code.interact(local=dict(globals(), **locals())) + +# Helper code to plot negative logs + +def semilogneg(x): + + y = np.sign(x)*np.log(abs(x)) + return(y) + +def semilog10net(x): + + y = np.sign(x)*np.log10(abs(x)) + return(y) + + +# ======================================================================================= +# This is the actual call to main + +if __name__ == "__main__": + main(sys.argv) diff --git a/functional_unit_testing/math_utils/bld/README b/functional_unit_testing/math_utils/bld/README new file mode 100644 index 0000000000..4e67e5f091 --- /dev/null +++ b/functional_unit_testing/math_utils/bld/README @@ -0,0 +1 @@ +PLACEHOLDER FOR DIR \ No newline at end of file diff --git a/functional_unit_testing/math_utils/build_math_objects.sh b/functional_unit_testing/math_utils/build_math_objects.sh new file mode 100755 index 0000000000..40ac3eb9d1 --- /dev/null +++ b/functional_unit_testing/math_utils/build_math_objects.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Path to FATES src + +FC='gfortran' + +F_OPTS="-shared -fPIC -g -ffpe-trap=zero,overflow,underflow -fbacktrace -fbounds-check" +#F_OPTS="-shared -fPIC -O" + + +MOD_FLAG="-J" + +rm -f bld/*.o +rm -f bld/*.mod + + +# First copy over the FatesConstants file, but change the types of the fates_r8 and fates_int + +old_fates_r8_str=`grep -e integer ../../main/FatesConstantsMod.F90 | grep fates_r8 | sed 's/^[ \t]*//;s/[ \t]*$//'` +new_fates_r8_str='use iso_c_binding, only: fates_r8 => c_double' + +old_fates_int_str=`grep -e integer ../../main/FatesConstantsMod.F90 | grep fates_int | sed 's/^[ \t]*//;s/[ \t]*$//'` +new_fates_int_str='use iso_c_binding, only: fates_int => c_int' + +# Add the new lines (need position change, don't swap) + +sed "/implicit none/i $new_fates_r8_str" ../../main/FatesConstantsMod.F90 > f90_src/FatesConstantsMod.F90 +sed -i "/implicit none/i $new_fates_int_str" f90_src/FatesConstantsMod.F90 +sed -i "/private /i public :: fates_r8" f90_src/FatesConstantsMod.F90 +sed -i "/private /i public :: fates_int" f90_src/FatesConstantsMod.F90 + +# Delete the old lines + +sed -i "/$old_fates_r8_str/d" f90_src/FatesConstantsMod.F90 +sed -i "/$old_fates_int_str/d" f90_src/FatesConstantsMod.F90 + +# Build the new file with constants + +${FC} ${F_OPTS} -I bld/ ${MOD_FLAG} bld/ -o bld/FatesConstantsMod.o f90_src/FatesConstantsMod.F90 + +${FC} ${F_OPTS} -I bld/ ${MOD_FLAG} bld/ -o bld/UnitWrapMod.o f90_src/UnitWrapMod.F90 + +${FC} ${F_OPTS} -I bld/ ${MOD_FLAG} bld/ -o bld/FatesUtilsMod.o ../../main/FatesUtilsMod.F90 + + + + diff --git a/functional_unit_testing/math_utils/f90_src/UnitWrapMod.F90 b/functional_unit_testing/math_utils/f90_src/UnitWrapMod.F90 new file mode 100644 index 0000000000..f12311655a --- /dev/null +++ b/functional_unit_testing/math_utils/f90_src/UnitWrapMod.F90 @@ -0,0 +1,49 @@ + +! ======================================================================================= +! +! This file is an alternative to key files in the fates +! filesystem. Noteably, we replace fates_r8 and fates_in +! with types that work with "ctypes". This is +! a key step in working with python +! +! We also wrap FatesGlobals to reduce the dependancy +! cascade that it pulls in from shr_log_mod. +! +! ======================================================================================= + +module shr_log_mod + + use iso_c_binding, only : c_char + use iso_c_binding, only : c_int + + contains + + function shr_log_errMsg(source, line) result(ans) + character(kind=c_char,len=*), intent(in) :: source + integer(c_int), intent(in) :: line + character(kind=c_char,len=128) :: ans + + ans = "source: " // trim(source) // " line: " + end function shr_log_errMsg + +end module shr_log_mod + + +module FatesGlobals + + contains + + integer function fates_log() + fates_log = -1 + end function fates_log + + subroutine fates_endrun(msg) + + implicit none + character(len=*), intent(in) :: msg ! string to be printed + + stop + + end subroutine fates_endrun + +end module FatesGlobals diff --git a/main/FatesUtilsMod.F90 b/main/FatesUtilsMod.F90 index 4699a6aa60..b3a98e6ede 100644 --- a/main/FatesUtilsMod.F90 +++ b/main/FatesUtilsMod.F90 @@ -5,7 +5,11 @@ module FatesUtilsMod use FatesConstantsMod, only : r8 => fates_r8 use FatesGlobals, only : fates_log - + use FatesConstantsMod, only : nearzero + use FatesGlobals, only : endrun => fates_endrun + + use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private ! Modules are private by default @@ -14,7 +18,11 @@ module FatesUtilsMod public :: check_var_real public :: GetNeighborDistance public :: FindIndex - + public :: QuadraticRoots + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + contains @@ -176,6 +184,61 @@ function FindIndex(input_string_array,string_to_match) result(array_index) end do end function FindIndex - + + subroutine QuadraticRoots(a,b,c,root1,root2) + + ! This code is based off of routines from the NSWC Mathematics Subroutine Library + ! From the NSWC README (https://github.com/jacobwilliams/nswc) + ! "The NSWC Mathematics Subroutine Library is a collection of Fortran 77 routines + ! specializing in numerical mathematics collected and developed by the U.S. + ! Naval Surface Warfare Center. This software is made available, without cost, + ! to the general scientific community." + ! The F77 code was updated to modern fortran by Jacob Williams: + ! https://jacobwilliams.github.io/polyroots-fortran + ! The FATES adaptation of this aborts if only imaginary roots are generated + + + real(r8),intent(in) :: a , b , c !! coefficients + real(r8),intent(out) :: root1 ! sr !! real part of first root + real(r8),intent(out) :: root2 ! lr !! real part of second root + + real(r8) :: b1, d, e + + if ( a==0.0_r8 ) then + root2 = 0.0_r8 + if ( b/=0.0_r8 ) root2 = -c/b + root1 = 0.0_r8 + elseif ( c/=0.0_r8 ) then + ! compute discriminant avoiding overflow + b1 = b/2.0_r8 + if ( abs(b1)=0.0_r8 ) d = -d + root1 = (-b1+d)/a + root2 = 0.0_r8 + if ( root1/=0.0_r8 ) root2 = (c/root1)/a + endif + else + root2 = 0.0_r8 + root1 = -b/a + endif + + end subroutine QuadraticRoots + + + ! ====================================================================================== end module FatesUtilsMod From 2dce50770c1c2f0f99870aad684f4608b72a97f6 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 8 Mar 2024 11:19:36 -0700 Subject: [PATCH 110/300] changed zero protections to near zero --- main/FatesUtilsMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesUtilsMod.F90 b/main/FatesUtilsMod.F90 index b3a98e6ede..03a2867af5 100644 --- a/main/FatesUtilsMod.F90 +++ b/main/FatesUtilsMod.F90 @@ -204,11 +204,11 @@ subroutine QuadraticRoots(a,b,c,root1,root2) real(r8) :: b1, d, e - if ( a==0.0_r8 ) then + if ( abs(a)nearzero ) then ! compute discriminant avoiding overflow b1 = b/2.0_r8 if ( abs(b1) Date: Fri, 8 Mar 2024 15:40:09 -0500 Subject: [PATCH 111/300] added other solver --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 +- .../math_utils/MathUtilsDriver.py | 13 ++++-- main/FatesUtilsMod.F90 | 45 +++++++++++++++++-- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 053323f6a8..df0450016b 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -38,7 +38,7 @@ module FATESPlantRespPhotosynthMod use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : numpft use FatesInterfaceTypesMod, only : nleafage - use FatesUtilsMod, only : QuadraticRoots + use FatesUtilsMod, only : QuadraticRoots => QuadraticRootsSridharachary use EDParamsMod, only : maxpft use EDParamsMod, only : nlevleaf use EDParamsMod, only : nclmax diff --git a/functional_unit_testing/math_utils/MathUtilsDriver.py b/functional_unit_testing/math_utils/MathUtilsDriver.py index 35f4d8182e..4add288126 100644 --- a/functional_unit_testing/math_utils/MathUtilsDriver.py +++ b/functional_unit_testing/math_utils/MathUtilsDriver.py @@ -48,6 +48,7 @@ neighbor_dist = f90_fatesutils_obj.__fatesutilsmod_MOD_getneighbordistance #quadratic_f = f90_fatesutils_obj.__fatesutilsmod_MOD_quadratic_f quadratic_roots = f90_fatesutils_obj.__fatesutilsmod_MOD_quadraticroots +quadratic_sroots = f90_fatesutils_obj.__fatesutilsmod_MOD_quadraticrootssridharachary # Some constants rwcft = [1.0,0.958,0.958,0.958] @@ -112,19 +113,23 @@ def main(argv): cd_r1 = c_double(-9.0) cd_r2 = c_double(-9.0) - r1 = np.zeros([2,1]) - r2 = np.zeros([2,1]) + r1 = np.zeros([3,1]) + r2 = np.zeros([3,1]) for ic in range(len(a)): #iret = quadratic_f(c8(a[ic]),c8(b[ic]),c8(c[ic]),byref(cd_r1),byref(cd_r2)) - r1[0] = cd_r1.value - r2[0] = cd_r2.value + #r1[0] = cd_r1.value + #r2[0] = cd_r2.value iret = quadratic_roots(c8(a[ic]),c8(b[ic]),c8(c[ic]),byref(cd_r1),byref(cd_r2)) r1[1] = cd_r1.value r2[1] = cd_r2.value + iret = quadratic_sroots(c8(a[ic]),c8(b[ic]),c8(c[ic]),byref(cd_r1),byref(cd_r2)) + r1[2] = cd_r2.value + r2[2] = cd_r1.value + print(a[ic],b[ic],c[ic]) print(r1) print(r2) diff --git a/main/FatesUtilsMod.F90 b/main/FatesUtilsMod.F90 index 03a2867af5..be955d5da0 100644 --- a/main/FatesUtilsMod.F90 +++ b/main/FatesUtilsMod.F90 @@ -18,7 +18,8 @@ module FatesUtilsMod public :: check_var_real public :: GetNeighborDistance public :: FindIndex - public :: QuadraticRoots + public :: QuadraticRootsNSWC + public :: QuadraticRootsSridharachary character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -185,7 +186,7 @@ function FindIndex(input_string_array,string_to_match) result(array_index) end function FindIndex - subroutine QuadraticRoots(a,b,c,root1,root2) + subroutine QuadraticRootsNSWC(a,b,c,root1,root2) ! This code is based off of routines from the NSWC Mathematics Subroutine Library ! From the NSWC README (https://github.com/jacobwilliams/nswc) @@ -236,9 +237,45 @@ subroutine QuadraticRoots(a,b,c,root1,root2) root1 = -b/a endif - end subroutine QuadraticRoots + end subroutine QuadraticRootsNSWC + subroutine QuadraticRootsSridharachary(a,b,c,root1,root2) + + + real(r8),intent(in) :: a , b , c !! coefficients + real(r8),intent(out) :: root1 ! sr !! real part of first root + real(r8),intent(out) :: root2 ! lr !! real part of second root + real(r8) :: d ! discriminant + real(r8) :: das ! sqrt(abs(d)) + + ! If a is 0, then equation is not quadratic, but linear + if (abs(a) < nearzero ) then + root2 = 0.0_r8 + if ( abs(b)>nearzero ) root2 = -c/b + root1 = 0.0_r8 + return + end if + + d = b * b - 4._r8 * a * c + das = sqrt(abs(d)) + + if (d > nearzero) then + + root1 = (-b + das) / (2._r8 * a) + root2 = (-b - das) / (2._r8 * a) + + elseif (abs(d) <= nearzero) then + + root1 = -b / (2._r8 * a) + root2 = root1 + else + + write (fates_log(),*)'error, imaginary roots detected in quadratic solve' + call endrun(msg=errMsg(sourcefile, __LINE__)) + + end if + + end subroutine QuadraticRootsSridharachary - ! ====================================================================================== end module FatesUtilsMod From 1d5e02cfb0826361d2177e7096caeb73ae9d567c Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 12 Mar 2024 14:34:49 -0600 Subject: [PATCH 112/300] adding nesterov module --- fire/SFFireWeatherMod.F90 | 32 +++++++++++++ fire/SFMainMod.F90 | 4 +- fire/SFNestorvMod.F90 | 95 +++++++++++++++++++++++++++++++++++++++ main/EDInitMod.F90 | 4 ++ main/EDTypesMod.F90 | 3 ++ 5 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 fire/SFFireWeatherMod.F90 create mode 100644 fire/SFNestorvMod.F90 diff --git a/fire/SFFireWeatherMod.F90 b/fire/SFFireWeatherMod.F90 new file mode 100644 index 0000000000..e39834ad1e --- /dev/null +++ b/fire/SFFireWeatherMod.F90 @@ -0,0 +1,32 @@ +module SFFireWeatherMod + + use FatesConstantsMod, only : r8 => fates_r8 + + implicit none + private + + type, abstract, public :: fire_weather + real(r8) :: fire_weather_index ! fire weather index + contains + procedure(initialize_fire_weather), public, deferred :: Init + procedure(update_fire_weather), public, deferred :: Update + end type fire_weather + + abstract interface + subroutine initialize_fire_weather(this) + import :: fire_weather + class(fire_weather), intent(inout) :: this + end subroutine initialize_fire_weather + + subroutine update_fire_weather(this, temp_C, precip, rh, wind) + use FatesConstantsMod, only : r8 => fates_r8 + import :: fire_weather + class(fire_weather), intent(inout) :: this + real(r8), intent(in) :: temp_C + real(r8), intent(in) :: precip + real(r8), intent(in) :: rh + real(r8), intent(in) :: wind + end subroutine update_fire_weather + end interface + +end module SFFireWeatherMod \ No newline at end of file diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index ef245b04f9..8525a0bb6f 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -1,7 +1,7 @@ module SFMainMod ! ============================================================================ - ! All subroutines realted to the SPITFIRE fire routine. + ! All subroutines related to the SPITFIRE fire routine. ! Code originally developed by Allan Spessa & Rosie Fisher as part of the NERC-QUEST project. ! ============================================================================ @@ -77,7 +77,7 @@ module SFMainMod ! ============================================================================ ! Area of site burned by fire ! ============================================================================ - subroutine fire_model( currentSite, bc_in) + subroutine fire_model(currentSite, bc_in) diff --git a/fire/SFNestorvMod.F90 b/fire/SFNestorvMod.F90 new file mode 100644 index 0000000000..860a2ec6f9 --- /dev/null +++ b/fire/SFNestorvMod.F90 @@ -0,0 +1,95 @@ +module SFNesterovMod + + use FatesConstantsMod, only : r8 => fates_r8 + use SFFireWeatherMod, only : fire_weather + + implicit none + private + + type, public, extends(fire_weather) :: nesterov_index + + contains + + procedure, public :: Init => init_nesterov_fire_weather + procedure, public :: Update => update_nesterov_index + procedure :: calc_nesterov_index + + end type nesterov_index + + real(r8), parameter :: min_precip_thresh = 3.0_r8 ! threshold for precipitation above which to 0.0 NI + + contains + + subroutine init_nesterov_fire_weather(this) + ! + ! DESCRIPTION: + ! Initializes class attributes + + ! ARGUMENTS + class(nesterov_index), intent(inout) :: this ! nesterov index extended class + + ! initialize values to 0.0 + this%fire_weather_index = 0.0_r8 + + end subroutine init_nesterov_fire_weather + + !------------------------------------------------------------------------------------- + + subroutine update_nesterov_index(this, temp_C, precip, rh, wind) + ! + ! DESCRIPTION: + ! Updates Nesterov Index + + ! ARGUMENTS + class(nesterov_index), intent(inout) :: this ! nesterov index extended class + real(r8), intent(in) :: temp_C ! daily averaged temperature [degrees C] + real(r8), intent(in) :: precip ! daily precipitation [mm] + real(r8), intent(in) :: rh ! daily relative humidity [%] + real(r8), intent(in) :: wind ! daily wind speed [m/min] + + if (precip > min_precip_thresh) then ! rezero NI if it rains + this%fire_weather_index = 0.0_r8 + else + ! Accumulate Nesterov index over fire season. + this%fire_weather_index = this%fire_weather_index + & + this%calc_nesterov_index(temp_C, precip, rh) + end if + + end subroutine update_nesterov_index + + !------------------------------------------------------------------------------------- + + real(r8) function calc_nesterov_index(this, temp_C, precip, rh) + ! + ! DESCRIPTION: + ! Calculates current day's Nesterov Index for a given input values + + use SFParamsMod, only : SF_val_fdi_a, SF_val_fdi_b + + ! ARGUMENTS: + class(nesterov_index), intent(in) :: this ! nesterov index extended class + real(r8), intent(in) :: temp_C ! daily averaged temperature [degrees C] + real(r8), intent(in) :: precip ! daily precipitation [mm] + real(r8), intent(in) :: rh ! daily relative humidity [rh] + + ! LOCALS: + real(r8) :: yipsolon ! intermediate variable for dewpoint calculation + real(r8) :: dewpoint ! dewpoint + + if (precip > min_precip_thresh) then ! NI is 0.0 if it rains + calc_nesterov_index = 0.0_r8 + else + ! Calculate dewpoint temperature + yipsolon = (SF_val_fdi_a*temp_C)/(SF_val_fdi_b + temp_C) + log(max(1.0_r8, rh)/100.0_r8) + dewpoint = (SF_val_fdi_b*yipsolon)/(SF_val_fdi_a - yipsolon) + + ! Nesterov 1968. Eq 5, Thonicke et al. 2010 + calc_nesterov_index = (temp_C - dewpoint)*temp_C + if (calc_nesterov_index < 0.0_r8) calc_nesterov_index = 0.0_r8 ! can't be negative + endif + + end function calc_nesterov_index + + !------------------------------------------------------------------------------------- + +end module SFNesterovMod \ No newline at end of file diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 4ab881c4f6..25ffbbdf19 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -92,6 +92,7 @@ module EDInitMod use DamageMainMod, only : undamaged_class use FatesConstantsMod, only : n_term_mort_types use FatesInterfaceTypesMod , only : hlm_num_luh2_transitions + use SFNesterovMod, only : nesterov_index ! CIME GLOBALS use shr_log_mod , only : errMsg => shr_log_errMsg @@ -220,6 +221,9 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%seed_in(1:numpft)) allocate(site_in%seed_out(1:numpft)) + allocate(nesterov_index :: site_in%fireWeather) + call site_in%fireWeather%Init() + end subroutine init_site_vars ! ============================================================================ diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index d310f0b84b..7203457fd7 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -31,6 +31,8 @@ module EDTypesMod use EDParamsMod, only : nclmax, nlevleaf, maxpft use FatesConstantsMod, only : n_dbh_bins, n_dist_types use shr_log_mod, only : errMsg => shr_log_errMsg + use SFFireWeatherMod, only : fire_weather + use SFNesterovMod, only : nesterov_index implicit none private ! By default everything is private @@ -339,6 +341,7 @@ module EDTypesMod real(r8) :: fdi ! daily probability an ignition event will start a fire real(r8) :: NF ! daily ignitions in km2 real(r8) :: NF_successful ! daily ignitions in km2 that actually lead to fire + type(fire_weather) :: fireWeather ! PLANT HYDRAULICS type(ed_site_hydr_type), pointer :: si_hydr From 46b26ceb1776f53fa4a6228e54ac9bf29c248bd2 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 12 Mar 2024 16:31:00 -0600 Subject: [PATCH 113/300] use site fire weather object --- fire/SFMainMod.F90 | 132 +++++++++++++++++++------------------------- main/EDTypesMod.F90 | 2 +- 2 files changed, 58 insertions(+), 76 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 8525a0bb6f..af59517004 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -52,7 +52,6 @@ module SFMainMod private public :: fire_model - public :: fire_danger_index public :: charecteristics_of_fuel public :: rate_of_spread public :: ground_fuel_consumption @@ -69,79 +68,72 @@ module SFMainMod integer :: write_SF = ifalse ! for debugging logical :: debug = .false. ! for debugging - ! ============================================================================ - ! ============================================================================ + ! ====================================================================================== contains - ! ============================================================================ - ! Area of site burned by fire - ! ============================================================================ subroutine fire_model(currentSite, bc_in) + ! + ! DESCRIPTION: + ! Runs the daily fire weather model + ! ARGUMENTS: + type(ed_site_type), intent(inout), target :: currentSite ! site object + type(bc_in_type), intent(in) :: bc_in ! BC in object + ! LOCALS: + type (fates_patch_type), pointer :: currentPatch ! patch object - type(ed_site_type) , intent(inout), target :: currentSite - type(bc_in_type) , intent(in) :: bc_in - - - type (fates_patch_type), pointer :: currentPatch - - !zero fire things + ! zero fire things currentPatch => currentSite%youngest_patch do while(associated(currentPatch)) - currentPatch%frac_burnt = 0.0_r8 - currentPatch%fire = 0 - currentPatch => currentPatch%older - enddo - - if(write_SF==itrue)then - write(fates_log(),*) 'spitfire_mode', hlm_spitfire_mode - endif - - if( hlm_spitfire_mode > hlm_sf_nofire_def )then - call fire_danger_index(currentSite, bc_in) - call wind_effect(currentSite, bc_in) - call charecteristics_of_fuel(currentSite) - call rate_of_spread(currentSite) - call ground_fuel_consumption(currentSite) - call area_burnt_intensity(currentSite, bc_in) - call crown_scorching(currentSite) - call crown_damage(currentSite) - call cambial_damage_kill(currentSite) - call post_fire_mortality(currentSite) + currentPatch%frac_burnt = 0.0_r8 + currentPatch%fire = 0 + currentPatch => currentPatch%older + end do + + if (hlm_spitfire_mode > hlm_sf_nofire_def) then + call UpdateFireWeather(currentSite, bc_in) + call wind_effect(currentSite, bc_in) + call charecteristics_of_fuel(currentSite) + call rate_of_spread(currentSite) + call ground_fuel_consumption(currentSite) + call area_burnt_intensity(currentSite, bc_in) + call crown_scorching(currentSite) + call crown_damage(currentSite) + call cambial_damage_kill(currentSite) + call post_fire_mortality(currentSite) end if end subroutine fire_model - !***************************************************************** - subroutine fire_danger_index ( currentSite, bc_in) - - !***************************************************************** - ! currentSite%acc_NI is the accumulated Nesterov fire danger index - - use SFParamsMod, only : SF_val_fdi_a, SF_val_fdi_b - use FatesConstantsMod , only : tfrz => t_water_freeze_k_1atm - use FatesConstantsMod , only : sec_per_day - - type(ed_site_type) , intent(inout), target :: currentSite - type(bc_in_type) , intent(in) :: bc_in + !--------------------------------------------------------------------------------------- + + subroutine UpdateFireWeather(currentSite, bc_in) + ! + ! DESCRIPTION: + ! Updates the site's fire weather index - type(fates_patch_type), pointer :: currentPatch + use SFParamsMod, only : SF_val_fdi_a, SF_val_fdi_b + use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm + use FatesConstantsMod, only : sec_per_day - real(r8) :: temp_in_C ! daily averaged temperature in celcius - real(r8) :: rainfall ! daily precip in mm/day - real(r8) :: rh ! daily rh - - real(r8) :: yipsolon !intermediate varable for dewpoint calculation - real(r8) :: dewpoint !dewpoint in K - real(r8) :: d_NI !daily change in Nesterov Index. C^2 - integer :: iofp ! index of oldest the fates patch + ! ARGUMENTS: + type(ed_site_type), intent(inout), target :: currentSite + type(bc_in_type), intent(in) :: bc_in + + ! LOCALS: + type(fates_patch_type), pointer :: currentPatch ! patch object + real(r8) :: temp_C ! daily averaged temperature [deg C] + real(r8) :: precip ! daily precip [mm/day] + real(r8) :: rh ! daily relative humidity [%] + real(r8) :: wind ! wind speed [m/s] + integer :: iofp ! index of oldest the fates patch ! NOTE that the boundary conditions of temperature, precipitation and relative humidity ! are available at the patch level. We are currently using a simplification where the whole site ! is simply using the values associated with the first patch. - ! which probably won't have much inpact, unless we decide to ever calculated the NI for each patch. + ! which probably won't have much inpact, unless we decide to ever calculated fire weather for each patch. currentPatch => currentSite%oldest_patch @@ -152,30 +144,20 @@ subroutine fire_danger_index ( currentSite, bc_in) endif iofp = currentPatch%patchno - - temp_in_C = currentPatch%tveg24%GetMean() - tfrz - rainfall = bc_in%precip24_pa(iofp)*sec_per_day - rh = bc_in%relhumid24_pa(iofp) - - if (rainfall > 3.0_r8) then !rezero NI if it rains... - d_NI = 0.0_r8 - currentSite%acc_NI = 0.0_r8 - else - yipsolon = (SF_val_fdi_a* temp_in_C)/(SF_val_fdi_b+ temp_in_C)+log(max(1.0_r8,rh)/100.0_r8) - dewpoint = (SF_val_fdi_b*yipsolon)/(SF_val_fdi_a-yipsolon) !Standard met. formula - d_NI = ( temp_in_C-dewpoint)* temp_in_C !follows Nesterov 1968. Equation 5. Thonicke et al. 2010. - if (d_NI < 0.0_r8) then !Change in NI cannot be negative. - d_NI = 0.0_r8 !check - endif - endif - currentSite%acc_NI = currentSite%acc_NI + d_NI !Accumulate Nesterov index over the fire season. + temp_C = currentPatch%tveg24%GetMean() - tfrz + precip = bc_in%precip24_pa(iofp)*sec_per_day + rh = bc_in%relhumid24_pa(iofp) + wind = bc_in%wind24_pa(iofp) - end subroutine fire_danger_index + ! update fire weather index + currentSite%fireWeather%Update(temp_C, precip, rh, wind) + currentSite%acc_ni = currentSite%fireWeather%fire_weather_index + end subroutine UpdateFireWeather + + !--------------------------------------------------------------------------------------- - !***************************************************************** subroutine charecteristics_of_fuel ( currentSite ) - !***************************************************************** use SFParamsMod, only : SF_val_drying_ratio, SF_val_SAV, SF_val_FBD diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 7203457fd7..e22c98fdcd 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -341,7 +341,7 @@ module EDTypesMod real(r8) :: fdi ! daily probability an ignition event will start a fire real(r8) :: NF ! daily ignitions in km2 real(r8) :: NF_successful ! daily ignitions in km2 that actually lead to fire - type(fire_weather) :: fireWeather + class(fire_weather), pointer :: fireWeather ! fire weather object ! PLANT HYDRAULICS type(ed_site_hydr_type), pointer :: si_hydr From 9e863c8d0557ed1e6b70ed2782d3ae4d0ffe78ad Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 12 Mar 2024 16:45:57 -0600 Subject: [PATCH 114/300] bug fix --- fire/SFMainMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index af59517004..69c77c913c 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -150,7 +150,7 @@ subroutine UpdateFireWeather(currentSite, bc_in) wind = bc_in%wind24_pa(iofp) ! update fire weather index - currentSite%fireWeather%Update(temp_C, precip, rh, wind) + call currentSite%fireWeather%Update(temp_C, precip, rh, wind) currentSite%acc_ni = currentSite%fireWeather%fire_weather_index end subroutine UpdateFireWeather From 055fd0098d38f2b48b509307dcc8ead7d8adacbf Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 12 Mar 2024 19:19:40 -0600 Subject: [PATCH 115/300] change acc_ni to nesterov --- fire/SFMainMod.F90 | 11 ++++++----- main/EDInitMod.F90 | 4 ---- main/EDTypesMod.F90 | 1 - main/FatesHistoryInterfaceMod.F90 | 2 +- main/FatesRestartInterfaceMod.F90 | 12 ++++++------ 5 files changed, 13 insertions(+), 17 deletions(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 69c77c913c..b5b9ad0ce6 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -151,7 +151,6 @@ subroutine UpdateFireWeather(currentSite, bc_in) ! update fire weather index call currentSite%fireWeather%Update(temp_C, precip, rh, wind) - currentSite%acc_ni = currentSite%fireWeather%fire_weather_index end subroutine UpdateFireWeather @@ -247,19 +246,21 @@ subroutine charecteristics_of_fuel ( currentSite ) ! Calculate fuel moisture for trunks to hold value for fuel consumption alpha_FMC(tw_sf:dl_sf) = SF_val_SAV(tw_sf:dl_sf)/SF_val_drying_ratio - fuel_moisture(tw_sf:dl_sf) = exp(-1.0_r8 * alpha_FMC(tw_sf:dl_sf) * currentSite%acc_NI) + fuel_moisture(tw_sf:dl_sf) = exp(-1.0_r8 * alpha_FMC(tw_sf:dl_sf) * & + currentSite%fireWeather%fire_weather_index) if(write_SF == itrue)then if ( hlm_masterproc == itrue ) write(fates_log(),*) 'ff3 ',currentPatch%fuel_frac if ( hlm_masterproc == itrue ) write(fates_log(),*) 'fm ',fuel_moisture - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'csa ',currentSite%acc_NI + if ( hlm_masterproc == itrue ) write(fates_log(),*) 'csa ',currentSite%fireWeather%fire_weather_index if ( hlm_masterproc == itrue ) write(fates_log(),*) 'sfv ',alpha_FMC endif ! live grass moisture is a function of SAV and changes via Nesterov Index ! along the same relationship as the 1 hour fuels (live grass has same SAV as dead grass, ! but retains more moisture with this calculation.) - fuel_moisture(lg_sf) = exp(-1.0_r8 * ((SF_val_SAV(tw_sf)/SF_val_drying_ratio) * currentSite%acc_NI)) + fuel_moisture(lg_sf) = exp(-1.0_r8 * ((SF_val_SAV(tw_sf)/SF_val_drying_ratio) * & + currentSite%fireWeather%fire_weather_index)) ! Average properties over the first three litter pools (twigs, s branches, l branches) currentPatch%fuel_bulkd = sum(currentPatch%fuel_frac(tw_sf:lb_sf) * SF_val_FBD(tw_sf:lb_sf)) @@ -715,7 +716,7 @@ subroutine area_burnt_intensity ( currentSite, bc_in ) ! force ignition potential to be extreme cloud_to_ground_strikes = 1.0_r8 ! cloud_to_ground = 1 = use 100% incoming observed ignitions else ! USING LIGHTNING DATA - currentSite%FDI = 1.0_r8 - exp(-SF_val_fdi_alpha*currentSite%acc_NI) + currentSite%FDI = 1.0_r8 - exp(-SF_val_fdi_alpha*currentSite%fireWeather%fire_weather_index) cloud_to_ground_strikes = cg_strikes end if diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 25ffbbdf19..e33ee5e7ec 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -274,7 +274,6 @@ subroutine zero_site( site_in ) site_in%disturbance_rates(:,:,:) = 0.0_r8 ! FIRE - site_in%acc_ni = 0.0_r8 ! daily nesterov index accumulating over time. time unlimited theoretically. site_in%FDI = 0.0_r8 ! daily fire danger index (0-1) site_in%NF = 0.0_r8 ! daily lightning strikes per km2 site_in%NF_successful = 0.0_r8 ! daily successful iginitions per km2 @@ -373,7 +372,6 @@ subroutine set_site_properties( nsites, sites,bc_in ) integer :: cstat ! cold status phenology flag real(r8) :: GDD integer :: dstat ! drought status phenology flag - real(r8) :: acc_NI real(r8) :: liqvolmem real(r8) :: smpmem real(r8) :: elong_factor ! Elongation factor (0 - fully off; 1 - fully on) @@ -405,7 +403,6 @@ subroutine set_site_properties( nsites, sites,bc_in ) cndleafon = 0 cndleafoff = 0 cstat = phen_cstat_notcold ! Leaves are on - acc_NI = 0.0_r8 dstat = phen_dstat_moiston ! Leaves are on dleafoff = 300 dleafon = 100 @@ -440,7 +437,6 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%dstatus(1:numpft) = dstat sites(s)%elong_factor(1:numpft) = elong_factor - sites(s)%acc_NI = acc_NI sites(s)%NF = 0.0_r8 sites(s)%NF_successful = 0.0_r8 sites(s)%area_pft(:) = 0.0_r8 diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index e22c98fdcd..c3f71d6ff8 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -337,7 +337,6 @@ module EDTypesMod ! FIRE real(r8) :: wind ! daily wind in m/min for Spitfire units - real(r8) :: acc_ni ! daily nesterov index accumulating over time. real(r8) :: fdi ! daily probability an ignition event will start a fire real(r8) :: NF ! daily ignitions in km2 real(r8) :: NF_successful ! daily ignitions in km2 that actually lead to fire diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 71013177ec..9edabe933a 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2734,7 +2734,7 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) ! site-level fire variables: ! Nesterov index (unitless) - hio_nesterov_fire_danger_si(io_si) = sites(s)%acc_NI + hio_nesterov_fire_danger_si(io_si) = sites(s)%fireWeather%fire_weather_index ! number of ignitions [#/km2/day -> #/m2/s] hio_fire_nignitions_si(io_si) = sites(s)%NF_successful / m2_per_km2 / & diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 90e282253b..ffef39eb6f 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -99,7 +99,7 @@ module FatesRestartInterfaceMod integer :: ir_cndaysleafon_si integer :: ir_cndaysleafoff_si integer :: ir_phenmodeldate_si - integer :: ir_acc_ni_si + integer :: ir_fireweather_index_si integer :: ir_gdd_si integer :: ir_snow_depth_si integer :: ir_trunk_product_si @@ -704,7 +704,7 @@ subroutine define_restart_vars(this, initialize_variables) call this%set_restart_var(vname='fates_acc_nesterov_id', vtype=site_r8, & long_name='a nesterov index accumulator', units='unitless', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_acc_ni_si ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fireweather_index_si ) call this%set_restart_var(vname='fates_gdd_site', vtype=site_r8, & long_name='growing degree days at each site', units='degC days', flushval = flushzero, & @@ -2034,7 +2034,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_cndaysleafon_si => this%rvars(ir_cndaysleafon_si)%int1d, & rio_cndaysleafoff_si => this%rvars(ir_cndaysleafoff_si)%int1d, & rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & - rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & + rio_fireweather_index_si => this%rvars(ir_fireweather_index_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & @@ -2638,7 +2638,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) - rio_acc_ni_si(io_idx_si) = sites(s)%acc_NI + rio_fireweather_index_si(io_idx_si) = sites(s)%fireWeather%fire_weather_index rio_snow_depth_si(io_idx_si) = sites(s)%snow_depth ! Accumulated trunk product @@ -3001,7 +3001,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_cndaysleafon_si => this%rvars(ir_cndaysleafon_si)%int1d, & rio_cndaysleafoff_si => this%rvars(ir_cndaysleafoff_si)%int1d, & rio_phenmodeldate_si => this%rvars(ir_phenmodeldate_si)%int1d, & - rio_acc_ni_si => this%rvars(ir_acc_ni_si)%r81d, & + rio_fireweather_index_si => this%rvars(ir_fireweather_index_si)%r81d, & rio_gdd_si => this%rvars(ir_gdd_si)%r81d, & rio_snow_depth_si => this%rvars(ir_snow_depth_si)%r81d, & rio_trunk_product_si => this%rvars(ir_trunk_product_si)%r81d, & @@ -3643,7 +3643,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) - sites(s)%acc_NI = rio_acc_ni_si(io_idx_si) + sites(s)%fireWeather%fire_weather_index = rio_fireweather_index_si(io_idx_si) sites(s)%snow_depth = rio_snow_depth_si(io_idx_si) sites(s)%resources_management%trunk_product_site = rio_trunk_product_si(io_idx_si) From 9d2724488738d30188571553c81f4254525516f4 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 12 Mar 2024 21:55:10 -0600 Subject: [PATCH 116/300] add unit test --- CMakeLists.txt | 74 +++++++++++++++++++ biogeochem/CMakeLists.txt | 9 +++ biogeophys/CMakeLists.txt | 5 ++ fire/CMakeLists.txt | 8 ++ fire/{SFNestorvMod.F90 => SFNesterovMod.F90} | 0 fire/SFParamsMod.F90 | 4 +- fire/test/CMakeLists.txt | 1 + fire/test/fire_weather_test/CMakeLists.txt | 5 ++ .../fire_weather_test/test_FireWeather.pf | 70 ++++++++++++++++++ main/CMakeLists.txt | 17 +++++ parteh/CMakeLists.txt | 8 ++ radiation/CMakeLists.txt | 6 ++ 12 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 biogeochem/CMakeLists.txt create mode 100644 biogeophys/CMakeLists.txt create mode 100644 fire/CMakeLists.txt rename fire/{SFNestorvMod.F90 => SFNesterovMod.F90} (100%) create mode 100644 fire/test/CMakeLists.txt create mode 100644 fire/test/fire_weather_test/CMakeLists.txt create mode 100644 fire/test/fire_weather_test/test_FireWeather.pf create mode 100644 parteh/CMakeLists.txt create mode 100644 radiation/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..5d37d14a81 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,74 @@ +cmake_minimum_required(VERSION 3.4) + +list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) +include(CIME_initial_setup) + +project(FATES_tests Fortran C) + +include(CIME_utils) + +set(HLM_ROOT "../../") + +# Add source directories from other share code (csm_share, etc.) +add_subdirectory(${HLM_ROOT}/share/src csm_share) +add_subdirectory(${HLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) + +# Add FATES source directories +add_subdirectory(${HLM_ROOT}/src/fates/main fates_main) +add_subdirectory(${HLM_ROOT}/src/fates/biogeochem fates_biogeochem) +add_subdirectory(${HLM_ROOT}/src/fates/biogeophys fates_biogeophys) +add_subdirectory(${HLM_ROOT}/src/fates/parteh fates_parteh) +add_subdirectory(${HLM_ROOT}/src/fates/fire fates_fire) +add_subdirectory(${HLM_ROOT}/src/fates/radiation fates_radiation) + +# Remove shr_mpi_mod from share_sources. +# This is needed because we want to use the mock shr_mpi_mod in place of the real one +# +# TODO: this should be moved into a general-purpose function in Sourcelist_utils. +# Then this block of code could be replaced with a single call, like: +# remove_source_file(${share_sources} "shr_mpi_mod.F90") +foreach (sourcefile ${share_sources}) + string(REGEX MATCH "shr_mpi_mod.F90" match_found ${sourcefile}) + if(match_found) + list(REMOVE_ITEM share_sources ${sourcefile}) + endif() +endforeach() + +# Remove shr_cal_mod from share_sources. +# +# shr_cal_mod depends on ESMF (or the lightweight esmf wrf timemgr, at +# least). Since CTSM doesn't currently use shr_cal_mod, we're avoiding +# the extra overhead of including esmf_wrf_timemgr sources in this +# build. +# +# TODO: like above, this should be moved into a general-purpose function +# in Sourcelist_utils. Then this block of code could be replaced with a +# single call, like: remove_source_file(${share_sources} +# "shr_cal_mod.F90") +foreach (sourcefile ${share_sources}) + string(REGEX MATCH "shr_cal_mod.F90" match_found ${sourcefile}) + if(match_found) + list(REMOVE_ITEM share_sources ${sourcefile}) + endif() +endforeach() + +# Build libraries containing stuff needed for the unit tests. +# Eventually, these add_library calls should probably be distributed into the correct location, rather than being in this top-level CMakeLists.txt file. +add_library(csm_share ${share_sources}) +declare_generated_dependencies(csm_share "${share_genf90_sources}") +add_library(fates ${fates_sources}) +add_dependencies(fates csm_share) + +# We need to look for header files here, in order to pick up shr_assert.h +include_directories(${HLM_ROOT}/share/include) + +# Tell cmake to look for libraries & mod files here, because this is where we built libraries +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +link_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Add the test directories +# Note: it's possible that these could be added by each source directory that +# has tests in it. However, it appears that the order needs to be done +# carefully: for example, include_directories and link_directories needs to be +# done before adding the tests themselves. +add_subdirectory(${HLM_ROOT}/src/fates/fire/test fates_fire_test) \ No newline at end of file diff --git a/biogeochem/CMakeLists.txt b/biogeochem/CMakeLists.txt new file mode 100644 index 0000000000..7cea7da00e --- /dev/null +++ b/biogeochem/CMakeLists.txt @@ -0,0 +1,9 @@ +list(APPEND fates_sources + FatesLitterMod.F90 + FatesCohortMod.F90 + FatesAllometryMod.F90 + DamageMainMod.F90 + FatesPatchMod.F90 + ) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/biogeophys/CMakeLists.txt b/biogeophys/CMakeLists.txt new file mode 100644 index 0000000000..a4252bcabf --- /dev/null +++ b/biogeophys/CMakeLists.txt @@ -0,0 +1,5 @@ +list(APPEND fates_sources + FatesHydroWTFMod.F90 + ) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/fire/CMakeLists.txt b/fire/CMakeLists.txt new file mode 100644 index 0000000000..0dff75efeb --- /dev/null +++ b/fire/CMakeLists.txt @@ -0,0 +1,8 @@ +list(APPEND fates_sources + SFMainMod.F90 + SFParamsMod.F90 + SFFireWeatherMod.F90 + SFNesterovMod.F90 + ) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/fire/SFNestorvMod.F90 b/fire/SFNesterovMod.F90 similarity index 100% rename from fire/SFNestorvMod.F90 rename to fire/SFNesterovMod.F90 diff --git a/fire/SFParamsMod.F90 b/fire/SFParamsMod.F90 index 306034a804..e07777f25d 100644 --- a/fire/SFParamsMod.F90 +++ b/fire/SFParamsMod.F90 @@ -19,8 +19,8 @@ module SFParamsMod ! this is what the user can use for the actual values ! - real(r8),protected, public :: SF_val_fdi_a - real(r8),protected, public :: SF_val_fdi_b + real(r8), public :: SF_val_fdi_a + real(r8), public :: SF_val_fdi_b real(r8),protected, public :: SF_val_fdi_alpha real(r8),protected, public :: SF_val_miner_total real(r8),protected, public :: SF_val_fuel_energy diff --git a/fire/test/CMakeLists.txt b/fire/test/CMakeLists.txt new file mode 100644 index 0000000000..4dcfa244d4 --- /dev/null +++ b/fire/test/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(fire_weather_test) \ No newline at end of file diff --git a/fire/test/fire_weather_test/CMakeLists.txt b/fire/test/fire_weather_test/CMakeLists.txt new file mode 100644 index 0000000000..2a3554cd86 --- /dev/null +++ b/fire/test/fire_weather_test/CMakeLists.txt @@ -0,0 +1,5 @@ +set(pfunit_sources test_FireWeather.pf) + +add_pfunit_ctest(FireWeather + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES fates csm_share) \ No newline at end of file diff --git a/fire/test/fire_weather_test/test_FireWeather.pf b/fire/test/fire_weather_test/test_FireWeather.pf new file mode 100644 index 0000000000..21338b5f90 --- /dev/null +++ b/fire/test/fire_weather_test/test_FireWeather.pf @@ -0,0 +1,70 @@ +module test_FireWeather + ! + ! DESCRIPTION: + ! Test the FATES fire weather portion of the SPITFIRE model + ! + use FatesConstantsMod, only : r8 => fates_r8 + use SFFireWeatherMod, only : fire_weather + use SFNesterovMod, only : nesterov_index + use SFParamsMod, only : SF_val_fdi_a, SF_val_fdi_b + use funit + + implicit none + + @TestCase + type, extends(TestCase) :: TestFireWeather + + class(fire_weather), allocatable :: fireWeatherNesterov + + contains + procedure :: setUp + procedure :: tearDown + end type TestFireWeather + + real(r8), parameter :: tol = 1.e-13_r8 + + contains + + subroutine setUp(this) + class(TestFireWeather), intent(inout) :: this + allocate(nesterov_index :: this%fireWeatherNesterov) + call this%fireWeatherNesterov%Init() + SF_val_fdi_a = 17.62_r8 + SF_val_fdi_b = 243.12_r8 + end subroutine setUp + + subroutine tearDown(this) + class(TestFireWeather), intent(inout) :: this + if (allocated(this%fireWeatherNesterov)) deallocate(this%fireWeatherNesterov) + end subroutine tearDown + + @Test + subroutine zero_NI_rain(this) + ! test that over 3 mm of rain is 0.0 + class(TestFireWeather), intent(inout) :: this ! fire weather object + + call this%fireWeatherNesterov%Update(25.0_r8, 3.1_r8, 10.0_r8, 0.0_r8) + @assertEqual(this%fireWeatherNesterov%fire_weather_index, 0.0_r8, tolerance=tol) + this%fireWeatherNesterov%fire_weather_index = 0.0_r8 + end subroutine zero_NI_rain + + @Test + subroutine NI_rain_min(this) + ! test that at 3 mm is over zero + class(TestFireWeather), intent(inout) :: this ! fire weather object + + call this%fireWeatherNesterov%Update(25.0_r8, 3.0_r8, 10.0_r8, 0.0_r8) + @assertGreaterThan(this%fireWeatherNesterov%fire_weather_index, 0.0_r8, tolerance=tol) + this%fireWeatherNesterov%fire_weather_index = 0.0_r8 + end subroutine NI_rain_min + + @Test + subroutine NI_not_negative(this) + ! test that NI is not negative + class(TestFireWeather), intent(inout) :: this ! fire weather object + + call this%fireWeatherNesterov%Update(-30.0_r8, 0.0_r8, 99.0_r8, 0.0_r8) + @assertEqual(this%fireWeatherNesterov%fire_weather_index, 0.0_r8, tolerance=tol) + end subroutine NI_not_negative + + end module test_FireWeather \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index dfd5eaba2a..d2be271c71 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -11,4 +11,21 @@ list(APPEND clm_sources FatesUtilsMod.F90 ) +list(APPEND fates_sources + FatesConstantsMod.F90 + FatesGlobals.F90 + FatesParametersInterface.F90 + FatesInterfaceTypesMod.F90 + EDTypesMod.F90 + FatesHydraulicsMemMod.F90 + FatesRunningMeanMod.F90 + EDParamsMod.F90 + FatesParameterDerivedMod.F90 + EDPftVarcon.F90 + FatesSizeAgeTypeIndicesMod.F90 + FatesIntegratorsMod.F90 + FatesUtilsMod.F90 + ) + +sourcelist_to_parent(fates_sources) sourcelist_to_parent(clm_sources) diff --git a/parteh/CMakeLists.txt b/parteh/CMakeLists.txt new file mode 100644 index 0000000000..bf9981b509 --- /dev/null +++ b/parteh/CMakeLists.txt @@ -0,0 +1,8 @@ +list(APPEND fates_sources + PRTGenericMod.F90 + PRTParametersMod.F90 + PRTAllometricCarbonMod.F90 + PRTAllometricCNPMod.F90 + ) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/radiation/CMakeLists.txt b/radiation/CMakeLists.txt new file mode 100644 index 0000000000..84e72877ec --- /dev/null +++ b/radiation/CMakeLists.txt @@ -0,0 +1,6 @@ +list(APPEND fates_sources + TwoStreamMLPEMod.F90 + FatesRadiationMemMod.F90 + ) + +sourcelist_to_parent(fates_sources) \ No newline at end of file From 1e1be1c64af0e686eead750d3e165870bcd5e5da Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 13 Mar 2024 09:41:18 -0600 Subject: [PATCH 117/300] update unit test --- CMakeLists.txt | 2 -- biogeochem/CMakeLists.txt | 4 ---- biogeophys/CMakeLists.txt | 5 ----- fire/CMakeLists.txt | 1 - main/CMakeLists.txt | 12 +----------- parteh/CMakeLists.txt | 8 -------- radiation/CMakeLists.txt | 1 - 7 files changed, 1 insertion(+), 32 deletions(-) delete mode 100644 biogeophys/CMakeLists.txt delete mode 100644 parteh/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d37d14a81..00544cc654 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,6 @@ add_subdirectory(${HLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) # Add FATES source directories add_subdirectory(${HLM_ROOT}/src/fates/main fates_main) add_subdirectory(${HLM_ROOT}/src/fates/biogeochem fates_biogeochem) -add_subdirectory(${HLM_ROOT}/src/fates/biogeophys fates_biogeophys) -add_subdirectory(${HLM_ROOT}/src/fates/parteh fates_parteh) add_subdirectory(${HLM_ROOT}/src/fates/fire fates_fire) add_subdirectory(${HLM_ROOT}/src/fates/radiation fates_radiation) diff --git a/biogeochem/CMakeLists.txt b/biogeochem/CMakeLists.txt index 7cea7da00e..692e22d9dc 100644 --- a/biogeochem/CMakeLists.txt +++ b/biogeochem/CMakeLists.txt @@ -1,9 +1,5 @@ list(APPEND fates_sources FatesLitterMod.F90 - FatesCohortMod.F90 - FatesAllometryMod.F90 - DamageMainMod.F90 - FatesPatchMod.F90 ) sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/biogeophys/CMakeLists.txt b/biogeophys/CMakeLists.txt deleted file mode 100644 index a4252bcabf..0000000000 --- a/biogeophys/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -list(APPEND fates_sources - FatesHydroWTFMod.F90 - ) - -sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/fire/CMakeLists.txt b/fire/CMakeLists.txt index 0dff75efeb..2cd6b992d1 100644 --- a/fire/CMakeLists.txt +++ b/fire/CMakeLists.txt @@ -1,5 +1,4 @@ list(APPEND fates_sources - SFMainMod.F90 SFParamsMod.F90 SFFireWeatherMod.F90 SFNesterovMod.F90 diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index d2be271c71..173d5c9f45 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -10,21 +10,11 @@ list(APPEND clm_sources FatesParametersInterface.F90 FatesUtilsMod.F90 ) - + list(APPEND fates_sources FatesConstantsMod.F90 FatesGlobals.F90 FatesParametersInterface.F90 - FatesInterfaceTypesMod.F90 - EDTypesMod.F90 - FatesHydraulicsMemMod.F90 - FatesRunningMeanMod.F90 - EDParamsMod.F90 - FatesParameterDerivedMod.F90 - EDPftVarcon.F90 - FatesSizeAgeTypeIndicesMod.F90 - FatesIntegratorsMod.F90 - FatesUtilsMod.F90 ) sourcelist_to_parent(fates_sources) diff --git a/parteh/CMakeLists.txt b/parteh/CMakeLists.txt deleted file mode 100644 index bf9981b509..0000000000 --- a/parteh/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -list(APPEND fates_sources - PRTGenericMod.F90 - PRTParametersMod.F90 - PRTAllometricCarbonMod.F90 - PRTAllometricCNPMod.F90 - ) - -sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/radiation/CMakeLists.txt b/radiation/CMakeLists.txt index 84e72877ec..7cb7a324c2 100644 --- a/radiation/CMakeLists.txt +++ b/radiation/CMakeLists.txt @@ -1,6 +1,5 @@ list(APPEND fates_sources TwoStreamMLPEMod.F90 - FatesRadiationMemMod.F90 ) sourcelist_to_parent(fates_sources) \ No newline at end of file From 214908da0710e43bbcdd36dcec7b502ba8d0e23d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 13 Mar 2024 11:48:14 -0400 Subject: [PATCH 118/300] Updated text and comments in history dimensioning --- main/FatesHistoryInterfaceMod.F90 | 67 ++----------------------------- main/FatesHistoryVariableType.F90 | 13 ++++-- 2 files changed, 14 insertions(+), 66 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 926567b7cb..9838bbf383 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2282,63 +2282,18 @@ subroutine update_history_dyn(this,nc,nsites,sites,bc_in) type(bc_in_type) , intent(in) :: bc_in(nsites) ! Locals - !type(site_fluxdiags_type), pointer :: flux_diags - !type(site_fluxdiags_type), pointer :: flux_diags_c - !integer :: s ! The local site index - !integer :: io_si ! The site index of the IO array - !integer :: ipa, ipa2 ! The local "I"ndex of "PA"tches - !integer :: ft ! functional type index - !integer :: elcwd, elpft ! combined index of element and pft or cwd - !integer :: i_scpf,i_pft,i_scls ! iterators for scpf, pft, and scls dims - !integer :: i_cacls, i_capf ! iterators for cohort age and cohort age x pft - !integer :: el ! Loop index for elements - !real(r8) :: store_max ! The target nutrient mass for storage element of interest [kg] - !real(r8) :: n_perm2 ! individuals per m2 for the whole column - !real(r8) :: dbh ! diameter ("at breast height") - !real(r8) :: coage ! cohort age - !real(r8) :: npp_partition_error ! a check that the NPP partitions sum to carbon allocation - - ! The following are all carbon states, turnover and net allocation flux variables - ! the organs of relevance should be self explanatory - ! real(r8) :: sapw_m ! Sapwood mass (elemental, c,n or p) [kg/plant] - ! real(r8) :: struct_m ! Structural mass "" - ! real(r8) :: leaf_m ! Leaf mass "" - ! real(r8) :: fnrt_m ! Fineroot mass "" - ! real(r8) :: store_m ! Storage mass "" - ! real(r8) :: alive_m ! Alive biomass (sap+leaf+fineroot+repro+storage) "" - ! real(r8) :: total_m ! Total vegetation mass - ! real(r8) :: repro_m ! Total reproductive mass (on plant) "" - ! real(r8) :: sapw_m_turnover ! Sapwood turnover rate - ! real(r8) :: store_m_turnover - ! real(r8) :: leaf_m_turnover - ! real(r8) :: fnrt_m_turnover - ! real(r8) :: struct_m_turnover - ! real(r8) :: sapw_m_net_alloc - ! real(r8) :: store_m_net_alloc - ! real(r8) :: leaf_m_net_alloc - ! real(r8) :: fnrt_m_net_alloc - ! real(r8) :: struct_m_net_alloc - ! real(r8) :: repro_m_net_alloc - ! integer :: return_code - ! type(fates_patch_type),pointer :: cpatch - ! type(fates_cohort_type),pointer :: ccohort - ! integer :: tmp - ! If we don't have dynamics turned on, we just abort these diagnostics - ! CONVERT THIS TO FORCE DYNAM LEVEL 0 - ! MAKE SURE THAT MARCOS' PHENOLOGY PR DOES NOT GET MESSED - ! UP ON THE MERGE. ST3 SHOULD ALLOW FOR ALL STATES, BUT - ! NO FLUXES IN THE FUTURE + ! There is future work slated to split dynamics diagnostics into those + ! related to states, and those related to fluxes. States should be fine + ! to report in ST3 mode. + if (hlm_use_ed_st3.eq.itrue) return if(hlm_hist_level_dynam>0) then call update_history_dyn1(this,nc,nsites,sites,bc_in) if(hlm_hist_level_dynam>1) then call update_history_dyn2(this,nc,nsites,sites,bc_in) - !if(hlm_hist_level_dynam>2) then - ! call update_history_dyn3(this,nc,nsites,sites,bc_in) - !end if end if end if return @@ -2618,7 +2573,6 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_seeds_in_si(io_si) = 0._r8 hio_seeds_in_local_si(io_si) = 0._r8 - ! Loop through patches to sum up diagonistics ipa = 0 cpatch => sites(s)%oldest_patch @@ -3701,7 +3655,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) hio_npp_stor_si_scpf(io_si,scpf) = hio_npp_stor_si_scpf(io_si,scpf) + & store_m_net_alloc*n_perm2 / days_per_year / sec_per_day - ! Woody State Variables (basal area growth increment) if ( prt_params%woody(ft) == itrue) then @@ -4548,18 +4501,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) flux_diags_c => sites(s)%flux_diags(element_pos(carbon12_element)) - - - cpatch => sites(s)%oldest_patch - do while(associated(cpatch)) - - - - - - cpatch => cpatch%younger - end do - ! ------------------------------------------------------------------------------ ! Diagnostics discretized by element type ! ------------------------------------------------------------------------------ diff --git a/main/FatesHistoryVariableType.F90 b/main/FatesHistoryVariableType.F90 index c2a890355e..b24bb1bf86 100644 --- a/main/FatesHistoryVariableType.F90 +++ b/main/FatesHistoryVariableType.F90 @@ -41,9 +41,16 @@ module FatesHistoryVariableType ! or infrequently used output datasets character(len=24) :: vtype character(len=1) :: avgflag - integer :: upfreq ! Update frequency (this is for checks and flushing) - ! 1 = dynamics "dyn" (daily) - ! 2 = production "prod" (prob model tstep) + integer :: upfreq ! Update frequency (this is for checks and flushing) + ! dynamics, high-frequency and hydraulic output, + ! split up by complex and non-complex dimensioning + ! group_dyna_simple = 1 + ! group_dyna_complx = 2 + ! group_hifr_simple = 3 + ! group_hifr_complx = 4 + ! group_hydr_simple = 5 + ! group_hydr_complx = 6 + real(r8) :: flushval integer :: dim_kinds_index ! Pointers (only one of these is allocated per variable) From 466729b39421dab08110f2601bddd2ae795aa771 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 13 Mar 2024 09:53:39 -0600 Subject: [PATCH 119/300] updated comments history dimension --- main/FatesInterfaceTypesMod.F90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 183e251ace..a36d5195f4 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -204,8 +204,7 @@ module FatesInterfaceTypesMod ! THe "_hifrq" refers to history fields that can be updated on the model (high-frequency) step ! 0 = no output ! 1 = site-level averages only - ! 2 = allow the second dimension, but nothing multi-plexed - ! 3 = allow the second dimension and include everything, including multiplexed + ! 2 = allow the second dimension integer, public :: hlm_hist_level_dynam From fce4287b45b738a6438780d65a77c3d718bbc4c4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 13 Mar 2024 14:20:02 -0400 Subject: [PATCH 120/300] Updated error reporting in 1d taylor solve for hydro --- biogeophys/FatesPlantHydraulicsMod.F90 | 57 +++++++++++++------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index e38e042252..0fe4829f97 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -3993,28 +3993,39 @@ subroutine Report1DError(cohort, csite_hydr, ilayer, z_node, v_node, & write(fates_log(),*) 'psi_z: ',h_node(:)-psi_node(:) write(fates_log(),*) 'vol, theta, H, Psi, kmax-' write(fates_log(),*) 'flux: ', q_top_eff*dt_step - write(fates_log(),*) 'l:',v_node(1),th_node(1),h_node(1),psi_node(1) - write(fates_log(),*) ' ',cohort_hydr%kmax_stem_upper(1)*rootfr_scaler - write(fates_log(),*) 's:',v_node(2),th_node(2),h_node(2),psi_node(2) - write(fates_log(),*) ' ',1._r8/(1._r8/(cohort_hydr%kmax_stem_lower(1)*rootfr_scaler) + 1._r8/(cohort_hydr%kmax_troot_upper*rootfr_scaler)) - write(fates_log(),*) 't:',v_node(3),th_node(3),h_node(3) - write(fates_log(),*) ' ',1._r8/(1._r8/cohort_hydr%kmax_troot_lower(ilayer)+ 1._r8/cohort_hydr%kmax_aroot_upper(ilayer)) - write(fates_log(),*) 'a:',v_node(4),th_node(4),h_node(4) - write(fates_log(),*) ' in:',1._r8/(1._r8/cohort_hydr%kmax_aroot_radial_in(ilayer) + & + + do i = 1,n_hypool_leaf + k = i + write(fates_log(),*) 'leaf node ',k,v_node(k),th_node(k),h_node(k),psi_node(k) + end do + do i = 1,n_hypool_stem + k = i+n_hypool_leaf + write(fates_log(),*) 'stem node',k,v_node(k),th_node(k),h_node(k),psi_node(k) + write(fates_log(),*) ' ',cohort_hydr%kmax_stem_upper(k)*rootfr_scaler + end do + write(fates_log(),*) 'troot to stem kmax: ', & + 1._r8/(1._r8/(cohort_hydr%kmax_stem_lower(n_hypool_stem)*rootfr_scaler) + 1._r8/(cohort_hydr%kmax_troot_upper*rootfr_scaler)) + k = n_hypool_leaf + n_hypool_stem + 1 + write(fates_log(),*) 'troot node:',k,v_node(k),th_node(k),h_node(k) + write(fates_log(),*) 'aroot to troot kmax: ', & + 1._r8/(1._r8/cohort_hydr%kmax_troot_lower(ilayer)+ 1._r8/cohort_hydr%kmax_aroot_upper(ilayer)) + k = n_hypool_leaf + n_hypool_stem + 2 + write(fates_log(),*) 'aroot node:',k,v_node(k),th_node(k),h_node(k) + write(fates_log(),*) ' kmax soil-root in:',1._r8/(1._r8/cohort_hydr%kmax_aroot_radial_in(ilayer) + & 1._r8/(csite_hydr%kmax_upper_shell(ilayer,1)*aroot_frac_plant) + & 1._r8/cohort_hydr%kmax_aroot_upper(ilayer)) - write(fates_log(),*) ' out:',1._r8/(1._r8/cohort_hydr%kmax_aroot_radial_out(ilayer) + & + write(fates_log(),*) ' kmax soil-root out:',1._r8/(1._r8/cohort_hydr%kmax_aroot_radial_out(ilayer) + & 1._r8/(csite_hydr%kmax_upper_shell(ilayer,1)*aroot_frac_plant) + & 1._r8/cohort_hydr%kmax_aroot_upper(ilayer)) - write(fates_log(),*) 'r1:',v_node(5),th_node(5),h_node(5) - write(fates_log(),*) ' ',1._r8/(1._r8/(csite_hydr%kmax_lower_shell(ilayer,1)*aroot_frac_plant) + 1._r8/(csite_hydr%kmax_upper_shell(ilayer,2)*aroot_frac_plant)) - write(fates_log(),*) 'r2:',v_node(6),th_node(6),h_node(6) - write(fates_log(),*) ' ',1._r8/(1._r8/(csite_hydr%kmax_lower_shell(ilayer,2)*aroot_frac_plant) + 1._r8/(csite_hydr%kmax_upper_shell(ilayer,3)*aroot_frac_plant)) - write(fates_log(),*) 'r3:',v_node(7),th_node(7),h_node(7) - write(fates_log(),*) ' ',1._r8/(1._r8/(csite_hydr%kmax_lower_shell(ilayer,3)*aroot_frac_plant) + 1._r8/(csite_hydr%kmax_upper_shell(ilayer,4)*aroot_frac_plant)) - write(fates_log(),*) 'r4:',v_node(8),th_node(8),h_node(8) - write(fates_log(),*) ' ',1._r8/(1._r8/(csite_hydr%kmax_lower_shell(ilayer,4)*aroot_frac_plant) + 1._r8/(csite_hydr%kmax_upper_shell(ilayer,5)*aroot_frac_plant)) - write(fates_log(),*) 'r5:',v_node(9),th_node(9),h_node(9) + do i = 1,nshell + k = = n_hypool_leaf + n_hypool_stem + 2 + i + write(fates_log(),*) 'rhizo shell k:',k,v_node(k),th_node(k),h_node(k) + if(i Date: Wed, 13 Mar 2024 16:32:03 -0700 Subject: [PATCH 121/300] refactoring the daylength factor application This reduces code duplication somewhat by updating a local value of the daylength factor based on the switch value. I also changed the switch to be zero for off and one for on to utilize the existing itrue/ifalse constants. --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 33 +++++++--------------- parameter_files/fates_params_default.cdl | 2 +- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 1d947d74bb..b750dff1ab 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -110,10 +110,6 @@ module FATESPlantRespPhotosynthMod integer, parameter :: medlyn_model = 2 integer, parameter :: ballberry_model = 1 - ! Constants used to define day_length switch for scaling photosynthetic parameters - integer, parameter :: dayl_on = 1 - integer, parameter :: dayl_off = 2 - ! Alternatively, Gross Assimilation can be used to estimate ! leaf co2 partial pressure and therefore conductance. The default ! is to use anet @@ -2449,7 +2445,8 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & ! (umol electrons/m**2/s) real(r8) :: co2_rcurve_islope25 ! leaf layer: Initial slope of CO2 response curve ! (C4 plants) at 25C - integer :: c3c4_path_index ! Index for which photosynthetic pathway + integer :: c3c4_path_index ! Index for which photosynthetic pathway + real(r8) :: dayl_factor_local ! Local version of daylength factor ! Parameters ! --------------------------------------------------------------------------------- @@ -2497,12 +2494,17 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & co2_rcurve_islope = 0._r8 else ! day time - if ( dayl_switch == dayl_on ) then + if ( dayl_switch == itrue ) then + dayl_factor_local = dayl_factor + else + dayl_factor_local = 1.0_r8 + endif + ! Vcmax25top was already calculated to derive the nscaler function - vcmax25 = vcmax25top_ft * nscaler * dayl_factor + vcmax25 = vcmax25top_ft * nscaler * dayl_factor_local select case(photo_tempsens_model) case (photosynth_acclim_model_none) - jmax25 = jmax25top_ft * nscaler * dayl_factor + jmax25 = jmax25top_ft * nscaler * dayl_factor_local case (photosynth_acclim_model_kumarathunge_etal_2019) jmax25 = vcmax25*jvr case default @@ -2510,21 +2512,6 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & call endrun(msg=errMsg(sourcefile, __LINE__)) end select - else if ( dayl_switch == dayl_off ) then - ! Vcmax25top was already calculated to derive the nscaler function - vcmax25 = vcmax25top_ft * nscaler - select case(photo_tempsens_model) - case (photosynth_acclim_model_none) - jmax25 = jmax25top_ft * nscaler - case (photosynth_acclim_model_kumarathunge_etal_2019) - jmax25 = vcmax25*jvr - case default - write (fates_log(),*)'error, incorrect leaf photosynthesis temperature acclimation model specified' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end select - - end if - co2_rcurve_islope25 = co2_rcurve_islope25top_ft * nscaler ! Adjust for temperature diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index f664793c47..e528654880 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -251,7 +251,7 @@ variables: fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; double fates_daylength_factor_switch ; fates_daylength_factor_switch:units = "unitless" ; - fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (2) the day length factor scaling for photosynthetic parameters" ; + fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters" ; double fates_dev_arbitrary_pft(fates_pft) ; fates_dev_arbitrary_pft:units = "unknown" ; fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; From 02af1cb2092c45a55d98c4ea466c25339d055109 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 13 Mar 2024 16:34:52 -0700 Subject: [PATCH 122/300] add check to verify that the use supplied an appropriate parameter value for daylength switch --- main/EDPftvarcon.F90 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 5745141c70..04db46c499 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1764,7 +1764,7 @@ subroutine FatesCheckParams(is_master) use FatesConstantsMod, only : lmr_r_2 use EDParamsMod , only : logging_mechanical_frac, logging_collateral_frac use EDParamsMod , only : logging_direct_frac,logging_export_frac - use EDParamsMod , only : radiation_model + use EDParamsMod , only : radiation_model, dayl_switch use FatesInterfaceTypesMod, only : hlm_use_fixed_biogeog,hlm_use_sp, hlm_name use FatesInterfaceTypesMod, only : hlm_use_inventory_init @@ -1810,6 +1810,13 @@ subroutine FatesCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if(.not.any(dayl_switch == [itrue,ifalse])) then + write(fates_log(),*) 'The only valid switch options for ' + write(fates_log(),*) 'fates_daylength_factor_switch is 0 or 1 ...' + write(fates_log(),*) 'You specified fates_daylength_factor_switch = ',dayl_switch + write(fates_log(),*) 'Aborting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if select case (hlm_parteh_mode) case (prt_cnp_flex_allom_hyp) From 482efe2074ba89cd5cffba880c71cd51b0f0ea89 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 13 Mar 2024 16:36:41 -0700 Subject: [PATCH 123/300] add code comment about daylength factor --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index b750dff1ab..caaced4556 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -2494,6 +2494,7 @@ subroutine LeafLayerBiophysicalRates( parsun_per_la, & co2_rcurve_islope = 0._r8 else ! day time + ! update the daylength factor local variable if the switch is on if ( dayl_switch == itrue ) then dayl_factor_local = dayl_factor else From 13c2caa2e3034479eb8b11af96e6102414362612 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Sun, 17 Mar 2024 17:49:26 -0600 Subject: [PATCH 124/300] correct minor build errors --- biogeophys/FatesPlantHydraulicsMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 0fe4829f97..73c4f442e7 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -3939,7 +3939,7 @@ subroutine Report1DError(cohort, csite_hydr, ilayer, z_node, v_node, & logical, intent(in) :: recruitflag type(ed_cohort_hydr_type),pointer :: cohort_hydr - integer :: i + integer :: i, k integer :: ft real(r8) :: leaf_water real(r8) :: stem_water @@ -4018,7 +4018,7 @@ subroutine Report1DError(cohort, csite_hydr, ilayer, z_node, v_node, & 1._r8/(csite_hydr%kmax_upper_shell(ilayer,1)*aroot_frac_plant) + & 1._r8/cohort_hydr%kmax_aroot_upper(ilayer)) do i = 1,nshell - k = = n_hypool_leaf + n_hypool_stem + 2 + i + k = n_hypool_leaf + n_hypool_stem + 2 + i write(fates_log(),*) 'rhizo shell k:',k,v_node(k),th_node(k),h_node(k) if(i Date: Tue, 19 Mar 2024 12:08:46 -0400 Subject: [PATCH 125/300] re-wrote LAI by patch age --- main/FatesHistoryInterfaceMod.F90 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index dd035c9214..87f6bd7070 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2585,7 +2585,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_npatches_sec_si(io_si) = hio_npatches_sec_si(io_si) + 1._r8 end if - hio_lai_si(io_si) = hio_lai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%elai_profile(:,:,:) ) * & + hio_lai_si(io_si) = hio_lai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%tlai_profile(:,:,:) ) * & cpatch%total_canopy_area * AREA_INV ! 24hr veg temperature @@ -3346,10 +3346,11 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! Increment some patch-age-resolved diagnostics hio_lai_si_age(io_si,cpatch%age_class) = hio_lai_si_age(io_si,cpatch%age_class) & - + sum(cpatch%tlai_profile(:,:,:)) * cpatch%area - + + sum(cpatch%tlai_profile(:,:,:) * cpatch%canopy_area_profile(:,:,:) ) * cpatch%total_canopy_area + hio_ncl_si_age(io_si,cpatch%age_class) = hio_ncl_si_age(io_si,cpatch%age_class) & + cpatch%ncl_p * cpatch%area + hio_npatches_si_age(io_si,cpatch%age_class) = hio_npatches_si_age(io_si,cpatch%age_class) + 1._r8 @@ -6145,7 +6146,7 @@ subroutine define_history_vars(this, initialize_variables) index=ih_canopy_spread_si) call this%set_history_var(vname='FATES_LAI', units='m2 m-2', & - long='leaf area index per m2 land area', & + long='total leaf area index per m2 land area', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index=ih_lai_si) @@ -6897,7 +6898,7 @@ subroutine define_history_vars(this, initialize_variables) initialize=initialize_variables, index=ih_area_si_age) call this%set_history_var(vname='FATES_LAI_AP', units='m2 m-2', & - long='leaf area index by age bin per m2 land area', & + long='total leaf area index by age bin per m2 land area', & use_default='active', avgflag='A', vtype=site_age_r8, hlms='CLM:ALM', & upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, & index=ih_lai_si_age) From 9c8a14a678821d9d7555d5d3dc1996135f18d1ca Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 19 Mar 2024 12:18:29 -0400 Subject: [PATCH 126/300] Added exposed LAI (FATES_ELAI) since FATES_LAI was changed to total LAI tohave matching with FATES_LAI_AP --- main/FatesHistoryInterfaceMod.F90 | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 87f6bd7070..763bf5c34c 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -431,7 +431,8 @@ module FatesHistoryInterfaceMod integer :: ih_h2oveg_growturn_err_si integer :: ih_h2oveg_hydro_err_si integer :: ih_lai_si - + integer :: ih_elai_si + integer :: ih_site_cstatus_si integer :: ih_gdd_si integer :: ih_site_nchilldays_si @@ -2420,7 +2421,8 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_tveg24 => this%hvars(ih_tveg24_si)%r81d, & hio_tlongterm => this%hvars(ih_tlongterm_si)%r81d, & hio_tgrowth => this%hvars(ih_tgrowth_si)%r81d, & - hio_lai_si => this%hvars(ih_lai_si)%r81d ) + hio_lai_si => this%hvars(ih_lai_si)%r81d, & + hio_elai_si => this%hvars(ih_elai_si)%r81d) ! --------------------------------------------------------------------------------- @@ -2587,7 +2589,10 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_lai_si(io_si) = hio_lai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%tlai_profile(:,:,:) ) * & cpatch%total_canopy_area * AREA_INV - + + hio_elai_si(io_si) = hio_elai_si(io_si) + sum( cpatch%canopy_area_profile(:,:,:) * cpatch%elai_profile(:,:,:) ) * & + cpatch%total_canopy_area * AREA_INV + ! 24hr veg temperature hio_tveg24(io_si) = hio_tveg24(io_si) + & (cpatch%tveg24%GetMean()- t_water_freeze_k_1atm)*cpatch%area*AREA_INV @@ -6150,7 +6155,13 @@ subroutine define_history_vars(this, initialize_variables) use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & index=ih_lai_si) - + + call this%set_history_var(vname='FATES_ELAI', units='m2 m-2', & + long='exposed (non snow-occluded) leaf area index per m2 land area', & + use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & + upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + index=ih_elai_si) + call this%set_history_var(vname='FATES_LAI_SECONDARY', units='m2 m-2', & long='leaf area index per m2 land area, secondary patches', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & From 0633d1e6d3c63f9a9d3b13c5c954734bee00723a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 21 Mar 2024 11:25:13 -0700 Subject: [PATCH 127/300] remove day length factor input to atkin subroutine --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index caaced4556..153db7f1f6 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -596,7 +596,6 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) nscaler, & ! in ft, & ! in bc_in(s)%t_veg_pa(ifp), & ! in - bc_in(s)%dayl_factor_pa(ifp), & ! in currentPatch%tveg_lpa%GetMean(), & ! in lmr_z(iv,ft,cl)) ! out @@ -2328,7 +2327,6 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & nscaler, & ft, & veg_tempk, & - dayl_factor, & tgrowth, & lmr) @@ -2347,7 +2345,6 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & integer, intent(in) :: ft ! (plant) Functional Type Index real(r8), intent(in) :: nscaler ! Scale for leaf nitrogen profile real(r8), intent(in) :: veg_tempk ! vegetation temperature (degrees K) - real(r8), intent(in) :: dayl_factor ! daylength scaling factor (0-1) real(r8), intent(in) :: tgrowth ! lagged vegetation temperature averaged over acclimation timescale (degrees K) real(r8), intent(out) :: lmr ! Leaf Maintenance Respiration (umol CO2/m**2/s) From 07dc8c1174342a8593083ee16e14dda6343edba9 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 25 Mar 2024 11:29:17 -0400 Subject: [PATCH 128/300] Adding simple tool to make unstructured grids --- tools/make_unstruct_grid/MakeUnstructGrid.py | 315 +++++++++++++++++++ tools/make_unstruct_grid/andes7x7.xml | 43 +++ 2 files changed, 358 insertions(+) create mode 100644 tools/make_unstruct_grid/MakeUnstructGrid.py create mode 100644 tools/make_unstruct_grid/andes7x7.xml diff --git a/tools/make_unstruct_grid/MakeUnstructGrid.py b/tools/make_unstruct_grid/MakeUnstructGrid.py new file mode 100644 index 0000000000..159fb92f8b --- /dev/null +++ b/tools/make_unstruct_grid/MakeUnstructGrid.py @@ -0,0 +1,315 @@ +import numpy as np +import xarray as xr +import matplotlib.pyplot as plt +import matplotlib +import matplotlib.dates as mdates +import sys +import code # For development: code.interact(local=locals()) code.interact(local=dict(globals(), **locals())) +import argparse +import math +from scipy.io import netcdf as nc +import xml.etree.ElementTree as et + +# The user specifies a couplet of domain/surface files +# from which they want to base their new unstructured grid. Then they provide +# a list of geographic coordinates in latitude and longitude. These coordinates +# are sampled from the base dataset, and written to an output dataset. +# +# This method is certainly useful for generating small sets of unstructured +# grid-cells. It may not be the best method for generating large sets. One +# may want to use "ncks" (ie Charlie Zender's NCO tools) for subsetting large +# grids. This method will arrange the new grid cells in a 1D vector, and assumes +# the input grids are based on a 2d array of cells. +# +# This method will assume that the grid-cell extents of the new unstructured grids +# match the extents of the base files. If you want finer or coarser resolution, +# just dig up a different base file. +# +# This method uses nearest neighbor. +# +# This may have trouble on newer surface files, particularly if they have topo +# unit information. It won't be difficult to add that type of functionality +# if it doesn't work, I (Ryan) just haven't tried it. +# +# All controls over this process can be found in the xml control file. See +# andes7x7.xml for an example. + +# Usage MakeUnstructGrid.py --fin=xmlfile.xml + +def TransferData(da_key,ds_base,ds_unst,minis,minjs,dset_type): + + print(' Transferring: {}'.format(da_key)) + + if(dset_type=='domain'): + xname = 'nj' + yname = 'ni' + ny = len(minis) #nj = len(minis) + nx = 1 #ni + nv = 4 + elif(dset_type=='surface'): + xname = 'lsmlat' + yname = 'lsmlon' + ny = len(minis) + nx = 1 + + #numurbl = 3 ; + #nlevurb = 5 ; + #numrad = 2 ; + #nchar = 256 ; + #nlevsoi = 10 ; + #time = UNLIMITED ; // (12 currently) + #lsmpft = 17 ; + #natpft = 17 ; + + + + # Determin the data type + if(ds_base[da_key].dtype == 'float64'): + dtype_out = np.float64 + elif(ds_base[da_key].dtype == 'int32'): + dtype_out = np.int32 + else: + print('unknown data type: {}.\n Exiting'.format(ds_base[da_key].dtype)) + exit(2) + + + + # The lat-lon is always the last two dimensions + # Time is always the first dimension + + # Check to see if this has spatial dimensions + dimlist = list(ds_base[da_key].dims) + + # 2D (nj,ni) + # (lsmlat,lsmlon) + # 3D (nj, ni, nv) + # (x, lsmlat, lsmlon) + # 4D (x,y,lsmlat, lsmlon) + + if(any([dim==xname for dim in dimlist]) and (len(dimlist)==2)): + + # This is 2D and they are or use geographic coordinates + + ds_unst[da_key] = \ + xr.DataArray(np.empty((nx,ny), dtype=dtype_out),dims=dimlist) + + for k in range(len(minis)): + i = minis[k] + j = minjs[k] + ds_unst[da_key].loc[0,k] = ds_base[da_key].data[j,i] + + elif(any([dim==xname for dim in dimlist]) and any([dim=='nv' for dim in dimlist]) ): + + # This is the 3D coordinate in the domain file for vertices + + ds_unst[da_key] = \ + xr.DataArray(np.empty((nx,ny,nv), dtype=dtype_out),dims=dimlist) + for k in range(len(minis)): + i = minis[k] + j = minjs[k] + ds_unst[da_key].loc[0,k,:] = ds_base[da_key].data[j,i,:] + + elif(any([dim==xname for dim in dimlist]) and len(dimlist)==3): + + # This has dim==3, surface file and contains coordinates (x,lsmlat, lsmlon) + + dim0 = ds_base.dims[dimlist[0]] + ds_unst[da_key] = \ + xr.DataArray(np.empty((dim0,nx,ny), dtype=dtype_out),dims=dimlist) + for k in range(len(minis)): + i = minis[k] + j = minjs[k] + ds_unst[da_key].loc[:,0,k] = ds_base[da_key].data[:,j,i] + + elif(any([dim==xname for dim in dimlist]) and len(dimlist)==4): + + # This has dim==4, surface file and contains coordinates (x,y,lsmlat, lsmlon) + + dim0 = ds_base.dims[dimlist[0]] + dim1 = ds_base.dims[dimlist[1]] + ds_unst[da_key] = \ + xr.DataArray(np.empty((dim0,dim1,nx,ny), dtype=dtype_out),dims=dimlist) + for k in range(len(minis)): + i = minis[k] + j = minjs[k] + ds_unst[da_key].loc[:,:,0,k] = ds_base[da_key].data[:,:,j,i] + + elif(len(dimlist)==1): + # If there is no spatial coordinate, then just copy over what is there + #dimsizes = tuple([ds_base.dims[txt] for txt in dimlist]) + #ds_unst[da_key] = \ + # xr.DataArray(np.empty(dimsizes,dtype=dtype_out),dims=dimlist) + #ds_unst[da_key].loc[:] = ds_base[da_key].data[:] + ds_unst[da_key] = ds_base[da_key] + else: + # If there is no spatial coordinate, then just copy over what is there + + ds_unst[da_key] = ds_base[da_key] + + + # Once the new dataarray is created, transfer over metadata from original + ds_unst[da_key].attrs = ds_base[da_key].attrs + + return(ds_unst) + + +def main(argv): + + parser = argparse.ArgumentParser(description='Parse command line arguments to this script.') + parser.add_argument('--fin', dest='xmlfile', type=str, help="path to the xml control file",required=True) + args = parser.parse_args() + + xmlroot = et.parse(args.xmlfile).getroot() + + print(' -------------------------------------------------------------- ') + print('\n Creating a new domain/surface couplet \n') + print(' --------------------------------------------------------------\n ') + + # Get the domain base name + try: + domain_base = xmlroot.find('domain_base').text.strip() + domain_base_file = domain_base.split('/')[-1] + + except: + print('Could not find xml entry: {}'.format('domain_base')) + exit(2) + + # Get the new unstructured domain name (ie output) + try: + domain_unst = xmlroot.find('domain_unst').text.strip() + except: + print('Could not find xml entry: {}'.format('domain_unst')) + exit(2) + + + # Get the surface base name + try: + surface_base = xmlroot.find('surface_base').text.strip() + surface_base_file = surface_base.split('/')[-1] + + except: + print('Could not find xml entry: {}'.format('surface_base')) + exit(2) + + # Get the new unstructured surface name (ie output) + try: + surface_unst = xmlroot.find('surface_unst').text.strip() + except: + print('Could not find xml entry: {}'.format('surface_unst')) + exit(2) + + + + # Get a list of lon coordinates (force them into 0-360 convention) + try: + lon_subset_text = xmlroot.find('lon_list').text.strip().split(',') + lon_subset = [] + for txt in lon_subset_text: + lon = float(txt) + if(lon<0.0): + lon = 360.0+lon + lon_subset.append(lon) + + except: + print('Could not find xml entry: {}'.format('lon_list')) + exit(2) + + # Get a list of lat coordinates + try: + lat_subset_text = xmlroot.find('lat_list').text.strip().split(',') + lat_subset = [float(txt) for txt in lat_subset_text] + + except: + print('Could not find xml entry: {}'.format('lat_list')) + exit(2) + + # Check to make sure that the lat and lons are same length + + if( len(lat_subset) != len(lon_subset) ): + print('number of latitude subset points must match number of longitude subsets') + exit(2) + else: + nj = len(lat_subset) + print(' Found N={} lat/lon coordinates'.format(nj)) + + + #code.interact(local=dict(globals(), **locals())) + # ------------------------------------------------------------------------------ + # >>> ds_domain_base.data_vars + # Data variables: + #xv (nj, ni, nv) float64 358.8 1.25 1.25 358.8 ... 358.7 358.7 356.2 + #yv (nj, ni, nv) float64 -90.0 -90.0 -89.05 -89.05 ... 89.05 90.0 90.0 + #mask (nj, ni) int32 1 1 1 1 1 1 1 1 1 1 1 1 ... 0 0 0 0 0 0 0 0 0 0 0 0 + #area (nj, ni) float64 5.964e-06 5.964e-06 ... 5.964e-06 5.964e-06 + #frac (nj, ni) float64 1.0 1.0 1.0 1.0 1.0 1.0 ... 0.0 0.0 0.0 0.0 0.0 + # >>> ds_domain_base.coords + #Coordinates: + # xc (nj, ni) float64 0.0 2.5 5.0 7.5 10.0 ... 350.0 352.5 355.0 357.5 + # yc (nj, ni) float64 -90.0 -90.0 -90.0 -90.0 ... 90.0 90.0 90.0 90.0 + # ------------------------------------------------------------------------------ + + lon_subset_faux_2d = np.reshape(lon_subset, (-1, 1)) + lat_subset_faux_2d = np.reshape(lat_subset, (-1, 1)) + + ds_domain_base = xr.open_dataset(domain_base) + + # Lets find the indices for xc and yc that most closely match our coordinates + minis = [] + minjs = [] + for j in range(nj): + lat = lat_subset[j] + lon = lon_subset[j] + delt = (ds_domain_base['xc'].data-lon)**2.0 + (ds_domain_base['yc'].data-lat)**2.0 + minj,mini = np.unravel_index(delt.argmin(), delt.shape) + minis.append(mini) + minjs.append(minj) + + # Domain Processing + # =========================================================================================== + # Initialize the new dataset + ds_domain_unst = xr.Dataset( + attrs=ds_domain_base.attrs, + ) + ds_domain_unst.attrs["modification"]="Modified with SurfToVec.py, based on {}.".format(domain_base_file) + + #ode.interact(local=dict(globals(), **locals())) + + # Loop through existing datasets, allocate new arrays + # and transfer over point data + for da_key in ds_domain_base.data_vars: + ds_domain_unst = TransferData(da_key,ds_domain_base,ds_domain_unst,minis,minjs,'domain') + + for da_key in ds_domain_base.coords: + ds_domain_unst = TransferData(da_key,ds_domain_base,ds_domain_unst,minis,minjs,'domain') + + print('\n Writing: {}'.format(domain_unst)) + ds_domain_unst.to_netcdf(domain_unst) #,mode='a') + + # Surface Processing + # =========================================================================================== + + ds_surface_base = xr.open_dataset(surface_base) + + # Initialize the new dataset + ds_surface_unst = xr.Dataset( + attrs=ds_surface_base.attrs, + ) + ds_surface_unst.attrs["modification"]="Modified with SurfToVec.py, based on {}.".format(surface_base_file) + + + # Loop through existing datasets, allocate new arrays + # and transfer over point data + for da_key in ds_surface_base.data_vars: + ds_surface_unst = TransferData(da_key,ds_surface_base,ds_surface_unst,minis,minjs,'surface') + + for da_key in ds_surface_base.coords: + ds_surface_unst = TransferData(da_key,ds_surface_base,ds_surface_unst,minis,minjs,'surface') + + print('\n Writing: {}'.format(surface_unst)) + ds_surface_unst.to_netcdf(surface_unst) #,mode='a') + + print('\n') + +# This is the actual call to main +if __name__ == "__main__": + main(sys.argv) diff --git a/tools/make_unstruct_grid/andes7x7.xml b/tools/make_unstruct_grid/andes7x7.xml new file mode 100644 index 0000000000..ae99882ccd --- /dev/null +++ b/tools/make_unstruct_grid/andes7x7.xml @@ -0,0 +1,43 @@ + + + + + + + + Bases/domain.lnd.fv1.9x2.5_gx1v6.090206.nc + Bases/surfdata_1.9x2.5_simyr2000_c180306.nc + + + SAHydroStress/domain.lnd.fv1.9x2.5_gx1v6_SAHydroStress_c240320.nc + SAHydroStress/surfdata_1.9x2.5_simyr2000_SAHydroStress_c240320.nc + + + + -19.8947368421, -19.8947368421, -19.8947368421, + -18, -18, -18, -18, + -16.1052631579, -16.1052631579, -16.1052631579, -16.1052631579, -16.1052631579, + -14.2105263158, -14.2105263158, -14.2105263158, -14.2105263158, -14.2105263158, + -12.3157894737, -12.3157894737, -12.3157894737, -12.3157894737, -12.3157894737, -12.3157894737, + -10.4210526316, -10.4210526316, -10.4210526316, -10.4210526316, -10.4210526316, -10.4210526316, + -8.52631578947, -8.52631578947, -8.52631578947, -8.52631578947, -8.52631578947, -8.52631578947, -8.52631578947 + + + + + + 290, 292.5, 295, + 287.5, 290, 292.5, 295, + 285, 287.5, 290, 292.5, 295, + 285, 287.5, 290, 292.5, 295, + 282.5, 285, 287.5, 290, 292.5, 295, + 282.5, 285, 287.5, 290, 292.5, 295, + 280, 282.5, 285, 287.5, 290, 292.5, 295 + + + From 8f85de87f6660df1d25356785163af93710e179a Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 25 Mar 2024 13:05:26 -0400 Subject: [PATCH 129/300] Adding ftc protections (ie 0 flux) for perilously low wcs --- biogeophys/FatesHydroWTFMod.F90 | 12 +++++------ biogeophys/FatesPlantHydraulicsMod.F90 | 30 ++++++++++++++++++-------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/biogeophys/FatesHydroWTFMod.F90 b/biogeophys/FatesHydroWTFMod.F90 index e1f1a40df2..c67ab65a6e 100644 --- a/biogeophys/FatesHydroWTFMod.F90 +++ b/biogeophys/FatesHydroWTFMod.F90 @@ -28,7 +28,7 @@ module FatesHydroWTFMod __FILE__ - real(r8), parameter :: min_ftc = 0.00001_r8 ! Minimum allowed fraction of total conductance + real(r8), parameter :: min_ftc = 0.0_r8 ! Minimum allowed fraction of total conductance ! Bounds on saturated fraction, outside of which we use linear PV or stop flow ! In this context, the saturated fraction is defined by the volumetric WC "th" @@ -44,7 +44,7 @@ module FatesHydroWTFMod ! elastic-caviation region - real(r8), parameter :: min_psi_cch = -9._r8 ! Minimum psi we are willing to track in cch + real(r8), parameter :: min_theta_cch = 0.01_r8 ! Minimum theta (matches ctsm) ! Generic class that can be extended to describe ! specific water retention functions @@ -627,7 +627,7 @@ function ftc_from_psi_vg(this,psi) result(ftc) ! Make sure this is well behaved ftc = min(1._r8,max(min_ftc,num/den)) - + else ftc = 1._r8 @@ -713,9 +713,9 @@ subroutine set_wrf_param_cch(this,params_in) this%psi_max = this%psi_from_th(this%th_max-tiny(this%th_max)) this%dpsidth_max = this%dpsidth_from_th(this%th_max-tiny(this%th_max)) - this%psi_min = min_psi_cch - this%th_min = this%th_from_psi(min_psi_cch+tiny(this%th_max)) - this%dpsidth_min = this%dpsidth_from_th(this%th_min+tiny(this%th_max)) + this%th_min = min_theta_cch + this%psi_min = this%psi_from_th(min_theta_cch+tiny(this%th_max)) + this%dpsidth_min = this%dpsidth_from_th(min_theta_cch+tiny(this%th_max)) return end subroutine set_wrf_param_cch diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 73c4f442e7..f666b3409b 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -4111,18 +4111,30 @@ subroutine GetImTaylorKAB(kmax_up,kmax_dn, & end if - ! Calculate total effective conductance over path [kg s-1 MPa-1] - k_eff = 1._r8/(1._r8/(ftc_up*kmax_up)+1._r8/(ftc_dn*kmax_dn)) - - ! "A" term, which operates on the downstream node (closer to atm) - a_term = k_eff**2.0_r8 * h_diff * kmax_dn**(-1.0_r8) * ftc_dn**(-2.0_r8) & - * dftc_dtheta_dn - k_eff * dpsi_dtheta_dn + ! Prevent issue with zero flux + if( (ftc_up*kmax_up)>nearzero .and. (ftc_dn*kmax_dn)>nearzero ) then + + ! Calculate total effective conductance over path [kg s-1 MPa-1] + k_eff = 1._r8/(1._r8/(ftc_up*kmax_up)+1._r8/(ftc_dn*kmax_dn)) + + ! "A" term, which operates on the downstream node (closer to atm) + a_term = k_eff**2.0_r8 * h_diff * kmax_dn**(-1.0_r8) * ftc_dn**(-2.0_r8) & + * dftc_dtheta_dn - k_eff * dpsi_dtheta_dn + + + ! "B" term, which operates on the upstream node (further from atm) + b_term = k_eff**2.0_r8 * h_diff * kmax_up**(-1.0_r8) * ftc_up**(-2.0_r8) & + * dftc_dtheta_up + k_eff * dpsi_dtheta_up + else - ! "B" term, which operates on the upstream node (further from atm) - b_term = k_eff**2.0_r8 * h_diff * kmax_up**(-1.0_r8) * ftc_up**(-2.0_r8) & - * dftc_dtheta_up + k_eff * dpsi_dtheta_up + k_eff = 0._r8 + a_term = 0._r8 + b_term = 0._r8 + + end if + ! Restore ftc ftc_dn = ftc_dn_tmp ftc_up = ftc_up_tmp From 1abba2fdaf72f9c70b54a674f2d632a1358ee671 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Mar 2024 09:56:24 -0400 Subject: [PATCH 130/300] hydro safemath, looking into pinning zero ftc to min psi --- biogeophys/FatesHydroWTFMod.F90 | 9 +- .../hydro/HydroUTestDriver.py | 187 +++++++++++++++--- main/FatesHydraulicsMemMod.F90 | 24 +-- 3 files changed, 179 insertions(+), 41 deletions(-) diff --git a/biogeophys/FatesHydroWTFMod.F90 b/biogeophys/FatesHydroWTFMod.F90 index c67ab65a6e..9c0ef60a89 100644 --- a/biogeophys/FatesHydroWTFMod.F90 +++ b/biogeophys/FatesHydroWTFMod.F90 @@ -903,7 +903,8 @@ subroutine set_wrf_param_smooth_cch(this,params_in) this%scch_b2 = 0.d0 this%scch_b3 = (2.d0 - bcAtPu*(2.d0+lambdaDeltaPuOnPu)) * oneOnDeltaPu * oneOnDeltaPu * oneOnDeltaPu if( this%scch_b3 <= 0.d0 ) then - write(fates_log(),*) 'set_wrf_param_smooth_cch b3 <=0',pu,ps,alpha,lambda,oneOnDeltaPu,lambdaDeltaPuOnPu,bcAtPu,this%psi_sat + write(fates_log(),*) 'set_wrf_param_smooth_cch b3 <=0',pu,ps,alpha,lambda,oneOnDeltaPu, & + lambdaDeltaPuOnPu,bcAtPu,this%psi_sat call endrun(msg=errMsg(sourcefile, __LINE__)) endif else @@ -980,9 +981,11 @@ subroutine set_wkf_param_smooth_cch(this,params_in) ! Store coefficients for cubic function. this%scch_b2 = 0.d0 - this%scch_b3 = (2.d0 - bcAtPu*(2.d0+lambdaDeltaPuOnPu)) * oneOnDeltaPu * oneOnDeltaPu * oneOnDeltaPu + this%scch_b3 = (2.d0 - bcAtPu*(2.d0+lambdaDeltaPuOnPu)) * & + oneOnDeltaPu * oneOnDeltaPu * oneOnDeltaPu if( this%scch_b3 <= 0.d0 ) then - write(fates_log(),*) 'set_wrf_param_smooth_cch b3 <=0',pu,ps,alpha,lambda,oneOnDeltaPu,lambdaDeltaPuOnPu,bcAtPu,this%psi_sat + write(fates_log(),*) 'set_wrf_param_smooth_cch b3 <=0', & + pu,ps,alpha,lambda,oneOnDeltaPu,lambdaDeltaPuOnPu,bcAtPu,this%psi_sat call endrun(msg=errMsg(sourcefile, __LINE__)) endif else diff --git a/functional_unit_testing/hydro/HydroUTestDriver.py b/functional_unit_testing/hydro/HydroUTestDriver.py index 5c2b026361..933c2aa837 100644 --- a/functional_unit_testing/hydro/HydroUTestDriver.py +++ b/functional_unit_testing/hydro/HydroUTestDriver.py @@ -150,18 +150,60 @@ def __init__(self,index,p50,avuln): iret = setwkf(ci(index),ci(tfs_type),ci(len(init_wkf_args)),c8_arr(init_wkf_args)) +def OMParams(zsoi): + + zsapric= 0.5 + om_watsat = max(0.93 - 0.1 *(zsoi/zsapric), 0.83) + om_bsw = min(2.7 + 9.3 *(zsoi/zsapric), 12.0) + om_sucsat = min(10.3 - 0.2 *(zsoi/zsapric), 10.1) + + #om_sucsat = SuctionMMtoMPa(om_sucsat) + + return(om_watsat,om_sucsat,om_bsw) + +def CCHParmsCosby84T5(zsoi,om_frac,sand_frac,clay_frac): + + # cosby_1984_table5 + + # Get pedotransfer for soil matrix + watsat = 0.489 - 0.00126*sand_frac + bsw = 2.91 + 0.159*clay_frac + sucsat = 10. * ( 10.**(1.88-0.0131*sand_frac) ) + + [om_watsat,om_sucsat,om_bsw] = OMParams(zsoi) + + # Update pedotransfer to include organic material + watsat = (1.0 - om_frac) * watsat + om_watsat * om_frac + bsw = (1.0 - om_frac) * bsw + om_bsw * om_frac + sucsat = (1.0 - om_frac) * sucsat + om_sucsat * om_frac + + # Convert from mm to MPa + sucsat = SuctionMMtoMPa(sucsat) + + + # psi = psi_sat*(th/th_sat)**(-beta) + # th = th_sat*(psi / psi_sat)^(-1/beta) + + return(watsat,sucsat,bsw) + + +def SuctionMMtoMPa(suction_mm): + + denh2o = 1.0e3 # kg/m3 + grav_earth = 9.8 # m/s2 + mpa_per_pa = 1.0e-6 # MPa per Pa + m_per_mm = 1.0e-3 # meters per millimeter + + suction_mpa = (-1.0)*suction_mm*denh2o*grav_earth*mpa_per_pa*m_per_mm + + return(suction_mpa) + def main(argv): - # First check to make sure python 2.7 is being used + version = platform.python_version() verlist = version.split('.') - if( not ((verlist[0] == '2') & (verlist[1] == '7') & (int(verlist[2])>=15) ) ): - print("The PARTEH driver mus be run with python 2.7") - print(" with tertiary version >=15.") - print(" your version is {}".format(version)) - print(" exiting...") - sys.exit(2) # Read in the arguments # ======================================================================================= @@ -178,21 +220,22 @@ def main(argv): # min_theta = np.full(shape=(2),dtype=np.float64,fill_value=np.nan) - -# wrf_type = [vg_type, vg_type, cch_type, cch_type] -# wkf_type = [vg_type, tfs_type, cch_type, tfs_type] - -# th_ress = [0.01, 0.10, -9, -9] -# th_sats = [0.55, 0.55, 0.65, 0.65] -# alphas = [1.0, 1.0, 1.0, 1.0] -# psds = [2.7, 2.7, 2.7, 2.7] -# tort = [0.5, 0.5, 0.5, 0.5] -# beta = [-9, -9, 6, 9] -# avuln = [2.0, 2.0, 2.5, 2.5] -# p50 = [-1.5, -1.5, -2.25, -2.25] - - ncomp= 4 - + # wrf_type = [vg_type, vg_type, cch_type, cch_type] + # wkf_type = [vg_type, tfs_type, cch_type, tfs_type] + + # th_ress = [0.01, 0.10, -9, -9] + # th_sats = [0.55, 0.55, 0.65, 0.65] + # alphas = [1.0, 1.0, 1.0, 1.0] + # psds = [2.7, 2.7, 2.7, 2.7] + # tort = [0.5, 0.5, 0.5, 0.5] + # beta = [-9, -9, 6, 9] + # avuln = [2.0, 2.0, 2.5, 2.5] + # p50 = [-1.5, -1.5, -2.25, -2.25] + + + ncomp = 4 + ncomp_tot = 20 + rwc_fd = [1.0,0.958,0.958,0.958] rwccap = [1.0,0.947,0.947,0.947] cap_slp = [] @@ -213,7 +256,7 @@ def main(argv): # Allocate memory to our objective classes - iret = initalloc_wtfs(ci(ncomp),ci(ncomp)) + iret = initalloc_wtfs(ci(ncomp_tot),ci(ncomp_tot)) print('Allocated') @@ -221,8 +264,8 @@ def main(argv): # vg_wrf(1,alpha=1.0,psd=2.7,th_sat=0.55,th_res=0.1) # vg_wkf(1,alpha=1.0,psd=2.7,th_sat=0.55,th_res=0.1,tort=0.5) - cch_wrf(1,th_sat=0.55, psi_sat=-1.56e-3, beta=6) - cch_wkf(1,th_sat=0.55, psi_sat=-1.56e-3, beta=6) + cch_wrf(1,th_sat=0.55, psi_sat=-1.56e-3, beta=3) + cch_wkf(1,th_sat=0.55, psi_sat=-1.56e-3, beta=3) # cch_wrf(3,th_sat=0.55, psi_sat=-1.56e-3, beta=6) # tfs_wkf(3,p50=-2.25, avuln=2.0) @@ -361,11 +404,103 @@ def main(argv): ax1.set_ylim([0,2]) # ax1.set_ylim([0,10]) ax1.legend(loc='upper right') - plt.show() + ndepth = 1000 + zdepth = np.linspace(0.01,10.0,num = ndepth) + + om_watsat_z = np.zeros(shape=(ndepth,1)) + om_sucsat_z = np.zeros(shape=(ndepth,1)) + om_bsw_z = np.zeros(shape=(ndepth,1)) + + for icl in range(ndepth): + [om_watsat_z[icl],om_sucsat_z[icl],om_bsw_z[icl]] = OMParams(zdepth[icl]) + + fig4,((ax1,ax2),(ax3,ax4)) = plt.subplots(2,2,figsize=(9,6)) + + ax1.plot(om_watsat_z,-zdepth) + ax2.plot(om_sucsat_z,-zdepth) + ax3.plot(om_bsw_z,-zdepth) + ax4.axis('off') + + + ax1.set_ylabel('soil depth') + ax1.set_xlabel('Saturated WC [m3/m3]') + ax2.set_xlabel('Saturated Suction [mm]') + ax3.set_ylabel('soil depth') + ax3.set_xlabel('beta ') + # ax1.set_xlim([-10,3]) + # ax1.set_ylim([0,2]) + # ax1.set_ylim([0,10]) + # ax1.legend(loc='upper right') + plt.tight_layout() + + + # Soil texture distributions + + #clay_frac = np.zeros(shape=(100,1)) + #sand_frac = np.zeros(shape=(100,1)) + #om_frac = np.zeros(shape=(100,1)) + #clay_frac = np.linspace(0.0, 0.7, num=npts) + + watsat_v = [] + sucsat_v = [] + bsw_v = [] + + ntex = 100 + for icl in range(ntex): + clay_frac = float(ic)/float(ntex) + for isa in range(ntex): + sand_frac = float(isa)/float(ntex) + + if( (clay_frac+sand_frac)<1.0 ): + for om_frac in [0.0,1.0]: + for zsoi in [0.01,10.0]: + [watsat,sucsat,bsw] = CCHParmsCosby84T5(zsoi,om_frac,sand_frac,clay_frac) + watsat_v.append(watsat) + sucsat_v.append(sucsat) + bsw_v.append(bsw) + + + fig5,((ax1,ax2),(ax3,ax4)) = plt.subplots(2,2,figsize=(9,6)) + + ax1.hist(watsat_v,bins=50) + ax2.hist(sucsat_v,bins=50) + ax3.hist(bsw_v,bins=50) + ax4.axis('off') + + + ax1.set_xlabel('Sat. WC [m3/m3]') + ax2.set_xlabel('Sat. Sucation [MPa]') + ax3.set_xlabel('Beta') + + plt.tight_layout() + + ind = [] + ind.append(np.argmin(bsw_v)) + ind.append(np.argmax(bsw_v)) + ind.append(np.argmin(sucsat_v)) + ind.append(np.argmax(sucsat_v)) + ind.append(np.argmin(watsat_v)) + ind.append(np.argmax(watsat_v)) + + # Now lets test the lowest possible water contents using these + + ii=4 + + for i in ind: + ii = ii+1 + cch_wrf(ii,th_sat=watsat_v[i], psi_sat=sucsat_v[i], beta=bsw_v[i]) + cch_wkf(ii,th_sat=watsat_v[i], psi_sat=sucsat_v[i], beta=bsw_v[i]) + print('---th sat: {}, psi sat: {}, beat: {}'.format(watsat_v[i],sucsat_v[i],bsw_v[i])) + for psi in -np.linspace(1,24,24): + th = th_from_psi(ci(ii),c8(psi)) + print('{}, psi: {}, th: {}'.format(ii,psi,th)) + + plt.show() + # code.interact(local=dict(globals(), **locals())) # Helper code to plot negative logs diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 61e97173c7..f31ffe7e25 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -168,19 +168,19 @@ module FatesHydraulicsMemMod real(r8), allocatable :: residual(:) real(r8), allocatable :: ajac(:,:) ! Jacobian (N terms, N equations) - real(r8), allocatable :: th_node_init(:) + real(r8), allocatable :: th_node_init(:) real(r8), allocatable :: th_node_prev(:) - real(r8), allocatable :: th_node(:) - real(r8), allocatable :: dth_node(:) - real(r8), allocatable :: h_node(:) - real(r8), allocatable :: v_node(:) - real(r8), allocatable :: z_node(:) - real(r8), allocatable :: psi_node(:) - real(r8), allocatable :: q_flux(:) - real(r8), allocatable :: dftc_dpsi_node(:) - real(r8), allocatable :: ftc_node(:) - real(r8), allocatable :: kmax_up(:) - real(r8), allocatable :: kmax_dn(:) + real(r8), allocatable :: th_node(:) ! Relative water content (theta) of node [m3/m3] + real(r8), allocatable :: dth_node(:) ! Change (time derivative) in water content of node + real(r8), allocatable :: h_node(:) ! + real(r8), allocatable :: v_node(:) ! Volume of the node [m3] + real(r8), allocatable :: z_node(:) ! Eleveation potential of the node (datum 0 is surface) + real(r8), allocatable :: psi_node(:) ! Suction of the node [MPa] + real(r8), allocatable :: q_flux(:) ! Mass flux of pathways between nodes [] + real(r8), allocatable :: dftc_dpsi_node(:) ! Differential of fraction total conductivity with suction + real(r8), allocatable :: ftc_node(:) ! fraction of total conductivity [-] + real(r8), allocatable :: kmax_up(:) ! Maximum conductivity for upstream side of compartment + real(r8), allocatable :: kmax_dn(:) ! Maximum conductivity for downstream side of compartment ! Scratch arrays real(r8) :: cohort_recruit_water_layer(nlevsoi_hyd_max) ! the recruit water requirement for a cohort From e1e9b07a383448adad2002209bbd2099c3da4dc0 Mon Sep 17 00:00:00 2001 From: jessica needham Date: Tue, 27 Feb 2024 14:58:05 -0800 Subject: [PATCH 131/300] merging in vert resp scaler coeffs --- main/EDPftvarcon.F90 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index f454a03013..5f457abca2 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -92,6 +92,10 @@ module EDPftvarcon real(r8), allocatable :: maintresp_leaf_ryan1991_baserate(:) ! leaf maintenance respiration per Ryan et al 1991 + real(r8), allocatable :: maintresp_leaf_vert_scaler_coeff1(:) ! leaf maintenance respiration decrease through the canopy param 1 + ! only with Atkin et al. 2017 respiration model + real(r8), allocatable :: maintresp_leaf_vert_scaler_coeff2(:) ! leaf maintenance respiration decrease through the canopy param 2 + ! only with Atkin et al. 2017 respiraiton model real(r8), allocatable :: bmort(:) real(r8), allocatable :: mort_ip_size_senescence(:) ! inflection point of dbh dependent senescence real(r8), allocatable :: mort_r_size_senescence(:) ! rate of change in mortality with dbh @@ -471,6 +475,14 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_maintresp_leaf_vert_scaler_coeff1' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_maintresp_leaf_vert_scaler_coeff2' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_prescribed_npp_canopy' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -912,6 +924,14 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%maintresp_leaf_ryan1991_baserate) + name = 'fates_maintresp_leaf_vert_scaler_coeff1' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%maintresp_leaf_vert_scaler_coeff1) + + name = 'fates_maintresp_leaf_vert_scaler_coeff2' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%maintresp_leaf_vert_scaler_coeff2) + name = 'fates_prescribed_npp_canopy' call fates_params%RetrieveParameterAllocate(name=name, & data=this%prescribed_npp_canopy) @@ -1737,6 +1757,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'hydro_vg_alpha_node = ',EDPftvarcon_inst%hydr_vg_alpha_node write(fates_log(),fmt0) 'hydro_vg_m_node = ',EDPftvarcon_inst%hydr_vg_m_node write(fates_log(),fmt0) 'hydro_vg_n_node = ',EDPftvarcon_inst%hydr_vg_n_node + write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff1 = ',maintresp_leaf_vert_scaler_coeff1 + write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff2 = ',maintresp_leaf_vert_scaler_coeff2 write(fates_log(),*) '-------------------------------------------------' end if From dc1d0290617eb51b2553178948feeaf1ed972590 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Mar 2024 11:22:11 -0400 Subject: [PATCH 132/300] added leaf vertical scaling parameter coefficients in read-in and xml --- main/EDPftvarcon.F90 | 29 ++++++++++++++++--- .../archive/api33.0.0_020524_patch_params.xml | 28 ++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 5f457abca2..46926caad4 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -92,10 +92,13 @@ module EDPftvarcon real(r8), allocatable :: maintresp_leaf_ryan1991_baserate(:) ! leaf maintenance respiration per Ryan et al 1991 - real(r8), allocatable :: maintresp_leaf_vert_scaler_coeff1(:) ! leaf maintenance respiration decrease through the canopy param 1 - ! only with Atkin et al. 2017 respiration model - real(r8), allocatable :: maintresp_leaf_vert_scaler_coeff2(:) ! leaf maintenance respiration decrease through the canopy param 2 - ! only with Atkin et al. 2017 respiraiton model + real(r8), allocatable :: leafn_vert_scaler_coeff1(:) ! Coefficient one for decrease of leaf N through the canopy + real(r8), allocatable :: leafn_vert_scaler_coeff2(:) ! Coefficient two for decrease of leaf N through the canopy + + real(r8), allocatable :: maintresp_leaf_vert_scaler_coeff1(:) ! leaf maintenance respiration decrease through the canopy param 1 + ! only with Atkin et al. 2017 respiration model + real(r8), allocatable :: maintresp_leaf_vert_scaler_coeff2(:) ! leaf maintenance respiration decrease through the canopy param 2 + ! only with Atkin et al. 2017 respiraiton model real(r8), allocatable :: bmort(:) real(r8), allocatable :: mort_ip_size_senescence(:) ! inflection point of dbh dependent senescence real(r8), allocatable :: mort_r_size_senescence(:) ! rate of change in mortality with dbh @@ -475,6 +478,14 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_leafn_vert_scaler_coeff1' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_leafn_vert_scaler_coeff2' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_maintresp_leaf_vert_scaler_coeff1' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -924,6 +935,14 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%maintresp_leaf_ryan1991_baserate) + name = 'fates_leafn_vert_scaler_coeff1' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%leafn_vert_scaler_coeff1) + + name = 'fates_leafn_vert_scaler_coeff2' + call fates_params%RetrieveParameterAllocate(name=name, & + data=this%leafn_vert_scaler_coeff2) + name = 'fates_maintresp_leaf_vert_scaler_coeff1' call fates_params%RetrieveParameterAllocate(name=name, & data=this%maintresp_leaf_vert_scaler_coeff1) @@ -1757,6 +1776,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'hydro_vg_alpha_node = ',EDPftvarcon_inst%hydr_vg_alpha_node write(fates_log(),fmt0) 'hydro_vg_m_node = ',EDPftvarcon_inst%hydr_vg_m_node write(fates_log(),fmt0) 'hydro_vg_n_node = ',EDPftvarcon_inst%hydr_vg_n_node + write(fates_log(),fmt0) 'leafn_vert_scaler_coeff1 = ',leafn_vert_scaler_coeff1 + write(fates_log(),fmt0) 'leafn_vert_scaler_coeff2 = ',leafn_vert_scaler_coeff2 write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff1 = ',maintresp_leaf_vert_scaler_coeff1 write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff2 = ',maintresp_leaf_vert_scaler_coeff2 write(fates_log(),*) '-------------------------------------------------' diff --git a/parameter_files/archive/api33.0.0_020524_patch_params.xml b/parameter_files/archive/api33.0.0_020524_patch_params.xml index d2c6858308..97689c0b2d 100644 --- a/parameter_files/archive/api33.0.0_020524_patch_params.xml +++ b/parameter_files/archive/api33.0.0_020524_patch_params.xml @@ -86,5 +86,33 @@ (INACTIVE, KEEP AT 0) critical value for biochemical production (ECA) 0,0,0,0,0,0,0,0,0,0,0,0 + + fates_leafn_vert_scaler_coeff1 + fates_pft + unitless + Coefficient one for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010. + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 + + + fates_leafn_vert_scaler_coeff2 + fates_pft + unitless + Coefficient two for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010. + 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 + + + fates_maintresp_leaf_vert_scaler_coeff1 + fates_pft + unitless + Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff1. + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 + + + fates_maintresp_leaf_vert_scaler_coeff2 + fates_pft + unitless + Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff2. + 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 + From 7ab9bcc649e51b1cc04d12a12ace0f4f64b94e8c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Mar 2024 12:12:09 -0400 Subject: [PATCH 133/300] updating api update xml files --- ...l => api.34.0.0_032624_params_default.cdl} | 54 ++++++------ .../archive/api33.0.0_020524_patch_params.xml | 2 +- parameter_files/fates_params_default.cdl | 84 +++++++++---------- 3 files changed, 68 insertions(+), 72 deletions(-) rename parameter_files/archive/{api33.0.0_020524_params_default.cdl => api.34.0.0_032624_params_default.cdl} (98%) diff --git a/parameter_files/archive/api33.0.0_020524_params_default.cdl b/parameter_files/archive/api.34.0.0_032624_params_default.cdl similarity index 98% rename from parameter_files/archive/api33.0.0_020524_params_default.cdl rename to parameter_files/archive/api.34.0.0_032624_params_default.cdl index 99bdaed02e..02bd77b647 100644 --- a/parameter_files/archive/api33.0.0_020524_params_default.cdl +++ b/parameter_files/archive/api.34.0.0_032624_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -958,11 +958,11 @@ data: fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + fates_allom_agb1 = 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, + 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; + fates_allom_agb2 = 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, + 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; @@ -973,42 +973,44 @@ data: fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, + 0, 0, 0, 0, 0 ; fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; + fates_allom_d2bl2 = 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, + 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; + fates_allom_d2ca_coefficient_min = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; + fates_allom_d2h1 = 78.4087704, 306.842667, 106.8745821, 104.3586841, + 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; + fates_allom_d2h2 = 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, + 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; + fates_allom_d2h3 = 47.6666164, 196.6865691, 93.9790461, 160.6835089, + 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; - fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, + 0.35, 0.35, 0.35 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1020,7 +1022,7 @@ data: fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1029,7 +1031,7 @@ data: fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 ; fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; @@ -1556,8 +1558,8 @@ data: fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; + fates_wood_density = 0.548327, 0.44235, 0.454845, 0.754336, 0.548327, + 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; diff --git a/parameter_files/archive/api33.0.0_020524_patch_params.xml b/parameter_files/archive/api33.0.0_020524_patch_params.xml index 97689c0b2d..154dc1100d 100644 --- a/parameter_files/archive/api33.0.0_020524_patch_params.xml +++ b/parameter_files/archive/api33.0.0_020524_patch_params.xml @@ -18,7 +18,7 @@ the variables --> - archive/api33.0.0_020524_params_default.cdl + archive/api.34.0.0_032624_params_default.cdl fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 1ecbb13725..02bd77b647 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -8,12 +8,12 @@ dimensions: fates_history_size_bins = 13 ; fates_hlm_pftno = 14 ; fates_hydr_organs = 4 ; - fates_landuseclass = 5 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; fates_plant_organs = 4 ; fates_string_length = 60 ; + fates_landuseclass = 5 ; variables: double fates_history_ageclass_bin_edges(fates_history_age_bins) ; fates_history_ageclass_bin_edges:units = "yr" ; @@ -84,6 +84,9 @@ variables: double fates_allom_cmode(fates_pft) ; fates_allom_cmode:units = "index" ; fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_crown_depth_frac(fates_pft) ; + fates_allom_crown_depth_frac:units = "fraction" ; + fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; double fates_allom_d2bl1(fates_pft) ; fates_allom_d2bl1:units = "variable" ; fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; @@ -111,9 +114,6 @@ variables: double fates_allom_dbh_maxheight(fates_pft) ; fates_allom_dbh_maxheight:units = "cm" ; fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; - double fates_allom_dmode(fates_pft) ; - fates_allom_dmode:units = "index" ; - fates_allom_dmode:long_name = "crown depth allometry function index" ; double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; @@ -129,12 +129,6 @@ variables: double fates_allom_frbstor_repro(fates_pft) ; fates_allom_frbstor_repro:units = "fraction" ; fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; - double fates_allom_h2cd1(fates_pft) ; - fates_allom_h2cd1:units = "variable" ; - fates_allom_h2cd1:long_name = "Parameter 1 for h2cd allometry (exp(log-intercept) or scaling). If allom_dmode=1; this is the same as former crown_depth_frac parameter" ; - double fates_allom_h2cd2(fates_pft) ; - fates_allom_h2cd2:units = "variable" ; - fates_allom_h2cd2:long_name = "Parameter 2 for h2cd allometry (log-slope or exponent). If allom_dmode=1; this is not needed (as exponent is assumed 1)" ; double fates_allom_hmode(fates_pft) ; fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; @@ -179,7 +173,7 @@ variables: fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; double fates_cnp_eca_alpha_ptase(fates_pft) ; fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "(INACTIVE, KEEP AT 0) fraction of P from ptase activity sent directly to plant (ECA)" ; + fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; double fates_cnp_eca_decompmicc(fates_pft) ; fates_cnp_eca_decompmicc:units = "gC/m3" ; fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; @@ -197,7 +191,7 @@ variables: fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; double fates_cnp_eca_lambda_ptase(fates_pft) ; fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "(INACTIVE, KEEP AT 0) critical value for biochemical production (ECA)" ; + fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; double fates_cnp_eca_vmax_ptase(fates_pft) ; fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; @@ -964,11 +958,11 @@ data: fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + fates_allom_agb1 = 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, + 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; + fates_allom_agb2 = 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, + 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; @@ -979,41 +973,44 @@ data: fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, + 0, 0, 0, 0, 0 ; fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, + 0.95, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; + fates_allom_d2bl2 = 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, + 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; - - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; + fates_allom_d2ca_coefficient_min = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; + fates_allom_d2h1 = 78.4087704, 306.842667, 106.8745821, 104.3586841, + 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; + fates_allom_d2h2 = 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, + 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + fates_allom_d2h3 = 47.6666164, 196.6865691, 93.9790461, 160.6835089, + 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; - fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, + 0.35, 0.35, 0.35 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1025,11 +1022,7 @@ data: fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_h2cd1 = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; - - fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1038,7 +1031,7 @@ data: fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 ; fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; @@ -1062,7 +1055,8 @@ data: fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_cnp_eca_alpha_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; @@ -1078,7 +1072,7 @@ data: fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_eca_lambda_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; @@ -1564,8 +1558,8 @@ data: fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; + fates_wood_density = 0.548327, 0.44235, 0.454845, 0.754336, 0.548327, + 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; From e218fb3414813a3160ad37397418dfa329e4a304 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Mar 2024 12:15:21 -0400 Subject: [PATCH 134/300] updated parameter xml names --- ...4_params_default.cdl => api34.0.0_032624_params_default.cdl} | 0 ...20524_patch_params.xml => api34.0.0_032624_patch_params.xml} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename parameter_files/archive/{api.34.0.0_032624_params_default.cdl => api34.0.0_032624_params_default.cdl} (100%) rename parameter_files/archive/{api33.0.0_020524_patch_params.xml => api34.0.0_032624_patch_params.xml} (98%) diff --git a/parameter_files/archive/api.34.0.0_032624_params_default.cdl b/parameter_files/archive/api34.0.0_032624_params_default.cdl similarity index 100% rename from parameter_files/archive/api.34.0.0_032624_params_default.cdl rename to parameter_files/archive/api34.0.0_032624_params_default.cdl diff --git a/parameter_files/archive/api33.0.0_020524_patch_params.xml b/parameter_files/archive/api34.0.0_032624_patch_params.xml similarity index 98% rename from parameter_files/archive/api33.0.0_020524_patch_params.xml rename to parameter_files/archive/api34.0.0_032624_patch_params.xml index 154dc1100d..3baa6a525f 100644 --- a/parameter_files/archive/api33.0.0_020524_patch_params.xml +++ b/parameter_files/archive/api34.0.0_032624_patch_params.xml @@ -18,7 +18,7 @@ the variables --> - archive/api.34.0.0_032624_params_default.cdl + archive/api34.0.0_032624_params_default.cdl fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12 From 4942a17765dbdc6ce58b2ad271bfddedf2d5d1a0 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Mar 2024 13:23:10 -0400 Subject: [PATCH 135/300] Applied batch patch script to api34 update --- .../archive/api34.0.0_032624_patch_params.xml | 8 +-- parameter_files/fates_params_default.cdl | 57 +++++++++++++++---- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/parameter_files/archive/api34.0.0_032624_patch_params.xml b/parameter_files/archive/api34.0.0_032624_patch_params.xml index 3baa6a525f..fd670b586d 100644 --- a/parameter_files/archive/api34.0.0_032624_patch_params.xml +++ b/parameter_files/archive/api34.0.0_032624_patch_params.xml @@ -86,28 +86,28 @@ (INACTIVE, KEEP AT 0) critical value for biochemical production (ECA) 0,0,0,0,0,0,0,0,0,0,0,0 - + fates_leafn_vert_scaler_coeff1 fates_pft unitless Coefficient one for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010. 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 - + fates_leafn_vert_scaler_coeff2 fates_pft unitless Coefficient two for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010. 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 - + fates_maintresp_leaf_vert_scaler_coeff1 fates_pft unitless Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff1. 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 - + fates_maintresp_leaf_vert_scaler_coeff2 fates_pft unitless diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 02bd77b647..847a7b3f85 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -8,12 +8,12 @@ dimensions: fates_history_size_bins = 13 ; fates_hlm_pftno = 14 ; fates_hydr_organs = 4 ; + fates_landuseclass = 5 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; fates_plant_organs = 4 ; fates_string_length = 60 ; - fates_landuseclass = 5 ; variables: double fates_history_ageclass_bin_edges(fates_history_age_bins) ; fates_history_ageclass_bin_edges:units = "yr" ; @@ -84,9 +84,6 @@ variables: double fates_allom_cmode(fates_pft) ; fates_allom_cmode:units = "index" ; fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; double fates_allom_d2bl1(fates_pft) ; fates_allom_d2bl1:units = "variable" ; fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; @@ -114,6 +111,9 @@ variables: double fates_allom_dbh_maxheight(fates_pft) ; fates_allom_dbh_maxheight:units = "cm" ; fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_dmode(fates_pft) ; + fates_allom_dmode:units = "index" ; + fates_allom_dmode:long_name = "crown depth allometry function index" ; double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; @@ -129,6 +129,12 @@ variables: double fates_allom_frbstor_repro(fates_pft) ; fates_allom_frbstor_repro:units = "fraction" ; fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_h2cd1(fates_pft) ; + fates_allom_h2cd1:units = "variable" ; + fates_allom_h2cd1:long_name = "Parameter 1 for h2cd allometry (exp(log-intercept) or scaling). If allom_dmode=1; this is the same as former crown_depth_frac parameter" ; + double fates_allom_h2cd2(fates_pft) ; + fates_allom_h2cd2:units = "variable" ; + fates_allom_h2cd2:long_name = "Parameter 2 for h2cd allometry (log-slope or exponent). If allom_dmode=1; this is not needed (as exponent is assumed 1)" ; double fates_allom_hmode(fates_pft) ; fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; @@ -173,7 +179,7 @@ variables: fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; double fates_cnp_eca_alpha_ptase(fates_pft) ; fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + fates_cnp_eca_alpha_ptase:long_name = "(INACTIVE, KEEP AT 0) fraction of P from ptase activity sent directly to plant (ECA)" ; double fates_cnp_eca_decompmicc(fates_pft) ; fates_cnp_eca_decompmicc:units = "gC/m3" ; fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; @@ -191,7 +197,7 @@ variables: fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; double fates_cnp_eca_lambda_ptase(fates_pft) ; fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + fates_cnp_eca_lambda_ptase:long_name = "(INACTIVE, KEEP AT 0) critical value for biochemical production (ECA)" ; double fates_cnp_eca_vmax_ptase(fates_pft) ; fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; @@ -381,12 +387,24 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leafn_vert_scaler_coeff1(fates_pft) ; + fates_leafn_vert_scaler_coeff1:units = "unitless" ; + fates_leafn_vert_scaler_coeff1:long_name = "Coefficient one for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010." ; + double fates_leafn_vert_scaler_coeff2(fates_pft) ; + fates_leafn_vert_scaler_coeff2:units = "unitless" ; + fates_leafn_vert_scaler_coeff2:long_name = "Coefficient two for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010." ; double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_leaf_vert_scaler_coeff1(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff1:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff1:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff1." ; + double fates_maintresp_leaf_vert_scaler_coeff2(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff2:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff2." ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -980,9 +998,6 @@ data: fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; @@ -1012,6 +1027,8 @@ data: fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, 0.35, 0.35, 0.35 ; + fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; @@ -1022,6 +1039,10 @@ data: fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_allom_h2cd1 = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; + + fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1055,8 +1076,7 @@ data: fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; + fates_cnp_eca_alpha_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; @@ -1072,7 +1092,7 @@ data: fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_eca_lambda_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; @@ -1305,6 +1325,12 @@ data: fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; + fates_leafn_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; + + fates_leafn_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43 ; + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; @@ -1312,6 +1338,13 @@ data: 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06 ; + fates_maintresp_leaf_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963 ; + + fates_maintresp_leaf_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; From 5a752b70596e5e940bf8b5d837ab4e4434d46368 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 26 Mar 2024 11:38:17 -0600 Subject: [PATCH 136/300] add bug fix --- fire/SFMainMod.F90 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index ef245b04f9..6a83ba30df 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -306,6 +306,10 @@ subroutine charecteristics_of_fuel ( currentSite ) currentPatch%litter_moisture(tr_sf) = fuel_moisture(tr_sf)/MEF(tr_sf) currentPatch%litter_moisture(dl_sf) = fuel_moisture(dl_sf)/MEF(dl_sf) currentPatch%litter_moisture(lg_sf) = fuel_moisture(lg_sf)/MEF(lg_sf) + + ! remove trunks from patch%sum_fuel because they should not be included in fire equations + ! NOTE: ACF will update this soon to be more clean/bug-proof + currentPatch%sum_fuel = currentPatch%sum_fuel - litt_c%ag_cwd(4) else From 48f0a81c64ef35b2c2649fb8df7036e506e2b8ca Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Mar 2024 13:42:28 -0400 Subject: [PATCH 137/300] adding daylight factor --- main/EDParamsMod.F90 | 13 ++++++++++++- .../archive/api34.0.0_032624_patch_params.xml | 8 ++++++++ parameter_files/fates_params_default.cdl | 5 +++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 8d78eec61c..e3454f430c 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -77,6 +77,7 @@ module EDParamsMod real(r8),protected, public :: ED_val_patch_fusion_tol ! minimum fraction in difference in profiles between patches real(r8),protected, public :: ED_val_canopy_closure_thresh ! site-level canopy closure point where trees take on forest (narrow) versus savannah (wide) crown allometry integer,protected, public :: stomatal_model ! switch for choosing between stomatal conductance models, 1 for Ball-Berry, 2 for Medlyn + integer,protected, public :: dayl_switch ! switch for turning on or off day length factor scaling for photosynthetic parameters integer,protected, public :: regeneration_model ! Switch for choosing between regeneration models: ! (1) for Fates default ! (2) for the Tree Recruitment Scheme (Hanbury-Brown et al., 2022) @@ -166,6 +167,7 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_patch_fusion_tol= "fates_patch_fusion_tol" character(len=param_string_length),parameter,public :: ED_name_canopy_closure_thresh= "fates_canopy_closure_thresh" character(len=param_string_length),parameter,public :: ED_name_stomatal_model= "fates_leaf_stomatal_model" + character(len=param_string_length),parameter,public :: ED_name_dayl_switch= "fates_daylength_factor_switch" character(len=param_string_length),parameter,public :: ED_name_regeneration_model= "fates_regeneration_model" character(len=param_string_length),parameter,public :: name_theta_cj_c3 = "fates_leaf_theta_cj_c3" @@ -338,6 +340,7 @@ subroutine FatesParamsInit() ED_val_patch_fusion_tol = nan ED_val_canopy_closure_thresh = nan stomatal_model = -9 + dayl_switch = -9 regeneration_model = -9 stomatal_assim_model = -9 max_cohort_per_patch = -9 @@ -492,7 +495,10 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_stomatal_model, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - + + call fates_params%RegisterParameter(name=ED_name_dayl_switch, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=ED_name_regeneration_model, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -712,6 +718,10 @@ subroutine FatesReceiveParams(fates_params) data=tmpreal) stomatal_model = nint(tmpreal) + call fates_params%RetrieveParameter(name=ED_name_dayl_switch, & + data=tmpreal) + dayl_switch = nint(tmpreal) + call fates_params%RetrieveParameter(name=ED_name_regeneration_model, & data=tmpreal) regeneration_model = nint(tmpreal) @@ -881,6 +891,7 @@ subroutine FatesReportParams(is_master) write(fates_log(),fmt0) 'ED_val_canopy_closure_thresh = ',ED_val_canopy_closure_thresh write(fates_log(),fmt0) 'regeneration_model = ',regeneration_model write(fates_log(),fmt0) 'stomatal_model = ',stomatal_model + write(fates_log(),fmt0) 'dayl_switch = ',dayl_switch write(fates_log(),fmt0) 'stomatal_assim_model = ',stomatal_assim_model write(fates_log(),fmt0) 'hydro_kmax_rsurf1 = ',hydr_kmax_rsurf1 write(fates_log(),fmt0) 'hydro_kmax_rsurf2 = ',hydr_kmax_rsurf2 diff --git a/parameter_files/archive/api34.0.0_032624_patch_params.xml b/parameter_files/archive/api34.0.0_032624_patch_params.xml index fd670b586d..e1b13bc4e2 100644 --- a/parameter_files/archive/api34.0.0_032624_patch_params.xml +++ b/parameter_files/archive/api34.0.0_032624_patch_params.xml @@ -114,5 +114,13 @@ Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff2. 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 + + fates_daylength_factor_switch + scalar + unitless + user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters (ie scale vcmax and jmax) + 1 + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 847a7b3f85..55c80ee1c6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -714,6 +714,9 @@ variables: double fates_damage_event_code ; fates_damage_event_code:units = "unitless" ; fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_daylength_factor_switch ; + fates_daylength_factor_switch:units = "unitless" ; + fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters (ie scale vcmax and jmax)" ; double fates_dev_arbitrary ; fates_dev_arbitrary:units = "unknown" ; fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; @@ -1648,6 +1651,8 @@ data: fates_damage_event_code = 1 ; + fates_daylength_factor_switch = 1 ; + fates_dev_arbitrary = _ ; fates_fire_active_crown_fire = 0 ; From 7444f26fa9ef82986a590e01f3438745aab32c4a Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Mar 2024 12:12:06 -0600 Subject: [PATCH 138/300] bug fix on parameter printing --- main/EDPftvarcon.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 46926caad4..bc821c0204 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1776,10 +1776,10 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'hydro_vg_alpha_node = ',EDPftvarcon_inst%hydr_vg_alpha_node write(fates_log(),fmt0) 'hydro_vg_m_node = ',EDPftvarcon_inst%hydr_vg_m_node write(fates_log(),fmt0) 'hydro_vg_n_node = ',EDPftvarcon_inst%hydr_vg_n_node - write(fates_log(),fmt0) 'leafn_vert_scaler_coeff1 = ',leafn_vert_scaler_coeff1 - write(fates_log(),fmt0) 'leafn_vert_scaler_coeff2 = ',leafn_vert_scaler_coeff2 - write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff1 = ',maintresp_leaf_vert_scaler_coeff1 - write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff2 = ',maintresp_leaf_vert_scaler_coeff2 + write(fates_log(),fmt0) 'leafn_vert_scaler_coeff1 = ',EDPftvarcon_inst%leafn_vert_scaler_coeff1 + write(fates_log(),fmt0) 'leafn_vert_scaler_coeff2 = ',EDPftvarcon_inst%leafn_vert_scaler_coeff2 + write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff1 = ',EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff1 + write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff2 = ',EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff2 write(fates_log(),*) '-------------------------------------------------' end if From 52eda6aa6a4426e28f1368747a4403be995fcb00 Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Tue, 26 Mar 2024 15:55:55 -0600 Subject: [PATCH 139/300] add index as constant --- fire/SFMainMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 6a83ba30df..35cd4ca763 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -309,7 +309,7 @@ subroutine charecteristics_of_fuel ( currentSite ) ! remove trunks from patch%sum_fuel because they should not be included in fire equations ! NOTE: ACF will update this soon to be more clean/bug-proof - currentPatch%sum_fuel = currentPatch%sum_fuel - litt_c%ag_cwd(4) + currentPatch%sum_fuel = currentPatch%sum_fuel - litt_c%ag_cwd(tr_sf) else From 97dc27a58ae748cd568cebe305ac0d80dff668a5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 26 Mar 2024 20:03:17 -0600 Subject: [PATCH 140/300] added carbon starvation mode --- parameter_files/archive/api34.0.0_032624_patch_params.xml | 8 ++++++++ parameter_files/fates_params_default.cdl | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/parameter_files/archive/api34.0.0_032624_patch_params.xml b/parameter_files/archive/api34.0.0_032624_patch_params.xml index e1b13bc4e2..1d9f263da6 100644 --- a/parameter_files/archive/api34.0.0_032624_patch_params.xml +++ b/parameter_files/archive/api34.0.0_032624_patch_params.xml @@ -121,6 +121,14 @@ user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters (ie scale vcmax and jmax) 1 + + fates_mort_cstarvation_model + scalar + unitless + switch defining the carbon starvation model ( 1) Linear or 2) Exponential) in the mortality_rates function. + 1 + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 55c80ee1c6..2eaeb875fe 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -843,6 +843,9 @@ variables: double fates_maxcohort ; fates_maxcohort:units = "count" ; fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_mort_cstarvation_model ; + fates_mort_cstarvation_model:units = "unitless" ; + fates_mort_cstarvation_model:long_name = "switch defining the carbon starvation model ( 1) Linear or 2) Exponential) in the mortality_rates function." ; double fates_mort_disturb_frac ; fates_mort_disturb_frac:units = "fraction" ; fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; @@ -1737,6 +1740,8 @@ data: fates_maxcohort = 100 ; + fates_mort_cstarvation_model = 1 ; + fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; From 35b396dacd30b87928f5dec9c232e2749f0860cd Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 29 Mar 2024 16:23:56 -0400 Subject: [PATCH 141/300] added hydro code to force zero conductance a psi_min --- biogeophys/FatesHydroWTFMod.F90 | 301 ++++++++++++++---- biogeophys/FatesPlantHydraulicsMod.F90 | 34 ++ .../hydro/HydroUTestDriver.py | 45 ++- .../hydro/f90_src/HydroUnitWrapMod.F90 | 15 +- 4 files changed, 317 insertions(+), 78 deletions(-) diff --git a/biogeophys/FatesHydroWTFMod.F90 b/biogeophys/FatesHydroWTFMod.F90 index 9c0ef60a89..a7c47efb7a 100644 --- a/biogeophys/FatesHydroWTFMod.F90 +++ b/biogeophys/FatesHydroWTFMod.F90 @@ -30,6 +30,12 @@ module FatesHydroWTFMod real(r8), parameter :: min_ftc = 0.0_r8 ! Minimum allowed fraction of total conductance + real(r8), parameter :: min_ftc_scalar=2.0_r8 ! This scalar is used to define the attenuation + ! of the weighting that we use for imposing + ! ftc min at the minimum allowable psi + ! A value of two yielded a wieghting factor of + ! about 0.175 after 1 MPa, and 0.025 after 2 MPA + ! Bounds on saturated fraction, outside of which we use linear PV or stop flow ! In this context, the saturated fraction is defined by the volumetric WC "th" ! and the volumetric residual and saturation "th_res" and "th_sat": (th-th_r)/(th_sat-th_res) @@ -44,7 +50,8 @@ module FatesHydroWTFMod ! elastic-caviation region - real(r8), parameter :: min_theta_cch = 0.01_r8 ! Minimum theta (matches ctsm) + !real(r8), parameter :: min_theta_cch = 0.05_r8 ! Minimum theta (matches ctsm) + real(r8), parameter :: min_psi_cch = -20.0_r8 ! Minimum theta (matches ctsm) ! Generic class that can be extended to describe ! specific water retention functions @@ -91,6 +98,7 @@ module FatesHydroWTFMod ! water conductance functions type, public :: wkf_type + type(wrf_type), pointer :: wrf ! Pointer to the matching water retention function contains procedure :: ftc_from_psi => ftc_from_psi_base procedure :: dftcdpsi_from_psi => dftcdpsi_from_psi_base @@ -242,7 +250,8 @@ module FatesHydroWTFMod procedure :: set_wkf_param => set_wkf_param_tfs end type wkf_type_tfs - + public :: get_min_ftc_weight + contains ! ===================================================================================== @@ -343,7 +352,34 @@ function th_linear_res(this,psi) result(th) end function th_linear_res ! =========================================================================== + + subroutine get_min_ftc_weight(psi_min,psi,min_ftc_weight,dmin_ftc_weight_dpsi) + + ! This routine determines the weighting factor used + ! to generate a smooth curve to impose that min_ftc happens at min_psi + ! This method is to be used with any and all water transfer functions + + real(r8),intent(in) :: psi ! MPa suction + real(r8),intent(in) :: psi_min ! Minimum value of psi we track, value that pins to ftc_min + real(r8),intent(out):: min_ftc_weight ! weighting factor for min_ftc + real(r8),intent(out):: dmin_ftc_weight_dpsi ! derivative of weighting factor wrt psi + min_ftc_weight = exp(min_ftc_scalar*(psi_min-psi)) + dmin_ftc_weight_dpsi = -min_ftc_scalar*exp(min_ftc_scalar*(psi_min-psi)) + + if(min_ftc_weight>=1.)then + min_ftc_weight = 1._r8 + dmin_ftc_weight_dpsi = 0._r8 + elseif(min_ftc_weight<=0._r8)then + min_ftc_weight = 0._r8 + dmin_ftc_weight_dpsi = 0._r8 + end if + + return + end subroutine get_min_ftc_weight + + ! ============================================================================= + subroutine set_wrf_param_base(this,params_in) class(wrf_type) :: this real(r8),intent(in) :: params_in(:) @@ -613,7 +649,11 @@ function ftc_from_psi_vg(this,psi) result(ftc) real(r8) :: psi_eff real(r8) :: m ! pore size distribution param () real(r8) :: n ! pore size distribution param (psd) + real(r8) :: min_ftc_weight + real(r8) :: dmin_ftc_weight_dpsi + real(r8), pointer :: psi_min + psi_min => this%wrf%psi_min n = this%n_vg m = this%m_vg @@ -626,8 +666,18 @@ function ftc_from_psi_vg(this,psi) result(ftc) den = (1._r8 + (this%alpha*psi_eff)**n)**(this%tort*(m)) ! Make sure this is well behaved - ftc = min(1._r8,max(min_ftc,num/den)) - + ftc = min(1._r8,num/den) + + if(ftc<=min_ftc) then + ftc = min_ftc + else + ! Add protections and ensure no conductance at incredibly + ! low suction + call get_min_ftc_weight(psi_min,psi,min_ftc_weight,dmin_ftc_weight_dpsi) + + ftc = ftc*(1._r8 - min_ftc_weight) + min_ftc*min_ftc_weight + end if + else ftc = 1._r8 @@ -635,6 +685,9 @@ function ftc_from_psi_vg(this,psi) result(ftc) end function ftc_from_psi_vg + + + ! ==================================================================================== function dftcdpsi_from_psi_vg(this,psi) result(dftcdpsi) @@ -656,7 +709,11 @@ function dftcdpsi_from_psi_vg(this,psi) result(dftcdpsi) real(r8) :: dftcdpsi ! change in frac total cond wrt psi real(r8) :: m ! pore size distribution param (1/psd) real(r8) :: n + real(r8) :: min_ftc_weight + real(r8) :: dmin_ftc_weight_dpsi + real(r8), pointer :: psi_min + psi_min => this%wrf%psi_min n =this%n_vg m =this%m_vg @@ -666,8 +723,8 @@ function dftcdpsi_from_psi_vg(this,psi) result(dftcdpsi) psi_eff = -psi ! switch VG 1980 convention ftc = this%ftc_from_psi(psi) - - if(ftc<=min_ftc) then + + if ( abs(ftc-min_ftc) this%wrf%psi_min + ! th = th_sat * (psi/psi_sat)^(-1/b) ! ftc = (th/th_sat)^(2*b+3) @@ -826,6 +900,15 @@ function ftc_from_psi_cch(this,psi) result(ftc) ftc = (psi_eff/this%psi_sat)**(-2._r8-3._r8/this%beta) + if(ftc<=min_ftc) then + ftc = min_ftc + else + call get_min_ftc_weight(psi_min,psi,min_ftc_weight,dmin_ftc_weight_dpsi) + + ftc = ftc*(1._r8 - min_ftc_weight) + min_ftc*min_ftc_weight + + end if + end function ftc_from_psi_cch ! ==================================================================================== @@ -835,15 +918,37 @@ function dftcdpsi_from_psi_cch(this,psi) result(dftcdpsi) class(wkf_type_cch) :: this real(r8),intent(in) :: psi real(r8) :: dftcdpsi ! change in frac total cond wrt psi + real(r8) :: min_ftc_weight,dmin_ftc_weight_dpsi + real(r8) :: ftc + real(r8), pointer :: psi_min - ! Differentiate: - ! ftc = (psi/this%psi_sat)**(-2._r8-3._r8/this%beta) - + psi_min => this%wrf%psi_min + ! Note that if we assume a constant, capped FTC=1.0 ! at saturation, then the derivative is zero there if(psi this%wrf%psi_min pc = psi sat_res = 0._r8 alpha = -1._r8/this%psi_sat @@ -1286,8 +1392,18 @@ function ftc_from_psi_smooth_cch(this,psi) result(ftc) ! Here, `pc >= ps`. kr = 1.d0 endif - ftc = max(kr, min_ftc) + !ftc = max(kr, min_ftc) + + if(kr<=min_ftc) then + ftc = min_ftc + else + call get_min_ftc_weight(psi_min,psi,min_ftc_weight,dmin_ftc_weight_dpsi) + + ftc = kr*(1._r8 - min_ftc_weight) + min_ftc*min_ftc_weight + + end if + end function ftc_from_psi_smooth_cch @@ -1298,11 +1414,10 @@ function dftcdpsi_from_psi_smooth_cch(this,psi) result(dftcdpsi) class(wkf_type_smooth_cch) :: this real(r8),intent(in) :: psi real(r8) :: dftcdpsi ! change in frac total cond wrt psi - + real(r8) :: ftc real(r8) :: pc real(r8) :: kr real(r8) :: dkr_dP - ! real(r8) :: sat_res real(r8) :: alpha real(r8) :: lambda @@ -1310,46 +1425,65 @@ function dftcdpsi_from_psi_smooth_cch(this,psi) result(dftcdpsi) real(r8) :: deltaPc real(r8) :: dSe_dpc real(r8) :: dkr_dSe + real(r8) :: min_ftc_weight,dmin_ftc_weight_dpsi + real(r8), pointer :: psi_min - pc = psi - sat_res = 0._r8 - alpha = -1._r8/this%psi_sat - lambda = 1._r8/this%beta + psi_min => this%wrf%psi_min + ftc = this%ftc_from_psi(psi) + + if( abs(ftc-min_ftc)= ps`. - kr = 1.d0 - dkr_dP = 0.d0 - endif - dftcdpsi = dkr_dP - if(kr<=min_ftc) then - dftcdpsi = 0._r8 - endif + dkr_dSe = (3.d0 + 2.d0/lambda)*kr/Se + dkr_dp = dkr_dSe*dSe_dpc + elseif( pc < this%scch_ps ) then + ! Cubic smoothing regime. + ! Here, `pu < pc < ps <= 0`. + deltaPc = pc - this%scch_ps + Se = 1.d0 + deltaPc*deltaPc*(this%scch_b2 + deltaPc*this%scch_b3) + + dSe_dpc = deltaPc*(2*this%scch_b2 + 3*deltaPc*this%scch_b3) + + kr = Se ** (2.5d0 + 2.d0/lambda) + + dkr_dSe = (2.5d0 + 2.d0/lambda)*kr/Se + dkr_dp = dkr_dSe*dSe_dpc + else + ! Saturated regime. + ! Here, `pc >= ps`. + kr = 1.d0 + dkr_dP = 0.d0 + endif + dftcdpsi = dkr_dP + call get_min_ftc_weight(psi_min,psi,min_ftc_weight,dmin_ftc_weight_dpsi) + + ! differentiate: + ! ftc = ftc*(1._r8 - min_ftc_weight) + min_ftc*min_ftc_weight + ! ftc = ftc - ftc*min_ftc_weight + min_ftc*min_ftc_weight + + dftcdpsi = dftcdpsi - & + (dftcdpsi*min_ftc_weight + ftc*dmin_ftc_weight_dpsi) + & + min_ftc*dmin_ftc_weight_dpsi + + end if end function dftcdpsi_from_psi_smooth_cch @@ -1747,11 +1881,26 @@ function ftc_from_psi_tfs(this,psi) result(ftc) real(r8),intent(in) :: psi ! real(r8) :: ftc real(r8) :: psi_eff + real(r8) :: min_ftc_weight,dmin_ftc_weight_dpsi + real(r8), pointer :: psi_min + psi_min => this%wrf%psi_min psi_eff = min(-nearzero,psi) - ftc = max(min_ftc,1._r8/(1._r8 + (psi_eff/this%p50)**this%avuln)) + ftc = 1._r8/(1._r8 + (psi_eff/this%p50)**this%avuln) + + if(ftc<=min_ftc) then + ftc = min_ftc + else + ! Add protections and ensure no conductance at incredibly + ! low suction + call get_min_ftc_weight(psi_min,psi_eff,min_ftc_weight,dmin_ftc_weight_dpsi) + + ftc = ftc*(1._r8 - min_ftc_weight) + min_ftc*min_ftc_weight + end if + + end function ftc_from_psi_tfs ! ==================================================================================== @@ -1764,20 +1913,38 @@ function dftcdpsi_from_psi_tfs(this,psi) result(dftcdpsi) real(r8) :: fx ! portion of ftc function real(r8) :: dfx ! differentiation of portion of func real(r8) :: dftcdpsi ! change in frac total cond wrt psi + real(r8) :: min_ftc_weight,dmin_ftc_weight_dpsi + real(r8), pointer :: psi_min + psi_min => this%wrf%psi_min + ! Differentiate ! ftc = 1._r8/(1._r8 + (psi/this%p50(ft))**this%avuln(ft)) if(psi>0._r8)then dftcdpsi = 0._r8 else - ftc = 1._r8/(1._r8 + (psi/this%p50)**this%avuln) - if(ftc sites(s)%si_hydr%wrf_soil(j)%p + end do + + ! Update static quantities related to the rhizosphere call UpdateSizeDepRhizVolLenCon(sites(s), bc_in(s)) @@ -1655,6 +1664,15 @@ subroutine HydrSiteColdStart(sites, bc_in ) write(fates_log(),*) 'TFS conductance not used in soil' call endrun(msg=errMsg(sourcefile, __LINE__)) end select + + ! The fraction of total conductance functions need to know psi_min + ! to handle very very low conductances, therefore we need to construct + ! a pointer in conductance structure to the water retention structure + + do j=1,sites(s)%si_hydr%nlevrhiz + sites(s)%si_hydr%wkf_soil(j)%p%wrf => sites(s)%si_hydr%wrf_soil(j)%p + end do + end do @@ -6315,6 +6333,14 @@ subroutine InitHydroGlobals() write(fates_log(),*) 'undefined water conductance type for plants, pm:',pm,'type: ',hydr_htftype_node(pm) call endrun(msg=errMsg(sourcefile, __LINE__)) end select + + ! The fraction of total conductance functions need to know psi_min + ! to handle very very low conductances, therefore we need to construct + ! a pointer in conductance structure to the water retention structure + do ft = 1,numpft + wkf_plant(pm,ft)%p%wrf => wrf_plant(pm,ft)%p + end do + end do ! There is only 1 stomata conductance hypothesis which uses the p50 and @@ -6328,6 +6354,14 @@ subroutine InitHydroGlobals() EDPftvarcon_inst%hydr_avuln_gs(ft)]) end do + ! The fraction of total conductance functions need to know psi_min + ! to handle very very low conductances, therefore we need to construct + ! a pointer in conductance structure to the water retention structure + do ft = 1,numpft + wkf_plant(stomata_p_media,ft)%p%wrf => wrf_plant(stomata_p_media,ft)%p + end do + + return end subroutine InitHydroGlobals diff --git a/functional_unit_testing/hydro/HydroUTestDriver.py b/functional_unit_testing/hydro/HydroUTestDriver.py index 933c2aa837..98c38a63c2 100644 --- a/functional_unit_testing/hydro/HydroUTestDriver.py +++ b/functional_unit_testing/hydro/HydroUTestDriver.py @@ -58,10 +58,10 @@ ftc_from_psi.restype = c_double dftcdpsi_from_psi = f90_hydrounitwrap_obj.__hydrounitwrapmod_MOD_wrapdftcdpsi dftcdpsi_from_psi.restype = c_double - +ftcminwt_from_psi = f90_hydrounitwrap_obj.__hydrounitwrapmod_MOD_wrapftcminweightfrompsi +ftcminwt_from_psi.restype = c_double # Some constants -rwcft = [1.0,0.958,0.958,0.958] rwccap = [1.0,0.947,0.947,0.947] pm_leaf = 1 pm_stem = 2 @@ -260,6 +260,13 @@ def main(argv): print('Allocated') + #min_psi = -10. + #min_psi_falloff = 1 + #test_psi = np.linspace(min_psi, 0, num=1000) + #weight = y = e^(2*(-10-x)) + + + # Define the funcions and their parameters # vg_wrf(1,alpha=1.0,psd=2.7,th_sat=0.55,th_res=0.1) # vg_wkf(1,alpha=1.0,psd=2.7,th_sat=0.55,th_res=0.1,tort=0.5) @@ -447,9 +454,9 @@ def main(argv): sucsat_v = [] bsw_v = [] - ntex = 100 + ntex = 5 for icl in range(ntex): - clay_frac = float(ic)/float(ntex) + clay_frac = float(icl)/float(ntex) for isa in range(ntex): sand_frac = float(isa)/float(ntex) @@ -486,19 +493,37 @@ def main(argv): # Now lets test the lowest possible water contents using these + #psi_v = -np.linspace(0.01,24,24) + psi_v = -np.logspace(-3,1.5,60) + fig10,(ax1,ax2,ax3) = plt.subplots(3,1,figsize=(6,9)) + + ii=4 - + th_v = [] + ftc_v = [] + ftc_min_wt_v = [] for i in ind: ii = ii+1 cch_wrf(ii,th_sat=watsat_v[i], psi_sat=sucsat_v[i], beta=bsw_v[i]) cch_wkf(ii,th_sat=watsat_v[i], psi_sat=sucsat_v[i], beta=bsw_v[i]) print('---th sat: {}, psi sat: {}, beat: {}'.format(watsat_v[i],sucsat_v[i],bsw_v[i])) - for psi in -np.linspace(1,24,24): - th = th_from_psi(ci(ii),c8(psi)) - print('{}, psi: {}, th: {}'.format(ii,psi,th)) + for psi in psi_v: + th_v.append(th_from_psi(ci(ii),c8(psi))) + ftc_v.append(ftc_from_psi(ci(ii),c8(psi))) + ftc_min_wt_v.append(ftcminwt_from_psi(ci(ii),c8(psi))) + + ax1.plot(psi_v,th_v) + ax2.plot(psi_v,ftc_v) + ax3.plot(psi_v,ftc_min_wt_v) + th_v = [] + ftc_v = [] + ftc_min_wt_v = [] + + ax2.set_xlabel('Suction MPa') + ax1.set_ylabel('Theta') + ax2.set_ylabel('FTC') + ax3.set_ylabel('FTC Min Weight') - - plt.show() # code.interact(local=dict(globals(), **locals())) diff --git a/functional_unit_testing/hydro/f90_src/HydroUnitWrapMod.F90 b/functional_unit_testing/hydro/f90_src/HydroUnitWrapMod.F90 index 03e95a6a32..02167209ef 100644 --- a/functional_unit_testing/hydro/f90_src/HydroUnitWrapMod.F90 +++ b/functional_unit_testing/hydro/f90_src/HydroUnitWrapMod.F90 @@ -14,7 +14,8 @@ module HydroUnitWrapMod use FatesHydroWTFMod, only : wrf_type,wrf_type_vg,wrf_type_cch use FatesHydroWTFMod, only : wkf_type,wkf_type_vg,wkf_type_cch,wkf_type_tfs use FatesHydroWTFMod, only : wrf_arr_type,wkf_arr_type,wrf_type_tfs - + use FatesHydroWTFMod, only : get_min_ftc_weight + implicit none public save @@ -107,6 +108,8 @@ subroutine SetWKF(index,itype,npvals,pvals) stop end if + wkfs(index)%p%wrf => wrfs(index)%p + return end subroutine SetWKF @@ -167,5 +170,15 @@ function WrapFTCFromPSI(index,psi) result(ftc) return end function WrapFTCFromPSI + function WrapFTCMinWeightFromPsi(index,psi) result(min_ftc_weight) + integer, intent(in) :: index + real(r8),intent(in) :: psi + real(r8) :: min_ftc_weight,dmin_ftc_weight_dpsi + + print*,"PSI_MIN: ",wkfs(index)%p%wrf%psi_min + + call get_min_ftc_weight(wkfs(index)%p%wrf%psi_min,psi,min_ftc_weight,dmin_ftc_weight_dpsi) + + end function WrapFTCMinWeightFromPsi end module HydroUnitWrapMod From 57b10d32409aa3ff9f3789eabc717c3c89de26ea Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 2 Apr 2024 10:51:04 -0400 Subject: [PATCH 142/300] Getting zero flux at psi_min in fates hydro --- biogeophys/FatesHydroWTFMod.F90 | 25 ++++++++++++++----------- biogeophys/FatesPlantHydraulicsMod.F90 | 17 +++++++++++------ main/FatesInterfaceMod.F90 | 3 ++- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/biogeophys/FatesHydroWTFMod.F90 b/biogeophys/FatesHydroWTFMod.F90 index a7c47efb7a..54833f979b 100644 --- a/biogeophys/FatesHydroWTFMod.F90 +++ b/biogeophys/FatesHydroWTFMod.F90 @@ -364,9 +364,9 @@ subroutine get_min_ftc_weight(psi_min,psi,min_ftc_weight,dmin_ftc_weight_dpsi) real(r8),intent(out):: min_ftc_weight ! weighting factor for min_ftc real(r8),intent(out):: dmin_ftc_weight_dpsi ! derivative of weighting factor wrt psi - min_ftc_weight = exp(min_ftc_scalar*(psi_min-psi)) - dmin_ftc_weight_dpsi = -min_ftc_scalar*exp(min_ftc_scalar*(psi_min-psi)) - + min_ftc_weight = exp(min_ftc_scalar*max(psi_min-psi,-10._r8)) + dmin_ftc_weight_dpsi = -min_ftc_scalar*exp(min_ftc_scalar*max(psi_min-psi,-10._r8)) + if(min_ftc_weight>=1.)then min_ftc_weight = 1._r8 dmin_ftc_weight_dpsi = 0._r8 @@ -785,7 +785,7 @@ subroutine set_wrf_param_cch(this,params_in) !this%psi_min = this%psi_from_th(min_theta_cch+tiny(this%th_max)) this%psi_min = min_psi_cch this%th_min = this%th_from_psi(min_psi_cch+tiny(this%th_max)) - this%dpsidth_min = this%dpsidth_from_th(this%th_min+tiny(this%th_max)) + this%dpsidth_min = this%dpsidth_from_th(this%th_min) return end subroutine set_wrf_param_cch @@ -1885,8 +1885,8 @@ function ftc_from_psi_tfs(this,psi) result(ftc) real(r8), pointer :: psi_min psi_min => this%wrf%psi_min - psi_eff = min(-nearzero,psi) - + psi_eff = max(psi_min,min(-nearzero,psi)) + ftc = 1._r8/(1._r8 + (psi_eff/this%p50)**this%avuln) if(ftc<=min_ftc) then @@ -1894,6 +1894,7 @@ function ftc_from_psi_tfs(this,psi) result(ftc) else ! Add protections and ensure no conductance at incredibly ! low suction + call get_min_ftc_weight(psi_min,psi_eff,min_ftc_weight,dmin_ftc_weight_dpsi) ftc = ftc*(1._r8 - min_ftc_weight) + min_ftc*min_ftc_weight @@ -1915,27 +1916,29 @@ function dftcdpsi_from_psi_tfs(this,psi) result(dftcdpsi) real(r8) :: dftcdpsi ! change in frac total cond wrt psi real(r8) :: min_ftc_weight,dmin_ftc_weight_dpsi real(r8), pointer :: psi_min + real(r8) :: psi_eff psi_min => this%wrf%psi_min + psi_eff = max(psi_min,min(-nearzero,psi)) ! Differentiate ! ftc = 1._r8/(1._r8 + (psi/this%p50(ft))**this%avuln(ft)) - if(psi>0._r8)then + if(psi_eff>0._r8)then dftcdpsi = 0._r8 else - ftc = this%ftc_from_psi(psi) + ftc = this%ftc_from_psi(psi_eff) if ( abs(ftc-min_ftc) sites(s)%si_hydr%wrf_soil(j)%p end do @@ -3128,7 +3128,7 @@ subroutine OrderLayersForSolve1D(csite_hydr,cohort,cohort_hydr,ordered, kbg_laye integer :: tmp ! temporarily holds a soil layer index integer :: ft ! functional type index of plant integer :: j,jj,k ! layer and shell indices - + real(r8), parameter :: neglibible_cond = 1.e-10_r8 kbg_tot = 0._r8 kbg_layer(:) = 0._r8 @@ -3164,7 +3164,9 @@ subroutine OrderLayersForSolve1D(csite_hydr,cohort,cohort_hydr,ordered, kbg_laye ! Calculate total effective conductance over path [kg s-1 MPa-1] ! from absorbing root node to 1st rhizosphere shell - r_bg = 1._r8/(kmax_aroot*ftc_aroot) + ! (since this is just about ordering, its ok to create a pseudo resistance + ! for nodes with zero conductance..) + r_bg = 1._r8/(kmax_aroot*max(ftc_aroot,neglibible_cond)) ! Path is across the upper an lower rhizosphere comparment ! on each side of the nodes. Since there is no flow across the outer @@ -3180,8 +3182,8 @@ subroutine OrderLayersForSolve1D(csite_hydr,cohort,cohort_hydr,ordered, kbg_laye ftc_shell = csite_hydr%wkf_soil(j)%p%ftc_from_psi(psi_shell) - r_bg = r_bg + 1._r8/(kmax_up*ftc_shell) - if(k wrf_plant(stomata_p_media,ft)%p + wkf_plant(stomata_p_media,ft)%p%wrf => wrf_plant(1,ft)%p end do diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 3c2093fa37..99e13fa5f4 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -41,6 +41,7 @@ module FatesInterfaceMod use FatesConstantsMod , only : n_landuse_cats use FatesConstantsMod , only : primaryland use FatesConstantsMod , only : secondaryland + use FatesConstantsMod , only : n_term_mort_types use FatesGlobals , only : fates_global_verbose use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun @@ -877,7 +878,7 @@ subroutine SetFatesGlobalElements2(use_fates) end if fates_maxElementsPerSite = max(fates_maxPatchesPerSite * fates_maxElementsPerPatch, & - numWatermem*numpft, num_vegtemp_mem, num_elements, nlevsclass*numpft) + numWatermem*numpft, num_vegtemp_mem, num_elements, nlevsclass*numpft*n_term_mort_types) if(hlm_use_planthydro==itrue)then fates_maxElementsPerSite = max(fates_maxElementsPerSite, nshell*nlevsoi_hyd_max ) From 2ade2b15244e3d25a40018df9dd4cc8981a080ae Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 2 Apr 2024 14:33:24 -0700 Subject: [PATCH 143/300] move get_current_landuse_statevector into ed_site_type --- biogeochem/EDPatchDynamicsMod.F90 | 39 ++---------------------------- main/EDMainMod.F90 | 3 +-- main/EDTypesMod.F90 | 40 ++++++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index e610e7c22a..b174ef8b9f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -127,7 +127,6 @@ module EDPatchDynamicsMod public :: check_patch_area public :: set_patchno private:: fuse_2_patches - public :: get_current_landuse_statevector character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -223,7 +222,7 @@ subroutine disturbance_rates( site_in, bc_in) !---------------------------------------------------------------------------------------------- ! first calculate the fraction of the site that is primary land - call get_current_landuse_statevector(site_in, current_fates_landuse_state_vector) + call site_in%get_current_landuse_statevector(current_fates_landuse_state_vector) ! check status of transition_landuse_from_off_to_on flag, and do some error checking on it if(site_in%transition_landuse_from_off_to_on) then @@ -3555,7 +3554,7 @@ subroutine terminate_patches(currentSite, bc_in) write(fates_log(),*) patchpointer%area, patchpointer%nocomp_pft_label, patchpointer%land_use_label patchpointer => patchpointer%older end do - call get_current_landuse_statevector(currentSite, state_vector_internal) + call currentSite%get_current_landuse_statevector(state_vector_internal) write(fates_log(),*) 'current landuse state vector: ', state_vector_internal write(fates_log(),*) 'current landuse state vector (not including bare gruond): ', state_vector_internal/(1._r8-currentSite%area_bareground) call get_luh_statedata(bc_in, state_vector_driver) @@ -3755,40 +3754,6 @@ end function countPatches ! ===================================================================================== - subroutine get_current_landuse_statevector(site_in, current_state_vector) - - ! - ! !DESCRIPTION: - ! Calculate how much of a site is each land use category. - ! this does not include bare ground when nocomp + fixed biogeography is on, - ! so will not sum to one in that case. otherwise it will sum to one. - ! - ! !USES: - use EDTypesMod , only : ed_site_type - ! - ! !ARGUMENTS: - type(ed_site_type) , intent(in), target :: site_in - real(r8) , intent(out) :: current_state_vector(n_landuse_cats) - - ! !LOCAL VARIABLES: - type (fates_patch_type), pointer :: currentPatch - - current_state_vector(:) = 0._r8 - - currentPatch => site_in%oldest_patch - do while (associated(currentPatch)) - if (currentPatch%land_use_label .gt. nocomp_bareground_land) then - current_state_vector(currentPatch%land_use_label) = & - current_state_vector(currentPatch%land_use_label) + & - currentPatch%area/AREA - end if - currentPatch => currentPatch%younger - end do - - end subroutine get_current_landuse_statevector - - ! ===================================================================================== - subroutine InsertPatch(currentSite, newPatch) ! !DESCRIPTION: diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index af41670045..3368d1284f 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -89,7 +89,6 @@ module EDMainMod use EDLoggingMortalityMod , only : IsItLoggingTime use EDLoggingMortalityMod , only : get_harvestable_carbon use DamageMainMod , only : IsItDamageTime - use EDPatchDynamicsMod , only : get_current_landuse_statevector use FatesGlobals , only : endrun => fates_endrun use ChecksBalancesMod , only : SiteMassStock use EDMortalityFunctionsMod , only : Mortality_Derivative @@ -415,7 +414,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) !----------------------------------------------------------------------- - call get_current_landuse_statevector(currentSite, current_fates_landuse_state_vector) + call currentSite%get_current_landuse_statevector(current_fates_landuse_state_vector) ! Clear site GPP and AR passing to HLM bc_out%gpp_site = 0._r8 diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index bb62dfba6e..deceac558b 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -438,6 +438,10 @@ module EDTypesMod logical, allocatable :: landuse_vector_gt_min(:) ! is the land use state vector for each land use type greater than the minimum below which we ignore? logical :: transition_landuse_from_off_to_on ! special flag to use only when reading restarts, which triggers procedure to initialize land use + contains + + public :: get_current_landuse_statevector + end type ed_site_type ! Make public necessary subroutines and functions @@ -508,7 +512,41 @@ subroutine dump_site(csite) write(fates_log(),*) '----------------------------------------' return -end subroutine dump_site + end subroutine dump_site + + ! ===================================================================================== + + subroutine get_current_landuse_statevector(this, current_state_vector) + + ! + ! !DESCRIPTION: + ! Calculate how much of a site is each land use category. + ! this does not include bare ground when nocomp + fixed biogeography is on, + ! so will not sum to one in that case. otherwise it will sum to one. + ! + ! !USES: + ! + ! !ARGUMENTS: + class(ed_site_type) :: this + real(r8), intent(out) :: current_state_vector(n_landuse_cats) + + ! !LOCAL VARIABLES: + type(fates_patch_type), pointer :: currentPatch + + current_state_vector(:) = 0._r8 + + currentPatch => this%oldest_patch + do while (associated(currentPatch)) + if (currentPatch%land_use_label .gt. nocomp_bareground_land) then + current_state_vector(currentPatch%land_use_label) = & + current_state_vector(currentPatch%land_use_label) + & + currentPatch%area/AREA + end if + currentPatch => currentPatch%younger + end do + + end subroutine get_current_landuse_statevector + end module EDTypesMod From 833e39719e5b3b51d24ce298269432f770adbcf5 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 2 Apr 2024 14:44:46 -0700 Subject: [PATCH 144/300] covert get_current_landuse_statevector to a function --- biogeochem/EDPatchDynamicsMod.F90 | 4 ++-- main/EDMainMod.F90 | 2 +- main/EDTypesMod.F90 | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index b174ef8b9f..4d37ecc6d3 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -222,7 +222,7 @@ subroutine disturbance_rates( site_in, bc_in) !---------------------------------------------------------------------------------------------- ! first calculate the fraction of the site that is primary land - call site_in%get_current_landuse_statevector(current_fates_landuse_state_vector) + current_fates_landuse_state_vector = site_in%get_current_landuse_statevector() ! check status of transition_landuse_from_off_to_on flag, and do some error checking on it if(site_in%transition_landuse_from_off_to_on) then @@ -3554,7 +3554,7 @@ subroutine terminate_patches(currentSite, bc_in) write(fates_log(),*) patchpointer%area, patchpointer%nocomp_pft_label, patchpointer%land_use_label patchpointer => patchpointer%older end do - call currentSite%get_current_landuse_statevector(state_vector_internal) + state_vector_internal = currentSite%get_current_landuse_statevector() write(fates_log(),*) 'current landuse state vector: ', state_vector_internal write(fates_log(),*) 'current landuse state vector (not including bare gruond): ', state_vector_internal/(1._r8-currentSite%area_bareground) call get_luh_statedata(bc_in, state_vector_driver) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 3368d1284f..cd98993a6b 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -414,7 +414,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) !----------------------------------------------------------------------- - call currentSite%get_current_landuse_statevector(current_fates_landuse_state_vector) + current_fates_landuse_state_vector = currentSite%get_current_landuse_statevector() ! Clear site GPP and AR passing to HLM bc_out%gpp_site = 0._r8 diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index deceac558b..18498230f6 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -516,7 +516,7 @@ end subroutine dump_site ! ===================================================================================== - subroutine get_current_landuse_statevector(this, current_state_vector) + function get_current_landuse_statevector(this) result(current_state_vector) ! ! !DESCRIPTION: @@ -527,8 +527,8 @@ subroutine get_current_landuse_statevector(this, current_state_vector) ! !USES: ! ! !ARGUMENTS: - class(ed_site_type) :: this - real(r8), intent(out) :: current_state_vector(n_landuse_cats) + class(ed_site_type) :: this + real(r8) :: current_state_vector(n_landuse_cats) ! !LOCAL VARIABLES: type(fates_patch_type), pointer :: currentPatch From a269473b505ac731e5c4fc0be8205b2a89f3f767 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 3 Apr 2024 16:18:02 -0700 Subject: [PATCH 145/300] adjusted ordering of initializing bounds on cch functions to avoid undefined variables, reduce minimum suction of cch and fixed an error check --- biogeophys/FatesHydroWTFMod.F90 | 51 +++++++++++++++----------- biogeophys/FatesPlantHydraulicsMod.F90 | 31 ++++++++++------ 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/biogeophys/FatesHydroWTFMod.F90 b/biogeophys/FatesHydroWTFMod.F90 index 54833f979b..f83aa4d5d9 100644 --- a/biogeophys/FatesHydroWTFMod.F90 +++ b/biogeophys/FatesHydroWTFMod.F90 @@ -51,7 +51,7 @@ module FatesHydroWTFMod !real(r8), parameter :: min_theta_cch = 0.05_r8 ! Minimum theta (matches ctsm) - real(r8), parameter :: min_psi_cch = -20.0_r8 ! Minimum theta (matches ctsm) + real(r8), parameter :: min_psi_cch = -15.0_r8 ! Minimum theta (matches ctsm) ! Generic class that can be extended to describe ! specific water retention functions @@ -88,7 +88,7 @@ module FatesHydroWTFMod procedure, non_overridable :: psi_linear_res procedure, non_overridable :: th_linear_sat procedure, non_overridable :: th_linear_res - procedure, non_overridable :: set_min_max + procedure, non_overridable :: set_min_max_from_satres procedure, non_overridable :: get_thmin end type wrf_type @@ -267,23 +267,25 @@ module FatesHydroWTFMod ! of numerical integration. ! ============================================================================ - subroutine set_min_max(this,th_res,th_sat) + subroutine set_min_max_from_satres(this,th_res,th_sat) ! This routine uses max_sf_interp and min_sft_interp ! to define the bounds of where the linear ranges start and stop - + ! This only works for functions defined by a saturation and + ! a residual value + class(wrf_type) :: this real(r8),intent(in) :: th_res real(r8),intent(in) :: th_sat this%th_max = max_sf_interp*(th_sat-th_res)+th_res this%th_min = min_sf_interp*(th_sat-th_res)+th_res - this%psi_max = this%psi_from_th(this%th_max-tiny(this%th_max)) - this%dpsidth_max = this%dpsidth_from_th(this%th_max-tiny(this%th_max)) - this%psi_min = this%psi_from_th(this%th_min+tiny(this%th_min)) - this%dpsidth_min = this%dpsidth_from_th(this%th_min+tiny(this%th_min)) + this%psi_max = this%psi_from_th(this%th_max) + this%dpsidth_max = this%dpsidth_from_th(this%th_max) + this%psi_min = this%psi_from_th(this%th_min) + this%dpsidth_min = this%dpsidth_from_th(this%th_min) - end subroutine set_min_max + end subroutine set_min_max_from_satres ! ============================================================================ @@ -364,6 +366,8 @@ subroutine get_min_ftc_weight(psi_min,psi,min_ftc_weight,dmin_ftc_weight_dpsi) real(r8),intent(out):: min_ftc_weight ! weighting factor for min_ftc real(r8),intent(out):: dmin_ftc_weight_dpsi ! derivative of weighting factor wrt psi + ! If the difference between psi and psi-min is greater than 10MPa + ! just assume there is no effect of the minimum function (ie weight 0) min_ftc_weight = exp(min_ftc_scalar*max(psi_min-psi,-10._r8)) dmin_ftc_weight_dpsi = -min_ftc_scalar*exp(min_ftc_scalar*max(psi_min-psi,-10._r8)) @@ -471,7 +475,7 @@ subroutine set_wrf_param_vg(this,params_in) this%th_sat = params_in(4) this%th_res = params_in(5) - call this%set_min_max(this%th_res,this%th_sat) + call this%set_min_max_from_satres(this%th_res,this%th_sat) return end subroutine set_wrf_param_vg @@ -778,13 +782,15 @@ subroutine set_wrf_param_cch(this,params_in) ! Set DERIVED constants ! used for interpolating in extreme ranges this%th_max = max_sf_interp*this%th_sat - this%psi_max = this%psi_from_th(this%th_max-tiny(this%th_max)) - this%dpsidth_max = this%dpsidth_from_th(this%th_max-tiny(this%th_max)) - - !this%th_min = min_theta_cch - !this%psi_min = this%psi_from_th(min_theta_cch+tiny(this%th_max)) this%psi_min = min_psi_cch - this%th_min = this%th_from_psi(min_psi_cch+tiny(this%th_max)) + ! Need a temporary th_min(this can't be uninitialized while calculating psi_max) + this%th_min = 0.001_r8 + + this%psi_max = this%psi_from_th(this%th_max) + this%dpsidth_max = this%dpsidth_from_th(this%th_max) + + ! Get the actual th_min which is equivalent to psi_min + this%th_min = this%th_from_psi(min_psi_cch) this%dpsidth_min = this%dpsidth_from_th(this%th_min) return @@ -826,7 +832,7 @@ function th_from_psi_cch(this,psi) result(th) th = this%th_max + (psi-this%psi_max)/this%dpsidth_max else if(psi csite%si_hydr - csite_hydr%h2oveg = 0.0_r8 + csite_hydr%h2oveg = 0.0_r8 currentPatch => csite%oldest_patch do while(associated(currentPatch)) currentCohort=>currentPatch%tallest @@ -1757,13 +1757,14 @@ subroutine UpdateH2OVeg(csite,bc_out,prev_site_h2o,icall) currentPatch => currentPatch%younger enddo !end patch loop + ! convert from kg/site to kg/m2 csite_hydr%h2oveg = csite_hydr%h2oveg*AREA_INV ! Note that h2oveg_dead is incremented wherever we have litter fluxes ! and it will be reduced via an evaporation term - ! growturn_err is a term to accomodate error in growth or - ! turnover. need to be improved for future(CX) - bc_out%plant_stored_h2o_si = csite_hydr%h2oveg + csite_hydr%h2oveg_dead - & + ! growturn_err is a term to accomodate error in growth or + ! turnover. need to be improved for future(CX) + bc_out%plant_stored_h2o_si = csite_hydr%h2oveg + csite_hydr%h2oveg_dead - & csite_hydr%h2oveg_growturn_err - & csite_hydr%h2oveg_hydro_err @@ -2816,13 +2817,21 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) delta_soil_storage = sum(csite_hydr%h2osoi_liqvol_shell(:,:) * & csite_hydr%v_shell(:,:)) * denh2o * AREA_INV - prev_h2osoil - if(abs(delta_plant_storage - (root_flux - transp_flux)) > error_thresh ) then + ! This is to check closure and include the known error + ! The error is essentially the overestimate transpiration + ! versus change in state (q_top_eff*dt_substep) - (w_tot_beg-w_tot_end) + ! That is why we remove the error from the transpiration in this check + if(abs(delta_plant_storage - (root_flux + csite_hydr%errh2o_hyd - transp_flux)) > error_thresh ) then write(fates_log(),*) 'Site plant water balance does not close' + write(fates_log(),*) 'Allowable, actual error (kg/m2): ',error_thresh, & + abs(delta_plant_storage - (root_flux + csite_hydr%dwat_veg - transp_flux)) write(fates_log(),*) 'delta plant storage: ',delta_plant_storage,' [kg/m2]' write(fates_log(),*) 'integrated root flux: ',root_flux,' [kg/m2]' write(fates_log(),*) 'transpiration flux: ',transp_flux,' [kg/m2]' write(fates_log(),*) 'end storage: ',csite_hydr%h2oveg write(fates_log(),*) 'pre_h2oveg', prev_h2oveg + write(fates_log(),*) 'csite_hydr%errh2o_hyd:',csite_hydr%errh2o_hyd + write(fates_log(),*) 'csite_hydr%dwat_veg:',csite_hydr%dwat_veg call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -3225,7 +3234,7 @@ end subroutine OrderLayersForSolve1D subroutine ImTaylorSolve1D(slat, slon,recruitflag,csite_hydr,cohort,cohort_hydr,dtime,q_top, & ordered,kbg_layer, sapflow,rootuptake,& - wb_err_plant,dwat_plant,dth_layershell_col) + wb_err_ps,dwat_plant,dth_layershell_col) ! ------------------------------------------------------------------------------- ! Calculate the hydraulic conductances across a list of paths. The list is a 1D vector, and @@ -3258,8 +3267,8 @@ subroutine ImTaylorSolve1D(slat, slon,recruitflag,csite_hydr,cohort,cohort_hydr, real(r8),intent(out) :: sapflow ! time integrated mass flux between transp-root and stem [kg] real(r8),intent(out) :: rootuptake(:) ! time integrated mass flux between rhizosphere and aroot [kg] - real(r8),intent(out) :: wb_err_plant ! total error from the plant, transpiration - ! should match change in storage [kg] + real(r8),intent(out) :: wb_err_ps ! total error from the plant-soil system, transpiration + ! should match change in storage [kg] real(r8),intent(out) :: dwat_plant ! Change in plant stored water [kg] real(r8),intent(inout) :: dth_layershell_col(:,:) ! accumulated water content change over all cohorts in a column [m3 m-3]) @@ -3348,8 +3357,8 @@ subroutine ImTaylorSolve1D(slat, slon,recruitflag,csite_hydr,cohort,cohort_hydr, cohort_hydr%iterh1 = 0 cohort_hydr%iterh2 = 0 - ! Initialize plant water error (integrated flux-storage) - wb_err_plant = 0._r8 + ! Initialize plant-soil water error (integrated flux-storage) + wb_err_ps = 0._r8 ! Initialize integrated change in total plant water dwat_plant = 0._r8 @@ -3910,7 +3919,7 @@ subroutine ImTaylorSolve1D(slat, slon,recruitflag,csite_hydr,cohort,cohort_hydr, dth_node(n_hypool_ag+2)*cohort_hydr%v_aroot_layer(ilayer))*denh2o ! Remember the error for the cohort - wb_err_plant = wb_err_plant + wb_err_layer + wb_err_ps = wb_err_ps + wb_err_layer ! Save the change in water mass in the rhizosphere. Note that we did ! not immediately update the state variables upon completing each From 157df2b583043b84e0468aad4c0d8d6aadec1148 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 4 Apr 2024 15:41:14 -0700 Subject: [PATCH 146/300] condense common code into a new subroutine --- biogeochem/EDPatchDynamicsMod.F90 | 77 +++++++++++-------------------- 1 file changed, 27 insertions(+), 50 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index e610e7c22a..ca997a5c63 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -774,24 +774,7 @@ subroutine spawn_patches( currentSite, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - - ! Copy any means or timers from the original patch to the new patch - ! These values will inherit all info from the original patch - ! -------------------------------------------------------------------------- - call newPatch%tveg24%CopyFromDonor(currentPatch%tveg24) - call newPatch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - call newPatch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) - - - if ( regeneration_model == TRS_regeneration ) then - call newPatch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) - call newPatch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) - call newPatch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) - do pft = 1,numpft - call newPatch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) - call newPatch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) - enddo - end if + call CopyPatchMeansTimers(newPatch, currentPatch) call newPatch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) @@ -1410,22 +1393,8 @@ subroutine spawn_patches( currentSite, bc_in) buffer_patch%tallest => null() buffer_patch%shortest => null() - ! Copy any means or timers from the original patch to the new patch - ! These values will inherit all info from the original patch - ! -------------------------------------------------------------------------- - call buffer_patch%tveg24%CopyFromDonor(copyPatch%tveg24) - call buffer_patch%tveg_lpa%CopyFromDonor(copyPatch%tveg_lpa) - call buffer_patch%tveg_longterm%CopyFromDonor(copyPatch%tveg_longterm) - - if ( regeneration_model == TRS_regeneration ) then - call buffer_patch%seedling_layer_par24%CopyFromDonor(copyPatch%seedling_layer_par24) - call buffer_patch%sdlng_mort_par%CopyFromDonor(copyPatch%sdlng_mort_par) - call buffer_patch%sdlng2sap_par%CopyFromDonor(copyPatch%sdlng2sap_par) - do pft = 1,numpft - call buffer_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(copyPatch%sdlng_emerg_smp(pft)%p) - call buffer_patch%sdlng_mdd(pft)%p%CopyFromDonor(copyPatch%sdlng_mdd(pft)%p) - enddo - end if + call CopyPatchMeansTimers() + buffer_patch_used = .false. currentPatch => currentSite%oldest_patch @@ -1669,23 +1638,8 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) new_patch%tallest => null() new_patch%shortest => null() - ! Copy any means or timers from the original patch to the new patch - ! These values will inherit all info from the original patch - ! -------------------------------------------------------------------------- - call new_patch%tveg24%CopyFromDonor(currentPatch%tveg24) - call new_patch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - call new_patch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) + call CopyPatchMeansTimers(new_patch, currentPatch) - if ( regeneration_model == TRS_regeneration ) then - call new_patch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) - call new_patch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) - call new_patch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) - do pft = 1,numpft - call new_patch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) - call new_patch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) - enddo - end if - currentPatch%burnt_frac_litter(:) = 0._r8 call TransLitterNewPatch( currentSite, currentPatch, new_patch, currentPatch%area * (1.-fraction_to_keep)) @@ -3953,4 +3907,27 @@ subroutine InsertPatch(currentSite, newPatch) end subroutine InsertPatch + ! ===================================================================================== + + subroutine CopyPatchMeansTimers(bufferPatch, currentPatch) + + type(fates_patch_type), intent(inout) :: bufferPatch, currentPatch + + ! Copy any means or timers from the original patch to the new patch + ! These values will inherit all info from the original patch + ! -------------------------------------------------------------------------- + call bufferPatch%tveg24%CopyFromDonor(currentPatch%tveg24) + call bufferPatch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) + call bufferPatch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) + + if ( regeneration_model == TRS_regeneration ) then + call bufferPatch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) + call bufferPatch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) + call bufferPatch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) + do pft = 1,numpft + call bufferPatch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) + call bufferPatch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) + enddo + end if + end module EDPatchDynamicsMod From 44fc070aa56a46d7ee33811be0e9254f0adc3edc Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 4 Apr 2024 16:02:26 -0700 Subject: [PATCH 147/300] move CopyPatchMeansTimers around to find more common patterns --- biogeochem/EDPatchDynamicsMod.F90 | 75 ++++++++++++++++++------------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ca997a5c63..843d520b87 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -742,10 +742,13 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch%burnt_frac_litter(:) = 0._r8 end if + call CopyPatchMeansTimers(newPatch, currentPatch) + + call newPatch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) + call TransLitterNewPatch( currentSite, currentPatch, newPatch, patch_site_areadis) ! Transfer in litter fluxes from plants in various contexts of death and destruction - select case(i_disturbance_type) case (dtype_ilog) call logging_litter_fluxes(currentSite, currentPatch, & @@ -774,10 +777,6 @@ subroutine spawn_patches( currentSite, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - call CopyPatchMeansTimers(newPatch, currentPatch) - - call newPatch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) - ! -------------------------------------------------------------------------- ! The newly formed patch from disturbance (newPatch), has now been given ! some litter from dead plants and pre-existing litter from the donor patches. @@ -1378,9 +1377,6 @@ subroutine spawn_patches( currentSite, bc_in) hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & regeneration_model) - ! make a note that this buffer patch has not been put into the linked list - buffer_patch_in_linked_list = .false. - ! Initialize the litter pools to zero do el=1,num_elements call buffer_patch%litter(el)%InitConditions(init_leaf_fines=0._r8, & @@ -1393,8 +1389,10 @@ subroutine spawn_patches( currentSite, bc_in) buffer_patch%tallest => null() buffer_patch%shortest => null() - call CopyPatchMeansTimers() + call CopyPatchMeansTimers(buffer_patch, currentPatch) + ! make a note that this buffer patch has not been put into the linked list + buffer_patch_in_linked_list = .false. buffer_patch_used = .false. currentPatch => currentSite%oldest_patch @@ -1634,15 +1632,15 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) init_seed=0._r8, & init_seed_germ=0._r8) end do - new_patch%tallest => null() new_patch%shortest => null() call CopyPatchMeansTimers(new_patch, currentPatch) - currentPatch%burnt_frac_litter(:) = 0._r8 call TransLitterNewPatch( currentSite, currentPatch, new_patch, currentPatch%area * (1.-fraction_to_keep)) + currentPatch%burnt_frac_litter(:) = 0._r8 + ! Next, we loop through the cohorts in the donor patch, copy them with ! area modified number density into the new-patch, and apply survivorship. ! ------------------------------------------------------------------------- @@ -3909,25 +3907,40 @@ end subroutine InsertPatch ! ===================================================================================== - subroutine CopyPatchMeansTimers(bufferPatch, currentPatch) - - type(fates_patch_type), intent(inout) :: bufferPatch, currentPatch - - ! Copy any means or timers from the original patch to the new patch - ! These values will inherit all info from the original patch - ! -------------------------------------------------------------------------- - call bufferPatch%tveg24%CopyFromDonor(currentPatch%tveg24) - call bufferPatch%tveg_lpa%CopyFromDonor(currentPatch%tveg_lpa) - call bufferPatch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) - - if ( regeneration_model == TRS_regeneration ) then - call bufferPatch%seedling_layer_par24%CopyFromDonor(currentPatch%seedling_layer_par24) - call bufferPatch%sdlng_mort_par%CopyFromDonor(currentPatch%sdlng_mort_par) - call bufferPatch%sdlng2sap_par%CopyFromDonor(currentPatch%sdlng2sap_par) - do pft = 1,numpft - call bufferPatch%sdlng_emerg_smp(pft)%p%CopyFromDonor(currentPatch%sdlng_emerg_smp(pft)%p) - call bufferPatch%sdlng_mdd(pft)%p%CopyFromDonor(currentPatch%sdlng_mdd(pft)%p) - enddo - end if + subroutine CopyPatchMeansTimers(dp, rp) + + ! !DESCRIPTION: + ! Copy any means or timers from the original patch to the new patch + ! These values will inherit all info from the original patch + ! -------------------------------------------------------------------------- + ! + ! !ARGUMENTS: + type (fates_patch_type) , pointer :: dp ! Donor Patch + type (fates_patch_type) , target, intent(inout) :: rp ! Recipient Patch + + call rp%tveg24%CopyFromDonor(dp%tveg24) + call rp%tveg_lpa%CopyFromDonor(dp%tveg_lpa) + call rp%tveg_longterm%CopyFromDonor(dp%tveg_longterm) + + if ( regeneration_model == TRS_regeneration ) then + call rp%seedling_layer_par24%CopyFromDonor(dp%seedling_layer_par24) + call rp%sdlng_mort_par%CopyFromDonor(dp%sdlng_mort_par) + call rp%sdlng2sap_par%CopyFromDonor(dp%sdlng2sap_par) + do pft = 1,numpft + call rp%sdlng_emerg_smp(pft)%p%CopyFromDonor(dp%sdlng_emerg_smp(pft)%p) + call rp%sdlng_mdd(pft)%p%CopyFromDonor(dp%sdlng_mdd(pft)%p) + enddo + end if + + ! ===================================================================================== + + subroutine newsub(dp, rp) + + ! !DESCRIPTION: + ! + ! !ARGUMENTS: + type (fates_patch_type) , pointer :: dp ! Donor Patch + type (fates_patch_type) , target, intent(inout) :: rp ! Recipient Patch + end module EDPatchDynamicsMod From 63045a99745b65128a73002c3fed17ae0b1ed60b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 4 Apr 2024 16:10:39 -0700 Subject: [PATCH 148/300] remove subroutine stub --- biogeochem/EDPatchDynamicsMod.F90 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 843d520b87..6e187e2f6e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -3932,15 +3932,5 @@ subroutine CopyPatchMeansTimers(dp, rp) enddo end if - ! ===================================================================================== - - subroutine newsub(dp, rp) - - ! !DESCRIPTION: - ! - ! !ARGUMENTS: - type (fates_patch_type) , pointer :: dp ! Donor Patch - type (fates_patch_type) , target, intent(inout) :: rp ! Recipient Patch - end module EDPatchDynamicsMod From c19d973fec104f251da09b248310156427b07470 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 4 Apr 2024 16:11:46 -0700 Subject: [PATCH 149/300] remove duplicate tveg_longterm update that has been condensed --- biogeochem/EDPatchDynamicsMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 6e187e2f6e..085291fdbe 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -744,8 +744,6 @@ subroutine spawn_patches( currentSite, bc_in) call CopyPatchMeansTimers(newPatch, currentPatch) - call newPatch%tveg_longterm%CopyFromDonor(currentPatch%tveg_longterm) - call TransLitterNewPatch( currentSite, currentPatch, newPatch, patch_site_areadis) ! Transfer in litter fluxes from plants in various contexts of death and destruction From 94028398c20894bcc136b0eeb6a47d26903a71ed Mon Sep 17 00:00:00 2001 From: Marcos Longo Date: Mon, 8 Apr 2024 13:52:09 -0400 Subject: [PATCH 150/300] Revision of some error message output for inventory initialisation, so it is more informative. --- main/FatesInventoryInitMod.F90 | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 61f77387f4..22a48537b5 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -686,7 +686,7 @@ subroutine set_inventory_patch_type1(newpatch,pss_file_unit,ipa,ios,patch_name) type(litter_type),pointer :: litt integer :: el ! index for elements real(r8) :: p_time ! Time patch was recorded - real(r8) :: p_trk ! Land Use index (see above descriptions) + integer :: p_trk ! Land Use index (see above descriptions) character(len=patchname_strlen) :: p_name ! unique string identifier of patch real(r8) :: p_age ! Patch age [years] real(r8) :: p_area ! Patch area [fraction] @@ -694,9 +694,10 @@ subroutine set_inventory_patch_type1(newpatch,pss_file_unit,ipa,ios,patch_name) integer :: ipft ! index for counting PFTs real(r8) :: pftfrac ! the inverse of the total number of PFTs - character(len=128),parameter :: wr_fmt = & - '(F5.2,2X,A4,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2)' - + character(len=30),parameter :: hd_fmt = & + '(A5,2X,A20,2X,A4,2X,A5,2X,A17)' + character(len=47),parameter :: wr_fmt = & + '(F5.2,2X,A20,2X,I4,2X,F5.2,2X,F17.14)' read(pss_file_unit,fmt=*,iostat=ios) p_time, p_name, p_trk, p_age, p_area @@ -705,6 +706,8 @@ subroutine set_inventory_patch_type1(newpatch,pss_file_unit,ipa,ios,patch_name) patch_name = trim(p_name) if( debug_inv) then + write(*,fmt=hd_fmt) & + ' time',' patch',' trk',' age',' area' write(*,fmt=wr_fmt) & p_time, p_name, p_trk, p_age, p_area end if @@ -828,8 +831,10 @@ subroutine set_inventory_cohort_type1(csite,bc_in,css_file_unit,npatches, & real(r8) :: stem_drop_fraction ! Stem abscission fraction integer :: i_pft, ncohorts_to_create - character(len=128),parameter :: wr_fmt = & - '(F7.1,2X,A20,2X,A20,2X,F5.2,2X,F5.2,2X,I4,2X,F5.2,2X,F5.2,2X,F5.2,2X,F5.2)' + character(len=35),parameter :: hd_fmt = & + '(A7,2X,A20,2X,A5,2X,A6,2X,A4,2X,A9)' + character(len=43),parameter :: wr_fmt = & + '(F7.1,2X,A20,2X,F5.2,2X,F6.2,2X,I4,2X,F9.6)' real(r8), parameter :: abnormal_large_nplant = 1000.0_r8 ! Used to catch bad values real(r8), parameter :: abnormal_large_dbh = 500.0_r8 ! I've never heard of a tree > 3m @@ -858,6 +863,8 @@ subroutine set_inventory_cohort_type1(csite,bc_in,css_file_unit,npatches, & if(.not.matched_patch)then write(fates_log(), *) 'could not match a cohort with a patch' + write(fates_log(),fmt=hd_fmt) & + ' time',' patch',' dbh','height',' pft',' nplant' write(fates_log(),fmt=wr_fmt) & c_time, p_name, c_dbh, c_height, c_pft, c_nplant call endrun(msg=errMsg(sourcefile, __LINE__)) From 2a5b19f749412f6824e98f17fe73a873a50de22a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 11 Apr 2024 10:16:51 -0700 Subject: [PATCH 151/300] fixing typos and minor formatting --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- biogeochem/EDPhysiologyMod.F90 | 2 +- biogeochem/FatesLandUseChangeMod.F90 | 5 ++--- main/EDInitMod.F90 | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index e610e7c22a..9d4da65b53 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -3549,7 +3549,7 @@ subroutine terminate_patches(currentSite, bc_in) call dump_site(currentSite) write(fates_log(),*) 'currentSite%area_bareground', currentSite%area_bareground - write(fates_log(),*) 'currentSite%%area_pft(:,:)', currentSite%area_pft(:,:) + write(fates_log(),*) 'currentSite%area_pft(:,:)', currentSite%area_pft(:,:) patchpointer => currentSite%youngest_patch do while(associated(patchpointer)) write(fates_log(),*) patchpointer%area, patchpointer%nocomp_pft_label, patchpointer%land_use_label diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index e02e1f0249..aa42fe8f11 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -2493,7 +2493,7 @@ subroutine recruitment(currentSite, currentPatch, bc_in) real(r8) :: seedling_layer_smp ! soil matric potential at seedling rooting depth [mm H2O suction] integer, parameter :: recruitstatus = 1 ! whether the newly created cohorts are recruited or initialized integer :: ilayer_seedling_root ! the soil layer at seedling rooting depth - logical :: use_this_pft ! logcla flag for whetehr o rnot to allow a given PFT to recruit + logical :: use_this_pft ! logical flag for whether or not to allow a given PFT to recruit !--------------------------------------------------------------------------- do ft = 1, numpft diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index eab70708df..c244f7267b 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -304,7 +304,6 @@ subroutine get_luh_statedata(bc_in, state_vector) ! check to ensure total area == 1, and correct if not if ( abs(sum(state_vector(:)) - 1._r8) .gt. nearzero ) then - !write(fates_log(),*) 'warning: sum(state_vector) = ', sum(state_vector(:)) state_vector(:) = state_vector(:) / sum(state_vector(:)) end if else @@ -381,8 +380,8 @@ end subroutine get_init_landuse_harvest_rate subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, landuse_vector_gt_min) - ! The purose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use - ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for + ! The purpose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use + ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. This is for ! the transitions other than harvest, i.e. from primary lands to all other categories aside from secondary lands. ! !ARGUMENTS: diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 4c65467b4f..718651c863 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -470,7 +470,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! where pft_areafrac_lu is the area of land in each HLM PFT and land use type (from surface dataset) ! hlm_pft_map is the area of that land in each FATES PFT (from param file) - ! first check for NaNs in bc_in(s)%pft_areafrac_lu. if so, make everything bare ground. + ! First check for NaNs in bc_in(s)%pft_areafrac_lu. If so, make everything bare ground. if ( .not. (any( isnan( bc_in(s)%pft_areafrac_lu (:,:) )) .or. isnan( bc_in(s)%baregroundfrac))) then do i_landusetype = 1, n_landuse_cats if (.not. is_crop(i_landusetype)) then @@ -558,7 +558,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) sites(s)%area_pft(:, i_landusetype) = temp_vec(:) ! write adjusted vector to log file - if(debug) write(fates_log(),*) 'new PFT vector for LU type', i_landusetype, i_landusetype,sites(s)%area_pft(:, i_landusetype) + if(debug) write(fates_log(),*) 'new PFT vector for LU type', i_landusetype, sites(s)%area_pft(:, i_landusetype) endif end do end if From f90412b30562d20bdada3ec3e46510279ac3a9f0 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 11 Apr 2024 10:19:47 -0700 Subject: [PATCH 152/300] refactor pft area normalization to avoid checking sumarea in pft loop --- main/EDInitMod.F90 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 718651c863..aa80e436fc 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -567,16 +567,16 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! for nocomp cases, track bare ground area as a separate quantity do i_landusetype = 1, n_landuse_cats sumarea = sum(sites(s)%area_pft(1:numpft,i_landusetype)) - do ft = 1,numpft - if(sumarea.gt.nearzero)then + if(sumarea.gt.nearzero)then + do ft = 1,numpft sites(s)%area_pft(ft, i_landusetype) = sites(s)%area_pft(ft, i_landusetype)/sumarea - else - ! if no PFT area in primary lands, set bare ground fraction to one. - if ( i_landusetype .eq. primaryland) then - sites(s)%area_bareground = 1._r8 - endif - end if - end do !ft + end do !ft + else + ! if no PFT area in primary lands, set bare ground fraction to one. + if ( i_landusetype .eq. primaryland) then + sites(s)%area_bareground = 1._r8 + endif + end if end do end if !fixed biogeog From e77dda4614ba644b0188b74acef5fd056547a1da Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 11 Apr 2024 10:35:49 -0700 Subject: [PATCH 153/300] convert loop to single line call Also make sure that all primaryland pft areas are exactly zero when bareground area is 1 --- main/EDInitMod.F90 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index aa80e436fc..658e127506 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -568,13 +568,12 @@ subroutine set_site_properties( nsites, sites,bc_in ) do i_landusetype = 1, n_landuse_cats sumarea = sum(sites(s)%area_pft(1:numpft,i_landusetype)) if(sumarea.gt.nearzero)then - do ft = 1,numpft - sites(s)%area_pft(ft, i_landusetype) = sites(s)%area_pft(ft, i_landusetype)/sumarea - end do !ft + sites(s)%area_pft(:, i_landusetype) = sites(s)%area_pft(:, i_landusetype)/sumarea else ! if no PFT area in primary lands, set bare ground fraction to one. if ( i_landusetype .eq. primaryland) then sites(s)%area_bareground = 1._r8 + sites(s)%area_pft(:, i_landusetype) = 0._r8 endif end if end do From b835a84b7fd22f12169727def452ef890e87ba71 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 11 Apr 2024 10:41:49 -0700 Subject: [PATCH 154/300] simplify indexing across all pfts for given landuse type now that we don't allocate a zero index for area_pft --- main/EDInitMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 658e127506..c416985416 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -566,7 +566,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) ! re-normalize PFT area to ensure it sums to one for each (active) land use type ! for nocomp cases, track bare ground area as a separate quantity do i_landusetype = 1, n_landuse_cats - sumarea = sum(sites(s)%area_pft(1:numpft,i_landusetype)) + sumarea = sum(sites(s)%area_pft(:,i_landusetype)) if(sumarea.gt.nearzero)then sites(s)%area_pft(:, i_landusetype) = sites(s)%area_pft(:, i_landusetype)/sumarea else From 1508b7b0e4a9ecb83de0977ef8f38c78b6ff991c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 11 Apr 2024 11:49:55 -0700 Subject: [PATCH 155/300] more minor typo fixes --- main/EDInitMod.F90 | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 718651c863..9185df8197 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -698,8 +698,6 @@ subroutine init_patches( nsites, sites, bc_in) else - ! state_vector(:) = 0._r8 - if(hlm_use_nocomp.eq.itrue)then num_nocomp_pfts = numpft else !default @@ -766,7 +764,7 @@ subroutine init_patches( nsites, sites, bc_in) hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod, & regeneration_model) - ! set poointers for first patch (or only patch, if nocomp is false) + ! set pointers for first patch (or only patch, if nocomp is false) newp%patchno = 1 newp%younger => null() newp%older => null() @@ -796,7 +794,7 @@ subroutine init_patches( nsites, sites, bc_in) end_landuse_idx = 1 endif - not_all_baregground_if: if ((1._r8 - sites(s)%area_bareground) .gt. nearzero) then + not_all_bareground_if: if ((1._r8 - sites(s)%area_bareground) .gt. nearzero) then ! now make one or more vegetated patches based on nocomp and land use logic luh_state_loop: do i_lu_state = 1, end_landuse_idx lu_state_present_if: if (state_vector(i_lu_state) .gt. nearzero) then @@ -876,7 +874,7 @@ subroutine init_patches( nsites, sites, bc_in) end do new_patch_nocomp_loop end if lu_state_present_if end do luh_state_loop - end if not_all_baregground_if + end if not_all_bareground_if ! if we had to skip small patches above, resize things accordingly if ( area_error .gt. nearzero) then From cf054753fc1000276e24b5343efb8d3ceb00945e Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 11 Apr 2024 13:33:47 -0700 Subject: [PATCH 156/300] Added btran to hydro restart, and protecting downscaling rhiz layer fluxes to soil layer fluxes when no conductance (trivial bug fix). --- biogeophys/FatesPlantHydraulicsMod.F90 | 48 ++++++++++++++-------- biogeophys/FatesPlantRespPhotosynthMod.F90 | 16 ++++++-- main/FatesHydraulicsMemMod.F90 | 11 +++-- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index c4061a0788..874ab80a94 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -663,9 +663,6 @@ subroutine InitPlantHydStates(site, cohort) cohort_hydr%btran = wkf_plant(stomata_p_media,ft)%p%ftc_from_psi(cohort_hydr%psi_ag(1)) - - !flc_gs_from_psi(cohort_hydr%psi_ag(1),cohort%pft) - ! We do allow for positive pressures. ! But starting off with positive pressures is something we try to avoid if ( (cohort_hydr%psi_troot>0.0_r8) .or. & @@ -711,6 +708,8 @@ subroutine UpdatePlantPsiFTCFromTheta(ccohort,csite_hydr) ccohort_hydr%ftc_ag(k) = wkf_plant(leaf_p_media,ft)%p%ftc_from_psi(ccohort_hydr%psi_ag(k)) end do + ccohort_hydr%btran = wkf_plant(stomata_p_media,ft)%p%ftc_from_psi(ccohort_hydr%psi_ag(1)) + do k = n_hypool_leaf+1, n_hypool_ag ccohort_hydr%psi_ag(k) = wrf_plant(stem_p_media,ft)%p%psi_from_th(ccohort_hydr%th_ag(k)) ccohort_hydr%ftc_ag(k) = wkf_plant(stem_p_media,ft)%p%ftc_from_psi(ccohort_hydr%psi_ag(k)) @@ -2458,8 +2457,15 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) csite_hydr => sites(s)%si_hydr + bc_out(s)%qflx_soil2root_sisl(:) = 0._r8 + csite_hydr%sapflow_scpf(:,:) = 0._r8 + csite_hydr%rootuptake_sl(:) = 0._r8 + csite_hydr%rootuptake0_scpf(:,:) = 0._r8 + csite_hydr%rootuptake10_scpf(:,:) = 0._r8 + csite_hydr%rootuptake50_scpf(:,:) = 0._r8 + csite_hydr%rootuptake100_scpf(:,:) = 0._r8 + if( sum(csite_hydr%l_aroot_layer) == 0._r8 ) then - bc_out(s)%qflx_soil2root_sisl(:) = 0._r8 cycle end if @@ -2479,14 +2485,6 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) bc_out(s)%qflx_ro_sisl(:) = 0._r8 - ! Zero out diagnotsics that rely on accumulation - csite_hydr%sapflow_scpf(:,:) = 0._r8 - csite_hydr%rootuptake_sl(:) = 0._r8 - csite_hydr%rootuptake0_scpf(:,:) = 0._r8 - csite_hydr%rootuptake10_scpf(:,:) = 0._r8 - csite_hydr%rootuptake50_scpf(:,:) = 0._r8 - csite_hydr%rootuptake100_scpf(:,:) = 0._r8 - ! Initialize water mass balancing terms [kg h2o / m2] ! -------------------------------------------------------------------------------- transp_flux = 0._r8 @@ -2501,6 +2499,7 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) ifp = 0 cpatch => sites(s)%oldest_patch do while (associated(cpatch)) + if(cpatch%nocomp_pft_label.ne.nocomp_bareground)then ifp = ifp + 1 @@ -2532,7 +2531,7 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) end if ccohort=>cpatch%tallest - do while(associated(ccohort)) + co_loop1: do while(associated(ccohort)) ccohort_hydr => ccohort%co_hydr ft = ccohort%pft @@ -2670,9 +2669,8 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) ccohort_hydr%btran = wkf_plant(stomata_p_media,ft)%p%ftc_from_psi(ccohort_hydr%psi_ag(1)) - ccohort => ccohort%shorter - enddo !cohort + enddo co_loop1 !cohort endif ! not bareground patch cpatch => cpatch%younger enddo !patch @@ -2763,9 +2761,9 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) sumweight = 0._r8 do j_bc = j_t,j_b if(rootflux_disagg == soilk_disagg)then - ! Weight disaggregation by K*dz, but only for flux - ! into the root, othersize weight by depth - if(qflx_soil2root_rhiz>0._r8)then + if(qflx_soil2root_rhiz>0._r8 )then + ! Weight disaggregation by K*dz, but only for flux + ! into the root, othersize weight by depth ! h2osoi_liqvol: [kg/m2] / [m] / [kg/m3] = [m3/m3] eff_por = bc_in(s)%eff_porosity_sl(j_bc) h2osoi_liqvol = min(eff_por, bc_in(s)%h2o_liq_sisl(j_bc)/(bc_in(s)%dz_sisl(j_bc)*denh2o)) @@ -2786,6 +2784,20 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) end do ! Second pass, apply normalized weighting factors for fluxes + + ! Note: It is possible that the soil is so dry there is no conductance + ! In these cases, solver error may create some non-zero, yet + ! trivially small fluxes. The conductances are exactly zero + ! so we need to renormalize the weighting function + if(sumweight < nearzero)then + sumweight = 0._r8 + do j_bc = j_t,j_b + weight_sl(j_bc) = csite_hydr%rootl_sl(j_bc)*bc_in(s)%h2o_liq_sisl(j_bc) + sumweight = sumweight + weight_sl(j_bc) + end do + end if + + do j_bc = j_t,j_b ! Fill the output array to the HLM diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index df0450016b..379baaff54 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1313,6 +1313,9 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! empirical curvature parameter for ap photosynthesis co-limitation real(r8),parameter :: theta_ip = 0.999_r8 + ! minimum Leaf area to solve, too little has shown instability + real(r8), parameter :: min_la_to_solve = 0.0000000001_r8 + associate( bb_slope => EDPftvarcon_inst%bb_slope ,& ! slope of BB relationship, unitless medlyn_slope=> EDPftvarcon_inst%medlyn_slope , & ! Slope for Medlyn stomatal conductance model method, the unit is KPa^0.5 stomatal_intercept=> EDPftvarcon_inst%stomatal_intercept ) !Unstressed minimum stomatal conductance, the unit is umol/m**2/s @@ -1360,7 +1363,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! absorbed per unit leaf area. if(sunsha == 1)then !sunlit - if(( laisun_lsl * canopy_area_lsl) > 0.0000000001_r8)then + if(( laisun_lsl * canopy_area_lsl) > min_la_to_solve)then qabs = parsun_lsl / (laisun_lsl * canopy_area_lsl ) qabs = qabs * 0.5_r8 * (1._r8 - fnps) * 4.6_r8 @@ -1370,9 +1373,16 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in end if else - qabs = parsha_lsl / (laisha_lsl * canopy_area_lsl) - qabs = qabs * 0.5_r8 * (1._r8 - fnps) * 4.6_r8 + if( (parsha_lsl>nearzero) .and. (laisha_lsl * canopy_area_lsl) > min_la_to_solve ) then + qabs = parsha_lsl / (laisha_lsl * canopy_area_lsl) + qabs = qabs * 0.5_r8 * (1._r8 - fnps) * 4.6_r8 + else + ! The radiative transfer schemes are imperfect + ! they can sometimes generate negative values here + qabs = 0._r8 + end if + end if !convert the absorbed par into absorbed par per m2 of leaf, diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index f31ffe7e25..2baaa9d240 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -3,10 +3,12 @@ module FatesHydraulicsMemMod use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : fates_unset_r8 use FatesGlobals, only : fates_log + use FatesGlobals, only : endrun => fates_endrun use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) use FatesConstantsMod, only : itrue,ifalse use FatesHydroWTFMod, only : wrf_arr_type use FatesHydroWTFMod, only : wkf_arr_type + use shr_log_mod , only : errMsg => shr_log_errMsg implicit none private @@ -319,7 +321,11 @@ module FatesHydraulicsMemMod procedure :: Dump end type ed_cohort_hydr_type - + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + + contains subroutine CopyCohortHydraulics(ncohort_hydr, ocohort_hydr) @@ -372,8 +378,7 @@ subroutine CopyCohortHydraulics(ncohort_hydr, ocohort_hydr) ncohort_hydr%iterh2 = ocohort_hydr%iterh2 ncohort_hydr%iterlayer = ocohort_hydr%iterlayer ncohort_hydr%errh2o = ocohort_hydr%errh2o - - + ! BC PLANT HYDRAULICS - flux terms ncohort_hydr%qtop = ocohort_hydr%qtop From 81f04e39899d7c42100fd55d3c0d490f985e64b5 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Sat, 13 Apr 2024 15:08:05 -0600 Subject: [PATCH 157/300] initial commit --- CMakeLists.txt | 75 ++ biogeochem/CMakeLists.txt | 8 + biogeophys/CMakeLists.txt | 4 + fire/CMakeLists.txt | 5 + functional_unit_testing/CMakeLists.txt | 1 + .../allometry/AutoGenVarCon.py | 140 ---- .../allometry/CMakeLists.txt | 12 + .../allometry/FatesTestAllometry.F90 | 16 + .../allometry/drive_allomtests.py | 730 ------------------ .../allometry/f90src/AllomUnitWrap.F90_in | 218 ------ .../allometry/include/README | 1 - .../allometry/plots/README | 1 - .../allometry/simple_build.sh | 58 -- .../build_fortran_tests.py | 217 ++++++ functional_unit_testing/run_fates_tests.py | 37 + functional_unit_testing/utils.py | 57 ++ main/CMakeLists.txt | 17 + parteh/CMakeLists.txt | 8 + radiation/CMakeLists.txt | 6 + unit_test_shr/CMakeLists.txt | 5 + unit_test_shr/FatesUnitTestIOMod.F90 | 571 ++++++++++++++ unit_test_shr/FatesUnitTestParamReaderMod.F90 | 59 ++ 22 files changed, 1098 insertions(+), 1148 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 biogeochem/CMakeLists.txt create mode 100644 biogeophys/CMakeLists.txt create mode 100644 fire/CMakeLists.txt create mode 100644 functional_unit_testing/CMakeLists.txt delete mode 100644 functional_unit_testing/allometry/AutoGenVarCon.py create mode 100644 functional_unit_testing/allometry/CMakeLists.txt create mode 100644 functional_unit_testing/allometry/FatesTestAllometry.F90 delete mode 100644 functional_unit_testing/allometry/drive_allomtests.py delete mode 100644 functional_unit_testing/allometry/f90src/AllomUnitWrap.F90_in delete mode 100644 functional_unit_testing/allometry/include/README delete mode 100644 functional_unit_testing/allometry/plots/README delete mode 100755 functional_unit_testing/allometry/simple_build.sh create mode 100644 functional_unit_testing/build_fortran_tests.py create mode 100755 functional_unit_testing/run_fates_tests.py create mode 100644 functional_unit_testing/utils.py create mode 100644 parteh/CMakeLists.txt create mode 100644 radiation/CMakeLists.txt create mode 100644 unit_test_shr/CMakeLists.txt create mode 100644 unit_test_shr/FatesUnitTestIOMod.F90 create mode 100644 unit_test_shr/FatesUnitTestParamReaderMod.F90 diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..3f15615d18 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.4) + +list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) +include(CIME_initial_setup) + +project(FATES_tests Fortran C) + +include(CIME_utils) + +set(HLM_ROOT "../../") + +# Add source directories from other share code (csm_share, etc.) +add_subdirectory(${HLM_ROOT}/share/src csm_share) +add_subdirectory(${HLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) + +# Add FATES source directories +add_subdirectory(${HLM_ROOT}/src/fates/main fates_main) +add_subdirectory(${HLM_ROOT}/src/fates/biogeochem fates_biogeochem) +add_subdirectory(${HLM_ROOT}/src/fates/biogeophys fates_biogeophys) +add_subdirectory(${HLM_ROOT}/src/fates/parteh fates_parteh) +add_subdirectory(${HLM_ROOT}/src/fates/fire fates_fire) +add_subdirectory(${HLM_ROOT}/src/fates/radiation fates_radiation) +add_subdirectory(${HLM_ROOT}/src/fates/unit_test_shr unit_share) + +# Remove shr_mpi_mod from share_sources. +# This is needed because we want to use the mock shr_mpi_mod in place of the real one +# +# TODO: this should be moved into a general-purpose function in Sourcelist_utils. +# Then this block of code could be replaced with a single call, like: +# remove_source_file(${share_sources} "shr_mpi_mod.F90") +foreach (sourcefile ${share_sources}) + string(REGEX MATCH "shr_mpi_mod.F90" match_found ${sourcefile}) + if(match_found) + list(REMOVE_ITEM share_sources ${sourcefile}) + endif() +endforeach() + +# Remove shr_cal_mod from share_sources. +# +# shr_cal_mod depends on ESMF (or the lightweight esmf wrf timemgr, at +# least). Since CTSM doesn't currently use shr_cal_mod, we're avoiding +# the extra overhead of including esmf_wrf_timemgr sources in this +# build. +# +# TODO: like above, this should be moved into a general-purpose function +# in Sourcelist_utils. Then this block of code could be replaced with a +# single call, like: remove_source_file(${share_sources} +# "shr_cal_mod.F90") +foreach (sourcefile ${share_sources}) + string(REGEX MATCH "shr_cal_mod.F90" match_found ${sourcefile}) + if(match_found) + list(REMOVE_ITEM share_sources ${sourcefile}) + endif() +endforeach() + +# Build libraries containing stuff needed for the unit tests. +# Eventually, these add_library calls should probably be distributed into the correct location, rather than being in this top-level CMakeLists.txt file. +add_library(csm_share ${share_sources}) +declare_generated_dependencies(csm_share "${share_genf90_sources}") +add_library(fates ${fates_sources}) +add_dependencies(fates csm_share) + +# We need to look for header files here, in order to pick up shr_assert.h +include_directories(${HLM_ROOT}/share/include) + +# Tell cmake to look for libraries & mod files here, because this is where we built libraries +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +link_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Add the test directories +# Note: it's possible that these could be added by each source directory that +# has tests in it. However, it appears that the order needs to be done +# carefully: for example, include_directories and link_directories needs to be +# done before adding the tests themselves. +add_subdirectory(${HLM_ROOT}/src/fates/functional_unit_testing/allometry fates_allom_test) \ No newline at end of file diff --git a/biogeochem/CMakeLists.txt b/biogeochem/CMakeLists.txt new file mode 100644 index 0000000000..268b0d4305 --- /dev/null +++ b/biogeochem/CMakeLists.txt @@ -0,0 +1,8 @@ +list(APPEND fates_sources + FatesLitterMod.F90 + FatesCohortMod.F90 + FatesAllometryMod.F90 + DamageMainMod.F90 + FatesPatchMod.F90) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/biogeophys/CMakeLists.txt b/biogeophys/CMakeLists.txt new file mode 100644 index 0000000000..c6048491b9 --- /dev/null +++ b/biogeophys/CMakeLists.txt @@ -0,0 +1,4 @@ +list(APPEND fates_sources + FatesHydroWTFMod.F90) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/fire/CMakeLists.txt b/fire/CMakeLists.txt new file mode 100644 index 0000000000..f5d64a17a4 --- /dev/null +++ b/fire/CMakeLists.txt @@ -0,0 +1,5 @@ +list(APPEND fates_sources + SFParamsMod.F90 + ) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/functional_unit_testing/CMakeLists.txt b/functional_unit_testing/CMakeLists.txt new file mode 100644 index 0000000000..90d16c8d18 --- /dev/null +++ b/functional_unit_testing/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(allometry) \ No newline at end of file diff --git a/functional_unit_testing/allometry/AutoGenVarCon.py b/functional_unit_testing/allometry/AutoGenVarCon.py deleted file mode 100644 index 7bf0f85a6b..0000000000 --- a/functional_unit_testing/allometry/AutoGenVarCon.py +++ /dev/null @@ -1,140 +0,0 @@ - - -# Walk through lines of a file, if a line contains -# the string of interest (EDPftvarcon_inst), then -# parse the string to find the variable name, and save that -# to the list - - -class ParamType: - - def __init__(self,var_sym,n_dims): - - self.var_sym = var_sym - self.n_dims = n_dims - self.var_name = '' - - - - -def CheckFile(filename,check_str): - file_ptr = open(filename,'r') - var_list = [] - found = False - for line in file_ptr: - if check_str in line: - line_split = line.split() - # substr = [i for i in line_split if check_str in i][0] - substr = line - p1 = substr.find('%')+1 - if(p1>0): - substr=substr[p1:] - p2 = substr.find('(') - p3 = substr.find(')') - # Count the number of commas between p2 and p3 - n_dims = substr[p2:p3].count(',')+1 - if(p2>0): - var_list.append(ParamType(substr[:p2],n_dims)) - - unique_list = [] - for var in var_list: - found = False - for uvar in unique_list: - if (var.var_sym == uvar.var_sym): - found = True - if(not found): - unique_list.append(var) - - return(unique_list) - - - -check_str = 'EDPftvarcon_inst%' -filename = '../../biogeochem/FatesAllometryMod.F90' - -var_list = CheckFile(filename,check_str) - - -# Add symbols here - -var_list.append(ParamType('hgt_min',1)) - - -# Now look through EDPftvarcon.F90 to determine the variable name in file -# that is associated with the variable pointer - -filename = '../../main/EDPftvarcon.F90' - -f = open(filename,"r") -contents = f.readlines() - - -var_name_list = [] -for var in var_list: - for i,line in enumerate(contents): - if (var.var_sym in line) and ('data' in line) and ('=' in line): - var.var_name = contents[i-2].split()[-1].strip('\'') - print("{} {} {}".format(var.var_sym,var.var_name,var.n_dims)) - - -f = open("f90src/AllomUnitWrap.F90_in", "r") -contents = f.readlines() -f.close() - -# Identify where we define the variables, and insert the variable definitions - -for i,str in enumerate(contents): - if 'VARIABLE-DEFINITIONS-HERE' in str: - index0=i - -index=index0+2 -for var in var_list: - if(var.n_dims==1): - contents.insert(index,' real(r8),pointer :: {}(:)\n'.format(var.var_sym)) - elif(var.n_dims==2): - contents.insert(index,' real(r8),pointer :: {}(:,:)\n'.format(var.var_sym)) - else: - print('Incorrect number of dims...') - exit(-2) - index=index+1 - -# Identify where we do the pointer assignments, and insert the pointer assignments - - -for i,str in enumerate(contents): - if 'POINTER-SPECIFICATION-HERE' in str: - index0=i - -index=index0+2 -for ivar,var in enumerate(var_list): - if(var.n_dims==1): - ins_l1='\t allocate(EDPftvarcon_inst%{}(1:numpft))\n'.format(var.var_sym) - ins_l2='\t EDPftvarcon_inst%{}(:) = nan\n'.format(var.var_sym) - ins_l3='\t iv1 = iv1 + 1\n' - ins_l4='\t EDPftvarcon_ptr%var1d(iv1)%var_name = "{}"\n'.format(var.var_name) - ins_l5='\t EDPftvarcon_ptr%var1d(iv1)%var_rp => EDPftvarcon_inst%{}\n'.format(var.var_sym) - ins_l6='\t EDPftvarcon_ptr%var1d(iv1)%vtype = 1\n' - ins_l7='\n' - if(var.n_dims==2): - ins_l1='\t allocate(EDPftvarcon_inst%{}(1:numpft,1))\n'.format(var.var_sym) - ins_l2='\t EDPftvarcon_inst%{}(:,:) = nan\n'.format(var.var_sym) - ins_l3='\t iv2 = iv2 + 1\n' - ins_l4='\t EDPftvarcon_ptr%var2d(iv2)%var_name = "{}"\n'.format(var.var_name) - ins_l5='\t EDPftvarcon_ptr%var2d(iv2)%var_rp => EDPftvarcon_inst%{}\n'.format(var.var_sym) - ins_l6='\t EDPftvarcon_ptr%var2d(iv2)%vtype = 1\n' - ins_l7='\n' - - contents.insert(index,ins_l1) - contents.insert(index+1,ins_l2) - contents.insert(index+2,ins_l3) - contents.insert(index+3,ins_l4) - contents.insert(index+4,ins_l5) - contents.insert(index+5,ins_l6) - contents.insert(index+6,ins_l7) - index=index+7 - - -f = open("f90src/AllomUnitWrap.F90", "w+") -contents = "".join(contents) -f.write(contents) -f.close() diff --git a/functional_unit_testing/allometry/CMakeLists.txt b/functional_unit_testing/allometry/CMakeLists.txt new file mode 100644 index 0000000000..362a541b61 --- /dev/null +++ b/functional_unit_testing/allometry/CMakeLists.txt @@ -0,0 +1,12 @@ +set(allom_sources FatesTestAllometry.F90) + +add_executable(FATES_allom_exe ${allom_sources}) + +target_link_libraries(FATES_allom_exe + fates + csm_share) + +add_test(allom_test FATES_allom_exe) + +# Tell CTest how to figure out that "STOP 1" fails for the current +define_Fortran_stop_failure(allom_test) \ No newline at end of file diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 new file mode 100644 index 0000000000..10be571f67 --- /dev/null +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -0,0 +1,16 @@ +program FatesTestAllometry + + !use FatesAllometryMod, only : h2d_allom + !use PRTParametersMod, only : prt_params + use FatesUnitTestParamReaderMod, only : fates_unit_test_param_reader + + implicit none + + ! LOCALS: + type(fates_unit_test_param_reader) :: param_reader + + call param_reader%param_read() + + print *, "Hello, allometry" + +end program FatesTestAllometry \ No newline at end of file diff --git a/functional_unit_testing/allometry/drive_allomtests.py b/functional_unit_testing/allometry/drive_allomtests.py deleted file mode 100644 index d97da4ded3..0000000000 --- a/functional_unit_testing/allometry/drive_allomtests.py +++ /dev/null @@ -1,730 +0,0 @@ -import numpy as np -import math -import matplotlib.pyplot as plt -import matplotlib as mp -import ctypes -import importlib -from ctypes import * #byref, cdll, c_int, c_double, c_char_p, c_long -import xml.etree.ElementTree as ET -import argparse -import re # This is a heftier string parser -import code # For development: code.interact(local=dict(globals(), **locals())) -import sys -sys.path.append('../shared/py_src') -from PyF90Utils import c8, ci, cchar, c8_arr, ci_arr - -# ======================================================================================= -# Set some constants. If they are used as constant arguments to the F90 routines, -# define them with their ctype identifiers -# ======================================================================================= - -ndbh = 200 -maxdbh = 50 -ccanopy_trim = c_double(1.0) # Crown Trim (0=0% of target, 1=100% of targ) -csite_spread = c_double(0.0) # Canopy spread (0=closed, 1=open) -cnplant = c_double(1.0) # Number of plants (don't change) -cilayer = c_int(1) # Index of the plant's canopy layer -ccanopy_lai = (2 * c_double)(1.0,1.0) # The LAI of the different canopy layers - # THIS VECTOR MUST MATCH ncanlayer -cdo_reverse = c_bool(0) # DO NOT GET REVERSE CROWN AREA - -# ======================================================================================= -# Setup references to fortran shared libraries -# ======================================================================================= - -allom_const_object = "./include/FatesConstantsMod.o" -allom_wrap_object = "./include/AllomUnitWrap.o" -allom_lib_object = "./include/FatesAllometryMod.o" - -# ============================================================================== -# Instantiate fortran allometry and other libraries -# ============================================================================== - -f90constlib= ctypes.CDLL(allom_const_object,mode=ctypes.RTLD_GLOBAL) -f90wraplib = ctypes.CDLL(allom_wrap_object,mode=ctypes.RTLD_GLOBAL) -f90funclib = ctypes.CDLL(allom_lib_object,mode=ctypes.RTLD_GLOBAL) - -# ======================================================================================= -# Create aliases to all of the different routines, set return types for functions -# ======================================================================================= - -f90_pftalloc = f90wraplib.__edpftvarcon_MOD_edpftvarconalloc #(numpft) -f90_pftset = f90wraplib.__edpftvarcon_MOD_edpftvarconpyset -f90_pftset.argtypes = [POINTER(c_int),POINTER(c_double),POINTER(c_int),c_char_p,c_long] -f90_h2d = f90funclib.__fatesallometrymod_MOD_h2d_allom #(h,ipft,d,dddh) -f90_h = f90funclib.__fatesallometrymod_MOD_h_allom #(d,ipft,h,dhdd) -f90_bagw = f90funclib.__fatesallometrymod_MOD_bagw_allom #(d,ipft,bagw,dbagwdd) -f90_bleaf = f90funclib.__fatesallometrymod_MOD_bleaf #(d,ipft,canopy_trim,bl,dbldd) -f90_bsap = f90funclib.__fatesallometrymod_MOD_bsap_allom #(d,ipft,canopy_trim,asapw,bsap,dbsapdd) -f90_bstore = f90funclib.__fatesallometrymod_MOD_bstore_allom #(d,ipft,canopy_trim,bstore,dbstoredd) -f90_bbgw = f90funclib.__fatesallometrymod_MOD_bbgw_allom #(d,ipft,canopy_trim,bbgw,dbbgwdd) -f90_bfineroot = f90funclib.__fatesallometrymod_MOD_bfineroot #(d,ipft,canopy_trim,bfr,dbfrdd) -f90_bdead = f90funclib.__fatesallometrymod_MOD_bdead_allom #(bagw,bbgw,bsap,ipft,bdead,dbagwdd,dbbgwdd,dbsapdd,dbdeaddd) -f90_carea = f90funclib.__fatesallometrymod_MOD_carea_allom #(d,nplant,site_spread,ipft,c_area)(d,nplant,site_spread,ipft,c_area) -f90_treelai = f90funclib.__fatesallometrymod_MOD_tree_lai #(leaf_c, pft, c_area, nplant, cl, canopy_lai, vcmax25top) -f90_treelai.restype = c_double - - -# This is the object type that holds our parameters -# ======================================================================================= -class parameter: - - def __init__(self,symbol): - - self.dtype = -9 - self.symbol = symbol - self.vals = [] - - def setval(self,val,ipft): - - self.vals[ipft] = val - -# This is just a helper script that generates random colors -# ======================================================================================= -def DiscreteCubeHelix(N): - - base = plt.cm.get_cmap('cubehelix') - np.random.seed(2) - color_list = base(np.random.randint(0,high=255,size=N)) - cmap_name = base.name + str(N) - return base.from_list(cmap_name, color_list, N) - - -# This will look through a CDL file for the provided parameter and determine -# the parameter's type, as well as fill an array with the data -# ======================================================================================= -def CDLParse(file_name,parm): - - fp = open(file_name,"r") - contents = fp.readlines() - fp.close() - - # Look in the file for the parameters - # symbol/name, record the line number - iline=-1 - isfirst = True - for i,line in enumerate(contents): - if(parm.symbol in line): - iline=i - if(isfirst): - dtype = line.split()[0] - if(dtype.strip()=="float" or (dtype.strip()=="double")): - parm.dtype = 0 - elif(dtype.strip()=="char"): - parm.dtype = 1 - isFirst=False - - if(iline==-1): - print('Could not find symbol: {} in file: {}'.format(parm.symbol,file_name)) - exit(2) - else: - search_field=True - line="" - lcount=0 - while(search_field and (lcount<100)): - line+=contents[iline] - if(line.count(';')>0): - search_field=False - else: - search_field=True - lcount=lcount+1 - iline=iline+1 - - # Parse the line - line_split = re.split(',|=',line) - # Remove the variable name entry - del line_split[0] - - # This is for read numbers - if(parm.dtype == 0): - ival=0 - for str0 in line_split: - str="" - isnum=False - for s in str0: - if (s.isdigit() or s=='.'): - str+=s - isnum=True - if(isnum): - parm.vals.append(float(str)) - - # This is a sting - elif(parm.dtype == 1): - for str0 in line_split: - # Loop several times to trim stuff off - for i in range(5): - str0=str0.strip().strip('\"').strip(';').strip() - parm.vals.append(str0) - - return(parm) - - - -# Read in the arguments -# ======================================================================================= - -parser = argparse.ArgumentParser(description='Parse command line arguments to this script.') -parser.add_argument('--fin', '--input', dest='fnamein', type=str, help="Input CDL filename. Required.", required=True) -args = parser.parse_args() - - -# Read in the parameters of interest that are used in the fortran objects. These -# parameters will be passed to the fortran allocation. -# ======================================================================================= - -parms = {} -parms['dbh_maxheight'] = CDLParse(args.fnamein,parameter('fates_allom_dbh_maxheight')) -parms['hmode'] = CDLParse(args.fnamein,parameter('fates_allom_hmode')) -parms['amode'] = CDLParse(args.fnamein,parameter('fates_allom_amode')) -parms['lmode'] = CDLParse(args.fnamein,parameter('fates_allom_lmode')) -parms['smode'] = CDLParse(args.fnamein,parameter('fates_allom_smode')) -parms['cmode'] = CDLParse(args.fnamein,parameter('fates_allom_cmode')) -parms['fmode'] = CDLParse(args.fnamein,parameter('fates_allom_fmode')) -parms['stmode'] = CDLParse(args.fnamein,parameter('fates_allom_stmode')) -parms['cushion'] = CDLParse(args.fnamein,parameter('fates_alloc_storage_cushion')) -parms['d2h1'] = CDLParse(args.fnamein,parameter('fates_allom_d2h1')) -parms['d2h2'] = CDLParse(args.fnamein,parameter('fates_allom_d2h2')) -parms['d2h3'] = CDLParse(args.fnamein,parameter('fates_allom_d2h3')) -parms['agb1'] = CDLParse(args.fnamein,parameter('fates_allom_agb1')) -parms['agb2'] = CDLParse(args.fnamein,parameter('fates_allom_agb2')) -parms['agb3'] = CDLParse(args.fnamein,parameter('fates_allom_agb3')) -parms['agb4'] = CDLParse(args.fnamein,parameter('fates_allom_agb4')) -parms['d2bl1'] = CDLParse(args.fnamein,parameter('fates_allom_d2bl1')) -parms['d2bl2'] = CDLParse(args.fnamein,parameter('fates_allom_d2bl2')) -parms['d2bl3'] = CDLParse(args.fnamein,parameter('fates_allom_d2bl3')) -parms['wood_density'] = CDLParse(args.fnamein,parameter('fates_wood_density')) -parms['c2b'] = CDLParse(args.fnamein,parameter('fates_c2b')) -parms['la_per_sa_int'] = CDLParse(args.fnamein,parameter('fates_allom_la_per_sa_int')) -parms['la_per_sa_slp'] = CDLParse(args.fnamein,parameter('fates_allom_la_per_sa_slp')) -parms['slatop'] = CDLParse(args.fnamein,parameter('fates_leaf_slatop')) -parms['slamax'] = CDLParse(args.fnamein,parameter('fates_leaf_slamax')) -parms['l2fr'] = CDLParse(args.fnamein,parameter('fates_allom_l2fr')) -parms['agb_frac'] = CDLParse(args.fnamein,parameter('fates_allom_agb_frac')) -parms['blca_expnt_diff'] = CDLParse(args.fnamein,parameter('fates_allom_blca_expnt_diff')) -parms['d2ca_coeff_min'] = CDLParse(args.fnamein,parameter('fates_allom_d2ca_coefficient_min')) -parms['d2ca_coeff_max'] = CDLParse(args.fnamein,parameter('fates_allom_d2ca_coefficient_max')) -parms['sai_scaler'] = CDLParse(args.fnamein,parameter('fates_allom_sai_scaler')) - -# Read in the parameters that are not necessary for the F90 allometry algorithms, -# but are useful for these scripts (e.g. the name of the parameter, and minimum height) -# ======================================================================================= - -eparms = {} -eparms['recruit_hgt_min'] = CDLParse(args.fnamein,parameter('fates_recruit_hgt_min')) -eparms['name'] = CDLParse(args.fnamein,parameter('fates_pftname')) -eparms['vcmax25top'] = CDLParse(args.fnamein,parameter('fates_leaf_vcmax25top')) - - -# Determine how many PFTs are here, also check to make sure that all parameters -# have the same number -# ======================================================================================= -numpft=-1 -for key, parm in parms.items(): - if( (len(parm.vals) == numpft) or (numpft==-1) ): - numpft=len(parm.vals) - else: - print('Bad length in PFT parameter') - print('parameter: {}, vals:'.format(parm.symbol),parm.vals) - - -# ============================================================================== -# Allocate fortran PFT arrays -# ============================================================================== - -iret=f90_pftalloc(ci(numpft)) - -# ============================================================================== -# Populate the Fortran PFT structure -# ============================================================================== - -for ipft in range(numpft): - for key, parm in parms.items(): - print('{} {} '.format(parm.symbol,parm.vals[ipft])) - iret=f90_pftset(c_int(ipft+1), \ - c_double(parm.vals[ipft]), \ - c_int(0), \ - c_char_p(parm.symbol.encode('utf-8')), \ - c_long(len(parm.symbol))) - - -# ========================================================================= -# Initialize Output Arrays -# ========================================================================= - -blmaxi = np.zeros((numpft,ndbh)) -blmaxd = np.zeros((numpft,ndbh)) -bfrmax = np.zeros((numpft,ndbh)) -hi = np.zeros((numpft,ndbh)) -hd = np.zeros((numpft,ndbh)) -bagwi = np.zeros((numpft,ndbh)) -bagwd = np.zeros((numpft,ndbh)) - -bagwr = np.zeros((numpft,ndbh)) - -dbh = np.zeros((numpft,ndbh)) -bbgw = np.zeros((numpft,ndbh)) -bsapi = np.zeros((numpft,ndbh)) -bsapd = np.zeros((numpft,ndbh)) -asapd = np.zeros((numpft,ndbh)) -bstore = np.zeros((numpft,ndbh)) -bdead = np.zeros((numpft,ndbh)) -dbhe = np.zeros((numpft,ndbh)) -camin = np.zeros((numpft,ndbh)) -ldense = np.zeros((numpft,ndbh)) -treelai = np.zeros((numpft,ndbh)) -blmax_o_dbagwdh = np.zeros((numpft,ndbh)) -blmax_o_dbagwdd = np.zeros((numpft,ndbh)) - - -for ipft in range(numpft): - - print('py: Solving for pft: {}'.format(ipft+1)) - - # Initialize Height #(d,ipft,h,dhdd) - ch_min = c_double(eparms['recruit_hgt_min'].vals[ipft]) - - cd = c_double(-9.0) - cdddh = c_double(-9.0) - cipft = c_int(ipft+1) - cinit = c_int(0) - - # Calculate the minimum dbh - iret=f90_h2d(byref(ch_min),byref(cipft),byref(cd),byref(cdddh)) - - # Generate a vector of diameters (use dbh) - dbh[ipft,:] = np.linspace(cd.value,maxdbh,num=ndbh) - - # Initialize various output vectors - cd = c_double(dbh[ipft,0]) - ch = c_double(-9.0) - cdhdd = c_double(-9.0) - cbagw = c_double(-9.0) - cdbagwdd = c_double(-9.0) - cblmax = c_double(-9.0) - cdblmaxdd = c_double(-9.0) - cbfrmax = c_double(-9.0) - cdbfrmaxdd = c_double(-9.0) - cbbgw = c_double(-9.0) - cdbbgwdd = c_double(-9.0) - cbsap = c_double(-9.0) - cdbsapdd = c_double(-9.0) - cbdead = c_double(-9.0) - cdbdeaddd = c_double(-9.0) - ccamin = c_double(-9.0) - casapw = c_double(-9.0) # Sapwood area - cbstore = c_double(-9.0) - cdbstoredd = c_double(-9.0) - - iret=f90_h(byref(cd),byref(cipft),byref(ch),byref(cdhdd)) - hi[ipft,0] = ch.value - hd[ipft,0] = ch.value - print('py: initialize h[{},0]={}'.format(ipft+1,ch.value)) - - # Initialize AGB #(d,ipft,bagw,dbagwdd) - iret=f90_bagw(byref(cd),byref(cipft),byref(cbagw),byref(cdbagwdd)) - bagwi[ipft,0] = cbagw.value - print('py: initialize bagwi[{},0]={}'.format(ipft+1,cbagw.value)) - - # Initialize bleaf #(d,ipft,canopy_trim,bl,dbldd) - iret=f90_bleaf(byref(cd),byref(cipft),byref(ccanopy_trim),byref(cblmax),byref(cdblmaxdd)) - blmaxi[ipft,0] = cblmax.value - blmaxd[ipft,0] = cblmax.value - print('py: initialize blmaxi[{},0]={}'.format(ipft+1,cblmax.value)) - - # Initialize bstore #(d,ipft,canopy_trim,bstore,dbstoredd) - iret=f90_bstore(byref(cd),byref(cipft),byref(ccanopy_trim),byref(cbstore),byref(cdbstoredd)) - bstore[ipft,0] = cbstore.value - - # calculate crown area (d,nplant,site_spread,ipft,c_area) Using nplant = 1, generates units of m2 - # spread is likely 0.0, which is the value it tends towards when canopies close - # (dbh, nplant, site_spread, ipft, c_area,inverse) - iret= f90_carea(byref(cd),byref(cnplant),byref(csite_spread),byref(cipft),byref(ccamin),byref(cdo_reverse)) - camin[ipft,0] = ccamin.value - - - ldense[ipft,0] = blmaxi[ipft,0]/camin[ipft,0] - print('py: initialize careai[{},0]={}'.format(ipft+1,ccamin.value)) - - #f90_treelai(leaf_c, pft, c_area, nplant, cl, canopy_lai, vcmax25top) - cvcmax=c_double(eparms['vcmax25top'].vals[ipft]) - treelai[ipft,0]=f90_treelai(byref(cblmax),byref(cipft),byref(ccamin), \ - byref(cnplant),byref(cilayer),byref(ccanopy_lai),byref(cvcmax)) - - # Initialize fine roots #(d,ipft,canopy_trim,bfr,dbfrdd) - iret=f90_bfineroot(byref(cd),byref(cipft),byref(ccanopy_trim), \ - byref(cbfrmax),byref(cdbfrmaxdd)) - bfrmax[ipft,0] = cbfrmax.value - print('py: initialize bfrmax[{},0]={}'.format(ipft+1,cbfrmax.value)) - - # Initialize coarse roots #(d,ipft,bbgw,dbbgwdd) - iret=f90_bbgw(byref(cd),byref(cipft),byref(c_double(1.0)), \ - byref(cbbgw),byref(cdbbgwdd)) - bbgw[ipft,0] = cbbgw.value - print('py: initialize bbgw[{},0]={}'.format(ipft+1,cbbgw.value)) - - - # Initialize bsap (d,ipft,canopy_trim,asapw,bsap,dbsapdd) - iret=f90_bsap(byref(cd),byref(cipft),byref(ccanopy_trim),byref(casapw),byref(cbsap),byref(cdbsapdd)) - bsapi[ipft,0] = cbsap.value - bsapd[ipft,0] = cbsap.value - asapd[ipft,0] = casapw.value - print('py: initialize bsapi[{},0]={}'.format(ipft+1,cbsap.value)) - - # bdead #(bagw,bbgw,bsap,ipft,bdead,dbagwdd,dbbgwdd,dbsapdd,dbdeaddd) - iret=f90_bdead(byref(cbagw),byref(cbbgw),byref(cbsap),byref(cipft), \ - byref(cbdead),byref(cdbagwdd),byref(cdbbgwdd), \ - byref(cdbsapdd),byref(cdbdeaddd)) - - bdead[ipft,0] = cbdead.value - print('py: initialize bdead[{},0]={}'.format(ipft+1,cbdead.value)) - - bagwr[ipft,0] = (bdead[ipft,0]) * 0.6 - - # the metric that shan't be spoken - blmax_o_dbagwdh[ipft,0] = blmaxi[ipft,0]/(cdbagwdd.value/cdhdd.value) - - # the metric that shan't be spoken - blmax_o_dbagwdd[ipft,0] = blmaxi[ipft,0]/(cdbagwdd.value) - - for idi in range(1,ndbh): - - dp = dbh[ipft,idi-1] # previous position - dc = dbh[ipft,idi] # current position - dd = dc-dp - - cdp = c_double(dp) - cdc = c_double(dc) - cdbhe = c_double(-9.0) - cddedh = c_double(-9.0) - - if(ipft==2): - print("===") - - # integrate height #(d,ipft,h,dhdd) - iret=f90_h(byref(cdc),byref(cipft),byref(ch),byref(cdhdd)) - hi[ipft,idi] = hi[ipft,idi-1] + cdhdd.value*dd - - # diagnosed height - hd[ipft,idi] = ch.value - - # diagnose AGB #(d,h,ipft,bagw,dbagwdd) - iret=f90_bagw(byref(cdc),byref(cipft),byref(cbagw),byref(cdbagwdd)) - bagwd[ipft,idi] = cbagw.value - - # integrate AGB #(d,h,ipft,bagw,dbagwdd) - iret=f90_bagw(byref(cdp),byref(cipft),byref(cbagw),byref(cdbagwdd)) - bagwi[ipft,idi] = bagwi[ipft,idi-1] + cdbagwdd.value*dd - - # diagnose bleaf #(d,ipft,blmax,dblmaxdd) - iret=f90_bleaf(byref(cdc),byref(cipft),byref(ccanopy_trim),byref(cblmax),byref(cdblmaxdd)) - blmaxd[ipft,idi] = cblmax.value - - # bstore #(d,ipft,canopy_trim,bstore,dbstoredd) - iret=f90_bstore(byref(cdc),byref(cipft),byref(ccanopy_trim),byref(cbstore),byref(cdbstoredd)) - bstore[ipft,idi] = cbstore.value - - # calculate crown area (d,nplant,site_spread,ipft,c_area) Using nplant = 1, generates units of m2 - iret= f90_carea(byref(cdc),byref(cnplant),byref(csite_spread),byref(cipft),byref(ccamin),byref(cdo_reverse)) - camin[ipft,idi] = ccamin.value - - #f90_treelai(leaf_c, pft, c_area, nplant, cl, canopy_lai, vcmax25top) - cvcmax=c_double(eparms['vcmax25top'].vals[ipft]) - treelai[ipft,idi]=f90_treelai(byref(cblmax),byref(cipft),byref(ccamin), \ - byref(cnplant),byref(cilayer),byref(ccanopy_lai),byref(cvcmax)) - - - - - # integrate bleaf #(d,ipft,blmax,dblmaxdd) - iret=f90_bleaf(byref(cdp),byref(cipft),byref(c_double(1.0)),byref(cblmax),byref(cdblmaxdd)) - blmaxi[ipft,idi] = blmaxi[ipft,idi-1] + cdblmaxdd.value*dd - - # leaf mass per square meter of crown - ldense[ipft,idi] = blmaxd[ipft,idi]/camin[ipft,idi] - - # integrate bfineroot #(d,ipft,canopy_trim,bfr,dbfrdd) - iret=f90_bfineroot(byref(cdp),byref(cipft),byref(c_double(1.0)),byref(cbfrmax),byref(cdbfrmaxdd)) - bfrmax[ipft,idi] = bfrmax[ipft,idi-1] + cdbfrmaxdd.value*dd - - # integrate bbgw #(d,h,ipft,bbgw,dbbgwdd) - iret=f90_bbgw(byref(cdp),byref(cipft),byref(cbbgw),byref(cdbbgwdd)) - bbgw[ipft,idi] = bbgw[ipft,idi-1] + cdbbgwdd.value*dd - - # diagnose bsap # (d,ipft,canopy_trim,asapw,bsap,dbsapdd) - iret=f90_bsap(byref(cdc),byref(cipft),byref(ccanopy_trim),byref(casapw),byref(cbsap),byref(cdbsapdd)) - bsapd[ipft,idi] = cbsap.value # Biomass - asapd[ipft,idi] = casapw.value # Area - - # integrate bsap - iret=f90_bsap(byref(cdp),byref(cipft),byref(ccanopy_trim),byref(casapw),byref(cbsap),byref(cdbsapdd)) - bsapi[ipft,idi] = bsapi[ipft,idi-1] + cdbsapdd.value*dd - - - - - # the metric that shan't be spoken - # previous t-step derivatives are used for simplicity - if cdhdd.value<0.000001: - blmax_o_dbagwdh[ipft,idi] = None - else: - blmax_o_dbagwdh[ipft,idi] = blmaxi[ipft,idi-1]/(cdbagwdd.value/cdhdd.value) - - # the metric that shan't be spoken - # previous t-step derivatives are used for simplicity - blmax_o_dbagwdd[ipft,idi] = blmaxi[ipft,idi-1]/(cdbagwdd.value) - - # Diagnose bdead (bagw,bbgw,bsap,ipft,bdead,dbagwdd,dbbgwdd,dbsapdd,dbdeaddd) - - iret=f90_bdead(byref(c_double(bagwd[ipft,idi])), \ - byref(c_double(bbgw[ipft,idi])), \ - byref(c_double(bsapd[ipft,idi])), \ - byref(cipft), byref(cbdead), \ - byref(cdbagwdd),byref(cdbbgwdd), \ - byref(cdbsapdd),byref(cdbdeaddd)) - bdead[ipft,idi] = cbdead.value - - - bagwr[ipft,idi] = (bdead[ipft,idi] + bsapd[ipft,idi]) * 0.6 - -# Create the appropriate number of line-styles, colors and widths -linestyles_base = ['-', '--', '-.', ':'] -linestyles=[] -for i in range(int(math.floor(float(numpft)/float(len(linestyles_base))))): - linestyles.extend(linestyles_base) -for i in range(numpft-len(linestyles)): - linestyles.append(linestyles_base[i]) - -my_colors = DiscreteCubeHelix(numpft) - - -mp.rcParams.update({'font.size': 14}) -mp.rcParams["savefig.directory"] = "" #os.chdir(os.path.dirname(__file__)) - -legfs = 12 -lwidth = 2.0 - -#code.interact(local=dict(globals(), **locals())) - -if(True): - fig0 = plt.figure() - figleg = plt.figure() - ax = fig0.add_subplot(111) - ax.axis("off") - ax.set_axis_off() - proxies = () - for ipft in range(numpft): - proxies = proxies + (mp.lines.Line2D([],[], \ - linestyle=linestyles[ipft], \ - color=my_colors(ipft), \ - label=eparms['name'].vals[ipft], \ - linewidth=lwidth),) - figleg.legend(handles=proxies,fontsize=12,frameon=False,labelspacing=0.25,loc='center') - plt.show(block=False) - plt.close(fig0) - - - -if(False): - fig1_12 = plt.figure() - for ipft in range(numpft): - plt.plot(bagwd[ipft,:],bagwr[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('bagw [m]') - plt.ylabel('bagr [m]') - plt.title('') - plt.grid(True) - plt.savefig("plots/bagw_vs_bagwr.png") - - -if(True): - fig1 = plt.figure() - figleg = plt.figure() - for ipft in range(numpft): - plt.plot(dbh[ipft,:],hi[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('diameter [cm]') - plt.ylabel('height [m]') - plt.title('Integrated Heights') - plt.grid(True) - plt.tight_layout() - -if(True): - fig1_1 = plt.figure() - for ipft in range(numpft): - plt.plot(hd[ipft,:],hi[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('height (diagnosed) [m]') - plt.ylabel('height (integrated) [m]') - plt.title('Height') - plt.grid(True) - plt.savefig("plots/hdhi.png") - -if(False): - fig2=plt.figure() - for ipft in range(numpft): - plt.plot(blmaxd[ipft,:],blmaxi[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('diagnosed [kgC]') - plt.ylabel('integrated [kgC]') - plt.title('Maximum Leaf Biomass') - plt.grid(True) - plt.tight_layout() - -if(True): - fig3=plt.figure() - for ipft in range(numpft): - plt.plot(dbh[ipft,:],blmaxi[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('diameter [cm]') - plt.ylabel('mass [kgC]') - plt.title('Maximum Leaf Biomass') - plt.grid(True) - plt.tight_layout() - -if(True): - fig3_1=plt.figure() - for ipft in range(numpft): - plt.plot(dbh[ipft,1:15],blmaxi[ipft,1:15],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('diameter [cm]') - plt.ylabel('mass [kgC]') - plt.title('Maximum Leaf Biomass (saplings)') - plt.grid(True) - plt.tight_layout() - - -if(True): - fig4=plt.figure() - for ipft in range(numpft): - plt.plot(dbh[ipft,:],camin[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('diameter [cm]') - plt.ylabel('[m2] (closed canopy)') - plt.title('Crown Area') - plt.grid(True) - plt.tight_layout() - -if(True): - fig4_1=plt.figure() - for ipft in range(numpft): - plt.plot(dbh[ipft,:],ldense[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('diameter [cm]') - plt.ylabel('[kgC/m2] (closed canopy)') - plt.title('Leaf Mass Per Crown Area') - plt.grid(True) - plt.tight_layout() - - -if(True): - fig6=plt.figure() - for ipft in range(numpft): - plt.plot(dbh[ipft,:],bagwi[ipft,:]/1000,linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('diameter [cm]') - plt.ylabel('AGB [MgC]') - plt.title('Above Ground Biomass') - plt.grid(True) - plt.tight_layout() - -if(False): - fig6_1=plt.figure() - for ipft in range(numpft): - plt.plot(bagwd[ipft,:]/1000,bagwi[ipft,:]/1000,linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('AGBW deterministic [MgC]') - plt.ylabel('AGBW integrated [MgC]') - plt.title('Above Ground Biomass') - plt.grid(True) - plt.tight_layout() - -if(False): - fig5=plt.figure() - for ipft in range(numpft): - gpmask = np.isfinite(blmax_o_dbagwdh[ipft,:]) - plt.plot(dbh[ipft,gpmask],blmax_o_dbagwdh[ipft,gpmask],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('diameter [cm]') - plt.ylabel('growth potential: bl/(dAGB/dh) [m]') - plt.title('Height Growth Potential') - plt.grid(True) - plt.tight_layout() - -if(False): - fig6=plt.figure() - for ipft in range(numpft): - plt.plot(dbh[ipft,:],blmax_o_dbagwdd[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('diameter [cm]') - plt.ylabel('growth potential: bl/(dAGB/dd) [cm]') - plt.title('Diameter Growth Potential') - plt.grid(True) - plt.tight_layout() - -if(False): - fig7=plt.figure() - for ipft in range(numpft): - plt.plot(bsapd[ipft,:],bsapi[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('deterministic [kgC]') - plt.ylabel('integrated [kgC]') - plt.title('Sapwood Biomass') - plt.grid(True) - plt.tight_layout() - -if(False): - fig7_0=plt.figure() - for ipft in range(numpft): - plt.plot(dbh[ipft,:],bsapd[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - plt.xlabel('Diameter [cm]') - plt.ylabel('[kgC]') - plt.title('Sapwood Biomass') - plt.grid(True) - plt.tight_layout() - -if(True): - fig7_2=plt.figure(figsize=(8,6)) - # Sapwood - ax = fig7_2.add_subplot(221) - for ipft in range(numpft): - ax.plot(dbh[ipft,:],bsapd[ipft,:]/(bsapd[ipft,:]+blmaxi[ipft,:]+bfrmax[ipft,:]+bstore[ipft,:]), \ - linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - ax.set_xlabel('diameter [cm]') - ax.set_ylabel('[kgC/kgC]') - ax.set_title('Sapwood (fraction of live)') - ax.grid(True) - # Leaf - ax = fig7_2.add_subplot(222) - for ipft in range(numpft): - ax.plot(dbh[ipft,:],blmaxi[ipft,:]/(bsapd[ipft,:]+blmaxi[ipft,:]+bfrmax[ipft,:]+bstore[ipft,:]), \ - linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - ax.set_xlabel('diameter [cm]') - ax.set_ylabel('[kgC/kgC]') - ax.set_title('Leaf (fraction of live)') - ax.grid(True) - # Fine Root - ax = fig7_2.add_subplot(223) - for ipft in range(numpft): - ax.plot(dbh[ipft,:],bfrmax[ipft,:]/(bsapd[ipft,:]+blmaxi[ipft,:]+bfrmax[ipft,:]+bstore[ipft,:]), \ - linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - ax.set_xlabel('diameter [cm]') - ax.set_ylabel('[kgC/kgC]') - ax.set_title('Fine-Root (fraction of live)') - ax.grid(True) - # Storage - ax = fig7_2.add_subplot(224) - for ipft in range(numpft): - ax.plot(dbh[ipft,:],bstore[ipft,:]/(bsapd[ipft,:]+blmaxi[ipft,:]+bfrmax[ipft,:]+bstore[ipft,:]), \ - linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - ax.set_xlabel('diameter [cm]') - ax.set_ylabel('[kgC/kgC]') - ax.set_title('Storage (fraction of live)') - ax.grid(True) - - plt.tight_layout() - - - -if(True): - fig8=plt.figure() - ax = fig8.add_subplot(111) - for ipft in range(numpft): - ax.plot(dbh[ipft,:],treelai[ipft,:],linestyle=linestyles[ipft],color=my_colors(ipft),linewidth=lwidth) - ax.ticklabel_format(style='plain') - ax.set_xlabel('diameter [cm]') - ax.set_ylabel('[m2/m2]') - ax.set_title('Untrimmed In-Crown LAI') - ax.grid(True) - plt.tight_layout() - - - - -plt.show() diff --git a/functional_unit_testing/allometry/f90src/AllomUnitWrap.F90_in b/functional_unit_testing/allometry/f90src/AllomUnitWrap.F90_in deleted file mode 100644 index 471314b0bf..0000000000 --- a/functional_unit_testing/allometry/f90src/AllomUnitWrap.F90_in +++ /dev/null @@ -1,218 +0,0 @@ - -! ======================================================================================= -! -! This file is an alternative to key files in the fates -! filesystem. Noteably, we replace fates_r8 and fates_in -! with types that work with "ctypes". This is -! a key step in working with python -! -! We also wrap FatesGlobals to reduce the dependancy -! cascade that it pulls in from shr_log_mod. -! -! ======================================================================================= - -module shr_log_mod - - use iso_c_binding, only : c_char - use iso_c_binding, only : c_int - - contains - - function shr_log_errMsg(source, line) result(ans) - character(kind=c_char,len=*), intent(in) :: source - integer(c_int), intent(in) :: line - character(kind=c_char,len=128) :: ans - - ans = "source: " // trim(source) // " line: " - end function shr_log_errMsg - -end module shr_log_mod - - -module FatesGlobals - - contains - - integer function fates_log() - fates_log = -1 - end function fates_log - - subroutine fates_endrun(msg) - - implicit none - character(len=*), intent(in) :: msg ! string to be printed - - stop - - end subroutine fates_endrun - -end module FatesGlobals - - -module EDTypesMod - - use iso_c_binding, only : r8 => c_double - - integer, parameter :: nclmax = 2 - integer, parameter :: nlevleaf = 30 - real(r8), parameter :: dinc_ed = 1.0_r8 - -end module EDTypesMod - - -module EDPftvarcon - - use iso_c_binding, only : r8 => c_double - use iso_c_binding, only : i4 => c_int - use iso_c_binding, only : c_char - - integer,parameter :: SHR_KIND_CS = 80 ! short char - - type, public :: EDPftvarcon_inst_type - - ! VARIABLE-DEFINITIONS-HERE (DO NOT REMOVE THIS LINE, OR MOVE IT) - - end type EDPftvarcon_inst_type - - type ptr_var1 - real(r8), dimension(:), pointer :: var_rp - integer(i4), dimension(:), pointer :: var_ip - character(len=shr_kind_cs) :: var_name - integer :: vtype - end type ptr_var1 - - type ptr_var2 - real(r8), dimension(:,:), pointer :: var_rp - integer(i4), dimension(:,:), pointer :: var_ip - character(len=shr_kind_cs) :: var_name - integer :: vtype - end type ptr_var2 - - type EDPftvarcon_ptr_type - type(ptr_var1), allocatable :: var1d(:) - type(ptr_var2), allocatable :: var2d(:) - end type EDPftvarcon_ptr_type - - - type(EDPftvarcon_inst_type), public :: EDPftvarcon_inst ! ED ecophysiological constants structure - type(EDPftvarcon_ptr_type), public :: EDPftvarcon_ptr ! Pointer structure for obj-oriented id - - integer :: numparm1d ! Number of different PFT parameters - integer :: numparm2d - integer :: numpft - - logical, parameter :: debug = .true. - -contains - - - subroutine EDPftvarconPySet(ipft,rval,ival,name) - - implicit none - ! Arguments - integer(i4),intent(in) :: ipft - character(kind=c_char,len=*), intent(in) :: name - real(r8),intent(in) :: rval - integer(i4),intent(in) :: ival - ! Locals - logical :: npfound - integer :: ip - integer :: namelen - - namelen = len(trim(name)) - - if(debug) print*,"F90: ARGS: ",trim(name)," IPFT: ",ipft," RVAL: ",rval," IVAL: ",ival - - ip=0 - npfound = .true. - do ip=1,numparm1d - - if (trim(name) == trim(EDPftvarcon_ptr%var1d(ip)%var_name ) ) then - print*,"F90: Found ",trim(name)," in lookup table" - npfound = .false. - if(EDPftvarcon_ptr%var1d(ip)%vtype == 1) then ! real - EDPftvarcon_ptr%var1d(ip)%var_rp(ipft) = rval - elseif(EDPftvarcon_ptr%var1d(ip)%vtype == 2) then ! integer - EDPftvarcon_ptr%var1d(ip)%var_ip(ipft) = ival - else - print*,"F90: STRANGE TYPE" - stop - end if - end if - end do - - if(npfound)then - print*,"F90: The parameter you loaded DNE: ",name(:) - stop - end if - - do ip=1,numparm2d - if (trim(name) == trim(EDPftvarcon_ptr%var2d(ip)%var_name)) then - print*,"F90: Found ",trim(name)," in lookup table" - print*,"BUT... WE AVOID USING 2D VARIABLES FOR NOW..." - print*,"REMOVE THIS TEST" - stop - end if - end do - - - ! Perform a check to see if the target array is being filled - if (trim(name) == 'fates_allom_d2h1') then - if (EDPftvarcon_inst%allom_d2h1(ipft) == rval) then - print*,"F90: POINTER CHECK PASSES:",rval," = ",EDPftvarcon_inst%allom_d2h1(ipft) - else - print*,"F90: POINTER CHECK FAILS:",rval," != ",EDPftvarcon_inst%allom_d2h1(ipft) - stop - end if - end if - - if (trim(name) == 'fates_wood_density' ) then - if (EDPftvarcon_inst%wood_density(ipft) == rval) then - print*,"F90: POINTER CHECK PASSES:",rval," = ",EDPftvarcon_inst%wood_density(ipft) - else - print*,"F90: POINTER CHECK FAILS:",rval," != ",EDPftvarcon_inst%wood_density(ipft) - stop - end if - end if - - return - end subroutine EDPftvarconPySet - - - subroutine EDPftvarconAlloc(numpft_in) - ! - - ! !ARGUMENTS: - integer(i4), intent(in) :: numpft_in - ! LOCALS: - integer :: iv1 ! The parameter incrementer - integer :: iv2 - !------------------------------------------------------------------------ - - numpft = numpft_in - - allocate( EDPftvarcon_ptr%var1d(100)) ! Make this plenty large - allocate( EDPftvarcon_ptr%var2d(100)) - iv1=0 - iv2=0 - - ! POINTER-SPECIFICATION-HERE (DO NOT REMOVE THIS LINE, OR MOVE IT) - -! allocate( EDPftvarcon_inst%allom_dbh_maxheight (1:numpft)); EDPftvarcon_inst%allom_dbh_maxheight (:) = nan -! iv = iv + 1 -! EDPftvarcon_ptr%var1d(iv)%var_name = "fates_allom_dbh_maxheight" -! EDPftvarcon_ptr%var1d(iv)%var_rp => EDPftvarcon_inst%allom_dbh_maxheight -! EDPftvarcon_ptr%var1d(iv)%vtype = 1 - - - numparm1d = iv1 - numparm2d = iv2 - - - print*,"F90: ALLOCATED ",numparm1d," PARAMETERS, FOR ",numpft," PFTs" - - - return - end subroutine EDPftvarconAlloc - -end module EDPftvarcon diff --git a/functional_unit_testing/allometry/include/README b/functional_unit_testing/allometry/include/README deleted file mode 100644 index bfa612f78d..0000000000 --- a/functional_unit_testing/allometry/include/README +++ /dev/null @@ -1 +0,0 @@ -This holds the place of the include folder \ No newline at end of file diff --git a/functional_unit_testing/allometry/plots/README b/functional_unit_testing/allometry/plots/README deleted file mode 100644 index c32df9df9a..0000000000 --- a/functional_unit_testing/allometry/plots/README +++ /dev/null @@ -1 +0,0 @@ -Placeholder for the folder \ No newline at end of file diff --git a/functional_unit_testing/allometry/simple_build.sh b/functional_unit_testing/allometry/simple_build.sh deleted file mode 100755 index 114c82a15d..0000000000 --- a/functional_unit_testing/allometry/simple_build.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash - -FC='gfortran -g -shared -fPIC' - -# First copy over the FatesConstants file, but change the types of the fates_r8 and fates_int - -old_fates_r8_str=`grep -e integer ../../main/FatesConstantsMod.F90 | grep fates_r8 | sed 's/^[ \t]*//;s/[ \t]*$//'` -new_fates_r8_str='use iso_c_binding, only: fates_r8 => c_double' - -old_fates_int_str=`grep -e integer ../../main/FatesConstantsMod.F90 | grep fates_int | sed 's/^[ \t]*//;s/[ \t]*$//'` -new_fates_int_str='use iso_c_binding, only: fates_int => c_int' - -# Add the new lines (need position change, don't swap) - -sed "/implicit none/i $new_fates_r8_str" ../../main/FatesConstantsMod.F90 > f90src/FatesConstantsMod.F90 -sed -i "/implicit none/i $new_fates_int_str" f90src/FatesConstantsMod.F90 - -# Delete the old lines - -sed -i "/$old_fates_r8_str/d" f90src/FatesConstantsMod.F90 -sed -i "/$old_fates_int_str/d" f90src/FatesConstantsMod.F90 - -sed -i "/private/d" f90src/FatesConstantsMod.F90 - -# This re-writes the wrapper so that it uses all the correct parameters -# in FatesAllometryMod.F90 -python AutoGenVarCon.py - - -# Procedure for auto-generating AllomUnitWrap -# 1) scan FatesAllometry and create list of EDPftVarcon_inst variables -# 2) scan EDpftVarcon and get the name of the in-file parameter names associated -# with these variables - - - - -rm -f include/*.o -rm -f include/*.mod - - -# Build the new file with constants - -${FC} -I include/ -J include/ -o include/FatesConstantsMod.o f90src/FatesConstantsMod.F90 - -${FC} -I include/ -J include/ -o include/AllomUnitWrap.o f90src/AllomUnitWrap.F90 - -${FC} -I include/ -J include/ -o include/FatesAllometryMod.o ../../biogeochem/FatesAllometryMod.F90 - - -#${FC} -g -o include/FatesConstantsMod.o ../main/FatesConstantsMod.F90 - -#gfortran -shared -fPIC -g -o include/EDTypesMod.o ../main/EDTypesMod.F90 - - - - -#gfortran diff --git a/functional_unit_testing/build_fortran_tests.py b/functional_unit_testing/build_fortran_tests.py new file mode 100644 index 0000000000..678a559f3c --- /dev/null +++ b/functional_unit_testing/build_fortran_tests.py @@ -0,0 +1,217 @@ +import os +import sys +import shutil + +_FATES_PYTHON = os.path.join(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(1, _FATES_PYTHON) + +from utils import add_cime_lib_to_path +add_cime_lib_to_path() + +from CIME.utils import get_src_root, run_cmd_no_fail, expect, stringify_bool +from CIME.build import CmakeTmpBuildDir +from CIME.XML.machines import Machines +from CIME.BuildTools.configure import configure, FakeCase +from CIME.XML.env_mach_specific import EnvMachSpecific + +_CIMEROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../cime") + +def run_cmake(name, test_dir, pfunit_path, cmake_args): + """Run cmake for the fortran unit tests + Arguments: + name (str) - name for output messages + test_dir (str) - directory to run Cmake in + pfunit_path (str) - path to pfunit + clean (bool) - clean the build + """ + if not os.path.isfile("CMakeCache.txt"): + print(f"Running cmake for {name}.") + + # directory with cmake modules + cmake_module_dir = os.path.abspath(os.path.join(_CIMEROOT, "CIME", "non_py", "src", "CMake")) + + # directory with genf90 + genf90_dir = os.path.join(_CIMEROOT, "CIME", "non_py", "externals", "genf90") + + cmake_command = [ + "cmake", + "-C Macros.cmake", + test_dir, + f"-DCIMEROOT={_CIMEROOT}", + f"-DSRC_ROOT={get_src_root()}", + f"-DCIME_CMAKE_MODULE_DIRECTORY={cmake_module_dir}", + "-DCMAKE_BUILD_TYPE=CESM_DEBUG", + f"-DCMAKE_PREFIX_PATH={pfunit_path}", + "-DUSE_MPI_SERIAL=ON", + "-DENABLE_GENF90=ON", + f"-DCMAKE_PROGRAM_PATH={genf90_dir}" + ] + + cmake_command.extend(cmake_args.split(" ")) + #print(" ".join(cmake_command)) + + run_cmd_no_fail(" ".join(cmake_command), combine_output=True) + + +def find_pfunit(caseroot, cmake_args): + """Find the pfunit installation we'll be using, and print its path + + Args: + caseroot (str): Directory with pfunit macros + cmake_args (str): The cmake args used to invoke cmake (so that we get the correct makefile vars) + """ + with CmakeTmpBuildDir(macroloc=caseroot) as cmaketmp: + all_vars = cmaketmp.get_makefile_vars(cmake_args=cmake_args) + + all_vars_list = all_vars.splitlines() + for all_var in all_vars_list: + if ":=" in all_var: + expect(all_var.count(":=") == 1, f"Bad makefile: {all_var}") + varname, value = [item.strip() for item in all_var.split(":=")] + if varname == "PFUNIT_PATH": + return value + + expect(False, "PFUNIT_PATH not found for this machine and compiler") + + return None + + +def prep_build_dir(build_dir, clean): + """Create (if necessary) build directory and clean contents (if asked to) + + Args: + build_dir (str): build directory name + clean (bool): whether or not to clean contents + """ + + # create the build directory + build_dir_path = os.path.abspath(build_dir) + if not os.path.isdir(build_dir_path): + os.mkdir(build_dir_path) + + # change into that directory + os.chdir(build_dir_path) + + # clean up any files if we want to + if clean: + clean_cmake_files() + + return build_dir_path + + +def clean_cmake_files(): + """Deletes all files related to build + + """ + if os.path.isfile("CMakeCache.txt"): + os.remove("CMakeCache.txt") + if os.path.isdir("CMakeFiles"): + shutil.rmtree("CMakeFiles") + + cwd_contents = os.listdir(os.getcwd()) + + # Clear contents to do with cmake cache + for file in cwd_contents: + if ( + file in ("Macros.cmake", "env_mach_specific.xml") + or file.startswith("Depends") + or file.startswith(".env_mach_specific") + ): + os.remove(file) + +def get_extra_cmake_args(build_dir, mpilib): + """Makes a fake case to grab the required cmake arguments + Args: + build_dir (str): build directory name + mpilib (str): MPI library name + """ + # get the machine objects file + machobj = Machines() + + # get compiler + compiler = machobj.get_default_compiler() + + # get operating system + os_ = machobj.get_value("OS") + + # Create the environment, and the Macros.cmake file + # + # + configure( + machobj, + build_dir, + ["CMake"], + compiler, + mpilib, + True, + "nuopc", + os_, + unit_testing=True, + ) + machspecific = EnvMachSpecific(build_dir, unit_testing=True) + + # make a fake case + fake_case = FakeCase(compiler, mpilib, True, "nuopc", threading=False) + + cmake_args = ( + "{}-DOS={} -DMACH={} -DCOMPILER={} -DDEBUG={} -DMPILIB={} -Dcompile_threaded={} -DCASEROOT={}".format( + "", + os_, + machobj.get_machine_name(), + compiler, + stringify_bool(True), + mpilib, + stringify_bool(False), + build_dir + ) + ) + + return cmake_args + +def run_make(name, make_j, clean=False, verbose=False): + """Run make in current working directory + + Args: + name (str): Name for output messages + make_j (int): number of processes to use for make + clean (bool, optional): whether or not to clean Defaults to False. + verbose (bool, optional): verbose error logging for make Defaults to False. + """ + + print(f"Running make for {name}.") + + if clean: + run_cmd_no_fail("make clean") + + make_command = ["make", "-j", str(make_j)] + + if verbose: + make_command.append("VERBOSE=1") + + run_cmd_no_fail(" ".join(make_command), combine_output=True) + + +def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False): + """Build the unit test executables + + Args: + build_dir (str): build directory + name (str): name for set of tests + cmake_directory (str): directory where the make CMakeLists.txt file is + make_j (int): number of processes to use for make + clean (bool, optional): whether or not to clean the build first. Defaults to False. + """ + # create the build directory + full_build_path = prep_build_dir(build_dir, clean=clean) + + # get cmake args and the pfunit path + cmake_args = get_extra_cmake_args(full_build_path, "mpi-serial") + pfunit_path = find_pfunit(full_build_path, cmake_args) + + # change into the build dir + os.chdir(full_build_path) + + # run cmake and make + run_cmake(name, cmake_directory, pfunit_path, cmake_args) + run_make(name, make_j, clean=clean) + diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py new file mode 100755 index 0000000000..3d08002291 --- /dev/null +++ b/functional_unit_testing/run_fates_tests.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import os +import sys +from build_fortran_tests import build_unit_tests + +_FATES_PYTHON = os.path.join(os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(1, _FATES_PYTHON) + +from utils import add_cime_lib_to_path +add_cime_lib_to_path() + +from CIME.utils import run_cmd_no_fail + + +if __name__ == "__main__": + + ## Arguments + clean = True + build = True + build_dir = "../_build" + name = "fates_unit_tests" + make_j = 8 + cmake_directory = os.path.abspath("../") + + ## Constants + test_dir = "fates_allom_test" + test_exe = "FATES_allom_exe" + + if build: + build_unit_tests(build_dir, name, cmake_directory, make_j, clean=clean) + + build_dir_path = os.path.abspath(build_dir) + exe_path = os.path.join(build_dir_path, test_dir, test_exe) + + out = run_cmd_no_fail(exe_path, combine_output=True) + print(out) \ No newline at end of file diff --git a/functional_unit_testing/utils.py b/functional_unit_testing/utils.py new file mode 100644 index 0000000000..e4f74e0b68 --- /dev/null +++ b/functional_unit_testing/utils.py @@ -0,0 +1,57 @@ +"""Utility functions related to getting paths to various important places +""" + +import os +import sys + +# ======================================================================== +# Constants that may need to be changed if directory structures change +# ======================================================================== + +# Path to the root directory of FATES, based on the path of this file +# +# Note: It's important that this NOT end with a trailing slash; +# os.path.normpath guarantees this. +_FATES_ROOT = os.path.normpath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir) +) + +def path_to_fates_root(): + """Returns the path to the root directory of FATES""" + return _FATES_ROOT + +def path_to_cime(): + """Returns the path to cime, if it can be found + + Raises a RuntimeError if it cannot be found + + """ + cime_path = os.path.join(path_to_fates_root(), "../../cime") + if os.path.isdir(cime_path): + return cime_path + raise RuntimeError("Cannot find cime.") + +def prepend_to_python_path(path): + """Adds the given path to python's sys.path if it isn't already in the path + + The path is added near the beginning, so that it takes precedence over existing + entries in the path + """ + if not path in sys.path: + # Insert at location 1 rather than 0, because 0 is special + sys.path.insert(1, path) + +def add_cime_lib_to_path(): + """Adds the CIME python library to the python path, to allow importing + modules from that library + + Returns the path to the top-level cime directory + + For documentation on standalone_only: See documentation in + path_to_cime + """ + cime_path = path_to_cime() + prepend_to_python_path(cime_path) + cime_lib_path = os.path.join(cime_path, "CIME", "Tools") + prepend_to_python_path(cime_lib_path) + return cime_path \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index dfd5eaba2a..a680dbaa4b 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -12,3 +12,20 @@ list(APPEND clm_sources ) sourcelist_to_parent(clm_sources) + +list(APPEND fates_sources + FatesConstantsMod.F90 + FatesGlobals.F90 + FatesParametersInterface.F90 + FatesInterfaceTypesMod.F90 + EDPftvarcon.F90 + EDParamsMod.F90 + EDTypesMod.F90 + FatesHydraulicsMemMod.F90 + FatesRunningMeanMod.F90 + FatesParameterDerivedMod.F90 + FatesSizeAgeTypeIndicesMod.F90 + FatesIntegratorsMod.F90 + FatesUtilsMod.F90) + +sourcelist_to_parent(fates_sources) diff --git a/parteh/CMakeLists.txt b/parteh/CMakeLists.txt new file mode 100644 index 0000000000..67c8a175a2 --- /dev/null +++ b/parteh/CMakeLists.txt @@ -0,0 +1,8 @@ +list(APPEND fates_sources + PRTParametersMod.F90 + PRTParamsFATESMod.F90 + PRTGenericMod.F90 + PRTAllometricCarbonMod.F90 + PRTAllometricCNPMod.F90) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/radiation/CMakeLists.txt b/radiation/CMakeLists.txt new file mode 100644 index 0000000000..84e72877ec --- /dev/null +++ b/radiation/CMakeLists.txt @@ -0,0 +1,6 @@ +list(APPEND fates_sources + TwoStreamMLPEMod.F90 + FatesRadiationMemMod.F90 + ) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/unit_test_shr/CMakeLists.txt b/unit_test_shr/CMakeLists.txt new file mode 100644 index 0000000000..18d2931194 --- /dev/null +++ b/unit_test_shr/CMakeLists.txt @@ -0,0 +1,5 @@ +list(APPEND fates_sources + FatesUnitTestParamReaderMod.F90 + ) + +sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 new file mode 100644 index 0000000000..07ae70c765 --- /dev/null +++ b/unit_test_shr/FatesUnitTestIOMod.F90 @@ -0,0 +1,571 @@ +module FatesUnitTestIOMod + use FatesConstantsMod, only : r8 => fates_r8 + use shr_kind_mod, only : SHR_KIND_CL + !use netcdf + + implicit none + + ! LOCALS + ! integer, parameter :: BASE_UNIT = 10 ! Base unit for files the first time unit_number is called + ! integer, parameter :: MAX_PATH = 256 ! Maximum path length + ! integer, parameter :: MAX_CHAR = 80 ! Maximum length for messages + ! integer :: logf ! Unit number for output log file + ! integer, parameter :: type_double = 1 ! type + ! integer, parameter :: type_int = 2 ! type + + ! interface GetVar + ! module procedure GetVar1DReal + ! module procedure GetVar2DReal + ! module procedure GetVar3DReal + ! module procedure GetVar1DInt + ! module procedure GetVar2DInt + ! module procedure GetVar3DInt + ! end interface + + contains + + character(len=*) function full_file_path(filename) + ! + ! DESCRIPTION: + ! Obtain full path of file + ! First check current working directory + ! Then check full pathname on disk + + ! ARGUMENTS: + character(len=*), intent(in) :: filename + + ! LOCALS: + + ! get local file name + !full_file_path = 'file_path'!get_filename(filename) + + end function full_file_path + + ! integer function UnitNumber() + ! ! + ! ! DESCRIPTION: + ! ! Generates a unit number to be used in opening files + ! ! The first time the function is called, it returns BASE_UNIT + ! ! + ! ! LOCALS: + ! integer :: iunit ! File unit (increments after first call) + ! logical :: first = .true. ! First time this has been called? + ! save + + ! if (first) then + ! ! Set first to false and iunit to base unit on first call + ! iunit = BASE_UNIT + ! first = .false. + ! else + ! ! Otherwise, increment + ! iunit = iunit + 1 + ! endif + + ! ! Set to output + ! UnitNumber = iunit + + ! end function UnitNumber + + ! !===================================================================================== + + ! character(len=9) function FileMode(mode) + ! ! + ! ! DESCRIPTION: + ! ! Gets a file mode + ! ! + + ! ! ARGUMENTS: + ! character(len=*), intent(in), optional :: mode ! Optional mode ('r', 'w', 'rw') + + ! ! Get mode of open (read, write, or read/write) + ! select case(mode) + ! case ('r', 'R') + ! FileMode = 'read' + ! case ('w', 'W') + ! FileMode = 'write' + ! case ('rw', 'RW', 'wr', 'WR') + ! FileMode = 'readwrite' + ! case DEFAULT + ! FileMode = 'readwrite' + ! end select + + ! end function FileMode + + ! !===================================================================================== + + ! logical function CheckFile(filename, fmode) + ! ! + ! ! DESCRIPTION: + ! ! Checks to see if a file exists and checks against the mode + ! ! + + ! ! ARGUMENTS: + ! character(len=*), intent(in) :: filename ! Name of file to open + ! character(len=*), intent(in) :: fmode ! File mode + + ! ! LOCALS: + ! character(len=MAX_PATH) :: fname ! Local filename (trimmed) + ! integer, dimension(MAX_PATH) :: farray ! Array of characters of file name + ! integer :: i ! looping index + ! integer :: ios ! I/O status + ! logical :: file_exists ! Does the file exist? + + ! ! trim filename of whitespace + ! fname = trim(adjustl(filename)) + + ! if (fmode == 'read' .or. fmode == 'readwrite') then + ! ! Check for valid name of file + ! farray = 0 + ! do i = 1, len_trim(fname) + ! farray(i) = ichar(fname(i:i)) + ! enddo + ! if (any(farray > MAX_PATH)) then + ! write(logf,'(A)') "Invalid filename" + ! CheckFile = .false. + ! return + ! endif + ! endif + + ! ! Does the file exist? + ! inquire(file=fname, exist=file_exists) + + ! ! Open file if conditions are correct + ! if (file_exists .and. fmode == 'write') then + ! write(logf,'(A,A,A)') "File ", fname(1:len_trim(fname)), & + ! " exists. Cannot open write only." + ! CheckFile = .false. + ! else if (.not. file_exists .and. fmode == 'read') then + ! write(logf, '(A,A,A)') "File ", fname(1:len_trim(fname)), & + ! " does not exist. Can't read." + ! CheckFile = .false. + ! else + ! CheckFile = .true. + ! endif + + ! end function CheckFile + + ! !===================================================================================== + + ! integer function OpenFile(filename, mode) + ! ! + ! ! DESCRIPTION: + ! ! Opens the file filename if it can, returns a unit number for it. + ! ! The first time the function is called, it returns BASE_UNIT + ! ! + + ! ! ARGUMENTS: + ! character(len = *), intent(in) :: filename ! Name of file to open + ! character(len = *), intent(in), optional :: mode ! Optional mode ('r', 'w', 'rw') + + ! ! LOCALS: + ! character(len=9) :: fmode ! file mode + ! integer :: iunit ! file unit number + ! integer :: ios ! I/O status + ! character(len=MAX_PATH) :: fname ! Local filename (trimmed) + + ! ! get the file mode, defaults to readwrite + ! if (present(mode)) then + ! fmode = FileMode(mode) + ! else + ! fmode = 'readwrite' + ! end if + + ! if (CheckFile(filename, fmode)) then + + ! ! trim filename of whitespace + ! fname = trim(adjustl(filename)) + + ! iunit = UnitNumber() + ! open(iunit, file=fname, action=fmode, iostat=ios) + ! if (ios /= 0) then + ! write(logf,'(A,A,A,I6)') "Problem opening", & + ! fname(1:len_trim(fname)), " ios: ", ios + ! stop + ! endif + ! else + ! stop + ! end if + + ! OpenFile = iunit + + ! end function OpenFile + + ! !===================================================================================== + + ! subroutine Check(status) + ! ! + ! ! DESCRIPTION: + ! ! Checks status of netcdf operations + + ! ! ARGUMENTS: + ! integer, intent(in) :: status ! return status code from a netcdf procedure + + ! if (status /= nf90_noerr) then + ! write(logf,*) trim(nf90_strerror(status)) + ! stop + ! end if + + ! end subroutine Check + + ! !===================================================================================== + + ! subroutine OpenNCFile(nc_file, ncid, fmode) + ! ! + ! ! DESCRIPTION: + ! ! Opens a netcdf file + + ! ! ARGUMENTS: + ! character(len=*), intent(in) :: nc_file ! file name + ! integer, intent(out) :: ncid ! netcdf file unit number + ! character(len=*) :: fmode ! file mode + + ! if (CheckFile(nc_file, fmode)) then + ! ! depending on mode + ! select case(fmode) + ! case ('read') + ! call Check(nf90_open(trim(nc_file), NF90_NOCLOBBER, ncid)) + ! case ('write') + ! call Check(nf90_create(trim(nc_file), NF90_CLOBBER, ncid)) + ! case ('readwrite') + ! call Check(nf90_create(trim(nc_file), NF90_CLOBBER, ncid)) + ! case DEFAULT + ! write(logf,*) 'Need to specify read, write, or readwrite' + ! stop + ! end select + ! else + ! write(logf,*) 'Problem reading file' + ! stop + ! end if + + ! end subroutine OpenNCFile + + ! !===================================================================================== + + ! subroutine CloseNCFile(ncid) + ! ! + ! ! DESCRIPTION: + ! ! Closes a netcdf file + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file unit number + + ! call Check(nf90_close(ncid)) + + ! end subroutine CloseNCFile + + ! !===================================================================================== + + ! subroutine GetDims(ncid, varID, dim_lens) + ! ! + ! ! DESCRIPTION: + ! ! Get dimensions for a netcdf variable + ! ! + + ! ! ARGUMENTS + ! integer, intent(in) :: ncid ! netcdf file unit ID + ! integer, intent(in) :: varID ! variable ID + ! integer, allocatable, intent(out) :: dim_lens(:) ! dimension lengths + + ! ! LOCALS: + ! integer :: numDims ! number of dimensions + ! integer, allocatable :: dimIDs(:) ! dimension IDs + ! integer :: i ! looping index + + ! ! find dimensions of data + ! call Check(nf90_inquire_variable(ncid, varID, ndims=numDims)) + + ! ! allocate data to grab dimension information + ! allocate(dim_lens(numDims)) + ! allocate(dimIDs(numDims)) + + ! ! get dimIDs + ! call Check(nf90_inquire_variable(ncid, varID, dimids=dimIDs)) + + ! ! grab these dimensions + ! do i = 1, numDims + ! call Check(nf90_inquire_dimension(ncid, dimIDs(i), len=dim_lens(i))) + ! end do + + ! end subroutine GetDims + + ! !===================================================================================== + + ! subroutine GetVar1DReal(ncid, var_name, data) + ! ! + ! ! DESCRIPTION: + ! ! Read in variables for 1D real data + ! ! + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file unit ID + ! character(len=*), intent(in) :: var_name ! variable name + ! real(r8), allocatable, intent(out) :: data(:) ! data values + + ! ! LOCALS: + ! integer :: varID ! variable ID + ! integer, allocatable :: dim_lens(:) ! dimension lengths + + ! ! find variable ID first + ! call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! ! get dimensions of data + ! call GetDims(ncid, varID, dim_lens) + + ! ! read data + ! allocate(data(dim_lens(1))) + ! call Check(nf90_get_var(ncid, varID, data)) + + ! end subroutine GetVar1DReal + + ! !===================================================================================== + + ! subroutine GetVar1DInt(ncid, var_name, data) + ! ! + ! ! DESCRIPTION: + ! ! Read in variables for 1D integer data + ! ! + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file unit ID + ! character(len=*), intent(in) :: var_name ! variable name + ! integer, allocatable, intent(out) :: data(:) ! data values + + ! ! LOCALS: + ! integer :: varID ! variable ID + ! integer, allocatable :: dim_lens(:) ! dimension lengths + + ! ! find variable ID first + ! call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! ! get dimensions of data + ! call GetDims(ncid, varID, dim_lens) + + ! ! read data + ! allocate(data(dim_lens(1))) + ! call Check(nf90_get_var(ncid, varID, data)) + + ! end subroutine GetVar1DInt + + ! !===================================================================================== + + ! subroutine GetVar2DReal(ncid, var_name, data) + ! ! + ! ! DESCRIPTION: + ! ! Read in variables for 2D real data + ! ! + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file unit ID + ! character(len=*), intent(in) :: var_name ! variable name + ! real(r8), allocatable, intent(out) :: data(:,:) ! data values + + ! ! LOCALS: + ! integer :: varID ! variable ID + ! integer, allocatable :: dim_lens(:) ! dimension lengths + + ! ! find variable ID first + ! call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! ! get dimensions of data + ! call GetDims(ncid, varID, dim_lens) + + ! ! read data + ! allocate(data(dim_lens(1), dim_lens(2))) + ! call Check(nf90_get_var(ncid, varID, data)) + + ! end subroutine GetVar2DReal + + ! !===================================================================================== + + ! subroutine GetVar2DInt(ncid, var_name, data) + ! ! + ! ! DESCRIPTION: + ! ! Read in variables for 2D integer data + ! ! + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file unit ID + ! character(len=*), intent(in) :: var_name ! variable name + ! integer, allocatable, intent(out) :: data(:,:) ! data values + + ! ! LOCALS: + ! integer :: varID ! variable ID + ! integer, allocatable :: dim_lens(:) ! dimension lengths + + ! ! find variable ID first + ! call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! ! get dimensions of data + ! call GetDims(ncid, varID, dim_lens) + + ! ! read data + ! allocate(data(dim_lens(1), dim_lens(2))) + ! call Check(nf90_get_var(ncid, varID, data)) + + ! end subroutine GetVar2DInt + + ! !===================================================================================== + + ! subroutine GetVar3DReal(ncid, var_name, data) + ! ! + ! ! DESCRIPTION: + ! ! Read in variables for 3D real data + ! ! + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file unit ID + ! character(len=*), intent(in) :: var_name ! variable name + ! real(r8), allocatable, intent(out) :: data(:,:,:) ! data values + + ! ! LOCALS: + ! integer :: varID ! variable ID + ! integer, allocatable :: dim_lens(:) ! dimension lengths + + ! ! find variable ID first + ! call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! ! get dimensions of data + ! call GetDims(ncid, varID, dim_lens) + + ! ! read data + ! allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) + ! call Check(nf90_get_var(ncid, varID, data)) + + ! end subroutine GetVar3DReal + + ! !===================================================================================== + + ! subroutine GetVar3DInt(ncid, var_name, data) + ! ! + ! ! DESCRIPTION: + ! ! Read in variables for 3D integer data + ! ! + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file unit ID + ! character(len=*), intent(in) :: var_name ! variable name + ! integer, allocatable, intent(out) :: data(:,:,:) ! data values + + ! ! LOCALS: + ! integer :: varID ! variable ID + ! integer, allocatable :: dim_lens(:) ! dimension lengths + + ! ! find variable ID first + ! call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! ! get dimensions of data + ! call GetDims(ncid, varID, dim_lens) + + ! ! read data + ! allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) + ! call Check(nf90_get_var(ncid, varID, data)) + + ! end subroutine GetVar3DInt + + ! !===================================================================================== + + ! subroutine RegisterNCDims(ncid, dim_names, dim_lens, num_dims, dim_IDs) + ! ! + ! ! DESCRIPTION: + ! ! Defines variables and dimensions + ! ! + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file id + ! character(len=*), intent(in) :: dim_names(num_dims) ! dimension names + ! integer, intent(in) :: dim_lens(num_dims) ! dimension lengths + ! integer, intent(in) :: num_dims ! number of dimensions + ! integer, intent(out) :: dim_IDs(num_dims) ! dimension IDs + + ! ! LOCALS: + ! integer :: i ! looping index + + ! do i = 1, num_dims + ! call Check(nf90_def_dim(ncid, dim_names(i), dim_lens(i), dim_IDs(i))) + ! end do + + ! end subroutine RegisterNCDims + + ! !===================================================================================== + + ! subroutine RegisterVar1D(ncid, var_name, dimID, type, att_names, atts, num_atts, varID) + ! ! + ! ! DESCRIPTION: + ! ! Defines variables and dimensions + ! ! + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file id + ! character(len=*), intent(in) :: var_name ! variable name + ! integer, intent(in) :: dimID(1) ! dimension ID + ! integer, intent(in) :: type ! type: int or double + ! character(len=*), intent(in) :: att_names(num_atts) ! attribute names + ! character(len=*), intent(in) :: atts(num_atts) ! attribute values + ! integer, intent(in) :: num_atts ! number of attributes + ! integer, intent(out) :: varID ! variable ID + + + ! ! LOCALS: + ! integer :: i ! looping index + ! integer :: nc_type ! netcdf type + + ! if (type == type_double) then + ! nc_type = NF90_DOUBLE + ! else if (type == type_int) then + ! nc_type = NF90_INT + ! else + ! write(logf, *) "Must pick correct type" + ! stop + ! end if + + ! call Check(nf90_def_var(ncid, var_name, nc_type, dimID, varID)) + + ! do i = 1, num_atts + ! call Check(nf90_put_att(ncid, varID, att_names(i), atts(i))) + ! end do + + ! end subroutine RegisterVar1D + + ! !===================================================================================== + + ! subroutine RegisterVar2D(ncid, var_name, dimID, type, att_names, atts, num_atts, varID) + ! ! + ! ! DESCRIPTION: + ! ! Defines variables and dimensions + ! ! + + ! ! ARGUMENTS: + ! integer, intent(in) :: ncid ! netcdf file id + ! character(len=*), intent(in) :: var_name ! variable name + ! integer, intent(in) :: dimID(1:2) ! dimension ID + ! integer, intent(in) :: type ! type: int or double + ! character(len=*), intent(in) :: att_names(num_atts) ! attribute names + ! character(len=*), intent(in) :: atts(num_atts) ! attribute values + ! integer, intent(in) :: num_atts ! number of attributes + ! integer, intent(out) :: varID ! variable ID + + + ! ! LOCALS: + ! integer :: i ! looping index + ! integer :: nc_type ! netcdf type + + ! if (type == type_double) then + ! nc_type = NF90_DOUBLE + ! else if (type == type_int) then + ! nc_type = NF90_INT + ! else + ! write(logf, *) "Must pick correct type" + ! stop + ! end if + + ! call Check(nf90_def_var(ncid, var_name, nc_type, dimID, varID)) + + ! do i = 1, num_atts + ! call Check(nf90_put_att(ncid, varID, att_names(i), atts(i))) + ! end do + + ! end subroutine RegisterVar2D + + !===================================================================================== + +end module FatesUnitTestIOMod \ No newline at end of file diff --git a/unit_test_shr/FatesUnitTestParamReaderMod.F90 b/unit_test_shr/FatesUnitTestParamReaderMod.F90 new file mode 100644 index 0000000000..6cefe91df5 --- /dev/null +++ b/unit_test_shr/FatesUnitTestParamReaderMod.F90 @@ -0,0 +1,59 @@ +module FatesUnitTestParamReaderMod + + use FatesParametersInterface, only : fates_param_reader_type + use FatesParametersInterface, only : fates_parameters_type + use PRTInitParamsFatesMod, only : PRTRegisterParams + + implicit none + private + + type, public, extends(fates_param_reader_type) :: fates_unit_test_param_reader + + character(:), allocatable :: filename ! local file name of parameter + + contains + procedure, public :: Read => read_parameters + procedure, public :: param_read + + end type fates_unit_test_param_reader + + contains + + subroutine read_parameters(this, fates_params) + ! + ! DESCRIPTION: + ! Read 'fates_params' parameters from storage + ! + ! ARGUMENTS: + class(fates_unit_test_param_reader) :: this + class(fates_parameters_type), intent(inout) :: fates_params + + print *, "read in parameters" + + !call ParametersFromNetCDF(fates_paramfile, is_host_file, fates_params) + + end subroutine read_parameters + + ! -------------------------------------------------------------------------------------- + + subroutine param_read(this) + ! + ! DESCRIPTION: + ! Read in fates parameters + ! + ! ARGUMENTS: + class(fates_unit_test_param_reader), intent(in) :: this + + ! LOCALS: + !class(fates_parameters_type), allocatable :: fates_params + + ! allocate and read in parameters + !allocate(fates_params) + !call fates_params%Init() + !call PRTRegisterParams(fates_params) + + !call this%Read(fates_params) + + end subroutine param_read + +end module FatesUnitTestParamReaderMod \ No newline at end of file From 762681d91284fdb9cbf8f0380aa7c6495462b595 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 15 Apr 2024 09:18:06 -0600 Subject: [PATCH 158/300] trying to get test to work --- functional_unit_testing/allometry/FatesTestAllometry.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index 10be571f67..03ef9ac4d3 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -2,6 +2,7 @@ program FatesTestAllometry !use FatesAllometryMod, only : h2d_allom !use PRTParametersMod, only : prt_params + use funit use FatesUnitTestParamReaderMod, only : fates_unit_test_param_reader implicit none From a5223429f69c7ce2e84791af3a79be4b0e7ca4c2 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 16 Apr 2024 12:25:46 -0600 Subject: [PATCH 159/300] allow read in of parameters --- CMakeLists.txt | 15 + .../allometry/CMakeLists.txt | 18 +- .../allometry/FatesTestAllometry.F90 | 12 +- functional_unit_testing/run_fates_tests.py | 12 + main/CMakeLists.txt | 3 +- main/FatesParametersInterface.F90 | 2 +- unit_test_shr/CMakeLists.txt | 1 + unit_test_shr/FatesUnitTestIOMod.F90 | 942 ++++++++---------- unit_test_shr/FatesUnitTestParamReaderMod.F90 | 173 +++- 9 files changed, 650 insertions(+), 528 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f15615d18..868614bfac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,21 @@ add_dependencies(fates csm_share) # We need to look for header files here, in order to pick up shr_assert.h include_directories(${HLM_ROOT}/share/include) +# This needs to be something we add dynamically +# via some calls using cime +set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2_1") +set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.1") + +FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) +FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) +MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") +MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") + +include_directories(${NETCDF_C_DIR}/include + ${NETCDF_FORTRAN_DIR}/include) +link_directories(${NETCDF_C_DIR}/lib + ${NETCDF_FORTRAN_DIR}/lib) + # Tell cmake to look for libraries & mod files here, because this is where we built libraries include_directories(${CMAKE_CURRENT_BINARY_DIR}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/functional_unit_testing/allometry/CMakeLists.txt b/functional_unit_testing/allometry/CMakeLists.txt index 362a541b61..3e05759809 100644 --- a/functional_unit_testing/allometry/CMakeLists.txt +++ b/functional_unit_testing/allometry/CMakeLists.txt @@ -1,10 +1,26 @@ set(allom_sources FatesTestAllometry.F90) +set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2_1") +set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.1") + +FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) +FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) + +include_directories(${NETCDF_C_DIR}/include + ${NETCDF_FORTRAN_DIR}/include) + +link_directories(${NETCDF_C_DIR}/lib + ${NETCDF_FORTRAN_DIR}/lib + ${PFUNIT_TOP_DIR}/lib) + add_executable(FATES_allom_exe ${allom_sources}) target_link_libraries(FATES_allom_exe + netcdf + netcdff fates - csm_share) + csm_share + funit) add_test(allom_test FATES_allom_exe) diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index 03ef9ac4d3..b9f9446ed2 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -1,17 +1,17 @@ program FatesTestAllometry !use FatesAllometryMod, only : h2d_allom - !use PRTParametersMod, only : prt_params - use funit + use PRTParametersMod, only : prt_params use FatesUnitTestParamReaderMod, only : fates_unit_test_param_reader implicit none ! LOCALS: type(fates_unit_test_param_reader) :: param_reader - - call param_reader%param_read() - - print *, "Hello, allometry" + character(len=*), parameter :: param_file = 'fates_params_default.nc' + + call param_reader%Init(param_file) + call param_reader%RetrieveParameters() + end program FatesTestAllometry \ No newline at end of file diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 3d08002291..6ca39c4fc7 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -22,6 +22,8 @@ name = "fates_unit_tests" make_j = 8 cmake_directory = os.path.abspath("../") + param_file = None + param_cdl_path = "../parameter_files/fates_params_default.cdl" ## Constants test_dir = "fates_allom_test" @@ -33,5 +35,15 @@ build_dir_path = os.path.abspath(build_dir) exe_path = os.path.join(build_dir_path, test_dir, test_exe) + if param_file is None: + file_basename = os.path.basename(param_cdl_path).split(".")[-2] + file_nc_name = f"{file_basename}.nc" + file_gen_command = [ + "ncgen -o", + os.path.join(file_nc_name), + param_cdl_path + ] + run_cmd_no_fail(" ".join(file_gen_command), combine_output=True) + out = run_cmd_no_fail(exe_path, combine_output=True) print(out) \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index a680dbaa4b..064ed5c992 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -26,6 +26,7 @@ list(APPEND fates_sources FatesParameterDerivedMod.F90 FatesSizeAgeTypeIndicesMod.F90 FatesIntegratorsMod.F90 - FatesUtilsMod.F90) + FatesUtilsMod.F90 + FatesSynchronizedParamsMod.F90) sourcelist_to_parent(fates_sources) diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index aa0ef85287..8ea2b8a13e 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -135,7 +135,7 @@ subroutine Destroy(this) integer :: n do n = 1, this%num_parameters - deallocate(this%parameters(n)%data) + if(allocated(this%parameters(n)%data)) deallocate(this%parameters(n)%data) end do end subroutine Destroy diff --git a/unit_test_shr/CMakeLists.txt b/unit_test_shr/CMakeLists.txt index 18d2931194..8cf4eb69c0 100644 --- a/unit_test_shr/CMakeLists.txt +++ b/unit_test_shr/CMakeLists.txt @@ -1,5 +1,6 @@ list(APPEND fates_sources FatesUnitTestParamReaderMod.F90 + FatesUnitTestIOMod.F90 ) sourcelist_to_parent(fates_sources) \ No newline at end of file diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 index 07ae70c765..bbdf72b90c 100644 --- a/unit_test_shr/FatesUnitTestIOMod.F90 +++ b/unit_test_shr/FatesUnitTestIOMod.F90 @@ -1,571 +1,513 @@ module FatesUnitTestIOMod use FatesConstantsMod, only : r8 => fates_r8 + use FatesGlobals, only : fates_endrun use shr_kind_mod, only : SHR_KIND_CL - !use netcdf + use netcdf implicit none + private ! LOCALS - ! integer, parameter :: BASE_UNIT = 10 ! Base unit for files the first time unit_number is called - ! integer, parameter :: MAX_PATH = 256 ! Maximum path length - ! integer, parameter :: MAX_CHAR = 80 ! Maximum length for messages - ! integer :: logf ! Unit number for output log file - ! integer, parameter :: type_double = 1 ! type - ! integer, parameter :: type_int = 2 ! type - - ! interface GetVar - ! module procedure GetVar1DReal - ! module procedure GetVar2DReal - ! module procedure GetVar3DReal - ! module procedure GetVar1DInt - ! module procedure GetVar2DInt - ! module procedure GetVar3DInt - ! end interface + integer, parameter :: type_double = 1 ! type + integer, parameter :: type_int = 2 ! type + + interface GetVar + module procedure GetVarScalarReal + module procedure GetVar1DReal + module procedure GetVar2DReal + module procedure GetVar3DReal + module procedure GetVar1DInt + module procedure GetVar2DInt + module procedure GetVar3DInt + end interface + + public :: OpenNCFile + public :: CloseNCFile + public :: GetDimID + public :: GetDimLen + public :: GetVar contains - character(len=*) function full_file_path(filename) - ! - ! DESCRIPTION: - ! Obtain full path of file - ! First check current working directory - ! Then check full pathname on disk - - ! ARGUMENTS: - character(len=*), intent(in) :: filename - - ! LOCALS: - - ! get local file name - !full_file_path = 'file_path'!get_filename(filename) - - end function full_file_path - - ! integer function UnitNumber() - ! ! - ! ! DESCRIPTION: - ! ! Generates a unit number to be used in opening files - ! ! The first time the function is called, it returns BASE_UNIT - ! ! - ! ! LOCALS: - ! integer :: iunit ! File unit (increments after first call) - ! logical :: first = .true. ! First time this has been called? - ! save - - ! if (first) then - ! ! Set first to false and iunit to base unit on first call - ! iunit = BASE_UNIT - ! first = .false. - ! else - ! ! Otherwise, increment - ! iunit = iunit + 1 - ! endif - - ! ! Set to output - ! UnitNumber = iunit - - ! end function UnitNumber - - ! !===================================================================================== - - ! character(len=9) function FileMode(mode) - ! ! - ! ! DESCRIPTION: - ! ! Gets a file mode - ! ! - - ! ! ARGUMENTS: - ! character(len=*), intent(in), optional :: mode ! Optional mode ('r', 'w', 'rw') - - ! ! Get mode of open (read, write, or read/write) - ! select case(mode) - ! case ('r', 'R') - ! FileMode = 'read' - ! case ('w', 'W') - ! FileMode = 'write' - ! case ('rw', 'RW', 'wr', 'WR') - ! FileMode = 'readwrite' - ! case DEFAULT - ! FileMode = 'readwrite' - ! end select - - ! end function FileMode - - ! !===================================================================================== - - ! logical function CheckFile(filename, fmode) - ! ! - ! ! DESCRIPTION: - ! ! Checks to see if a file exists and checks against the mode - ! ! - - ! ! ARGUMENTS: - ! character(len=*), intent(in) :: filename ! Name of file to open - ! character(len=*), intent(in) :: fmode ! File mode - - ! ! LOCALS: - ! character(len=MAX_PATH) :: fname ! Local filename (trimmed) - ! integer, dimension(MAX_PATH) :: farray ! Array of characters of file name - ! integer :: i ! looping index - ! integer :: ios ! I/O status - ! logical :: file_exists ! Does the file exist? - - ! ! trim filename of whitespace - ! fname = trim(adjustl(filename)) - - ! if (fmode == 'read' .or. fmode == 'readwrite') then - ! ! Check for valid name of file - ! farray = 0 - ! do i = 1, len_trim(fname) - ! farray(i) = ichar(fname(i:i)) - ! enddo - ! if (any(farray > MAX_PATH)) then - ! write(logf,'(A)') "Invalid filename" - ! CheckFile = .false. - ! return - ! endif - ! endif - - ! ! Does the file exist? - ! inquire(file=fname, exist=file_exists) - - ! ! Open file if conditions are correct - ! if (file_exists .and. fmode == 'write') then - ! write(logf,'(A,A,A)') "File ", fname(1:len_trim(fname)), & - ! " exists. Cannot open write only." - ! CheckFile = .false. - ! else if (.not. file_exists .and. fmode == 'read') then - ! write(logf, '(A,A,A)') "File ", fname(1:len_trim(fname)), & - ! " does not exist. Can't read." - ! CheckFile = .false. - ! else - ! CheckFile = .true. - ! endif - - ! end function CheckFile - - ! !===================================================================================== - - ! integer function OpenFile(filename, mode) - ! ! - ! ! DESCRIPTION: - ! ! Opens the file filename if it can, returns a unit number for it. - ! ! The first time the function is called, it returns BASE_UNIT - ! ! - - ! ! ARGUMENTS: - ! character(len = *), intent(in) :: filename ! Name of file to open - ! character(len = *), intent(in), optional :: mode ! Optional mode ('r', 'w', 'rw') - - ! ! LOCALS: - ! character(len=9) :: fmode ! file mode - ! integer :: iunit ! file unit number - ! integer :: ios ! I/O status - ! character(len=MAX_PATH) :: fname ! Local filename (trimmed) - - ! ! get the file mode, defaults to readwrite - ! if (present(mode)) then - ! fmode = FileMode(mode) - ! else - ! fmode = 'readwrite' - ! end if - - ! if (CheckFile(filename, fmode)) then - - ! ! trim filename of whitespace - ! fname = trim(adjustl(filename)) - - ! iunit = UnitNumber() - ! open(iunit, file=fname, action=fmode, iostat=ios) - ! if (ios /= 0) then - ! write(logf,'(A,A,A,I6)') "Problem opening", & - ! fname(1:len_trim(fname)), " ios: ", ios - ! stop - ! endif - ! else - ! stop - ! end if - - ! OpenFile = iunit - - ! end function OpenFile - - ! !===================================================================================== - - ! subroutine Check(status) - ! ! - ! ! DESCRIPTION: - ! ! Checks status of netcdf operations - - ! ! ARGUMENTS: - ! integer, intent(in) :: status ! return status code from a netcdf procedure - - ! if (status /= nf90_noerr) then - ! write(logf,*) trim(nf90_strerror(status)) - ! stop - ! end if + !======================================================================================= - ! end subroutine Check + logical function CheckFile(filename, fmode) + ! + ! DESCRIPTION: + ! Checks to see if a file exists and checks against the mode + ! - ! !===================================================================================== + ! ARGUMENTS: + character(len=*), intent(in) :: filename ! Name of file to open + character(len=*), intent(in) :: fmode ! File mode - ! subroutine OpenNCFile(nc_file, ncid, fmode) - ! ! - ! ! DESCRIPTION: - ! ! Opens a netcdf file + ! LOCALS: + character(len=len(filename)) :: fname ! Local filename (trimmed) + integer :: ios ! I/O status + logical :: file_exists ! Does the file exist? - ! ! ARGUMENTS: - ! character(len=*), intent(in) :: nc_file ! file name - ! integer, intent(out) :: ncid ! netcdf file unit number - ! character(len=*) :: fmode ! file mode - - ! if (CheckFile(nc_file, fmode)) then - ! ! depending on mode - ! select case(fmode) - ! case ('read') - ! call Check(nf90_open(trim(nc_file), NF90_NOCLOBBER, ncid)) - ! case ('write') - ! call Check(nf90_create(trim(nc_file), NF90_CLOBBER, ncid)) - ! case ('readwrite') - ! call Check(nf90_create(trim(nc_file), NF90_CLOBBER, ncid)) - ! case DEFAULT - ! write(logf,*) 'Need to specify read, write, or readwrite' - ! stop - ! end select - ! else - ! write(logf,*) 'Problem reading file' - ! stop - ! end if - - ! end subroutine OpenNCFile - - ! !===================================================================================== - - ! subroutine CloseNCFile(ncid) - ! ! - ! ! DESCRIPTION: - ! ! Closes a netcdf file + ! trim filename of whitespace + fname = trim(adjustl(filename)) + + ! Does the file exist? + inquire(file=fname, exist=file_exists) + + select case (fmode) + case('read') + + if (.not. file_exists) then + write(*,'(a,a,a)') "File ", fname(1:len_trim(fname)), " does not exist. Can't read." + CheckFile = .false. + else + CheckFile = .true. + end if + + case('readwrite') + + if (.not. file_exists) then + write(*,'(a,a,a)') "File ", fname(1:len_trim(fname)), " does not exist. Can't read." + CheckFile = .false. + else + CheckFile = .true. + end if + + case('write') + if (file_exists) then + write(*, '(a, a, a)') "File ", fname(1:len_trim(fname)), " exists. Cannot open write only." + else + CheckFile = .true. + CheckFile = .false. + end if + case default + write(*,'(a)') "Invalid file mode." + CheckFile = .false. + end select + + end function CheckFile + + !======================================================================================= + + subroutine Check(status) + ! + ! DESCRIPTION: + ! Checks status of netcdf operations + + ! ARGUMENTS: + integer, intent(in) :: status ! return status code from a netcdf procedure - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file unit number + if (status /= nf90_noerr) then + write(*,*) trim(nf90_strerror(status)) + stop + end if - ! call Check(nf90_close(ncid)) + end subroutine Check - ! end subroutine CloseNCFile + ! ======================================================================================= - ! !===================================================================================== + subroutine OpenNCFile(nc_file, ncid, fmode) + ! + ! DESCRIPTION: + ! Opens a netcdf file - ! subroutine GetDims(ncid, varID, dim_lens) - ! ! - ! ! DESCRIPTION: - ! ! Get dimensions for a netcdf variable - ! ! - - ! ! ARGUMENTS - ! integer, intent(in) :: ncid ! netcdf file unit ID - ! integer, intent(in) :: varID ! variable ID - ! integer, allocatable, intent(out) :: dim_lens(:) ! dimension lengths - - ! ! LOCALS: - ! integer :: numDims ! number of dimensions - ! integer, allocatable :: dimIDs(:) ! dimension IDs - ! integer :: i ! looping index + ! ARGUMENTS: + character(len=*), intent(in) :: nc_file ! file name + integer, intent(out) :: ncid ! netcdf file unit number + character(len=*) :: fmode ! file mode + + if (CheckFile(nc_file, fmode)) then + ! depending on mode + select case(fmode) + case ('read') + call Check(nf90_open(trim(nc_file), NF90_NOCLOBBER, ncid)) + case ('write') + call Check(nf90_create(trim(nc_file), NF90_CLOBBER, ncid)) + case ('readwrite') + call Check(nf90_create(trim(nc_file), NF90_CLOBBER, ncid)) + case DEFAULT + write(*,*) 'Need to specify read, write, or readwrite' + stop + end select + else + write(*,*) 'Problem reading file' + stop + end if + + end subroutine OpenNCFile + + !======================================================================================= + + subroutine CloseNCFile(ncid) + ! + ! DESCRIPTION: + ! Closes a netcdf file - ! ! find dimensions of data - ! call Check(nf90_inquire_variable(ncid, varID, ndims=numDims)) + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit number - ! ! allocate data to grab dimension information - ! allocate(dim_lens(numDims)) - ! allocate(dimIDs(numDims)) + call Check(nf90_close(ncid)) - ! ! get dimIDs - ! call Check(nf90_inquire_variable(ncid, varID, dimids=dimIDs)) + end subroutine CloseNCFile - ! ! grab these dimensions - ! do i = 1, numDims - ! call Check(nf90_inquire_dimension(ncid, dimIDs(i), len=dim_lens(i))) - ! end do + !======================================================================================= - ! end subroutine GetDims + subroutine GetDimID(ncid, var_name, dim_id) + integer, intent(in) :: ncid + character(len=*), intent(in) :: var_name + integer, intent(out) :: dim_id - ! !===================================================================================== + call Check(nf90_inq_dimid(ncid, var_name, dim_id)) - ! subroutine GetVar1DReal(ncid, var_name, data) - ! ! - ! ! DESCRIPTION: - ! ! Read in variables for 1D real data - ! ! + end subroutine GetDimID - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file unit ID - ! character(len=*), intent(in) :: var_name ! variable name - ! real(r8), allocatable, intent(out) :: data(:) ! data values + !======================================================================================= - ! ! LOCALS: - ! integer :: varID ! variable ID - ! integer, allocatable :: dim_lens(:) ! dimension lengths + subroutine GetDimLen(ncid, dim_id, dim_len) + integer, intent(in) :: ncid + integer, intent(in) :: dim_id + integer, intent(out) :: dim_len - ! ! find variable ID first - ! call Check(nf90_inq_varid(ncid, var_name, varID)) + call Check(nf90_inquire_dimension(ncid, dim_id, len=dim_len)) - ! ! get dimensions of data - ! call GetDims(ncid, varID, dim_lens) + end subroutine GetDimLen - ! ! read data - ! allocate(data(dim_lens(1))) - ! call Check(nf90_get_var(ncid, varID, data)) + !======================================================================================= - ! end subroutine GetVar1DReal + subroutine GetDims(ncid, varID, dim_lens) + ! + ! DESCRIPTION: + ! Get dimensions for a netcdf variable + ! - ! !===================================================================================== + ! ARGUMENTS + integer, intent(in) :: ncid ! netcdf file unit ID + integer, intent(in) :: varID ! variable ID + integer, allocatable, intent(out) :: dim_lens(:) ! dimension lengths - ! subroutine GetVar1DInt(ncid, var_name, data) - ! ! - ! ! DESCRIPTION: - ! ! Read in variables for 1D integer data - ! ! + ! LOCALS: + integer :: numDims ! number of dimensions + integer, allocatable :: dimIDs(:) ! dimension IDs + integer :: i ! looping index - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file unit ID - ! character(len=*), intent(in) :: var_name ! variable name - ! integer, allocatable, intent(out) :: data(:) ! data values + ! find dimensions of data + call Check(nf90_inquire_variable(ncid, varID, ndims=numDims)) - ! ! LOCALS: - ! integer :: varID ! variable ID - ! integer, allocatable :: dim_lens(:) ! dimension lengths + ! allocate data to grab dimension information + allocate(dim_lens(numDims)) + allocate(dimIDs(numDims)) - ! ! find variable ID first - ! call Check(nf90_inq_varid(ncid, var_name, varID)) + ! get dimIDs + call Check(nf90_inquire_variable(ncid, varID, dimids=dimIDs)) - ! ! get dimensions of data - ! call GetDims(ncid, varID, dim_lens) + ! grab these dimensions + do i = 1, numDims + call Check(nf90_inquire_dimension(ncid, dimIDs(i), len=dim_lens(i))) + end do - ! ! read data - ! allocate(data(dim_lens(1))) - ! call Check(nf90_get_var(ncid, varID, data)) - - ! end subroutine GetVar1DInt + end subroutine GetDims - ! !===================================================================================== + !===================================================================================== - ! subroutine GetVar2DReal(ncid, var_name, data) - ! ! - ! ! DESCRIPTION: - ! ! Read in variables for 2D real data - ! ! + subroutine GetVarScalarReal(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for scalar real data + ! - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file unit ID - ! character(len=*), intent(in) :: var_name ! variable name - ! real(r8), allocatable, intent(out) :: data(:,:) ! data values + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + real(r8), intent(out) :: data ! data value - ! ! LOCALS: - ! integer :: varID ! variable ID - ! integer, allocatable :: dim_lens(:) ! dimension lengths + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths - ! ! find variable ID first - ! call Check(nf90_inq_varid(ncid, var_name, varID)) + ! find variable ID first + call Check(nf90_inq_varid(ncid, var_name, varID)) - ! ! get dimensions of data - ! call GetDims(ncid, varID, dim_lens) + ! read data + call Check(nf90_get_var(ncid, varID, data)) - ! ! read data - ! allocate(data(dim_lens(1), dim_lens(2))) - ! call Check(nf90_get_var(ncid, varID, data)) - - ! end subroutine GetVar2DReal + end subroutine GetVarScalarReal - ! !===================================================================================== + !===================================================================================== - ! subroutine GetVar2DInt(ncid, var_name, data) - ! ! - ! ! DESCRIPTION: - ! ! Read in variables for 2D integer data - ! ! + subroutine GetVar1DReal(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 1D real data + ! - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file unit ID - ! character(len=*), intent(in) :: var_name ! variable name - ! integer, allocatable, intent(out) :: data(:,:) ! data values + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + real(r8), allocatable, intent(out) :: data(:) ! data values - ! ! LOCALS: - ! integer :: varID ! variable ID - ! integer, allocatable :: dim_lens(:) ! dimension lengths + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths - ! ! find variable ID first - ! call Check(nf90_inq_varid(ncid, var_name, varID)) + ! find variable ID first + call Check(nf90_inq_varid(ncid, var_name, varID)) - ! ! get dimensions of data - ! call GetDims(ncid, varID, dim_lens) + ! get dimensions of data + call GetDims(ncid, varID, dim_lens) - ! ! read data - ! allocate(data(dim_lens(1), dim_lens(2))) - ! call Check(nf90_get_var(ncid, varID, data)) - - ! end subroutine GetVar2DInt + ! read data + allocate(data(dim_lens(1))) + call Check(nf90_get_var(ncid, varID, data)) - ! !===================================================================================== + end subroutine GetVar1DReal - ! subroutine GetVar3DReal(ncid, var_name, data) - ! ! - ! ! DESCRIPTION: - ! ! Read in variables for 3D real data - ! ! + !===================================================================================== - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file unit ID - ! character(len=*), intent(in) :: var_name ! variable name - ! real(r8), allocatable, intent(out) :: data(:,:,:) ! data values + subroutine GetVar1DInt(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 1D integer data + ! - ! ! LOCALS: - ! integer :: varID ! variable ID - ! integer, allocatable :: dim_lens(:) ! dimension lengths + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + integer, allocatable, intent(out) :: data(:) ! data values - ! ! find variable ID first - ! call Check(nf90_inq_varid(ncid, var_name, varID)) + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths - ! ! get dimensions of data - ! call GetDims(ncid, varID, dim_lens) + ! find variable ID first + call Check(nf90_inq_varid(ncid, var_name, varID)) - ! ! read data - ! allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) - ! call Check(nf90_get_var(ncid, varID, data)) - - ! end subroutine GetVar3DReal + ! get dimensions of data + call GetDims(ncid, varID, dim_lens) + + ! read data + allocate(data(dim_lens(1))) + call Check(nf90_get_var(ncid, varID, data)) + + end subroutine GetVar1DInt + + !===================================================================================== + + subroutine GetVar2DReal(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 2D real data + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + real(r8), allocatable, intent(out) :: data(:,:) ! data values + + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths + + ! find variable ID first + call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! get dimensions of data + call GetDims(ncid, varID, dim_lens) + + ! read data + allocate(data(dim_lens(1), dim_lens(2))) + call Check(nf90_get_var(ncid, varID, data)) + + end subroutine GetVar2DReal + + !===================================================================================== + + subroutine GetVar2DInt(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 2D integer data + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + integer, allocatable, intent(out) :: data(:,:) ! data values + + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths + + ! find variable ID first + call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! get dimensions of data + call GetDims(ncid, varID, dim_lens) - ! !===================================================================================== + ! read data + allocate(data(dim_lens(1), dim_lens(2))) + call Check(nf90_get_var(ncid, varID, data)) - ! subroutine GetVar3DInt(ncid, var_name, data) - ! ! - ! ! DESCRIPTION: - ! ! Read in variables for 3D integer data - ! ! + end subroutine GetVar2DInt - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file unit ID - ! character(len=*), intent(in) :: var_name ! variable name - ! integer, allocatable, intent(out) :: data(:,:,:) ! data values + !===================================================================================== - ! ! LOCALS: - ! integer :: varID ! variable ID - ! integer, allocatable :: dim_lens(:) ! dimension lengths + subroutine GetVar3DReal(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 3D real data + ! - ! ! find variable ID first - ! call Check(nf90_inq_varid(ncid, var_name, varID)) + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + real(r8), allocatable, intent(out) :: data(:,:,:) ! data values - ! ! get dimensions of data - ! call GetDims(ncid, varID, dim_lens) + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths - ! ! read data - ! allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) - ! call Check(nf90_get_var(ncid, varID, data)) + ! find variable ID first + call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! get dimensions of data + call GetDims(ncid, varID, dim_lens) + + ! read data + allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) + call Check(nf90_get_var(ncid, varID, data)) + + end subroutine GetVar3DReal + + !===================================================================================== + + subroutine GetVar3DInt(ncid, var_name, data) + ! + ! DESCRIPTION: + ! Read in variables for 3D integer data + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit ID + character(len=*), intent(in) :: var_name ! variable name + integer, allocatable, intent(out) :: data(:,:,:) ! data values + + ! LOCALS: + integer :: varID ! variable ID + integer, allocatable :: dim_lens(:) ! dimension lengths + + ! find variable ID first + call Check(nf90_inq_varid(ncid, var_name, varID)) + + ! get dimensions of data + call GetDims(ncid, varID, dim_lens) + + ! read data + allocate(data(dim_lens(1), dim_lens(2), dim_lens(3))) + call Check(nf90_get_var(ncid, varID, data)) + + end subroutine GetVar3DInt + + !===================================================================================== + + subroutine RegisterNCDims(ncid, dim_names, dim_lens, num_dims, dim_IDs) + ! + ! DESCRIPTION: + ! Defines variables and dimensions + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file id + character(len=*), intent(in) :: dim_names(num_dims) ! dimension names + integer, intent(in) :: dim_lens(num_dims) ! dimension lengths + integer, intent(in) :: num_dims ! number of dimensions + integer, intent(out) :: dim_IDs(num_dims) ! dimension IDs + + ! LOCALS: + integer :: i ! looping index + + do i = 1, num_dims + call Check(nf90_def_dim(ncid, dim_names(i), dim_lens(i), dim_IDs(i))) + end do + + end subroutine RegisterNCDims + + !===================================================================================== + + subroutine RegisterVar1D(ncid, var_name, dimID, type, att_names, atts, num_atts, varID) + ! + ! DESCRIPTION: + ! Defines variables and dimensions + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file id + character(len=*), intent(in) :: var_name ! variable name + integer, intent(in) :: dimID(1) ! dimension ID + integer, intent(in) :: type ! type: int or double + character(len=*), intent(in) :: att_names(num_atts) ! attribute names + character(len=*), intent(in) :: atts(num_atts) ! attribute values + integer, intent(in) :: num_atts ! number of attributes + integer, intent(out) :: varID ! variable ID + + + ! LOCALS: + integer :: i ! looping index + integer :: nc_type ! netcdf type + + if (type == type_double) then + nc_type = NF90_DOUBLE + else if (type == type_int) then + nc_type = NF90_INT + else + write(*, *) "Must pick correct type" + stop + end if + + call Check(nf90_def_var(ncid, var_name, nc_type, dimID, varID)) + + do i = 1, num_atts + call Check(nf90_put_att(ncid, varID, att_names(i), atts(i))) + end do - ! end subroutine GetVar3DInt - - ! !===================================================================================== - - ! subroutine RegisterNCDims(ncid, dim_names, dim_lens, num_dims, dim_IDs) - ! ! - ! ! DESCRIPTION: - ! ! Defines variables and dimensions - ! ! - - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file id - ! character(len=*), intent(in) :: dim_names(num_dims) ! dimension names - ! integer, intent(in) :: dim_lens(num_dims) ! dimension lengths - ! integer, intent(in) :: num_dims ! number of dimensions - ! integer, intent(out) :: dim_IDs(num_dims) ! dimension IDs - - ! ! LOCALS: - ! integer :: i ! looping index - - ! do i = 1, num_dims - ! call Check(nf90_def_dim(ncid, dim_names(i), dim_lens(i), dim_IDs(i))) - ! end do - - ! end subroutine RegisterNCDims - - ! !===================================================================================== - - ! subroutine RegisterVar1D(ncid, var_name, dimID, type, att_names, atts, num_atts, varID) - ! ! - ! ! DESCRIPTION: - ! ! Defines variables and dimensions - ! ! - - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file id - ! character(len=*), intent(in) :: var_name ! variable name - ! integer, intent(in) :: dimID(1) ! dimension ID - ! integer, intent(in) :: type ! type: int or double - ! character(len=*), intent(in) :: att_names(num_atts) ! attribute names - ! character(len=*), intent(in) :: atts(num_atts) ! attribute values - ! integer, intent(in) :: num_atts ! number of attributes - ! integer, intent(out) :: varID ! variable ID - - - ! ! LOCALS: - ! integer :: i ! looping index - ! integer :: nc_type ! netcdf type - - ! if (type == type_double) then - ! nc_type = NF90_DOUBLE - ! else if (type == type_int) then - ! nc_type = NF90_INT - ! else - ! write(logf, *) "Must pick correct type" - ! stop - ! end if - - ! call Check(nf90_def_var(ncid, var_name, nc_type, dimID, varID)) - - ! do i = 1, num_atts - ! call Check(nf90_put_att(ncid, varID, att_names(i), atts(i))) - ! end do - - ! end subroutine RegisterVar1D - - ! !===================================================================================== - - ! subroutine RegisterVar2D(ncid, var_name, dimID, type, att_names, atts, num_atts, varID) - ! ! - ! ! DESCRIPTION: - ! ! Defines variables and dimensions - ! ! - - ! ! ARGUMENTS: - ! integer, intent(in) :: ncid ! netcdf file id - ! character(len=*), intent(in) :: var_name ! variable name - ! integer, intent(in) :: dimID(1:2) ! dimension ID - ! integer, intent(in) :: type ! type: int or double - ! character(len=*), intent(in) :: att_names(num_atts) ! attribute names - ! character(len=*), intent(in) :: atts(num_atts) ! attribute values - ! integer, intent(in) :: num_atts ! number of attributes - ! integer, intent(out) :: varID ! variable ID - - - ! ! LOCALS: - ! integer :: i ! looping index - ! integer :: nc_type ! netcdf type - - ! if (type == type_double) then - ! nc_type = NF90_DOUBLE - ! else if (type == type_int) then - ! nc_type = NF90_INT - ! else - ! write(logf, *) "Must pick correct type" - ! stop - ! end if - - ! call Check(nf90_def_var(ncid, var_name, nc_type, dimID, varID)) - - ! do i = 1, num_atts - ! call Check(nf90_put_att(ncid, varID, att_names(i), atts(i))) - ! end do - - ! end subroutine RegisterVar2D + end subroutine RegisterVar1D + + !===================================================================================== + + subroutine RegisterVar2D(ncid, var_name, dimID, type, att_names, atts, num_atts, varID) + ! + ! DESCRIPTION: + ! Defines variables and dimensions + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file id + character(len=*), intent(in) :: var_name ! variable name + integer, intent(in) :: dimID(1:2) ! dimension ID + integer, intent(in) :: type ! type: int or double + character(len=*), intent(in) :: att_names(num_atts) ! attribute names + character(len=*), intent(in) :: atts(num_atts) ! attribute values + integer, intent(in) :: num_atts ! number of attributes + integer, intent(out) :: varID ! variable ID + + + ! LOCALS: + integer :: i ! looping index + integer :: nc_type ! netcdf type + + if (type == type_double) then + nc_type = NF90_DOUBLE + else if (type == type_int) then + nc_type = NF90_INT + else + write(*, *) "Must pick correct type" + stop + end if + + call Check(nf90_def_var(ncid, var_name, nc_type, dimID, varID)) + + do i = 1, num_atts + call Check(nf90_put_att(ncid, varID, att_names(i), atts(i))) + end do + + end subroutine RegisterVar2D - !===================================================================================== +! ===================================================================================== end module FatesUnitTestIOMod \ No newline at end of file diff --git a/unit_test_shr/FatesUnitTestParamReaderMod.F90 b/unit_test_shr/FatesUnitTestParamReaderMod.F90 index 6cefe91df5..f36f2fd58e 100644 --- a/unit_test_shr/FatesUnitTestParamReaderMod.F90 +++ b/unit_test_shr/FatesUnitTestParamReaderMod.F90 @@ -1,8 +1,17 @@ module FatesUnitTestParamReaderMod - use FatesParametersInterface, only : fates_param_reader_type - use FatesParametersInterface, only : fates_parameters_type - use PRTInitParamsFatesMod, only : PRTRegisterParams + use FatesConstantsMod, only : r8 => fates_r8 + use FatesParametersInterface, only : fates_param_reader_type + use FatesParametersInterface, only : fates_parameters_type + use FatesParametersInterface, only : param_string_length + use FatesParametersInterface, only : max_dimensions, max_used_dimensions + use FatesParametersInterface, only : dimension_shape_scalar, dimension_shape_1d, dimension_shape_2d + use EDParamsMod, only : FatesRegisterParams, FatesReceiveParams + use SFParamsMod, only : SpitFireRegisterParams, SpitFireReceiveParams + use PRTInitParamsFatesMod, only : PRTRegisterParams, PRTReceiveParams + use FatesSynchronizedParamsMod, only : FatesSynchronizedParamsInst + use EDPftvarcon, only : EDPftvarcon_inst + use FatesUnitTestIOMod, only : OpenNCFile, GetDimID, GetDimLen, GetVar, CloseNCFile implicit none private @@ -12,14 +21,30 @@ module FatesUnitTestParamReaderMod character(:), allocatable :: filename ! local file name of parameter contains - procedure, public :: Read => read_parameters - procedure, public :: param_read + procedure, public :: Read => ReadParameters + procedure, public :: Init + procedure, public :: RetrieveParameters end type fates_unit_test_param_reader - contains + contains - subroutine read_parameters(this, fates_params) + subroutine Init(this, param_file) + ! + ! DESCRIPTION: + ! Initialize the parameter reader class + ! + ! ARGUMENTS: + class(fates_unit_test_param_reader) :: this + character(len=*) :: param_file + + this%filename = trim(param_file) + + end subroutine Init + + ! -------------------------------------------------------------------------------------- + + subroutine ReadParameters(this, fates_params) ! ! DESCRIPTION: ! Read 'fates_params' parameters from storage @@ -28,15 +53,54 @@ subroutine read_parameters(this, fates_params) class(fates_unit_test_param_reader) :: this class(fates_parameters_type), intent(inout) :: fates_params - print *, "read in parameters" - - !call ParametersFromNetCDF(fates_paramfile, is_host_file, fates_params) - - end subroutine read_parameters + ! LOCALS: + real(r8), allocatable :: data2d(:, :) + real(r8), allocatable :: data1d(:) + real(r8) :: data_scalar + integer :: ncid + integer :: num_params + integer :: dimension_shape + integer :: i + integer :: max_dim_size + character(len=param_string_length) :: name + integer :: dimension_sizes(max_dimensions) + character(len=param_string_length) :: dimension_names(max_dimensions) + logical :: is_host_param + + call OpenNCFile(this%filename, ncid, 'read') + call SetParameterDimensions(ncid, fates_params) + + num_params = fates_params%num_params() + do i = 1, num_params + call fates_params%GetMetaData(i, name, dimension_shape, dimension_sizes, & + dimension_names, is_host_param) + select case(dimension_shape) + case(dimension_shape_scalar) + call GetVar(ncid, name, data_scalar) + call fates_params%SetData(i, data_scalar) + case(dimension_shape_1d) + call GetVar(ncid, name, data1d) + call fates_params%SetData(i, data1d) + case(dimension_shape_2d) + call GetVar(ncid, name, data2d) + call fates_params%SetData(i, data2d) + case default + write(*, '(a,a)') 'dimension shape:', dimension_shape + write(*, '(a)') 'unsupported number of dimensions reading parameters.' + stop + end select + end do + + if (allocated(data1d)) deallocate(data1d) + if (allocated(data2d)) deallocate(data2d) + + call CloseNCFile(ncid) + + end subroutine ReadParameters ! -------------------------------------------------------------------------------------- - subroutine param_read(this) + subroutine RetrieveParameters(this) ! ! DESCRIPTION: ! Read in fates parameters @@ -45,15 +109,86 @@ subroutine param_read(this) class(fates_unit_test_param_reader), intent(in) :: this ! LOCALS: - !class(fates_parameters_type), allocatable :: fates_params + class(fates_parameters_type), allocatable :: fates_params + class(fates_parameters_type), allocatable :: fates_pft_params ! allocate and read in parameters - !allocate(fates_params) - !call fates_params%Init() - !call PRTRegisterParams(fates_params) + allocate(fates_params) + allocate(fates_pft_params) + call fates_params%Init() + call fates_pft_params%Init() + + call EDPftvarcon_inst%Init() + + call PRTRegisterParams(fates_params) + call FatesRegisterParams(fates_params) + call SpitFireRegisterParams(fates_params) + call FatesSynchronizedParamsInst%RegisterParams(fates_params) + call EDPftvarcon_inst%Register(fates_pft_params) + + call this%Read(fates_params) - !call this%Read(fates_params) + call FatesReceiveParams(fates_params) + call SpitFireReceiveParams(fates_params) + call PRTReceiveParams(fates_params) + call FatesSynchronizedParamsInst%ReceiveParams(fates_params) + + call fates_params%Destroy() + call fates_pft_params%Destroy() + deallocate(fates_params) + deallocate(fates_pft_params) + + end subroutine RetrieveParameters + + ! -------------------------------------------------------------------------------------- - end subroutine param_read + subroutine SetParameterDimensions(ncid, fates_params) + ! + ! DESCRIPTION: + ! Read in fates parameters + ! + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file ID + class(fates_parameters_type), intent(inout) :: fates_params ! fates parameters class + + ! LOCALS: + integer :: num_used_dimensions + character(len=param_string_length) :: used_dimension_names(max_used_dimensions) + integer :: used_dimension_sizes(max_used_dimensions) + + call fates_params%GetUsedDimensions(.false., num_used_dimensions, used_dimension_names) + + call GetUsedDimensionSizes(ncid, num_used_dimensions, used_dimension_names, & + used_dimension_sizes) + + call fates_params%SetDimensionSizes(.false., num_used_dimensions, & + used_dimension_names, used_dimension_sizes) + + end subroutine SetParameterDimensions + + ! -------------------------------------------------------------------------------------- + + subroutine GetUsedDimensionSizes(ncid, num_used_dimensions, dimension_names, dimension_sizes) + ! + ! DESCRIPTION: + ! Get dimension sizes for parameters + ! + ! ARGUMENTS: + integer, intent(in) :: ncid + integer, intent(in) :: num_used_dimensions + character(len=param_string_length), intent(in) :: dimension_names(:) + integer, intent(out) :: dimension_sizes(:) + + ! LOCALS + integer :: d + integer :: dim_id + + dimension_sizes(:) = 0 + do d = 1, num_used_dimensions + call GetDimID(ncid, dimension_names(d), dim_id) + call GetDimLen(ncid, dim_id, dimension_sizes(d)) + end do + + end subroutine GetUsedDimensionSizes end module FatesUnitTestParamReaderMod \ No newline at end of file From dfb4260c4854307234edbcb9eb6b2d52e52a1ea9 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 16 Apr 2024 12:37:07 -0600 Subject: [PATCH 160/300] start adding allometry calculations --- .../allometry/FatesTestAllometry.F90 | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index b9f9446ed2..23ce863cc1 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -1,6 +1,7 @@ program FatesTestAllometry - !use FatesAllometryMod, only : h2d_allom + use FatesConstantsMod, only : r8 => fates_r8 + use FatesAllometryMod, only : h_allom use PRTParametersMod, only : prt_params use FatesUnitTestParamReaderMod, only : fates_unit_test_param_reader @@ -9,9 +10,22 @@ program FatesTestAllometry ! LOCALS: type(fates_unit_test_param_reader) :: param_reader character(len=*), parameter :: param_file = 'fates_params_default.nc' + integer :: numpft + integer :: i + real(r8) :: height + + ! CONSTANTS: + real(r8) :: min_dbh = 0.5_r8 ! minimum DBH to calculate [cm] + real(r8) :: max_dbh = 200.0_r8 ! maximum DBH to calculate [cm] + ! read in parameter file call param_reader%Init(param_file) call param_reader%RetrieveParameters() - + numpft = size(prt_params%wood_density, dim=1) - 1 + do i = 1, numpft + call h_allom(25.0_r8, i, height) + print *, height + end do + end program FatesTestAllometry \ No newline at end of file From fc3e66c22d6637b5f56a09d7dfea08825c7acc63 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 16 Apr 2024 15:30:12 -0600 Subject: [PATCH 161/300] get plotting to work --- .../allometry/FatesTestAllometry.F90 | 123 +++++++++++++++++- functional_unit_testing/run_fates_tests.py | 122 ++++++++++++++--- 2 files changed, 221 insertions(+), 24 deletions(-) diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index 23ce863cc1..b83e83a1c4 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -10,22 +10,133 @@ program FatesTestAllometry ! LOCALS: type(fates_unit_test_param_reader) :: param_reader character(len=*), parameter :: param_file = 'fates_params_default.nc' + character(len=*), parameter :: out_file = 'allometry_out.nc' integer :: numpft - integer :: i - real(r8) :: height + integer :: i, j + integer :: numdbh + real(r8), allocatable :: dbh(:) ! diameter at breast height [cm] + real(r8), allocatable :: height(:, :) ! height [m] ! CONSTANTS: real(r8) :: min_dbh = 0.5_r8 ! minimum DBH to calculate [cm] real(r8) :: max_dbh = 200.0_r8 ! maximum DBH to calculate [cm] + real(r8) :: dbh_inc = 0.5_r8 ! DBH increment to use [cm] + + interface + + subroutine WriteAllometryData(out_file, ndbh, numpft, dbh, height) + + use FatesUnitTestIOMod, only : OpenNCFile, RegisterNCDims, CloseNCFile + use FatesUnitTestIOMod, only : RegisterVar1D, WriteVar, RegisterVar2D + use FatesUnitTestIOMod, only : type_double, type_int + use FatesConstantsMod, only : r8 => fates_r8 + implicit none + + character(len=*), intent(in) :: out_file + integer, intent(in) :: ndbh, numpft + real(r8), intent(in) :: dbh(:) + real(r8), intent(in) :: height(:,:) + + end subroutine WriteAllometryData + + end interface ! read in parameter file call param_reader%Init(param_file) call param_reader%RetrieveParameters() - numpft = size(prt_params%wood_density, dim=1) - 1 + numpft = size(prt_params%wood_density, dim=1) + + ! allocate arrays and initialize DBH array + numdbh = int((max_dbh - min_dbh)/dbh_inc + 1) + + allocate(dbh(numdbh)) + allocate(height(numdbh, numpft)) + + do i = 1, numdbh + dbh(i) = min_dbh + dbh_inc*(i-1) + end do + ! calculate allometries do i = 1, numpft - call h_allom(25.0_r8, i, height) - print *, height + do j = 1, numdbh + call h_allom(dbh(j), i, height(j, i)) + end do end do + + call WriteAllometryData(out_file, numdbh, numpft, dbh, height) -end program FatesTestAllometry \ No newline at end of file +end program FatesTestAllometry + +! ---------------------------------------------------------------------------------------- + +subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height) + ! + ! DESCRIPTION: + ! Writes out data from the allometry test + ! + use FatesConstantsMod, only : r8 => fates_r8 + use FatesUnitTestIOMod, only : OpenNCFile, RegisterNCDims, CloseNCFile + use FatesUnitTestIOMod, only : RegisterVar1D, WriteVar, RegisterVar2D + use FatesUnitTestIOMod, only : EndNCDef + use FatesUnitTestIOMod, only : type_double, type_int + + implicit none + + ! ARGUMENTS: + character(len=*), intent(in) :: out_file + integer, intent(in) :: numdbh, numpft + real(r8), intent(in) :: dbh(:) + real(r8), intent(in) :: height(:,:) + + ! LOCALS: + integer, allocatable :: pft_indices(:) ! array of pft indices to write out + integer :: i ! looping index + integer :: ncid ! netcdf file id + character(len=8) :: dim_names(2) ! dimension names + integer :: dimIDs(2) ! dimension IDs + integer :: dbhID, pftID ! variable IDs for dimensions + integer :: heightID + + ! create pft indices + allocate(pft_indices(numpft)) + do i = 1, numpft + pft_indices(i) = i + end do + + ! dimension names + dim_names = [character(len=12) :: 'dbh', 'pft'] + + ! open file + call OpenNCFile(trim(out_file), ncid, 'readwrite') + + ! register dimensions + call RegisterNCDims(ncid, dim_names, (/numdbh, numpft/), 2, dimIDs) + + ! register dbh + call RegisterVar1D(ncid, dim_names(1), dimIDs(1), type_double, & + [character(len=20) :: 'units', 'long_name'], & + [character(len=150) :: 'cm', 'diameter at breast height'], 2, dbhID) + + ! register pft + call RegisterVar1D(ncid, dim_names(2), dimIDs(2), type_int, & + [character(len=20) :: 'units', 'long_name'], & + [character(len=150) :: '', 'plant functional type'], 2, pftID) + + ! register height + call RegisterVar2D(ncid, 'height', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'm', 'plant height'], & + 3, heightID) + + ! finish defining variables + call EndNCDef(ncid) + + ! write out data + call WriteVar(ncid, dbhID, dbh(:)) + call WriteVar(ncid, pftID, pft_indices(:)) + call WriteVar(ncid, heightID, height(:,:)) + + ! close the file + call CloseNCFile(ncid) + +end subroutine WriteAllometryData \ No newline at end of file diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 6ca39c4fc7..1e513dcd87 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -1,23 +1,97 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python import os import sys from build_fortran_tests import build_unit_tests -_FATES_PYTHON = os.path.join(os.path.dirname(os.path.abspath(__file__))) -sys.path.insert(1, _FATES_PYTHON) +import math +import pandas as pd +import numpy as np +import xarray as xr +import matplotlib +import matplotlib.pyplot as plt from utils import add_cime_lib_to_path add_cime_lib_to_path() from CIME.utils import run_cmd_no_fail +def round_up(n, decimals=0): + multiplier = 10**decimals + return math.ceil(n * multiplier) / multiplier + +def truncate(n, decimals=0): + multiplier = 10**decimals + return int(n * multiplier) / multiplier + +def get_color_pallete(): + + colors = [(31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120), + (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150), + (148, 103, 189), (197, 176, 213), (140, 86, 75), (196, 156, 148), + (227, 119, 194), (247, 182, 210), (127, 127, 127), (199, 199, 199), + (188, 189, 34), (219, 219, 141), (23, 190, 207), (158, 218, 229)] + + for i in range(len(colors)): + r, g, b = colors[i] + colors[i] = (r/255., g/255., b/255.) + + return colors + + +def plot_allometry_var(data, var, varname, units): + df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), + 'pft': np.repeat(data.pft, len(data.dbh)), + var: data.values.flatten()}) + + maxdbh = df['dbh'].max() + maxvar = round_up(df[var].max()) + + colors = get_color_pallete() + + plt.figure(figsize=(7, 5)) + ax = plt.subplot(111) + ax.spines["top"].set_visible(False) + ax.spines["bottom"].set_visible(False) + ax.spines["right"].set_visible(False) + ax.spines["left"].set_visible(False) + + ax.get_xaxis().tick_bottom() + ax.get_yaxis().tick_left() + + plt.xlim(0.0, maxdbh) + plt.ylim(0.0, maxvar) + + plt.yticks(fontsize=10) + plt.xticks(fontsize=10) + + for y in range(0, int(maxvar), 5): + plt.plot(range(math.floor(0), math.ceil(maxdbh)), + [y] * len(range(math.floor(0), math.ceil(maxdbh))), + "--", lw=0.5, color="black", alpha=0.3) + + plt.tick_params(bottom=False, top=False, left=False, right=False) + + pfts = np.unique(df.pft.values) + for rank, pft in enumerate(pfts): + data = df[df.pft == pft] + plt.plot(data.dbh.values, data[var].values, lw=2, color=colors[rank], + label=pft) + + plt.xlabel('DBH (cm)', fontsize=11) + plt.ylabel(f'{varname} ({units})', fontsize=11) + plt.title(f"Simulated {varname} for input parameter file", fontsize=11) + plt.legend(loc='upper left', title='PFT') + + plt.show() + if __name__ == "__main__": ## Arguments clean = True - build = True + build = False + run = False build_dir = "../_build" name = "fates_unit_tests" make_j = 8 @@ -26,24 +100,36 @@ param_cdl_path = "../parameter_files/fates_params_default.cdl" ## Constants + out_file = "allometry_out.nc" test_dir = "fates_allom_test" test_exe = "FATES_allom_exe" + build_dir_path = os.path.abspath(build_dir) + + ## Actual Program if build: build_unit_tests(build_dir, name, cmake_directory, make_j, clean=clean) - build_dir_path = os.path.abspath(build_dir) - exe_path = os.path.join(build_dir_path, test_dir, test_exe) - - if param_file is None: - file_basename = os.path.basename(param_cdl_path).split(".")[-2] - file_nc_name = f"{file_basename}.nc" - file_gen_command = [ - "ncgen -o", - os.path.join(file_nc_name), - param_cdl_path - ] - run_cmd_no_fail(" ".join(file_gen_command), combine_output=True) + if run: + exe_path = os.path.join(build_dir_path, test_dir, test_exe) + + if param_file is None: + file_basename = os.path.basename(param_cdl_path).split(".")[-2] + file_nc_name = f"{file_basename}.nc" + file_gen_command = [ + "ncgen -o", + os.path.join(file_nc_name), + param_cdl_path + ] + run_cmd_no_fail(" ".join(file_gen_command), combine_output=True) - out = run_cmd_no_fail(exe_path, combine_output=True) - print(out) \ No newline at end of file + out = run_cmd_no_fail(exe_path, combine_output=True) + print(out) + + # read in allometry data + allometry_dat = xr.open_dataset(os.path.join(build_dir_path, out_file)) + + # plot allometry data + plot_allometry_var(allometry_dat.height, 'height', 'height', 'm') + + \ No newline at end of file From 4ecaeedefbd6182f29ad7ff0eb0a53d96523b0dd Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 16 Apr 2024 16:01:41 -0600 Subject: [PATCH 162/300] add parameter file as argument to program --- .../allometry/FatesTestAllometry.F90 | 10 +- functional_unit_testing/run_fates_tests.py | 98 +++++++++++-------- functional_unit_testing/utils.py | 11 ++- 3 files changed, 75 insertions(+), 44 deletions(-) diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index b83e83a1c4..471b8711e9 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -9,11 +9,12 @@ program FatesTestAllometry ! LOCALS: type(fates_unit_test_param_reader) :: param_reader - character(len=*), parameter :: param_file = 'fates_params_default.nc' + character(len=*), :: param_file character(len=*), parameter :: out_file = 'allometry_out.nc' integer :: numpft integer :: i, j integer :: numdbh + integer :: nargs real(r8), allocatable :: dbh(:) ! diameter at breast height [cm] real(r8), allocatable :: height(:, :) ! height [m] @@ -40,6 +41,13 @@ subroutine WriteAllometryData(out_file, ndbh, numpft, dbh, height) end subroutine WriteAllometryData end interface + + nargs = command_argument_count() + if (nargs /= 1) then + write(*, '(a, i, a)') "Incorrect number of arguments: ", nargs, ". Should only be 1" + else + call get_command_argument(1, param_file) + endif ! read in parameter file call param_reader%Init(param_file) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 1e513dcd87..67370636f0 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -11,20 +11,17 @@ import matplotlib import matplotlib.pyplot as plt -from utils import add_cime_lib_to_path +from utils import add_cime_lib_to_path, round_up add_cime_lib_to_path() from CIME.utils import run_cmd_no_fail -def round_up(n, decimals=0): - multiplier = 10**decimals - return math.ceil(n * multiplier) / multiplier - -def truncate(n, decimals=0): - multiplier = 10**decimals - return int(n * multiplier) / multiplier - def get_color_pallete(): + """Generate a color pallete + + Returns: + real: array of colors to use in plotting + """ colors = [(31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120), (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150), @@ -40,6 +37,14 @@ def get_color_pallete(): def plot_allometry_var(data, var, varname, units): + """Plot an allometry variable + + Args: + data (xarray DataArray): the data array of the variable to plot + var (str): variable name (for data structure) + varname (str): variable name for plot labels + units (str): variable units for plot labels + """ df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), 'pft': np.repeat(data.pft, len(data.dbh)), var: data.values.flatten()}) @@ -84,52 +89,61 @@ def plot_allometry_var(data, var, varname, units): plt.legend(loc='upper left', title='PFT') plt.show() - - -if __name__ == "__main__": - ## Arguments - clean = True - build = False - run = False - build_dir = "../_build" - name = "fates_unit_tests" - make_j = 8 - cmake_directory = os.path.abspath("../") - param_file = None - param_cdl_path = "../parameter_files/fates_params_default.cdl" +def create_nc_file(cdl_path): + file_basename = os.path.basename(cdl_path).split(".")[-2] + file_nc_name = f"{file_basename}.nc" - ## Constants + file_gen_command = [ + "ncgen -o", + os.path.join(file_nc_name), + cdl_path + ] + run_cmd_no_fail(" ".join(file_gen_command), combine_output=True) + +def main(clean, build, run, build_dir, make_j, param_file): + + # Constants for now out_file = "allometry_out.nc" test_dir = "fates_allom_test" test_exe = "FATES_allom_exe" + name = "fates_unit_tests" + default_cdl_path = "../parameter_files/fates_params_default.cdl" - build_dir_path = os.path.abspath(build_dir) + # absolute path to desired build directory + build_dir_path = os.path.abspath(build_dir) - ## Actual Program + if param_file is None: + print("Using default parameter file.") + param_file = default_cdl_path + create_nc_file(param_file) + else: + print("Using parameter file {param_file}.") + if build: - build_unit_tests(build_dir, name, cmake_directory, make_j, clean=clean) - + build_unit_tests(build_dir, name, os.path.abspath("../"), make_j, clean=clean) + if run: exe_path = os.path.join(build_dir_path, test_dir, test_exe) + run_command = [exe_path, os.path.abspath(param_file)] + out = run_cmd_no_fail(" ".join(run_command), combine_output=True) + print(out) - if param_file is None: - file_basename = os.path.basename(param_cdl_path).split(".")[-2] - file_nc_name = f"{file_basename}.nc" - file_gen_command = [ - "ncgen -o", - os.path.join(file_nc_name), - param_cdl_path - ] - run_cmd_no_fail(" ".join(file_gen_command), combine_output=True) - - out = run_cmd_no_fail(exe_path, combine_output=True) - print(out) - # read in allometry data - allometry_dat = xr.open_dataset(os.path.join(build_dir_path, out_file)) + allometry_dat = xr.open_dataset(out_file) # plot allometry data plot_allometry_var(allometry_dat.height, 'height', 'height', 'm') - \ No newline at end of file + +if __name__ == "__main__": + + ## Arguments + clean = False + build = False + run = True + build_dir = "../_build" + make_j = 8 + param_file = None + + main(clean, build, run, build_dir, make_j, param_file) \ No newline at end of file diff --git a/functional_unit_testing/utils.py b/functional_unit_testing/utils.py index e4f74e0b68..86e7038f34 100644 --- a/functional_unit_testing/utils.py +++ b/functional_unit_testing/utils.py @@ -3,6 +3,7 @@ import os import sys +import math # ======================================================================== # Constants that may need to be changed if directory structures change @@ -54,4 +55,12 @@ def add_cime_lib_to_path(): prepend_to_python_path(cime_path) cime_lib_path = os.path.join(cime_path, "CIME", "Tools") prepend_to_python_path(cime_lib_path) - return cime_path \ No newline at end of file + return cime_path + +def round_up(n, decimals=0): + multiplier = 10**decimals + return math.ceil(n * multiplier) / multiplier + +def truncate(n, decimals=0): + multiplier = 10**decimals + return int(n * multiplier) / multiplier \ No newline at end of file From 0a52c5298107da910135586616c979b03050c46e Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 17 Apr 2024 11:57:55 -0600 Subject: [PATCH 163/300] plot all allometries --- .../allometry/FatesTestAllometry.F90 | 208 +++++++++-- .../build_fortran_tests.py | 1 - functional_unit_testing/run_fates_tests.py | 326 ++++++++++++++++-- unit_test_shr/FatesUnitTestIOMod.F90 | 111 +++++- unit_test_shr/FatesUnitTestParamReaderMod.F90 | 7 + 5 files changed, 587 insertions(+), 66 deletions(-) diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index 471b8711e9..c7c542a8b2 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -1,7 +1,9 @@ program FatesTestAllometry use FatesConstantsMod, only : r8 => fates_r8 - use FatesAllometryMod, only : h_allom + use FatesAllometryMod, only : h_allom, bagw_allom, blmax_allom + use FatesAllometryMod, only : carea_allom, bsap_allom, bbgw_allom + use FatesAllometryMod, only : bfineroot, bstore_allom, bdead_allom use PRTParametersMod, only : prt_params use FatesUnitTestParamReaderMod, only : fates_unit_test_param_reader @@ -9,23 +11,45 @@ program FatesTestAllometry ! LOCALS: type(fates_unit_test_param_reader) :: param_reader - character(len=*), :: param_file + character(len=:), allocatable :: param_file character(len=*), parameter :: out_file = 'allometry_out.nc' integer :: numpft + integer :: arglen integer :: i, j integer :: numdbh integer :: nargs - real(r8), allocatable :: dbh(:) ! diameter at breast height [cm] - real(r8), allocatable :: height(:, :) ! height [m] + real(r8), allocatable :: dbh(:) ! diameter at breast height [cm] + real(r8), allocatable :: height(:, :) ! height [m] + real(r8), allocatable :: bagw(:, :) ! aboveground woody biomass [kgC] + real(r8), allocatable :: blmax(:, :) ! plant leaf biomass [kgC] + real(r8), allocatable :: crown_area(:, :) ! crown area per cohort [m2] + real(r8), allocatable :: sapwood_area(:, :) ! cross sectional area of sapwood at reference height [m2] + real(r8), allocatable :: bsap(:, :) ! sapwood biomass [kgC] + real(r8), allocatable :: bbgw(:, :) ! belowground woody biomass [kgC] + real(r8), allocatable :: fineroot_biomass(:, :) ! belowground fineroot biomass [kgC] + real(r8), allocatable :: bstore(:, :) ! allometric target storage biomass [kgC] + real(r8), allocatable :: bdead(:, :) ! structural biomass (heartwood/struct) [kgC] + real(r8), allocatable :: total_biom_tissues(:,:) ! total biomass calculated as bleaf + bfineroot + bdead + bsap [kgC] + real(r8), allocatable :: total_biom_parts(:,:) ! total biomass calculated as bleaf + bfineroot + agbw + bgbw [kgC] ! CONSTANTS: - real(r8) :: min_dbh = 0.5_r8 ! minimum DBH to calculate [cm] - real(r8) :: max_dbh = 200.0_r8 ! maximum DBH to calculate [cm] - real(r8) :: dbh_inc = 0.5_r8 ! DBH increment to use [cm] + real(r8), parameter :: min_dbh = 0.5_r8 ! minimum DBH to calculate [cm] + real(r8), parameter :: max_dbh = 200.0_r8 ! maximum DBH to calculate [cm] + real(r8), parameter :: dbh_inc = 0.5_r8 ! DBHncrement to use [cm] + + integer, parameter :: crown_damage = 1 + real(r8), parameter :: elongation_factor = 1.0_r8 + real(r8), parameter :: elongation_factor_roots = 1.0_r8 + real(r8), parameter :: site_spread = 1.0_r8 + real(r8), parameter :: canopy_trim = 1.0_r8 + real(r8), parameter :: nplant = 1.0_r8 + real(r8), parameter :: leaf_to_fineroot = 1.0_r8 interface - subroutine WriteAllometryData(out_file, ndbh, numpft, dbh, height) + subroutine WriteAllometryData(out_file, ndbh, numpft, dbh, height, bagw, blmax, & + crown_area, sapwood_area, bsap, bbgw, fineroot_biomass, bstore, bdead, & + total_biom_parts, total_biom_tissues) use FatesUnitTestIOMod, only : OpenNCFile, RegisterNCDims, CloseNCFile use FatesUnitTestIOMod, only : RegisterVar1D, WriteVar, RegisterVar2D @@ -37,47 +61,95 @@ subroutine WriteAllometryData(out_file, ndbh, numpft, dbh, height) integer, intent(in) :: ndbh, numpft real(r8), intent(in) :: dbh(:) real(r8), intent(in) :: height(:,:) - + real(r8), intent(in) :: bagw(:,:) + real(r8), intent(in) :: blmax(:, :) + real(r8), intent(in) :: crown_area(:, :) + real(r8), intent(in) :: sapwood_area(:, :) + real(r8), intent(in) :: bsap(:, :) + real(r8), intent(in) :: bbgw(:, :) + real(r8), intent(in) :: fineroot_biomass(:, :) + real(r8), intent(in) :: bstore(:, :) + real(r8), intent(in) :: bdead(:, :) + real(r8), intent(in) :: total_biom_parts(:, :) + real(r8), intent(in) :: total_biom_tissues(:, :) end subroutine WriteAllometryData end interface + ! get parameter file from command-line argument nargs = command_argument_count() if (nargs /= 1) then - write(*, '(a, i, a)') "Incorrect number of arguments: ", nargs, ". Should only be 1" + write(*, '(a, i2, a)') "Incorrect number of arguments: ", nargs, ". Should be 1" + stop else - call get_command_argument(1, param_file) + call get_command_argument(1, length=arglen) + allocate(character(arglen) :: param_file) + call get_command_argument(1, value=param_file) endif ! read in parameter file call param_reader%Init(param_file) call param_reader%RetrieveParameters() - numpft = size(prt_params%wood_density, dim=1) - ! allocate arrays and initialize DBH array + ! determine sizes of arrays + numpft = size(prt_params%wood_density, dim=1) numdbh = int((max_dbh - min_dbh)/dbh_inc + 1) + ! allocate arrays allocate(dbh(numdbh)) allocate(height(numdbh, numpft)) + allocate(bagw(numdbh, numpft)) + allocate(blmax(numdbh, numpft)) + allocate(crown_area(numdbh, numpft)) + allocate(sapwood_area(numdbh, numpft)) + allocate(bsap(numdbh, numpft)) + allocate(bbgw(numdbh, numpft)) + allocate(fineroot_biomass(numdbh, numpft)) + allocate(bstore(numdbh, numpft)) + allocate(bdead(numdbh, numpft)) + allocate(total_biom_parts(numdbh, numpft)) + allocate(total_biom_tissues(numdbh, numpft)) + ! initialize dbh array do i = 1, numdbh dbh(i) = min_dbh + dbh_inc*(i-1) end do + ! total biomass = bleaf + bfineroot + agbw + bgbw + ! ... or ... + ! total biomass = bleaf + bfineroot + bdead + bsap + ! calculate allometries do i = 1, numpft do j = 1, numdbh call h_allom(dbh(j), i, height(j, i)) + call bagw_allom(dbh(j), i, crown_damage, elongation_factor, bagw(j, i)) + call blmax_allom(dbh(j), i, blmax(j, i)) + call carea_allom(dbh(j), nplant, site_spread, i, crown_damage, crown_area(j, i)) + call bsap_allom(dbh(j), i, crown_damage, canopy_trim, elongation_factor, & + sapwood_area(j, i), bsap(j, i)) + call bbgw_allom(dbh(j), i, elongation_factor, bbgw(j, i)) + call bfineroot(dbh(j), i, canopy_trim, leaf_to_fineroot, elongation_factor_roots, & + fineroot_biomass(j, i)) + call bstore_allom(dbh(j), i, crown_damage, canopy_trim, bstore(j, i)) + call bdead_allom(bagw(j, i), bbgw(j, i), bsap(j, i), i, bdead(j, i)) + total_biom_parts(j, i) = blmax(j, i) + fineroot_biomass(j, i) + bagw(j, i) + bbgw(j, i) + total_biom_tissues(j, i) = blmax(j, i) + fineroot_biomass(j, i) + bdead(j, i) + bsap(j, i) end do end do - call WriteAllometryData(out_file, numdbh, numpft, dbh, height) + ! write out data to netcdf file + call WriteAllometryData(out_file, numdbh, numpft, dbh, height, bagw, blmax, crown_area, & + sapwood_area, bsap, bbgw, fineroot_biomass, bstore, bdead, total_biom_parts, & + total_biom_tissues) end program FatesTestAllometry ! ---------------------------------------------------------------------------------------- -subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height) +subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height, bagw, blmax, & + crown_area, sapwood_area, bsap, bbgw, fineroot_biomass, bstore, bdead, total_biom_parts, & + total_biom_tissues) ! ! DESCRIPTION: ! Writes out data from the allometry test @@ -95,6 +167,17 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height) integer, intent(in) :: numdbh, numpft real(r8), intent(in) :: dbh(:) real(r8), intent(in) :: height(:,:) + real(r8), intent(in) :: bagw(:,:) + real(r8), intent(in) :: blmax(:, :) + real(r8), intent(in) :: crown_area(:, :) + real(r8), intent(in) :: sapwood_area(:, :) + real(r8), intent(in) :: bsap(:, :) + real(r8), intent(in) :: bbgw(:, :) + real(r8), intent(in) :: fineroot_biomass(:, :) + real(r8), intent(in) :: bstore(:, :) + real(r8), intent(in) :: bdead(:, :) + real(r8), intent(in) :: total_biom_parts(:, :) + real(r8), intent(in) :: total_biom_tissues(:, :) ! LOCALS: integer, allocatable :: pft_indices(:) ! array of pft indices to write out @@ -103,8 +186,13 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height) character(len=8) :: dim_names(2) ! dimension names integer :: dimIDs(2) ! dimension IDs integer :: dbhID, pftID ! variable IDs for dimensions - integer :: heightID - + integer :: heightID, bagwID + integer :: blmaxID, c_areaID + integer :: sapwoodareaID, bsapID + integer :: bbgwID, finerootID + integer :: bstoreID, bdeadID + integer :: totbiomID1, totbiomID2 + ! create pft indices allocate(pft_indices(numpft)) do i = 1, numpft @@ -121,21 +209,88 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height) call RegisterNCDims(ncid, dim_names, (/numdbh, numpft/), 2, dimIDs) ! register dbh - call RegisterVar1D(ncid, dim_names(1), dimIDs(1), type_double, & + call RegisterVar1D(ncid, dim_names(1), dimIDs(1), type_double, & [character(len=20) :: 'units', 'long_name'], & [character(len=150) :: 'cm', 'diameter at breast height'], 2, dbhID) ! register pft - call RegisterVar1D(ncid, dim_names(2), dimIDs(2), type_int, & - [character(len=20) :: 'units', 'long_name'], & + call RegisterVar1D(ncid, dim_names(2), dimIDs(2), type_int, & + [character(len=20) :: 'units', 'long_name'], & [character(len=150) :: '', 'plant functional type'], 2, pftID) ! register height - call RegisterVar2D(ncid, 'height', dimIDs(1:2), type_double, & + call RegisterVar2D(ncid, 'height', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'm', 'plant height'], & 3, heightID) + ! register aboveground biomass + call RegisterVar2D(ncid, 'bagw', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant aboveground woody biomass'], & + 3, bagwID) + + ! register leaf biomass + call RegisterVar2D(ncid, 'blmax', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant maximum leaf biomass'], & + 3, blmaxID) + + ! register crown area + call RegisterVar2D(ncid, 'crown_area', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'm2', 'plant crown area per cohort'], & + 3, c_areaID) + + ! register sapwood area + call RegisterVar2D(ncid, 'sapwood_area', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'm2', 'plant cross section area sapwood at reference height'], & + 3, sapwoodareaID) + + ! register sapwood biomass + call RegisterVar2D(ncid, 'bsap', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant sapwood biomass'], & + 3, bsapID) + + ! register belowground woody biomass + call RegisterVar2D(ncid, 'bbgw', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant belowground woody biomass'], & + 3, bbgwID) + + ! register fineroot biomass + call RegisterVar2D(ncid, 'fineroot_biomass', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant fineroot biomass'], & + 3, finerootID) + + ! register storage biomass + call RegisterVar2D(ncid, 'bstore', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant storage biomass'], & + 3, bstoreID) + + ! register structural biomass + call RegisterVar2D(ncid, 'bdead', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant deadwood (structural/heartwood) biomass'], & + 3, bdeadID) + + ! register total biomass (parts) + call RegisterVar2D(ncid, 'total_biomass_parts', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant total biomass calculated from parts'], & + 3, totbiomID1) + + ! register total biomass (tissues) + call RegisterVar2D(ncid, 'total_biomass_tissues', dimIDs(1:2), type_double, & + [character(len=20) :: 'coordinates', 'units', 'long_name'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant total biomass calculated from tissues'], & + 3, totbiomID2) + + ! finish defining variables call EndNCDef(ncid) @@ -143,6 +298,17 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height) call WriteVar(ncid, dbhID, dbh(:)) call WriteVar(ncid, pftID, pft_indices(:)) call WriteVar(ncid, heightID, height(:,:)) + call WriteVar(ncid, bagwID, bagw(:,:)) + call WriteVar(ncid, blmaxID, blmax(:,:)) + call WriteVar(ncid, c_areaID, crown_area(:,:)) + call WriteVar(ncid, sapwoodareaID, sapwood_area(:,:)) + call WriteVar(ncid, bsapID, bsap(:,:)) + call WriteVar(ncid, bbgwID, bbgw(:,:)) + call WriteVar(ncid, finerootID, fineroot_biomass(:,:)) + call WriteVar(ncid, bstoreID, bstore(:,:)) + call WriteVar(ncid, bdeadID, bdead(:,:)) + call WriteVar(ncid, totbiomID1, total_biom_parts(:,:)) + call WriteVar(ncid, totbiomID2, total_biom_tissues(:,:)) ! close the file call CloseNCFile(ncid) diff --git a/functional_unit_testing/build_fortran_tests.py b/functional_unit_testing/build_fortran_tests.py index 678a559f3c..16072450c2 100644 --- a/functional_unit_testing/build_fortran_tests.py +++ b/functional_unit_testing/build_fortran_tests.py @@ -48,7 +48,6 @@ def run_cmake(name, test_dir, pfunit_path, cmake_args): ] cmake_command.extend(cmake_args.split(" ")) - #print(" ".join(cmake_command)) run_cmd_no_fail(" ".join(cmake_command), combine_output=True) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 67370636f0..93ab844bc4 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -4,6 +4,7 @@ import sys from build_fortran_tests import build_unit_tests +import argparse import math import pandas as pd import numpy as np @@ -16,6 +17,15 @@ from CIME.utils import run_cmd_no_fail +DEFAULT_CDL_PATH = "../parameter_files/fates_params_default.cdl" +CMAKE_BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../") + +# Constants for now +out_file = "allometry_out.nc" +test_dir = "fates_allom_test" +test_exe = "FATES_allom_exe" +name = "fates_unit_tests" + def get_color_pallete(): """Generate a color pallete @@ -70,7 +80,9 @@ def plot_allometry_var(data, var, varname, units): plt.yticks(fontsize=10) plt.xticks(fontsize=10) - for y in range(0, int(maxvar), 5): + inc = (int(maxvar) - 0)/20 + for i in range(0, 20): + y = 0.0 + i*inc plt.plot(range(math.floor(0), math.ceil(maxdbh)), [y] * len(range(math.floor(0), math.ceil(maxdbh))), "--", lw=0.5, color="black", alpha=0.3) @@ -88,62 +100,310 @@ def plot_allometry_var(data, var, varname, units): plt.title(f"Simulated {varname} for input parameter file", fontsize=11) plt.legend(loc='upper left', title='PFT') - plt.show() -def create_nc_file(cdl_path): +def plot_total_biomass(data): + """Plot two calculations of total biomass against each other + + Args: + data (xarray DataSet): the allometry dataset + """ + df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), + 'pft': np.repeat(data.pft, len(data.dbh)), + 'total_biomass_parts': data.total_biomass_parts.values.flatten(), + 'total_biomass_tissues': data.total_biomass_tissues.values.flatten()}) + + colors = get_color_pallete() + + plt.figure(figsize=(7, 5)) + ax = plt.subplot(111) + ax.spines["top"].set_visible(False) + ax.spines["bottom"].set_visible(False) + ax.spines["right"].set_visible(False) + ax.spines["left"].set_visible(False) + + ax.get_xaxis().tick_bottom() + ax.get_yaxis().tick_left() + + maxbiomass = np.maximum(df['total_biomass_parts'].max(), df['total_biomass_tissues'].max()) + + plt.xlim(0.0, maxbiomass) + plt.ylim(0.0, maxbiomass) + + plt.yticks(fontsize=10) + plt.xticks(fontsize=10) + plt.tick_params(bottom=False, top=False, left=False, right=False) + + pfts = np.unique(df.pft.values) + for rank, pft in enumerate(pfts): + data = df[df.pft == pft] + plt.scatter(data.total_biomass_parts.values, data.total_biomass_parts.values, + color=colors[rank], label=pft) + + plt.xlabel('Total biomass (kgC) from parts', fontsize=11) + plt.ylabel('Total biomass (kgC) from tissues', fontsize=11) + plt.title("Simulated total biomass for input parameter file", fontsize=11) + plt.legend(loc='upper left', title='PFT') + +def create_nc_file(cdl_path, run_dir): + """Creates a netcdf file from a cdl file + + Args: + cdl_path (str): full path to desired cdl file + run_dir (str): where the file should be written to + """ file_basename = os.path.basename(cdl_path).split(".")[-2] file_nc_name = f"{file_basename}.nc" file_gen_command = [ "ncgen -o", - os.path.join(file_nc_name), + os.path.join(run_dir, file_nc_name), cdl_path ] - run_cmd_no_fail(" ".join(file_gen_command), combine_output=True) + out = run_cmd_no_fail(" ".join(file_gen_command), combine_output=True) + print(out) + + return file_nc_name + +def copy_file(file_path, dir): + """Copies a file file to a desired directory -def main(clean, build, run, build_dir, make_j, param_file): + Args: + file_path (str): full path to file + dir (str): where the file should be copied to + """ + file_basename = os.path.basename(file_path) + + file_copy_command = [ + "cp", + os.path.abspath(file_path), + os.path.abspath(dir) + ] + run_cmd_no_fail(" ".join(file_copy_command), combine_output=True) - # Constants for now - out_file = "allometry_out.nc" - test_dir = "fates_allom_test" - test_exe = "FATES_allom_exe" - name = "fates_unit_tests" - default_cdl_path = "../parameter_files/fates_params_default.cdl" + return file_basename + + +def run_exectuables(build_dir, test_dir, test_exe, run_dir, args): + """Run the generated executables + + Args: + build_dir (str): full path to build directory + run_dir (str): full path to run directory + test_dir (str): test directory within the run directory + test_exe (str): test executable to run + args ([str]): arguments for executable + """ + # move executable to run directory + exe_path = os.path.join(build_dir, test_dir, test_exe) + copy_file(exe_path, run_dir) + + # run the executable + new_exe_path = os.path.join(run_dir, test_exe) + run_command = [new_exe_path] + run_command.extend(args) + + os.chdir(run_dir) + print("Running exectuables") + out = run_cmd_no_fail(" ".join(run_command), combine_output=True) + print(out) + + +def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file): + # absolute path to desired build directory build_dir_path = os.path.abspath(build_dir) + # absolute path to desired run directory + run_dir_path = os.path.abspath(run_dir) + + if not os.path.isdir(run_dir_path): + os.mkdir(run_dir_path) + if param_file is None: - print("Using default parameter file.") - param_file = default_cdl_path - create_nc_file(param_file) + print("Using default parameter file.") + param_file = DEFAULT_CDL_PATH + param_file = create_nc_file(param_file, run_dir_path) else: - print("Using parameter file {param_file}.") + print(f"Using parameter file {param_file}.") + file_suffix = os.path.basename(param_file).split(".")[-1] + if file_suffix == 'cdl': + param_file = create_nc_file(param_file, run_dir_path) + elif file_suffix == "nc": + param_file = copy_file(param_file, run_dir_path) + else: + raise RuntimeError("Must supply file with .cdl or .nc ending.") if build: - build_unit_tests(build_dir, name, os.path.abspath("../"), make_j, clean=clean) - + build_unit_tests(build_dir, name, CMAKE_BASE_DIR, make_j, clean=clean) + if run: - exe_path = os.path.join(build_dir_path, test_dir, test_exe) - run_command = [exe_path, os.path.abspath(param_file)] - out = run_cmd_no_fail(" ".join(run_command), combine_output=True) - print(out) - + run_exectuables(build_dir_path, test_dir, test_exe, run_dir_path, [param_file]) + # read in allometry data - allometry_dat = xr.open_dataset(out_file) + allometry_dat = xr.open_dataset(os.path.join(run_dir_path, out_file)) # plot allometry data plot_allometry_var(allometry_dat.height, 'height', 'height', 'm') + plot_allometry_var(allometry_dat.bagw, 'bagw', 'aboveground biomass', 'kgC') + plot_allometry_var(allometry_dat.blmax, 'blmax', 'maximum leaf biomass', 'kgC') + plot_allometry_var(allometry_dat.crown_area, 'crown_area', 'crown area', 'm$^2$') + plot_allometry_var(allometry_dat.sapwood_area, 'sapwood_area', 'sapwood area', 'm$^2$') + plot_allometry_var(allometry_dat.bsap, 'bsap', 'sapwood biomass', 'kgC') + plot_allometry_var(allometry_dat.bbgw, 'bbgw', 'belowground biomass', 'kgC') + plot_allometry_var(allometry_dat.fineroot_biomass, 'fineroot_biomass', 'fineroot biomass', 'kgC') + plot_allometry_var(allometry_dat.bstore, 'bstore', 'storage biomass', 'kgC') + plot_allometry_var(allometry_dat.bdead, 'bdead', 'deadwood biomass', 'kgC') + plot_allometry_var(allometry_dat.total_biomass_parts, 'total_biomass_parts', 'total biomass (calculated from parts)', 'kgC') + plot_allometry_var(allometry_dat.total_biomass_tissues, 'total_biomass_tissues', 'total biomass (calculated from tissues)', 'kgC') + plot_total_biomass(allometry_dat) + plt.show() + + +def commandline_args(): + """Parse and return command-line arguments""" + + description = """ + Driver for running FATES unit and functional tests + + Typical usage: + + ./run_fates_tests -f parameter_file.nc + """ + + parser = argparse.ArgumentParser( + description=description, formatter_class=argparse.RawTextHelpFormatter + ) + + parser.add_argument( + "-f", + "--parameter-file", + default=DEFAULT_CDL_PATH, + help="Parameter file to run the FATES tests with.\n" + "Can be a netcdf (.nc) or cdl (.cdl) file.\n" + "If no file is specified the script will use the default .cdl file in the\n" + "parameter_files directory.\n", + ) -if __name__ == "__main__": + parser.add_argument( + "-b", + "--build-dir", + default="../_build", + help="Directory where tests are built.\n" + "Will be created if it does not exist.\n", + ) + + parser.add_argument( + "-r", + "--run-dir", + default="../_run", + help="Directory where tests are run.\n" + "Will be created if it does not exist.\n", + ) + + parser.add_argument( + "--make-j", + type=int, + default=8, + help="Number of processes to use for build.", + ) + + parser.add_argument( + "-c", + "--clean", + action="store_true", + help="Clean build directory before building.\n" + "Removes CMake cache and runs 'make clean'.\n", + ) + + parser.add_argument( + "--skip-build", + action="store_true", + help="Skip building and compiling the test code.\n" + "Only do this if you already have run build.\n" + "Script will check to make sure executables are present.\n", + ) + + parser.add_argument( + "--skip-run", + action="store_true", + help="Skip running test code executables.\n" + "Only do this if you already have run the code previously.\n" + "Script will check to make sure required output files are present.\n", + ) + + args = parser.parse_args() - ## Arguments - clean = False - build = False - run = True - build_dir = "../_build" - make_j = 8 - param_file = None + check_arg_validity(args) + + return args + + +def check_build_exists(build_dir): + """Checks to see if the build directory and associated executables exist. + + Args: + build_dir (str): build directory + """ + + build_path = os.path.abspath(build_dir) + if not os.path.isdir(build_path): + return False + + exe_path = os.path.join(build_path, test_dir, test_exe) + if not os.path.isfile(exe_path): + return False + + return True + + +def check_out_file_exists(out_file): + """Checks to see if the required output files exist. + + Args: + out_file (str): required output file + """ + + full_path = os.path.abspath(out_file) + if not os.path.isfile(full_path): + return False + + return True + + +def check_arg_validity(args): + """Checks validity of input script arguments + + Args: + args (parse_args): input arguments + + Raises: + RuntimeError: Can't find input parameter file + RuntimeError: Can't find build directory or required executables + RuntimeError: Can't find required output files for plotting + """ + if args.parameter_file is not None: + if not os.path.isfile(args.parameter_file): + raise RuntimeError(f"Cannot find file {args.parameter_file}.") + if args.skip_build: + if not check_build_exists(os.path.abspath(args.build_dir)): + raise RuntimeError("Can't find build directory or executables, run again without --skip-build") + if args.skip_run: + if not check_out_file_exists(os.path.join(os.path.abspath(args.run_dir), out_file)): + raise RuntimeError(f"Can't find output file {out_file}, run again without --skip-run") + +def main(): + """Main script + """ + + args = commandline_args() + + build = not args.skip_build + run = not args.skip_run + + run_tests(args.clean, build, run, args.build_dir, args.run_dir, args.make_j, args.parameter_file) + +if __name__ == "__main__": - main(clean, build, run, build_dir, make_j, param_file) \ No newline at end of file + main() \ No newline at end of file diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 index bbdf72b90c..cb65fdffa3 100644 --- a/unit_test_shr/FatesUnitTestIOMod.F90 +++ b/unit_test_shr/FatesUnitTestIOMod.F90 @@ -8,8 +8,8 @@ module FatesUnitTestIOMod private ! LOCALS - integer, parameter :: type_double = 1 ! type - integer, parameter :: type_int = 2 ! type + integer, public, parameter :: type_double = 1 ! type + integer, public, parameter :: type_int = 2 ! type interface GetVar module procedure GetVarScalarReal @@ -21,11 +21,22 @@ module FatesUnitTestIOMod module procedure GetVar3DInt end interface + interface WriteVar + module procedure WriteVar1DReal + module procedure WriteVar2DReal + module procedure WriteVar1DInt + module procedure WriteVar2DInt + end interface + public :: OpenNCFile public :: CloseNCFile public :: GetDimID public :: GetDimLen public :: GetVar + public :: RegisterNCDims + public :: RegisterVar2D, RegisterVar1D + public :: WriteVar + public :: EndNCDef contains @@ -64,13 +75,8 @@ logical function CheckFile(filename, fmode) case('readwrite') - if (.not. file_exists) then - write(*,'(a,a,a)') "File ", fname(1:len_trim(fname)), " does not exist. Can't read." - CheckFile = .false. - else - CheckFile = .true. - end if - + CheckFile = .true. + case('write') if (file_exists) then write(*, '(a, a, a)') "File ", fname(1:len_trim(fname)), " exists. Cannot open write only." @@ -439,7 +445,7 @@ subroutine RegisterVar1D(ncid, var_name, dimID, type, att_names, atts, num_atts, ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file id character(len=*), intent(in) :: var_name ! variable name - integer, intent(in) :: dimID(1) ! dimension ID + integer, intent(in) :: dimID ! dimension ID integer, intent(in) :: type ! type: int or double character(len=*), intent(in) :: att_names(num_atts) ! attribute names character(len=*), intent(in) :: atts(num_atts) ! attribute values @@ -508,6 +514,89 @@ subroutine RegisterVar2D(ncid, var_name, dimID, type, att_names, atts, num_atts, end subroutine RegisterVar2D -! ===================================================================================== + ! ===================================================================================== + + subroutine EndNCDef(ncid) + ! + ! DESCRIPTION: + ! End defining of netcdf dimensions and variables + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file id + + call Check(nf90_enddef(ncid)) + + end subroutine EndNCDef + + ! ===================================================================================== + + subroutine WriteVar1DReal(ncid, varID, data) + ! + ! DESCRIPTION: + ! Write 1D real data + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file id + integer, intent(in) :: varID ! variable ID + real(r8), intent(in) :: data(:) ! data to write + + call Check(nf90_put_var(ncid, varID, data(:))) + + end subroutine WriteVar1DReal + + ! ===================================================================================== + + subroutine WriteVar2DReal(ncid, varID, data) + ! + ! DESCRIPTION: + ! Write 2D real data + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file id + integer, intent(in) :: varID ! variable ID + real(r8), intent(in) :: data(:,:) ! data to write + + call Check(nf90_put_var(ncid, varID, data(:,:))) + + end subroutine WriteVar2DReal + + ! ===================================================================================== + + subroutine WriteVar1DInt(ncid, varID, data) + ! + ! DESCRIPTION: + ! Write 1D integer data + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file id + integer, intent(in) :: varID ! variable ID + integer, intent(in) :: data(:) ! data to write + + call Check(nf90_put_var(ncid, varID, data(:))) + + end subroutine WriteVar1DInt + + ! ===================================================================================== + + subroutine WriteVar2DInt(ncid, varID, data) + ! + ! DESCRIPTION: + ! Write 2D integer data + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file id + integer, intent(in) :: varID ! variable ID + integer, intent(in) :: data(:,:) ! data to write + + call Check(nf90_put_var(ncid, varID, data(:,:))) + + end subroutine WriteVar2DInt + + ! ===================================================================================== end module FatesUnitTestIOMod \ No newline at end of file diff --git a/unit_test_shr/FatesUnitTestParamReaderMod.F90 b/unit_test_shr/FatesUnitTestParamReaderMod.F90 index f36f2fd58e..3b14b98824 100644 --- a/unit_test_shr/FatesUnitTestParamReaderMod.F90 +++ b/unit_test_shr/FatesUnitTestParamReaderMod.F90 @@ -9,6 +9,8 @@ module FatesUnitTestParamReaderMod use EDParamsMod, only : FatesRegisterParams, FatesReceiveParams use SFParamsMod, only : SpitFireRegisterParams, SpitFireReceiveParams use PRTInitParamsFatesMod, only : PRTRegisterParams, PRTReceiveParams + use PRTParametersMod, only : prt_params + use FatesParameterDerivedMod, only : param_derived use FatesSynchronizedParamsMod, only : FatesSynchronizedParamsInst use EDPftvarcon, only : EDPftvarcon_inst use FatesUnitTestIOMod, only : OpenNCFile, GetDimID, GetDimLen, GetVar, CloseNCFile @@ -127,17 +129,22 @@ subroutine RetrieveParameters(this) call EDPftvarcon_inst%Register(fates_pft_params) call this%Read(fates_params) + call this%Read(fates_pft_params) call FatesReceiveParams(fates_params) call SpitFireReceiveParams(fates_params) call PRTReceiveParams(fates_params) call FatesSynchronizedParamsInst%ReceiveParams(fates_params) + call EDPftvarcon_inst%Receive(fates_pft_params) call fates_params%Destroy() call fates_pft_params%Destroy() deallocate(fates_params) deallocate(fates_pft_params) + ! initialize derived parameters + call param_derived%Init(size(prt_params%wood_density, dim=1)) + end subroutine RetrieveParameters ! -------------------------------------------------------------------------------------- From c6e95bc3ed10b70d0f028f4d189ca91401b2fa32 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 17 Apr 2024 12:00:13 -0600 Subject: [PATCH 164/300] add function docstring --- functional_unit_testing/run_fates_tests.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 93ab844bc4..8089a3e930 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -210,6 +210,20 @@ def run_exectuables(build_dir, test_dir, test_exe, run_dir, args): def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file): + """Builds and runs the fates tests + + Args: + clean (bool): whether or not to clean the build directory + build (bool): whether or not to build the exectuables + run (bool): whether or not to run the executables + build_dir (str): build directory + run_dir (str): run directory + make_j (int): number of processors for the build + param_file (str): input FATES parameter file + + Raises: + RuntimeError: Parameter file is not the correct file type + """ # absolute path to desired build directory build_dir_path = os.path.abspath(build_dir) From 101974e96d25e810f9304229717975e9a1f8dbf0 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 17 Apr 2024 12:21:46 -0600 Subject: [PATCH 165/300] add more comments and instructions --- .../allometry/FatesTestAllometry.F90 | 61 ++++++++++--------- functional_unit_testing/run_fates_tests.py | 33 ++++++++-- unit_test_shr/FatesUnitTestIOMod.F90 | 24 ++++++-- unit_test_shr/FatesUnitTestParamReaderMod.F90 | 51 ++++++++-------- 4 files changed, 103 insertions(+), 66 deletions(-) diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index c7c542a8b2..5f021d57ed 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -10,14 +10,14 @@ program FatesTestAllometry implicit none ! LOCALS: - type(fates_unit_test_param_reader) :: param_reader - character(len=:), allocatable :: param_file - character(len=*), parameter :: out_file = 'allometry_out.nc' - integer :: numpft - integer :: arglen - integer :: i, j - integer :: numdbh - integer :: nargs + type(fates_unit_test_param_reader) :: param_reader ! param reader instance + character(len=:), allocatable :: param_file ! input parameter file + character(len=*), parameter :: out_file = 'allometry_out.nc' ! output file + integer :: numpft ! number of pfts (from parameter file) + integer :: arglen ! length of command line argument + integer :: i, j ! looping indices + integer :: numdbh ! size of dbh array + integer :: nargs ! number of command line arguments real(r8), allocatable :: dbh(:) ! diameter at breast height [cm] real(r8), allocatable :: height(:, :) ! height [m] real(r8), allocatable :: bagw(:, :) ! aboveground woody biomass [kgC] @@ -37,13 +37,13 @@ program FatesTestAllometry real(r8), parameter :: max_dbh = 200.0_r8 ! maximum DBH to calculate [cm] real(r8), parameter :: dbh_inc = 0.5_r8 ! DBHncrement to use [cm] - integer, parameter :: crown_damage = 1 - real(r8), parameter :: elongation_factor = 1.0_r8 - real(r8), parameter :: elongation_factor_roots = 1.0_r8 - real(r8), parameter :: site_spread = 1.0_r8 - real(r8), parameter :: canopy_trim = 1.0_r8 - real(r8), parameter :: nplant = 1.0_r8 - real(r8), parameter :: leaf_to_fineroot = 1.0_r8 + integer, parameter :: crown_damage = 1 ! crown damage + real(r8), parameter :: elongation_factor = 1.0_r8 ! elongation factor for stem + real(r8), parameter :: elongation_factor_roots = 1.0_r8 ! elongation factor for roots + real(r8), parameter :: site_spread = 1.0_r8 ! site spread + real(r8), parameter :: canopy_trim = 1.0_r8 ! canopy trim + real(r8), parameter :: nplant = 1.0_r8 ! number of plants per cohort + real(r8), parameter :: leaf_to_fineroot = 1.0_r8 ! leaf to fineroot ratio interface @@ -163,21 +163,22 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height, bagw, blmax implicit none ! ARGUMENTS: - character(len=*), intent(in) :: out_file - integer, intent(in) :: numdbh, numpft - real(r8), intent(in) :: dbh(:) - real(r8), intent(in) :: height(:,:) - real(r8), intent(in) :: bagw(:,:) - real(r8), intent(in) :: blmax(:, :) - real(r8), intent(in) :: crown_area(:, :) - real(r8), intent(in) :: sapwood_area(:, :) - real(r8), intent(in) :: bsap(:, :) - real(r8), intent(in) :: bbgw(:, :) - real(r8), intent(in) :: fineroot_biomass(:, :) - real(r8), intent(in) :: bstore(:, :) - real(r8), intent(in) :: bdead(:, :) - real(r8), intent(in) :: total_biom_parts(:, :) - real(r8), intent(in) :: total_biom_tissues(:, :) + character(len=*), intent(in) :: out_file ! output file name + integer, intent(in) :: numdbh ! size of dbh array + integer, intent(in) :: numpft ! number of pfts + real(r8), intent(in) :: dbh(:) ! diameter at breast height [cm] + real(r8), intent(in) :: height(:,:) ! height [m] + real(r8), intent(in) :: bagw(:,:) ! aboveground biomass [kgC] + real(r8), intent(in) :: blmax(:, :) ! leaf biomass [kgC] + real(r8), intent(in) :: crown_area(:, :) ! crown area [m2] + real(r8), intent(in) :: sapwood_area(:, :) ! sapwood cross-sectional area [m2] + real(r8), intent(in) :: bsap(:, :) ! sapwood biomass [kgC] + real(r8), intent(in) :: bbgw(:, :) ! belowground biomass [kgC] + real(r8), intent(in) :: fineroot_biomass(:, :) ! fineroot biomass [kgC] + real(r8), intent(in) :: bstore(:, :) ! storage biomass [kgC] + real(r8), intent(in) :: bdead(:, :) ! deadwood biomass [kgC] + real(r8), intent(in) :: total_biom_parts(:, :) ! total biomass calculated from parts [kgC] + real(r8), intent(in) :: total_biom_tissues(:, :) ! total biomass calculated from tissues [kgC] ! LOCALS: integer, allocatable :: pft_indices(:) ! array of pft indices to write out diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 8089a3e930..8f97827365 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -1,11 +1,36 @@ #!/usr/bin/env python -import os -import sys -from build_fortran_tests import build_unit_tests +""" +|------------------------------------------------------------------| +|--------------------- Instructions -----------------------------| +|------------------------------------------------------------------| +To run this script the following python packages are required: + - numpy + - xarray + - matplotlib + - pandas -import argparse +Though this script does not require any host land model code, it does require some CIME and shr code, +so you should still get these repositories as you normally would (i.e., manage_externals, etc.) + +Additionally, this requires netcdf and netcdff as well as a fortran compiler. + +You must also have a .cime folder in your home directory which specifies machine +configurations for CIME. + +This script builds and runs various FATES unit and functional tests, and plots any +relevant output from those tests. + +You can supply your own parameter file (either a .cdl or a .nc file), or if you do not +specify anything, the sript will use the default FATES parameter cdl file. + +""" + +import os import math +import argparse + +from build_fortran_tests import build_unit_tests import pandas as pd import numpy as np import xarray as xr diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 index cb65fdffa3..d1428ea3ec 100644 --- a/unit_test_shr/FatesUnitTestIOMod.F90 +++ b/unit_test_shr/FatesUnitTestIOMod.F90 @@ -157,9 +157,15 @@ end subroutine CloseNCFile !======================================================================================= subroutine GetDimID(ncid, var_name, dim_id) - integer, intent(in) :: ncid - character(len=*), intent(in) :: var_name - integer, intent(out) :: dim_id + ! + ! DESCRIPTION: + ! Gets dimension IDs for a variable ID + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit number + character(len=*), intent(in) :: var_name ! variable name + integer, intent(out) :: dim_id ! dimension ID call Check(nf90_inq_dimid(ncid, var_name, dim_id)) @@ -168,9 +174,15 @@ end subroutine GetDimID !======================================================================================= subroutine GetDimLen(ncid, dim_id, dim_len) - integer, intent(in) :: ncid - integer, intent(in) :: dim_id - integer, intent(out) :: dim_len + ! + ! DESCRIPTION: + ! Gets dimension lengths given a dimension ID + ! + + ! ARGUMENTS: + integer, intent(in) :: ncid ! netcdf file unit number + integer, intent(in) :: dim_id ! dimension ID + integer, intent(out) :: dim_len ! dimension length call Check(nf90_inquire_dimension(ncid, dim_id, len=dim_len)) diff --git a/unit_test_shr/FatesUnitTestParamReaderMod.F90 b/unit_test_shr/FatesUnitTestParamReaderMod.F90 index 3b14b98824..624c98ea68 100644 --- a/unit_test_shr/FatesUnitTestParamReaderMod.F90 +++ b/unit_test_shr/FatesUnitTestParamReaderMod.F90 @@ -56,17 +56,16 @@ subroutine ReadParameters(this, fates_params) class(fates_parameters_type), intent(inout) :: fates_params ! LOCALS: - real(r8), allocatable :: data2d(:, :) - real(r8), allocatable :: data1d(:) - real(r8) :: data_scalar - integer :: ncid - integer :: num_params - integer :: dimension_shape - integer :: i - integer :: max_dim_size - character(len=param_string_length) :: name - integer :: dimension_sizes(max_dimensions) - character(len=param_string_length) :: dimension_names(max_dimensions) + real(r8), allocatable :: data2d(:, :) ! data for 2D parameters + real(r8), allocatable :: data1d(:) ! data for 1D parameters + real(r8) :: data_scalar ! data for scalar parameters + integer :: ncid ! netcdf file ID + integer :: num_params ! total number of parameters + integer :: dimension_shape ! shape of parameter's dimension + integer :: i ! looping index + character(len=param_string_length) :: name ! parameter name + integer :: dimension_sizes(max_dimensions) ! sizes of dimensions from parameter file + character(len=param_string_length) :: dimension_names(max_dimensions) ! names of dimensions from parameter file logical :: is_host_param call OpenNCFile(this%filename, ncid, 'read') @@ -108,11 +107,11 @@ subroutine RetrieveParameters(this) ! Read in fates parameters ! ! ARGUMENTS: - class(fates_unit_test_param_reader), intent(in) :: this - + class(fates_unit_test_param_reader), intent(in) :: this ! parameter reader class + ! LOCALS: - class(fates_parameters_type), allocatable :: fates_params - class(fates_parameters_type), allocatable :: fates_pft_params + class(fates_parameters_type), allocatable :: fates_params ! fates parameters (for non-pft parameters) + class(fates_parameters_type), allocatable :: fates_pft_params ! fates parameters (for pft parameters) ! allocate and read in parameters allocate(fates_params) @@ -122,9 +121,9 @@ subroutine RetrieveParameters(this) call EDPftvarcon_inst%Init() - call PRTRegisterParams(fates_params) - call FatesRegisterParams(fates_params) + call FatesRegisterParams(fates_params) call SpitFireRegisterParams(fates_params) + call PRTRegisterParams(fates_params) call FatesSynchronizedParamsInst%RegisterParams(fates_params) call EDPftvarcon_inst%Register(fates_pft_params) @@ -152,16 +151,16 @@ end subroutine RetrieveParameters subroutine SetParameterDimensions(ncid, fates_params) ! ! DESCRIPTION: - ! Read in fates parameters + ! Gets and sets the parameter dimensions for the fates parameters class ! ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file ID class(fates_parameters_type), intent(inout) :: fates_params ! fates parameters class ! LOCALS: - integer :: num_used_dimensions - character(len=param_string_length) :: used_dimension_names(max_used_dimensions) - integer :: used_dimension_sizes(max_used_dimensions) + integer :: num_used_dimensions ! total number of dimensions + character(len=param_string_length) :: used_dimension_names(max_used_dimensions) ! dimension names + integer :: used_dimension_sizes(max_used_dimensions) ! dimension sizes call fates_params%GetUsedDimensions(.false., num_used_dimensions, used_dimension_names) @@ -178,13 +177,13 @@ end subroutine SetParameterDimensions subroutine GetUsedDimensionSizes(ncid, num_used_dimensions, dimension_names, dimension_sizes) ! ! DESCRIPTION: - ! Get dimension sizes for parameters + ! Gets dimension sizes for parameters ! ! ARGUMENTS: - integer, intent(in) :: ncid - integer, intent(in) :: num_used_dimensions - character(len=param_string_length), intent(in) :: dimension_names(:) - integer, intent(out) :: dimension_sizes(:) + integer, intent(in) :: ncid ! netcdf file ID + integer, intent(in) :: num_used_dimensions ! number of dimensions + character(len=param_string_length), intent(in) :: dimension_names(:) ! dimension names + integer, intent(out) :: dimension_sizes(:) ! dimension sizes ! LOCALS integer :: d From e800023987947b526add19aaa1277efa95f3e758 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 17 Apr 2024 12:24:54 -0600 Subject: [PATCH 166/300] absolute path for parameter file --- functional_unit_testing/run_fates_tests.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 8f97827365..7a429b08a5 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -42,14 +42,15 @@ from CIME.utils import run_cmd_no_fail -DEFAULT_CDL_PATH = "../parameter_files/fates_params_default.cdl" +DEFAULT_CDL_PATH = os.path.abspath("../parameter_files/fates_params_default.cdl") CMAKE_BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../") +NAME = "fates_unit_tests" # Constants for now +## TODO update this to be some kind of dictionary we can loop through out_file = "allometry_out.nc" test_dir = "fates_allom_test" test_exe = "FATES_allom_exe" -name = "fates_unit_tests" def get_color_pallete(): """Generate a color pallete @@ -274,7 +275,7 @@ def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file): raise RuntimeError("Must supply file with .cdl or .nc ending.") if build: - build_unit_tests(build_dir, name, CMAKE_BASE_DIR, make_j, clean=clean) + build_unit_tests(build_dir, NAME, CMAKE_BASE_DIR, make_j, clean=clean) if run: run_exectuables(build_dir_path, test_dir, test_exe, run_dir_path, [param_file]) From c4bc8e61919eb0e497650a0d1de4f6f8a07af113 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 17 Apr 2024 12:30:35 -0600 Subject: [PATCH 167/300] remove if allocated statement --- main/FatesParametersInterface.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index 8ea2b8a13e..0559ec3eb6 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -135,7 +135,7 @@ subroutine Destroy(this) integer :: n do n = 1, this%num_parameters - if(allocated(this%parameters(n)%data)) deallocate(this%parameters(n)%data) + deallocate(this%parameters(n)%data) end do end subroutine Destroy From 98cb1a45caa7401b06132cf11870dc2d9b107217 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 17 Apr 2024 13:24:06 -0600 Subject: [PATCH 168/300] automatically find netcdf paths --- CMakeLists.txt | 4 +-- .../allometry/CMakeLists.txt | 4 +-- .../build_fortran_tests.py | 28 +++++++++++-------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 868614bfac..a8822035a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,8 +65,8 @@ include_directories(${HLM_ROOT}/share/include) # This needs to be something we add dynamically # via some calls using cime -set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2_1") -set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.1") +set(NETCDF_C_DIR ${NETCDF_C_PATH}) +set(NETCDF_FORTRAN_DIR ${NETCDF_F_PATH}) FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) diff --git a/functional_unit_testing/allometry/CMakeLists.txt b/functional_unit_testing/allometry/CMakeLists.txt index 3e05759809..f43992847d 100644 --- a/functional_unit_testing/allometry/CMakeLists.txt +++ b/functional_unit_testing/allometry/CMakeLists.txt @@ -1,7 +1,7 @@ set(allom_sources FatesTestAllometry.F90) -set(NETCDF_C_DIR "/usr/local/Cellar/netcdf/4.9.2_1") -set(NETCDF_FORTRAN_DIR "/usr/local/Cellar/netcdf-fortran/4.6.1") +set(NETCDF_C_DIR ${NETCDF_C_PATH}) +set(NETCDF_FORTRAN_DIR ${NETCDF_F_PATH}) FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) diff --git a/functional_unit_testing/build_fortran_tests.py b/functional_unit_testing/build_fortran_tests.py index 16072450c2..fa609a0929 100644 --- a/functional_unit_testing/build_fortran_tests.py +++ b/functional_unit_testing/build_fortran_tests.py @@ -16,12 +16,14 @@ _CIMEROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../cime") -def run_cmake(name, test_dir, pfunit_path, cmake_args): +def run_cmake(name, test_dir, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_args): """Run cmake for the fortran unit tests Arguments: name (str) - name for output messages test_dir (str) - directory to run Cmake in pfunit_path (str) - path to pfunit + netcdf_c_path (str) - path to netcdf + netcdf_f_path (str) - path to netcdff clean (bool) - clean the build """ if not os.path.isfile("CMakeCache.txt"): @@ -42,6 +44,8 @@ def run_cmake(name, test_dir, pfunit_path, cmake_args): f"-DCIME_CMAKE_MODULE_DIRECTORY={cmake_module_dir}", "-DCMAKE_BUILD_TYPE=CESM_DEBUG", f"-DCMAKE_PREFIX_PATH={pfunit_path}", + f"-DNETCDF_C_PATH={netcdf_c_path}", + f"-DNETCDF_F_PATH={netcdf_f_path}", "-DUSE_MPI_SERIAL=ON", "-DENABLE_GENF90=ON", f"-DCMAKE_PROGRAM_PATH={genf90_dir}" @@ -52,8 +56,8 @@ def run_cmake(name, test_dir, pfunit_path, cmake_args): run_cmd_no_fail(" ".join(cmake_command), combine_output=True) -def find_pfunit(caseroot, cmake_args): - """Find the pfunit installation we'll be using, and print its path +def find_library(caseroot, cmake_args, lib_string): + """Find the library installation we'll be using, and print its path Args: caseroot (str): Directory with pfunit macros @@ -67,14 +71,14 @@ def find_pfunit(caseroot, cmake_args): if ":=" in all_var: expect(all_var.count(":=") == 1, f"Bad makefile: {all_var}") varname, value = [item.strip() for item in all_var.split(":=")] - if varname == "PFUNIT_PATH": + if varname == lib_string: return value - expect(False, "PFUNIT_PATH not found for this machine and compiler") + expect(False, f"{lib_string} not found for this machine and compiler") return None - - + + def prep_build_dir(build_dir, clean): """Create (if necessary) build directory and clean contents (if asked to) @@ -203,14 +207,16 @@ def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False): # create the build directory full_build_path = prep_build_dir(build_dir, clean=clean) - # get cmake args and the pfunit path + # get cmake args and the pfunit and netcdf paths cmake_args = get_extra_cmake_args(full_build_path, "mpi-serial") - pfunit_path = find_pfunit(full_build_path, cmake_args) - + pfunit_path = find_library(full_build_path, cmake_args, "PFUNIT_PATH") + netcdf_c_path = find_library(full_build_path, cmake_args, "NETCDF_C_PATH") + netcdf_f_path = find_library(full_build_path, cmake_args, "NETCDF_FORTRAN_PATH") + # change into the build dir os.chdir(full_build_path) # run cmake and make - run_cmake(name, cmake_directory, pfunit_path, cmake_args) + run_cmake(name, cmake_directory, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_args) run_make(name, make_j, clean=clean) From e5571ed2ba12857595cd6dd8336cb6be910951d9 Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Wed, 17 Apr 2024 14:37:29 -0600 Subject: [PATCH 169/300] get working on derecho, save figures --- .../build_fortran_tests.py | 17 ++++-- functional_unit_testing/run_fates_tests.py | 61 +++++++++++++------ 2 files changed, 57 insertions(+), 21 deletions(-) diff --git a/functional_unit_testing/build_fortran_tests.py b/functional_unit_testing/build_fortran_tests.py index fa609a0929..66556ac189 100644 --- a/functional_unit_testing/build_fortran_tests.py +++ b/functional_unit_testing/build_fortran_tests.py @@ -44,13 +44,17 @@ def run_cmake(name, test_dir, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_a f"-DCIME_CMAKE_MODULE_DIRECTORY={cmake_module_dir}", "-DCMAKE_BUILD_TYPE=CESM_DEBUG", f"-DCMAKE_PREFIX_PATH={pfunit_path}", - f"-DNETCDF_C_PATH={netcdf_c_path}", - f"-DNETCDF_F_PATH={netcdf_f_path}", "-DUSE_MPI_SERIAL=ON", "-DENABLE_GENF90=ON", f"-DCMAKE_PROGRAM_PATH={genf90_dir}" ] + if netcdf_c_path is not None: + cmake_command.append(f"-DNETCDF_C_PATH={netcdf_c_path}") + + if netcdf_f_path is not None: + cmake_command.append(f"-DNETCDF_F_PATH={netcdf_f_path}") + cmake_command.extend(cmake_args.split(" ")) run_cmd_no_fail(" ".join(cmake_command), combine_output=True) @@ -210,8 +214,13 @@ def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False): # get cmake args and the pfunit and netcdf paths cmake_args = get_extra_cmake_args(full_build_path, "mpi-serial") pfunit_path = find_library(full_build_path, cmake_args, "PFUNIT_PATH") - netcdf_c_path = find_library(full_build_path, cmake_args, "NETCDF_C_PATH") - netcdf_f_path = find_library(full_build_path, cmake_args, "NETCDF_FORTRAN_PATH") + + if not "NETCDF" in os.environ: + netcdf_c_path = find_library(full_build_path, cmake_args, "NETCDF_C_PATH") + netcdf_f_path = find_library(full_build_path, cmake_args, "NETCDF_FORTRAN_PATH") + else: + netcdf_c_path = None + netcdf_f_path = None # change into the build dir os.chdir(full_build_path) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 7a429b08a5..3ab6be6941 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -72,7 +72,7 @@ def get_color_pallete(): return colors -def plot_allometry_var(data, var, varname, units): +def plot_allometry_var(data, var, varname, units, save_fig, plot_dir=None): """Plot an allometry variable Args: @@ -80,6 +80,8 @@ def plot_allometry_var(data, var, varname, units): var (str): variable name (for data structure) varname (str): variable name for plot labels units (str): variable units for plot labels + save_fig (bool): whether or not to write out plot + plot_dir (str): if saving figure, where to write to """ df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), 'pft': np.repeat(data.pft, len(data.dbh)), @@ -126,8 +128,12 @@ def plot_allometry_var(data, var, varname, units): plt.title(f"Simulated {varname} for input parameter file", fontsize=11) plt.legend(loc='upper left', title='PFT') + if save_fig: + fig_name = os.path.join(plot_dir, f"allometry_plot_{var}.png") + plt.savefig(fig_name) -def plot_total_biomass(data): + +def plot_total_biomass(data, save_fig, plot_dir): """Plot two calculations of total biomass against each other Args: @@ -169,6 +175,10 @@ def plot_total_biomass(data): plt.ylabel('Total biomass (kgC) from tissues', fontsize=11) plt.title("Simulated total biomass for input parameter file", fontsize=11) plt.legend(loc='upper left', title='PFT') + + if save_fig: + fig_name = os.path.join(plot_dir, "allometry_plot_total_biomass_compare.png") + plt.savefig(fig_name) def create_nc_file(cdl_path, run_dir): """Creates a netcdf file from a cdl file @@ -235,7 +245,7 @@ def run_exectuables(build_dir, test_dir, test_exe, run_dir, args): print(out) -def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file): +def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file, save_figs): """Builds and runs the fates tests Args: @@ -246,6 +256,7 @@ def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file): run_dir (str): run directory make_j (int): number of processors for the build param_file (str): input FATES parameter file + save_figs (bool): whether or not to write figures to file Raises: RuntimeError: Parameter file is not the correct file type @@ -260,6 +271,13 @@ def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file): if not os.path.isdir(run_dir_path): os.mkdir(run_dir_path) + if save_figs: + plot_dir = os.path.join(run_dir_path, 'plots') + if not os.path.isdir(plot_dir): + os.mkdir(plot_dir) + else: + plot_dir = None + if param_file is None: print("Using default parameter file.") param_file = DEFAULT_CDL_PATH @@ -284,19 +302,19 @@ def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file): allometry_dat = xr.open_dataset(os.path.join(run_dir_path, out_file)) # plot allometry data - plot_allometry_var(allometry_dat.height, 'height', 'height', 'm') - plot_allometry_var(allometry_dat.bagw, 'bagw', 'aboveground biomass', 'kgC') - plot_allometry_var(allometry_dat.blmax, 'blmax', 'maximum leaf biomass', 'kgC') - plot_allometry_var(allometry_dat.crown_area, 'crown_area', 'crown area', 'm$^2$') - plot_allometry_var(allometry_dat.sapwood_area, 'sapwood_area', 'sapwood area', 'm$^2$') - plot_allometry_var(allometry_dat.bsap, 'bsap', 'sapwood biomass', 'kgC') - plot_allometry_var(allometry_dat.bbgw, 'bbgw', 'belowground biomass', 'kgC') - plot_allometry_var(allometry_dat.fineroot_biomass, 'fineroot_biomass', 'fineroot biomass', 'kgC') - plot_allometry_var(allometry_dat.bstore, 'bstore', 'storage biomass', 'kgC') - plot_allometry_var(allometry_dat.bdead, 'bdead', 'deadwood biomass', 'kgC') - plot_allometry_var(allometry_dat.total_biomass_parts, 'total_biomass_parts', 'total biomass (calculated from parts)', 'kgC') - plot_allometry_var(allometry_dat.total_biomass_tissues, 'total_biomass_tissues', 'total biomass (calculated from tissues)', 'kgC') - plot_total_biomass(allometry_dat) + plot_allometry_var(allometry_dat.height, 'height', 'height', 'm', save_figs, plot_dir) + plot_allometry_var(allometry_dat.bagw, 'bagw', 'aboveground biomass', 'kgC', save_figs, plot_dir) + plot_allometry_var(allometry_dat.blmax, 'blmax', 'maximum leaf biomass', 'kgC', save_figs, plot_dir) + plot_allometry_var(allometry_dat.crown_area, 'crown_area', 'crown area', 'm$^2$', save_figs, plot_dir) + plot_allometry_var(allometry_dat.sapwood_area, 'sapwood_area', 'sapwood area', 'm$^2$', save_figs, plot_dir) + plot_allometry_var(allometry_dat.bsap, 'bsap', 'sapwood biomass', 'kgC', save_figs, plot_dir) + plot_allometry_var(allometry_dat.bbgw, 'bbgw', 'belowground biomass', 'kgC', save_figs, plot_dir) + plot_allometry_var(allometry_dat.fineroot_biomass, 'fineroot_biomass', 'fineroot biomass', 'kgC', save_figs, plot_dir) + plot_allometry_var(allometry_dat.bstore, 'bstore', 'storage biomass', 'kgC', save_figs, plot_dir) + plot_allometry_var(allometry_dat.bdead, 'bdead', 'deadwood biomass', 'kgC', save_figs, plot_dir) + plot_allometry_var(allometry_dat.total_biomass_parts, 'total_biomass_parts', 'total biomass (calculated from parts)', 'kgC', save_figs, plot_dir) + plot_allometry_var(allometry_dat.total_biomass_tissues, 'total_biomass_tissues', 'total biomass (calculated from tissues)', 'kgC', save_figs, plot_dir) + plot_total_biomass(allometry_dat, save_figs, plot_dir) plt.show() @@ -373,6 +391,14 @@ def commandline_args(): "Script will check to make sure required output files are present.\n", ) + parser.add_argument( + "--save-figs", + action="store_true", + help="Write out generated figures to files.\n" + "Will be placed in run_dir/plots.\n" + "Should probably do this on remote machines.\n", + ) + args = parser.parse_args() check_arg_validity(args) @@ -442,7 +468,8 @@ def main(): build = not args.skip_build run = not args.skip_run - run_tests(args.clean, build, run, args.build_dir, args.run_dir, args.make_j, args.parameter_file) + run_tests(args.clean, build, run, args.build_dir, args.run_dir, args.make_j, + args.parameter_file, args.save_figs) if __name__ == "__main__": From 73cd037372f0f54563340ff5cbe9ddb506d0bff6 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Thu, 18 Apr 2024 10:48:12 -0600 Subject: [PATCH 170/300] Convert an array index from real to int, satisfing nag compiler. --- main/EDInitMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 9185df8197..10bd6224f6 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -482,7 +482,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) end do !hlm_pft else ! for crops, we need to use different logic because the bc_in(s)%pft_areafrac_lu() information only exists for natural PFTs - sites(s)%area_pft(crop_lu_pft_vector(i_landusetype),i_landusetype) = 1._r8 + sites(s)%area_pft(int(crop_lu_pft_vector(i_landusetype)),i_landusetype) = 1._r8 endif end do From c03a4ba64a7e59817658f1c3357ffff681d8b958 Mon Sep 17 00:00:00 2001 From: Sam Rabin Date: Thu, 18 Apr 2024 11:29:48 -0600 Subject: [PATCH 171/300] Change crop_lu_pft_vector from real to int. --- main/EDInitMod.F90 | 2 +- main/EDParamsMod.F90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 10bd6224f6..9185df8197 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -482,7 +482,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) end do !hlm_pft else ! for crops, we need to use different logic because the bc_in(s)%pft_areafrac_lu() information only exists for natural PFTs - sites(s)%area_pft(int(crop_lu_pft_vector(i_landusetype)),i_landusetype) = 1._r8 + sites(s)%area_pft(crop_lu_pft_vector(i_landusetype),i_landusetype) = 1._r8 endif end do diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index f63698afb8..49271eb890 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -260,7 +260,7 @@ module EDParamsMod integer, public :: maxpatch_total ! which crops can be grown on a given crop land use type - real(r8),protected,public :: crop_lu_pft_vector(n_landuse_cats) + integer,protected,public :: crop_lu_pft_vector(n_landuse_cats) ! Maximum allowable cohorts per patch integer, protected, public :: max_cohort_per_patch From 3621cb0259cff493b8653fd15bdb046c18819fd7 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 18 Apr 2024 17:21:32 -0600 Subject: [PATCH 172/300] implement Ryan's fix for the sp mode indexing issue #1182 --- main/FatesInterfaceMod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index 3c2093fa37..99e13fa5f4 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -41,6 +41,7 @@ module FatesInterfaceMod use FatesConstantsMod , only : n_landuse_cats use FatesConstantsMod , only : primaryland use FatesConstantsMod , only : secondaryland + use FatesConstantsMod , only : n_term_mort_types use FatesGlobals , only : fates_global_verbose use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun @@ -877,7 +878,7 @@ subroutine SetFatesGlobalElements2(use_fates) end if fates_maxElementsPerSite = max(fates_maxPatchesPerSite * fates_maxElementsPerPatch, & - numWatermem*numpft, num_vegtemp_mem, num_elements, nlevsclass*numpft) + numWatermem*numpft, num_vegtemp_mem, num_elements, nlevsclass*numpft*n_term_mort_types) if(hlm_use_planthydro==itrue)then fates_maxElementsPerSite = max(fates_maxElementsPerSite, nshell*nlevsoi_hyd_max ) From a3dd198cdbf9371e638d0a98a856e4b1c1080b9c Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 19 Apr 2024 09:53:11 -0600 Subject: [PATCH 173/300] add quadratic test; refactor to allow picking which test to run --- CMakeLists.txt | 3 +- functional_unit_testing/CMakeLists.txt | 3 +- .../allometry/AllometryUtils.py | 179 +++++++ .../allometry/CMakeLists.txt | 9 +- .../allometry/FatesTestAllometry.F90 | 72 ++- .../build_fortran_tests.py | 90 ++-- .../math_utils/CMakeLists.txt | 10 + .../math_utils/FatesTestMathUtils.F90 | 138 ++++++ .../math_utils/MathUtils.py | 34 ++ .../math_utils/MathUtilsDriver.py | 172 ------- functional_unit_testing/math_utils/bld/README | 1 - .../math_utils/build_math_objects.sh | 47 -- .../math_utils/f90_src/UnitWrapMod.F90 | 49 -- functional_unit_testing/path_utils.py | 51 ++ functional_unit_testing/run_fates_tests.py | 451 +++++++----------- functional_unit_testing/utils.py | 111 +++-- 16 files changed, 726 insertions(+), 694 deletions(-) create mode 100644 functional_unit_testing/allometry/AllometryUtils.py create mode 100644 functional_unit_testing/math_utils/CMakeLists.txt create mode 100644 functional_unit_testing/math_utils/FatesTestMathUtils.F90 create mode 100644 functional_unit_testing/math_utils/MathUtils.py delete mode 100644 functional_unit_testing/math_utils/MathUtilsDriver.py delete mode 100644 functional_unit_testing/math_utils/bld/README delete mode 100755 functional_unit_testing/math_utils/build_math_objects.sh delete mode 100644 functional_unit_testing/math_utils/f90_src/UnitWrapMod.F90 create mode 100644 functional_unit_testing/path_utils.py diff --git a/CMakeLists.txt b/CMakeLists.txt index a8822035a8..b8b7b12a08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,4 +87,5 @@ link_directories(${CMAKE_CURRENT_BINARY_DIR}) # has tests in it. However, it appears that the order needs to be done # carefully: for example, include_directories and link_directories needs to be # done before adding the tests themselves. -add_subdirectory(${HLM_ROOT}/src/fates/functional_unit_testing/allometry fates_allom_test) \ No newline at end of file +add_subdirectory(${HLM_ROOT}/src/fates/functional_unit_testing/allometry fates_allom_test) +add_subdirectory(${HLM_ROOT}/src/fates/functional_unit_testing/math_utils fates_math_test) \ No newline at end of file diff --git a/functional_unit_testing/CMakeLists.txt b/functional_unit_testing/CMakeLists.txt index 90d16c8d18..1ab61abfc2 100644 --- a/functional_unit_testing/CMakeLists.txt +++ b/functional_unit_testing/CMakeLists.txt @@ -1 +1,2 @@ -add_subdirectory(allometry) \ No newline at end of file +add_subdirectory(allometry) +add_subdirectory(math_utils) \ No newline at end of file diff --git a/functional_unit_testing/allometry/AllometryUtils.py b/functional_unit_testing/allometry/AllometryUtils.py new file mode 100644 index 0000000000..ac0a285672 --- /dev/null +++ b/functional_unit_testing/allometry/AllometryUtils.py @@ -0,0 +1,179 @@ +"""Utility functions for allometry functional unit tests +""" +import os +import math +import pandas as pd +import numpy as np +import xarray as xr +import matplotlib +import matplotlib.pyplot as plt +from utils import get_color_pallete, round_up + +def plot_allometry_var(data, varname, units, save_fig, plot_dir=None): + """Plot an allometry variable + + Args: + data (xarray DataArray): the data array of the variable to plot + var (str): variable name (for data structure) + varname (str): variable name for plot labels + units (str): variable units for plot labels + save_fig (bool): whether or not to write out plot + plot_dir (str): if saving figure, where to write to + """ + df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), + 'pft': np.repeat(data.pft, len(data.dbh)), + data.name: data.values.flatten()}) + + maxdbh = df['dbh'].max() + maxvar = round_up(df[data.name].max()) + + colors = get_color_pallete() + + plt.figure(figsize=(7, 5)) + ax = plt.subplot(111) + ax.spines["top"].set_visible(False) + ax.spines["bottom"].set_visible(False) + ax.spines["right"].set_visible(False) + ax.spines["left"].set_visible(False) + + ax.get_xaxis().tick_bottom() + ax.get_yaxis().tick_left() + + plt.xlim(0.0, maxdbh) + plt.ylim(0.0, maxvar) + + plt.yticks(fontsize=10) + plt.xticks(fontsize=10) + + inc = (int(maxvar) - 0)/20 + for i in range(0, 20): + y = 0.0 + i*inc + plt.plot(range(math.floor(0), math.ceil(maxdbh)), + [y] * len(range(math.floor(0), math.ceil(maxdbh))), + "--", lw=0.5, color="black", alpha=0.3) + + plt.tick_params(bottom=False, top=False, left=False, right=False) + + pfts = np.unique(df.pft.values) + for rank, pft in enumerate(pfts): + dat = df[df.pft == pft] + plt.plot(dat.dbh.values, dat[data.name].values, lw=2, color=colors[rank], + label=pft) + + plt.xlabel('DBH (cm)', fontsize=11) + plt.ylabel(f'{varname} ({units})', fontsize=11) + plt.title(f"Simulated {varname} for input parameter file", fontsize=11) + plt.legend(loc='upper left', title='PFT') + + if save_fig: + fig_name = os.path.join(plot_dir, f"allometry_plot_{var}.png") + plt.savefig(fig_name) + +def plot_total_biomass(data, save_fig, plot_dir): + """Plot two calculations of total biomass against each other + + Args: + data (xarray DataSet): the allometry dataset + """ + df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), + 'pft': np.repeat(data.pft, len(data.dbh)), + 'total_biomass_parts': data.total_biomass_parts.values.flatten(), + 'total_biomass_tissues': data.total_biomass_tissues.values.flatten()}) + + colors = get_color_pallete() + + plt.figure(figsize=(7, 5)) + ax = plt.subplot(111) + ax.spines["top"].set_visible(False) + ax.spines["bottom"].set_visible(False) + ax.spines["right"].set_visible(False) + ax.spines["left"].set_visible(False) + + ax.get_xaxis().tick_bottom() + ax.get_yaxis().tick_left() + + maxbiomass = np.maximum(df['total_biomass_parts'].max(), df['total_biomass_tissues'].max()) + + plt.xlim(0.0, maxbiomass) + plt.ylim(0.0, maxbiomass) + + plt.yticks(fontsize=10) + plt.xticks(fontsize=10) + plt.tick_params(bottom=False, top=False, left=False, right=False) + + pfts = np.unique(df.pft.values) + for rank, pft in enumerate(pfts): + data = df[df.pft == pft] + plt.scatter(data.total_biomass_parts.values, data.total_biomass_parts.values, + color=colors[rank], label=pft) + + plt.xlabel('Total biomass (kgC) from parts', fontsize=11) + plt.ylabel('Total biomass (kgC) from tissues', fontsize=11) + plt.title("Simulated total biomass for input parameter file", fontsize=11) + plt.legend(loc='upper left', title='PFT') + + if save_fig: + fig_name = os.path.join(plot_dir, "allometry_plot_total_biomass_compare.png") + plt.savefig(fig_name) + +def plot_allometry_dat(run_dir, out_file, save_figs, plot_dir): + + # read in allometry data + allometry_dat = xr.open_dataset(os.path.join(run_dir, out_file)) + + plot_dict = { + 'height': { + 'varname': 'height', + 'units': 'm', + }, + 'bagw': { + 'varname': 'aboveground biomass', + 'units': 'kgC', + }, + 'blmax': { + 'varname': 'maximum leaf biomass', + 'units': 'kgC', + }, + 'crown_area': { + 'varname': 'crown area', + 'units': 'm$^2$', + }, + 'sapwood_area': { + 'varname': 'sapwood area', + 'units': 'm$^2$', + }, + 'bsap': { + 'varname': 'sapwood biomass', + 'units': 'kgC', + }, + 'bbgw': { + 'varname': 'belowground biomass', + 'units': 'kgC', + }, + 'fineroot_biomass': { + 'varname': 'fineroot biomass', + 'units': 'kgC', + }, + 'bstore': { + 'varname': 'storage biomass', + 'units': 'kgC', + }, + 'bdead': { + 'varname': 'deadwood biomass', + 'units': 'kgC', + }, + 'total_biomass_parts': { + 'varname': 'total biomass (calculated from parts)', + 'units': 'kgC', + }, + 'total_biomass_tissues': { + 'varname': 'total biomass (calculated from tissues)', + 'units': 'kgC', + }, + + } + for plot in plot_dict: + plot_allometry_var(allometry_dat[plot], plot_dict[plot]['varname'], + plot_dict[plot]['units'], save_figs, plot_dir) + + plot_total_biomass(allometry_dat, save_figs, plot_dir) \ No newline at end of file diff --git a/functional_unit_testing/allometry/CMakeLists.txt b/functional_unit_testing/allometry/CMakeLists.txt index f43992847d..0a48161e49 100644 --- a/functional_unit_testing/allometry/CMakeLists.txt +++ b/functional_unit_testing/allometry/CMakeLists.txt @@ -16,13 +16,8 @@ link_directories(${NETCDF_C_DIR}/lib add_executable(FATES_allom_exe ${allom_sources}) target_link_libraries(FATES_allom_exe - netcdf + netcdf netcdff fates csm_share - funit) - -add_test(allom_test FATES_allom_exe) - -# Tell CTest how to figure out that "STOP 1" fails for the current -define_Fortran_stop_failure(allom_test) \ No newline at end of file + funit) \ No newline at end of file diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index 5f021d57ed..7ee85b7675 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -12,7 +12,6 @@ program FatesTestAllometry ! LOCALS: type(fates_unit_test_param_reader) :: param_reader ! param reader instance character(len=:), allocatable :: param_file ! input parameter file - character(len=*), parameter :: out_file = 'allometry_out.nc' ! output file integer :: numpft ! number of pfts (from parameter file) integer :: arglen ! length of command line argument integer :: i, j ! looping indices @@ -33,17 +32,18 @@ program FatesTestAllometry real(r8), allocatable :: total_biom_parts(:,:) ! total biomass calculated as bleaf + bfineroot + agbw + bgbw [kgC] ! CONSTANTS: - real(r8), parameter :: min_dbh = 0.5_r8 ! minimum DBH to calculate [cm] - real(r8), parameter :: max_dbh = 200.0_r8 ! maximum DBH to calculate [cm] - real(r8), parameter :: dbh_inc = 0.5_r8 ! DBHncrement to use [cm] - - integer, parameter :: crown_damage = 1 ! crown damage - real(r8), parameter :: elongation_factor = 1.0_r8 ! elongation factor for stem - real(r8), parameter :: elongation_factor_roots = 1.0_r8 ! elongation factor for roots - real(r8), parameter :: site_spread = 1.0_r8 ! site spread - real(r8), parameter :: canopy_trim = 1.0_r8 ! canopy trim - real(r8), parameter :: nplant = 1.0_r8 ! number of plants per cohort - real(r8), parameter :: leaf_to_fineroot = 1.0_r8 ! leaf to fineroot ratio + character(len=*), parameter :: out_file = 'allometry_out.nc' ! output file + real(r8), parameter :: min_dbh = 0.5_r8 ! minimum DBH to calculate [cm] + real(r8), parameter :: max_dbh = 200.0_r8 ! maximum DBH to calculate [cm] + real(r8), parameter :: dbh_inc = 0.5_r8 ! DBH increment to use [cm] + + integer, parameter :: crown_damage = 1 ! crown damage + real(r8), parameter :: elongation_factor = 1.0_r8 ! elongation factor for stem + real(r8), parameter :: elongation_factor_roots = 1.0_r8 ! elongation factor for roots + real(r8), parameter :: site_spread = 1.0_r8 ! site spread + real(r8), parameter :: canopy_trim = 1.0_r8 ! canopy trim + real(r8), parameter :: nplant = 1.0_r8 ! number of plants per cohort + real(r8), parameter :: leaf_to_fineroot = 1.0_r8 ! leaf to fineroot ratio interface @@ -66,9 +66,9 @@ subroutine WriteAllometryData(out_file, ndbh, numpft, dbh, height, bagw, blmax, real(r8), intent(in) :: crown_area(:, :) real(r8), intent(in) :: sapwood_area(:, :) real(r8), intent(in) :: bsap(:, :) - real(r8), intent(in) :: bbgw(:, :) - real(r8), intent(in) :: fineroot_biomass(:, :) - real(r8), intent(in) :: bstore(:, :) + real(r8), intent(in) :: bbgw(:, :) + real(r8), intent(in) :: fineroot_biomass(:, :) + real(r8), intent(in) :: bstore(:, :) real(r8), intent(in) :: bdead(:, :) real(r8), intent(in) :: total_biom_parts(:, :) real(r8), intent(in) :: total_biom_tissues(:, :) @@ -79,14 +79,14 @@ end subroutine WriteAllometryData ! get parameter file from command-line argument nargs = command_argument_count() if (nargs /= 1) then - write(*, '(a, i2, a)') "Incorrect number of arguments: ", nargs, ". Should be 1" + write(*, '(a, i2, a)') "Incorrect number of arguments: ", nargs, ". Should be 1." stop else call get_command_argument(1, length=arglen) allocate(character(arglen) :: param_file) call get_command_argument(1, value=param_file) endif - + ! read in parameter file call param_reader%Init(param_file) call param_reader%RetrieveParameters() @@ -94,7 +94,7 @@ end subroutine WriteAllometryData ! determine sizes of arrays numpft = size(prt_params%wood_density, dim=1) numdbh = int((max_dbh - min_dbh)/dbh_inc + 1) - + ! allocate arrays allocate(dbh(numdbh)) allocate(height(numdbh, numpft)) @@ -109,16 +109,12 @@ end subroutine WriteAllometryData allocate(bdead(numdbh, numpft)) allocate(total_biom_parts(numdbh, numpft)) allocate(total_biom_tissues(numdbh, numpft)) - + ! initialize dbh array do i = 1, numdbh dbh(i) = min_dbh + dbh_inc*(i-1) end do - ! total biomass = bleaf + bfineroot + agbw + bgbw - ! ... or ... - ! total biomass = bleaf + bfineroot + bdead + bsap - ! calculate allometries do i = 1, numpft do j = 1, numdbh @@ -142,7 +138,7 @@ end subroutine WriteAllometryData call WriteAllometryData(out_file, numdbh, numpft, dbh, height, bagw, blmax, crown_area, & sapwood_area, bsap, bbgw, fineroot_biomass, bstore, bdead, total_biom_parts, & total_biom_tissues) - + end program FatesTestAllometry ! ---------------------------------------------------------------------------------------- @@ -193,7 +189,7 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height, bagw, blmax integer :: bbgwID, finerootID integer :: bstoreID, bdeadID integer :: totbiomID1, totbiomID2 - + ! create pft indices allocate(pft_indices(numpft)) do i = 1, numpft @@ -222,73 +218,73 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height, bagw, blmax ! register height call RegisterVar2D(ncid, 'height', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'm', 'plant height'], & + [character(len=150) :: 'pft dbh', 'm', 'plant height'], & 3, heightID) ! register aboveground biomass call RegisterVar2D(ncid, 'bagw', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'kgC', 'plant aboveground woody biomass'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant aboveground woody biomass'], & 3, bagwID) ! register leaf biomass call RegisterVar2D(ncid, 'blmax', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'kgC', 'plant maximum leaf biomass'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant maximum leaf biomass'], & 3, blmaxID) ! register crown area call RegisterVar2D(ncid, 'crown_area', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'm2', 'plant crown area per cohort'], & + [character(len=150) :: 'pft dbh', 'm2', 'plant crown area per cohort'], & 3, c_areaID) ! register sapwood area call RegisterVar2D(ncid, 'sapwood_area', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'm2', 'plant cross section area sapwood at reference height'], & + [character(len=150) :: 'pft dbh', 'm2', 'plant cross section area sapwood at reference height'], & 3, sapwoodareaID) - + ! register sapwood biomass call RegisterVar2D(ncid, 'bsap', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'kgC', 'plant sapwood biomass'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant sapwood biomass'], & 3, bsapID) ! register belowground woody biomass call RegisterVar2D(ncid, 'bbgw', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'kgC', 'plant belowground woody biomass'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant belowground woody biomass'], & 3, bbgwID) ! register fineroot biomass call RegisterVar2D(ncid, 'fineroot_biomass', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'kgC', 'plant fineroot biomass'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant fineroot biomass'], & 3, finerootID) ! register storage biomass call RegisterVar2D(ncid, 'bstore', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'kgC', 'plant storage biomass'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant storage biomass'], & 3, bstoreID) ! register structural biomass call RegisterVar2D(ncid, 'bdead', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'kgC', 'plant deadwood (structural/heartwood) biomass'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant deadwood (structural/heartwood) biomass'], & 3, bdeadID) ! register total biomass (parts) call RegisterVar2D(ncid, 'total_biomass_parts', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'kgC', 'plant total biomass calculated from parts'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant total biomass calculated from parts'], & 3, totbiomID1) ! register total biomass (tissues) call RegisterVar2D(ncid, 'total_biomass_tissues', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & - [character(len=150) :: 'pft dbh', 'kgC', 'plant total biomass calculated from tissues'], & + [character(len=150) :: 'pft dbh', 'kgC', 'plant total biomass calculated from tissues'], & 3, totbiomID2) diff --git a/functional_unit_testing/build_fortran_tests.py b/functional_unit_testing/build_fortran_tests.py index 66556ac189..ef6d6577e9 100644 --- a/functional_unit_testing/build_fortran_tests.py +++ b/functional_unit_testing/build_fortran_tests.py @@ -28,13 +28,13 @@ def run_cmake(name, test_dir, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_a """ if not os.path.isfile("CMakeCache.txt"): print(f"Running cmake for {name}.") - + # directory with cmake modules cmake_module_dir = os.path.abspath(os.path.join(_CIMEROOT, "CIME", "non_py", "src", "CMake")) - + # directory with genf90 genf90_dir = os.path.join(_CIMEROOT, "CIME", "non_py", "externals", "genf90") - + cmake_command = [ "cmake", "-C Macros.cmake", @@ -48,17 +48,16 @@ def run_cmake(name, test_dir, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_a "-DENABLE_GENF90=ON", f"-DCMAKE_PROGRAM_PATH={genf90_dir}" ] - + if netcdf_c_path is not None: cmake_command.append(f"-DNETCDF_C_PATH={netcdf_c_path}") - + if netcdf_f_path is not None: cmake_command.append(f"-DNETCDF_F_PATH={netcdf_f_path}") - + cmake_command.extend(cmake_args.split(" ")) - - run_cmd_no_fail(" ".join(cmake_command), combine_output=True) + run_cmd_no_fail(" ".join(cmake_command), combine_output=True) def find_library(caseroot, cmake_args, lib_string): """Find the library installation we'll be using, and print its path @@ -79,10 +78,9 @@ def find_library(caseroot, cmake_args, lib_string): return value expect(False, f"{lib_string} not found for this machine and compiler") - + return None - - + def prep_build_dir(build_dir, clean): """Create (if necessary) build directory and clean contents (if asked to) @@ -90,36 +88,35 @@ def prep_build_dir(build_dir, clean): build_dir (str): build directory name clean (bool): whether or not to clean contents """ - + # create the build directory build_dir_path = os.path.abspath(build_dir) if not os.path.isdir(build_dir_path): os.mkdir(build_dir_path) - + # change into that directory os.chdir(build_dir_path) - + # clean up any files if we want to if clean: clean_cmake_files() - - return build_dir_path + return build_dir_path def clean_cmake_files(): """Deletes all files related to build - + """ if os.path.isfile("CMakeCache.txt"): os.remove("CMakeCache.txt") if os.path.isdir("CMakeFiles"): shutil.rmtree("CMakeFiles") - + cwd_contents = os.listdir(os.getcwd()) - + # Clear contents to do with cmake cache for file in cwd_contents: - if ( + if ( file in ("Macros.cmake", "env_mach_specific.xml") or file.startswith("Depends") or file.startswith(".env_mach_specific") @@ -134,13 +131,13 @@ def get_extra_cmake_args(build_dir, mpilib): """ # get the machine objects file machobj = Machines() - + # get compiler compiler = machobj.get_default_compiler() - + # get operating system os_ = machobj.get_value("OS") - + # Create the environment, and the Macros.cmake file # # @@ -156,10 +153,10 @@ def get_extra_cmake_args(build_dir, mpilib): unit_testing=True, ) machspecific = EnvMachSpecific(build_dir, unit_testing=True) - + # make a fake case fake_case = FakeCase(compiler, mpilib, True, "nuopc", threading=False) - + cmake_args = ( "{}-DOS={} -DMACH={} -DCOMPILER={} -DDEBUG={} -DMPILIB={} -Dcompile_threaded={} -DCASEROOT={}".format( "", @@ -172,9 +169,9 @@ def get_extra_cmake_args(build_dir, mpilib): build_dir ) ) - + return cmake_args - + def run_make(name, make_j, clean=False, verbose=False): """Run make in current working directory @@ -184,19 +181,40 @@ def run_make(name, make_j, clean=False, verbose=False): clean (bool, optional): whether or not to clean Defaults to False. verbose (bool, optional): verbose error logging for make Defaults to False. """ - + print(f"Running make for {name}.") - + if clean: run_cmd_no_fail("make clean") - + make_command = ["make", "-j", str(make_j)] - + if verbose: make_command.append("VERBOSE=1") - + run_cmd_no_fail(" ".join(make_command), combine_output=True) +def build_exists(build_dir, test_dir, test_exe=None): + """Checks to see if the build directory and associated executables exist. + + Args: + build_dir (str): build directory + test_dir (str): test directory + test_exe (str): test executable + """ + + build_path = os.path.abspath(build_dir) + if not os.path.isdir(build_path): + return False + + if not os.path.isdir(os.path.join(build_path, test_dir)): + return False + + if test_exe is not None: + if not os.path.isfile(os.path.join(build_path, test_dir, test_exe)): + return False + + return True def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False): """Build the unit test executables @@ -210,21 +228,21 @@ def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False): """ # create the build directory full_build_path = prep_build_dir(build_dir, clean=clean) - + # get cmake args and the pfunit and netcdf paths cmake_args = get_extra_cmake_args(full_build_path, "mpi-serial") pfunit_path = find_library(full_build_path, cmake_args, "PFUNIT_PATH") - + if not "NETCDF" in os.environ: netcdf_c_path = find_library(full_build_path, cmake_args, "NETCDF_C_PATH") netcdf_f_path = find_library(full_build_path, cmake_args, "NETCDF_FORTRAN_PATH") else: netcdf_c_path = None netcdf_f_path = None - + # change into the build dir os.chdir(full_build_path) - + # run cmake and make run_cmake(name, cmake_directory, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_args) run_make(name, make_j, clean=clean) diff --git a/functional_unit_testing/math_utils/CMakeLists.txt b/functional_unit_testing/math_utils/CMakeLists.txt new file mode 100644 index 0000000000..e23eac3dcf --- /dev/null +++ b/functional_unit_testing/math_utils/CMakeLists.txt @@ -0,0 +1,10 @@ +set(math_sources FatesTestMathUtils.F90) + +link_directories(${PFUNIT_TOP_DIR}/lib) + +add_executable(FATES_math_exe ${math_sources}) + +target_link_libraries(FATES_math_exe + fates + csm_share + funit) \ No newline at end of file diff --git a/functional_unit_testing/math_utils/FatesTestMathUtils.F90 b/functional_unit_testing/math_utils/FatesTestMathUtils.F90 new file mode 100644 index 0000000000..f13b888d47 --- /dev/null +++ b/functional_unit_testing/math_utils/FatesTestMathUtils.F90 @@ -0,0 +1,138 @@ +program FatesTestQuadSolvers + + use FatesConstantsMod, only : r8 => fates_r8 + use FatesUtilsMod, only : QuadraticRootsNSWC, QuadraticRootsSridharachary + use FatesUtilsMod, only : GetNeighborDistance + + implicit none + + ! CONSTANTS: + integer, parameter :: n = 4 ! number of points to test + character(len=*), parameter :: out_file = 'quad_out.nc' ! output file + + + ! LOCALS: + integer :: i ! looping index + real(r8) :: a(n), b(n), c(n) ! coefficients for quadratic solvers + real(r8) :: root1(n) ! real part of first root of quadratic solver + real(r8) :: root2(n) ! real part of second root of quadratic solver + + interface + + subroutine WriteQuadData(out_file, n, a, b, c, root1, root2) + + use FatesUnitTestIOMod, only : OpenNCFile, RegisterNCDims, CloseNCFile + use FatesUnitTestIOMod, only : RegisterVar1D, WriteVar, RegisterVar2D + use FatesUnitTestIOMod, only : type_double, type_int + use FatesConstantsMod, only : r8 => fates_r8 + implicit none + + character(len=*), intent(in) :: out_file + integer, intent(in) :: n + real(r8), intent(in) :: a(:) + real(r8), intent(in) :: b(:) + real(r8), intent(in) :: c(:) + real(r8), intent(in) :: root1(:) + real(r8), intent(in) :: root2(:) + end subroutine WriteQuadData + + end interface + + a = (/1.0_r8, 1.0_r8, 5.0_r8, 1.5_r8/) + b = (/-2.0_r8, 7.0_r8, 10.0_r8, 3.2_r8/) + c = (/1.0_r8, 12.0_r8, 3.0_r8, 1.1_r8/) + + do i = 1, n + call QuadraticRootsNSWC(a(i), b(i), c(i), root1(i), root2(i)) + end do + + call WriteQuadData(out_file, n, a, b, c, root1, root2) + +end program FatesTestQuadSolvers + +! ---------------------------------------------------------------------------------------- + +subroutine WriteQuadData(out_file, n, a, b, c, root1, root2) + ! + ! DESCRIPTION: + ! Writes out data from the quadratic solver test + ! + use FatesConstantsMod, only : r8 => fates_r8 + use FatesUnitTestIOMod, only : OpenNCFile, RegisterNCDims, CloseNCFile + use FatesUnitTestIOMod, only : RegisterVar1D, WriteVar, RegisterVar2D + use FatesUnitTestIOMod, only : EndNCDef + use FatesUnitTestIOMod, only : type_double, type_int + + implicit none + + ! ARGUMENTS: + character(len=*), intent(in) :: out_file ! output file name + integer, intent(in) :: n ! number of points to write out + real(r8), intent(in) :: a(:) ! coefficient a + real(r8), intent(in) :: b(:) ! coefficient b + real(r8), intent(in) :: c(:) ! coefficient c + real(r8), intent(in) :: root1(:) ! root1 from quadratic solver + real(r8), intent(in) :: root2(:) ! root2 from quadratic solver + + ! LOCALS: + integer :: n_index(n) ! array of pft indices to write out + integer :: i ! looping index + integer :: ncid ! netcdf file id + character(len=8) :: dim_names(1) ! dimension names + integer :: dimIDs(1) ! dimension IDs + integer :: aID, bID, cID + integer :: root1ID, root2ID + + ! make index + do i = 1, n + n_index(i) = i + end do + + ! dimension names + dim_names = [character(len=12) :: 'n'] + + ! open file + call OpenNCFile(trim(out_file), ncid, 'readwrite') + + ! register dimensions + call RegisterNCDims(ncid, dim_names, (/n/), 1, dimIDs) + + ! register a + call RegisterVar1D(ncid, 'a', dimIDs(1), type_double, & + [character(len=20) :: 'units', 'long_name'], & + [character(len=150) :: '', 'coefficient a'], 2, aID) + + ! register b + call RegisterVar1D(ncid, 'b', dimIDs(1), type_double, & + [character(len=20) :: 'units', 'long_name'], & + [character(len=150) :: '', 'coefficient b'], 2, bID) + + ! register c + call RegisterVar1D(ncid, 'c', dimIDs(1), type_double, & + [character(len=20) :: 'units', 'long_name'], & + [character(len=150) :: '', 'coefficient c'], 2, cID) + + ! register root1 + call RegisterVar1D(ncid, 'root1', dimIDs(1), type_double, & + [character(len=20) :: 'units', 'long_name'], & + [character(len=150) :: '', 'root 1'], 2, root1ID) + + ! register root2 + call RegisterVar1D(ncid, 'root2', dimIDs(1), type_double, & + [character(len=20) :: 'units', 'long_name'], & + [character(len=150) :: '', 'root 2'], 2, root2ID) + + ! finish defining variables + call EndNCDef(ncid) + + ! write out data + call WriteVar(ncid, aID, a(:)) + call WriteVar(ncid, bID, b(:)) + call WriteVar(ncid, cID, c(:)) + call WriteVar(ncid, root1ID, root1(:)) + call WriteVar(ncid, root2ID, root2(:)) + + ! close the file + call CloseNCFile(ncid) + +end subroutine WriteQuadData diff --git a/functional_unit_testing/math_utils/MathUtils.py b/functional_unit_testing/math_utils/MathUtils.py new file mode 100644 index 0000000000..63c68ae820 --- /dev/null +++ b/functional_unit_testing/math_utils/MathUtils.py @@ -0,0 +1,34 @@ +"""Utility functions for allometry functional unit tests +""" +import os +import math +import xarray as xr +import pandas as pd +import numpy as np +import matplotlib +import matplotlib.pyplot as plt + +from utils import get_color_pallete + +def plot_quadratic_dat(run_dir, out_file, save_figs, plot_dir): + + # read in quadratic data + quadratic_dat = xr.open_dataset(os.path.join(run_dir, out_file)) + + # plot output + PlotQuadAndRoots(quadratic_dat.a.values, quadratic_dat.b.values, + quadratic_dat.c.values, quadratic_dat.root1.values, + quadratic_dat.root2.values) + +def PlotQuadAndRoots(a, b, c, r1, r2): + + colors = get_color_pallete() + + fig, axs = plt.subplots(ncols=1, nrows=1, figsize=(8,8)) + x = np.linspace(-10.0, 10.0, num=20) + + for i in range(0, len(a)): + y = a[i]*x**2 + b[i]*x + c[i] + plt.plot(x, y, lw=2, color=colors[i]) + plt.scatter(r1[i], r2[i], color=colors[i], s=50) + plt.axhline(y=0.0, color='k', linestyle='dotted') diff --git a/functional_unit_testing/math_utils/MathUtilsDriver.py b/functional_unit_testing/math_utils/MathUtilsDriver.py deleted file mode 100644 index 4add288126..0000000000 --- a/functional_unit_testing/math_utils/MathUtilsDriver.py +++ /dev/null @@ -1,172 +0,0 @@ -# ======================================================================================= -# -# For usage: $python HydroUTestDriver.py --help -# -# This script runs unit tests on the hydraulics functions. -# -# -# ======================================================================================= - -import matplotlib as mpl -#mpl.use('Agg') -import matplotlib.pyplot as plt -from datetime import datetime -import argparse -#from matplotlib.backends.backend_pdf import PdfPages -import platform -import numpy as np -import os -import sys -import getopt -import code # For development: code.interact(local=dict(globals(), **locals())) -import time -import imp -import ctypes -from ctypes import * -from operator import add - - -#CDLParse = imp.load_source('CDLParse','../shared/py_src/CDLParse.py') -#F90ParamParse = imp.load_source('F90ParamParse','../shared/py_src/F90ParamParse.py') -PyF90Utils = imp.load_source('PyF90Utils','../shared/py_src/PyF90Utils.py') - - -#from CDLParse import CDLParseDims, CDLParseParam, cdl_param_type -#from F90ParamParse import f90_param_type, GetSymbolUsage, GetPFTParmFileSymbols, MakeListUnique - -from PyF90Utils import c8, ci, cchar, c8_arr, ci_arr - -# Load the fortran objects via CTYPES - -f90_unitwrap_obj = ctypes.CDLL('bld/UnitWrapMod.o',mode=ctypes.RTLD_GLOBAL) -f90_constants_obj = ctypes.CDLL('bld/FatesConstantsMod.o',mode=ctypes.RTLD_GLOBAL) -f90_fatesutils_obj = ctypes.CDLL('bld/FatesUtilsMod.o',mode=ctypes.RTLD_GLOBAL) - -# Alias the F90 functions, specify the return type -# ----------------------------------------------------------------------------------- - -neighbor_dist = f90_fatesutils_obj.__fatesutilsmod_MOD_getneighbordistance -#quadratic_f = f90_fatesutils_obj.__fatesutilsmod_MOD_quadratic_f -quadratic_roots = f90_fatesutils_obj.__fatesutilsmod_MOD_quadraticroots -quadratic_sroots = f90_fatesutils_obj.__fatesutilsmod_MOD_quadraticrootssridharachary - -# Some constants -rwcft = [1.0,0.958,0.958,0.958] -rwccap = [1.0,0.947,0.947,0.947] -pm_leaf = 1 -pm_stem = 2 -pm_troot = 3 -pm_aroot = 4 -pm_rhiz = 5 - -# These parameters are matched with the indices in FATES-HYDRO -vg_type = 1 -cch_type = 2 -tfs_type = 3 - -isoil1 = 0 # Top soil layer parameters (@BCI) -isoil2 = 1 # Bottom soil layer parameters - -# Constants for rhizosphere -watsat = [0.567, 0.444] -sucsat = [159.659, 256.094] -bsw = [6.408, 9.27] - -unconstrained = True - - -# ======================================================================================== -# ======================================================================================== -# Main -# ======================================================================================== -# ======================================================================================== - -def main(argv): - - # First check to make sure python 2.7 is being used - version = platform.python_version() - verlist = version.split('.') - - #if( not ((verlist[0] == '2') & (verlist[1] == '7') & (int(verlist[2])>=15) ) ): - # print("The PARTEH driver mus be run with python 2.7") - # print(" with tertiary version >=15.") - # print(" your version is {}".format(version)) - # print(" exiting...") - # sys.exit(2) - - # Read in the arguments - # ======================================================================================= - - # parser = argparse.ArgumentParser(description='Parse command line arguments to this script.') - # parser.add_argument('--cdl-file', dest='cdlfile', type=str, \ - # help="Input CDL filename. Required.", required=True) - # args = parser.parse_args() - - # Set number of analysis points - - # y = ax2 + bx + c - - a = [1,1,5,1.5] - b = [-2,7,10,3.2] - c = [1,12,3,1.1] - - cd_r1 = c_double(-9.0) - cd_r2 = c_double(-9.0) - - r1 = np.zeros([3,1]) - r2 = np.zeros([3,1]) - - for ic in range(len(a)): - - #iret = quadratic_f(c8(a[ic]),c8(b[ic]),c8(c[ic]),byref(cd_r1),byref(cd_r2)) - #r1[0] = cd_r1.value - #r2[0] = cd_r2.value - - iret = quadratic_roots(c8(a[ic]),c8(b[ic]),c8(c[ic]),byref(cd_r1),byref(cd_r2)) - r1[1] = cd_r1.value - r2[1] = cd_r2.value - - iret = quadratic_sroots(c8(a[ic]),c8(b[ic]),c8(c[ic]),byref(cd_r1),byref(cd_r2)) - r1[2] = cd_r2.value - r2[2] = cd_r1.value - - print(a[ic],b[ic],c[ic]) - print(r1) - print(r2) - - #PlotQuadAndRoots(a[ic],b[ic],c[ic],r1,r2) - - -def PlotQuadAndRoots(a,b,c,d,r1,r2): - - fig, axs = plt.subplots(ncols=1,nrows=1,figsize=(8,8)) - ax1s = axs.reshape(-1) - ic=0 - - npts = 1000 - - for i in range(npts): - print(i) - - - -# code.interact(local=dict(globals(), **locals())) - -# Helper code to plot negative logs - -def semilogneg(x): - - y = np.sign(x)*np.log(abs(x)) - return(y) - -def semilog10net(x): - - y = np.sign(x)*np.log10(abs(x)) - return(y) - - -# ======================================================================================= -# This is the actual call to main - -if __name__ == "__main__": - main(sys.argv) diff --git a/functional_unit_testing/math_utils/bld/README b/functional_unit_testing/math_utils/bld/README deleted file mode 100644 index 4e67e5f091..0000000000 --- a/functional_unit_testing/math_utils/bld/README +++ /dev/null @@ -1 +0,0 @@ -PLACEHOLDER FOR DIR \ No newline at end of file diff --git a/functional_unit_testing/math_utils/build_math_objects.sh b/functional_unit_testing/math_utils/build_math_objects.sh deleted file mode 100755 index 40ac3eb9d1..0000000000 --- a/functional_unit_testing/math_utils/build_math_objects.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -# Path to FATES src - -FC='gfortran' - -F_OPTS="-shared -fPIC -g -ffpe-trap=zero,overflow,underflow -fbacktrace -fbounds-check" -#F_OPTS="-shared -fPIC -O" - - -MOD_FLAG="-J" - -rm -f bld/*.o -rm -f bld/*.mod - - -# First copy over the FatesConstants file, but change the types of the fates_r8 and fates_int - -old_fates_r8_str=`grep -e integer ../../main/FatesConstantsMod.F90 | grep fates_r8 | sed 's/^[ \t]*//;s/[ \t]*$//'` -new_fates_r8_str='use iso_c_binding, only: fates_r8 => c_double' - -old_fates_int_str=`grep -e integer ../../main/FatesConstantsMod.F90 | grep fates_int | sed 's/^[ \t]*//;s/[ \t]*$//'` -new_fates_int_str='use iso_c_binding, only: fates_int => c_int' - -# Add the new lines (need position change, don't swap) - -sed "/implicit none/i $new_fates_r8_str" ../../main/FatesConstantsMod.F90 > f90_src/FatesConstantsMod.F90 -sed -i "/implicit none/i $new_fates_int_str" f90_src/FatesConstantsMod.F90 -sed -i "/private /i public :: fates_r8" f90_src/FatesConstantsMod.F90 -sed -i "/private /i public :: fates_int" f90_src/FatesConstantsMod.F90 - -# Delete the old lines - -sed -i "/$old_fates_r8_str/d" f90_src/FatesConstantsMod.F90 -sed -i "/$old_fates_int_str/d" f90_src/FatesConstantsMod.F90 - -# Build the new file with constants - -${FC} ${F_OPTS} -I bld/ ${MOD_FLAG} bld/ -o bld/FatesConstantsMod.o f90_src/FatesConstantsMod.F90 - -${FC} ${F_OPTS} -I bld/ ${MOD_FLAG} bld/ -o bld/UnitWrapMod.o f90_src/UnitWrapMod.F90 - -${FC} ${F_OPTS} -I bld/ ${MOD_FLAG} bld/ -o bld/FatesUtilsMod.o ../../main/FatesUtilsMod.F90 - - - - diff --git a/functional_unit_testing/math_utils/f90_src/UnitWrapMod.F90 b/functional_unit_testing/math_utils/f90_src/UnitWrapMod.F90 deleted file mode 100644 index f12311655a..0000000000 --- a/functional_unit_testing/math_utils/f90_src/UnitWrapMod.F90 +++ /dev/null @@ -1,49 +0,0 @@ - -! ======================================================================================= -! -! This file is an alternative to key files in the fates -! filesystem. Noteably, we replace fates_r8 and fates_in -! with types that work with "ctypes". This is -! a key step in working with python -! -! We also wrap FatesGlobals to reduce the dependancy -! cascade that it pulls in from shr_log_mod. -! -! ======================================================================================= - -module shr_log_mod - - use iso_c_binding, only : c_char - use iso_c_binding, only : c_int - - contains - - function shr_log_errMsg(source, line) result(ans) - character(kind=c_char,len=*), intent(in) :: source - integer(c_int), intent(in) :: line - character(kind=c_char,len=128) :: ans - - ans = "source: " // trim(source) // " line: " - end function shr_log_errMsg - -end module shr_log_mod - - -module FatesGlobals - - contains - - integer function fates_log() - fates_log = -1 - end function fates_log - - subroutine fates_endrun(msg) - - implicit none - character(len=*), intent(in) :: msg ! string to be printed - - stop - - end subroutine fates_endrun - -end module FatesGlobals diff --git a/functional_unit_testing/path_utils.py b/functional_unit_testing/path_utils.py new file mode 100644 index 0000000000..85aea6085a --- /dev/null +++ b/functional_unit_testing/path_utils.py @@ -0,0 +1,51 @@ +"""Utility functions related to getting paths to various important places +""" + +import os +import sys + +# Path to the root directory of FATES, based on the path of this file +# Note: It's important that this NOT end with a trailing slash; +_FATES_ROOT = os.path.normpath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir) +) + +def path_to_fates_root(): + """Returns the path to the root directory of FATES""" + return _FATES_ROOT + +def path_to_cime(): + """Returns the path to cime, if it can be found + + Raises a RuntimeError if it cannot be found + + """ + cime_path = os.path.join(path_to_fates_root(), "../../cime") + if os.path.isdir(cime_path): + return cime_path + raise RuntimeError("Cannot find cime.") + +def prepend_to_python_path(path): + """Adds the given path to python's sys.path if it isn't already in the path + + The path is added near the beginning, so that it takes precedence over existing + entries in the path + """ + if not path in sys.path: + # Insert at location 1 rather than 0, because 0 is special + sys.path.insert(1, path) + +def add_cime_lib_to_path(): + """Adds the CIME python library to the python path, to allow importing + modules from that library + + Returns the path to the top-level cime directory + + For documentation on standalone_only: See documentation in + path_to_cime + """ + cime_path = path_to_cime() + prepend_to_python_path(cime_path) + cime_lib_path = os.path.join(cime_path, "CIME", "Tools") + prepend_to_python_path(cime_lib_path) + return cime_path diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 3ab6be6941..ed3e64b1bf 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -14,7 +14,7 @@ so you should still get these repositories as you normally would (i.e., manage_externals, etc.) Additionally, this requires netcdf and netcdff as well as a fortran compiler. - + You must also have a .cime folder in your home directory which specifies machine configurations for CIME. @@ -22,203 +22,51 @@ relevant output from those tests. You can supply your own parameter file (either a .cdl or a .nc file), or if you do not -specify anything, the sript will use the default FATES parameter cdl file. +specify anything, the script will use the default FATES parameter cdl file. """ - import os -import math import argparse - -from build_fortran_tests import build_unit_tests -import pandas as pd -import numpy as np -import xarray as xr import matplotlib import matplotlib.pyplot as plt +from build_fortran_tests import build_unit_tests, build_exists +from path_utils import add_cime_lib_to_path +from utils import round_up, copy_file, create_nc_file +from allometry.AllometryUtils import plot_allometry_dat +from math_utils.MathUtils import plot_quadratic_dat -from utils import add_cime_lib_to_path, round_up add_cime_lib_to_path() from CIME.utils import run_cmd_no_fail +# Constants for this script DEFAULT_CDL_PATH = os.path.abspath("../parameter_files/fates_params_default.cdl") CMAKE_BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../") NAME = "fates_unit_tests" -# Constants for now -## TODO update this to be some kind of dictionary we can loop through -out_file = "allometry_out.nc" -test_dir = "fates_allom_test" -test_exe = "FATES_allom_exe" - -def get_color_pallete(): - """Generate a color pallete - - Returns: - real: array of colors to use in plotting - """ - - colors = [(31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120), - (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150), - (148, 103, 189), (197, 176, 213), (140, 86, 75), (196, 156, 148), - (227, 119, 194), (247, 182, 210), (127, 127, 127), (199, 199, 199), - (188, 189, 34), (219, 219, 141), (23, 190, 207), (158, 218, 229)] - - for i in range(len(colors)): - r, g, b = colors[i] - colors[i] = (r/255., g/255., b/255.) - - return colors - - -def plot_allometry_var(data, var, varname, units, save_fig, plot_dir=None): - """Plot an allometry variable - - Args: - data (xarray DataArray): the data array of the variable to plot - var (str): variable name (for data structure) - varname (str): variable name for plot labels - units (str): variable units for plot labels - save_fig (bool): whether or not to write out plot - plot_dir (str): if saving figure, where to write to - """ - df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), - 'pft': np.repeat(data.pft, len(data.dbh)), - var: data.values.flatten()}) - - maxdbh = df['dbh'].max() - maxvar = round_up(df[var].max()) - - colors = get_color_pallete() - - plt.figure(figsize=(7, 5)) - ax = plt.subplot(111) - ax.spines["top"].set_visible(False) - ax.spines["bottom"].set_visible(False) - ax.spines["right"].set_visible(False) - ax.spines["left"].set_visible(False) - - ax.get_xaxis().tick_bottom() - ax.get_yaxis().tick_left() - - plt.xlim(0.0, maxdbh) - plt.ylim(0.0, maxvar) - - plt.yticks(fontsize=10) - plt.xticks(fontsize=10) - - inc = (int(maxvar) - 0)/20 - for i in range(0, 20): - y = 0.0 + i*inc - plt.plot(range(math.floor(0), math.ceil(maxdbh)), - [y] * len(range(math.floor(0), math.ceil(maxdbh))), - "--", lw=0.5, color="black", alpha=0.3) - - plt.tick_params(bottom=False, top=False, left=False, right=False) - - pfts = np.unique(df.pft.values) - for rank, pft in enumerate(pfts): - data = df[df.pft == pft] - plt.plot(data.dbh.values, data[var].values, lw=2, color=colors[rank], - label=pft) - - plt.xlabel('DBH (cm)', fontsize=11) - plt.ylabel(f'{varname} ({units})', fontsize=11) - plt.title(f"Simulated {varname} for input parameter file", fontsize=11) - plt.legend(loc='upper left', title='PFT') - - if save_fig: - fig_name = os.path.join(plot_dir, f"allometry_plot_{var}.png") - plt.savefig(fig_name) - - -def plot_total_biomass(data, save_fig, plot_dir): - """Plot two calculations of total biomass against each other - - Args: - data (xarray DataSet): the allometry dataset - """ - df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), - 'pft': np.repeat(data.pft, len(data.dbh)), - 'total_biomass_parts': data.total_biomass_parts.values.flatten(), - 'total_biomass_tissues': data.total_biomass_tissues.values.flatten()}) - - colors = get_color_pallete() - - plt.figure(figsize=(7, 5)) - ax = plt.subplot(111) - ax.spines["top"].set_visible(False) - ax.spines["bottom"].set_visible(False) - ax.spines["right"].set_visible(False) - ax.spines["left"].set_visible(False) - - ax.get_xaxis().tick_bottom() - ax.get_yaxis().tick_left() - - maxbiomass = np.maximum(df['total_biomass_parts'].max(), df['total_biomass_tissues'].max()) - - plt.xlim(0.0, maxbiomass) - plt.ylim(0.0, maxbiomass) - - plt.yticks(fontsize=10) - plt.xticks(fontsize=10) - plt.tick_params(bottom=False, top=False, left=False, right=False) - - pfts = np.unique(df.pft.values) - for rank, pft in enumerate(pfts): - data = df[df.pft == pft] - plt.scatter(data.total_biomass_parts.values, data.total_biomass_parts.values, - color=colors[rank], label=pft) - - plt.xlabel('Total biomass (kgC) from parts', fontsize=11) - plt.ylabel('Total biomass (kgC) from tissues', fontsize=11) - plt.title("Simulated total biomass for input parameter file", fontsize=11) - plt.legend(loc='upper left', title='PFT') - - if save_fig: - fig_name = os.path.join(plot_dir, "allometry_plot_total_biomass_compare.png") - plt.savefig(fig_name) - -def create_nc_file(cdl_path, run_dir): - """Creates a netcdf file from a cdl file - - Args: - cdl_path (str): full path to desired cdl file - run_dir (str): where the file should be written to - """ - file_basename = os.path.basename(cdl_path).split(".")[-2] - file_nc_name = f"{file_basename}.nc" - - file_gen_command = [ - "ncgen -o", - os.path.join(run_dir, file_nc_name), - cdl_path - ] - out = run_cmd_no_fail(" ".join(file_gen_command), combine_output=True) - print(out) - - return file_nc_name - -def copy_file(file_path, dir): - """Copies a file file to a desired directory +# Dictionary with needed constants for running the executables and reading in the +# output files - developers who add tests should add things here. +test_dict = { + "allometry": { + "test_dir": "fates_allom_test", + "test_exe": "FATES_allom_exe", + "out_file": "allometry_out.nc", + "unit_test": False, + "use_param_file": True, + "other_args": [], + "plotting_function": plot_allometry_dat, + }, + "quadratic": { + "test_dir": "fates_math_test", + "test_exe": "FATES_math_exe", + "out_file": "quad_out.nc", + "unit_test": False, + "use_param_file": False, + "other_args": [], + "plotting_function": plot_quadratic_dat, + } + } - Args: - file_path (str): full path to file - dir (str): where the file should be copied to - """ - file_basename = os.path.basename(file_path) - - file_copy_command = [ - "cp", - os.path.abspath(file_path), - os.path.abspath(dir) - ] - run_cmd_no_fail(" ".join(file_copy_command), combine_output=True) - - return file_basename - - def run_exectuables(build_dir, test_dir, test_exe, run_dir, args): """Run the generated executables @@ -229,23 +77,52 @@ def run_exectuables(build_dir, test_dir, test_exe, run_dir, args): test_exe (str): test executable to run args ([str]): arguments for executable """ - + # move executable to run directory exe_path = os.path.join(build_dir, test_dir, test_exe) copy_file(exe_path, run_dir) - + # run the executable new_exe_path = os.path.join(run_dir, test_exe) run_command = [new_exe_path] run_command.extend(args) - + os.chdir(run_dir) print("Running exectuables") out = run_cmd_no_fail(" ".join(run_command), combine_output=True) print(out) - -def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file, save_figs): +def make_plotdirs(run_dir, test_list): + # make main plot directory + plot_dir = os.path.join(run_dir, 'plots') + if not os.path.isdir(plot_dir): + os.mkdir(plot_dir) + + # make sub-plot directories + for test in test_list: + if test_dict[test]['plotting_function'] is not None: + sub_dir = os.path.join(plot_dir, test) + if not os.path.isdir(sub_dir): + os.mkdir(sub_dir) + +def create_param_file(param_file, run_dir): + if param_file is None: + print("Using default parameter file.") + param_file = DEFAULT_CDL_PATH + param_file_update = create_nc_file(param_file, run_dir) + else: + print(f"Using parameter file {param_file}.") + file_suffix = os.path.basename(param_file).split(".")[-1] + if file_suffix == 'cdl': + param_file_update = create_nc_file(param_file, run_dir) + elif file_suffix == "nc": + param_file_update = copy_file(param_file, run_dir) + else: + raise RuntimeError("Must supply parameter file with .cdl or .nc ending.") + + return param_file_update + +def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file, save_figs, test_list): """Builds and runs the fates tests Args: @@ -261,62 +138,49 @@ def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file, save_fi Raises: RuntimeError: Parameter file is not the correct file type """ - + # absolute path to desired build directory build_dir_path = os.path.abspath(build_dir) - + # absolute path to desired run directory run_dir_path = os.path.abspath(run_dir) - + + # make run directory if it doesn't already exist if not os.path.isdir(run_dir_path): os.mkdir(run_dir_path) - + + # create plot directories if we need to if save_figs: - plot_dir = os.path.join(run_dir_path, 'plots') - if not os.path.isdir(plot_dir): - os.mkdir(plot_dir) - else: - plot_dir = None - - if param_file is None: - print("Using default parameter file.") - param_file = DEFAULT_CDL_PATH - param_file = create_nc_file(param_file, run_dir_path) - else: - print(f"Using parameter file {param_file}.") - file_suffix = os.path.basename(param_file).split(".")[-1] - if file_suffix == 'cdl': - param_file = create_nc_file(param_file, run_dir_path) - elif file_suffix == "nc": - param_file = copy_file(param_file, run_dir_path) - else: - raise RuntimeError("Must supply file with .cdl or .nc ending.") + make_plotdirs(os.path.abspath(run_dir), test_list) + + # move parameter file to correct location (creates nc file if cdl supplied) + param_file = create_param_file(param_file, run_dir) if build: build_unit_tests(build_dir, NAME, CMAKE_BASE_DIR, make_j, clean=clean) - + if run: - run_exectuables(build_dir_path, test_dir, test_exe, run_dir_path, [param_file]) - - # read in allometry data - allometry_dat = xr.open_dataset(os.path.join(run_dir_path, out_file)) - - # plot allometry data - plot_allometry_var(allometry_dat.height, 'height', 'height', 'm', save_figs, plot_dir) - plot_allometry_var(allometry_dat.bagw, 'bagw', 'aboveground biomass', 'kgC', save_figs, plot_dir) - plot_allometry_var(allometry_dat.blmax, 'blmax', 'maximum leaf biomass', 'kgC', save_figs, plot_dir) - plot_allometry_var(allometry_dat.crown_area, 'crown_area', 'crown area', 'm$^2$', save_figs, plot_dir) - plot_allometry_var(allometry_dat.sapwood_area, 'sapwood_area', 'sapwood area', 'm$^2$', save_figs, plot_dir) - plot_allometry_var(allometry_dat.bsap, 'bsap', 'sapwood biomass', 'kgC', save_figs, plot_dir) - plot_allometry_var(allometry_dat.bbgw, 'bbgw', 'belowground biomass', 'kgC', save_figs, plot_dir) - plot_allometry_var(allometry_dat.fineroot_biomass, 'fineroot_biomass', 'fineroot biomass', 'kgC', save_figs, plot_dir) - plot_allometry_var(allometry_dat.bstore, 'bstore', 'storage biomass', 'kgC', save_figs, plot_dir) - plot_allometry_var(allometry_dat.bdead, 'bdead', 'deadwood biomass', 'kgC', save_figs, plot_dir) - plot_allometry_var(allometry_dat.total_biomass_parts, 'total_biomass_parts', 'total biomass (calculated from parts)', 'kgC', save_figs, plot_dir) - plot_allometry_var(allometry_dat.total_biomass_tissues, 'total_biomass_tissues', 'total biomass (calculated from tissues)', 'kgC', save_figs, plot_dir) - plot_total_biomass(allometry_dat, save_figs, plot_dir) + for test in test_list: + if not test_dict[test]['unit_test']: + args = test_dict[test]['other_args'] + if test_dict[test]['use_param_file']: + args.insert(0, param_file) + run_exectuables(build_dir_path, test_dict[test]['test_dir'], + test_dict[test]['test_exe'], run_dir_path, args) + + # plot output + for test in test_list: + if test_dict[test]['plotting_function'] is not None: + test_dict[test]['plotting_function'](run_dir_path, + test_dict[test]['out_file'], save_figs, + os.path.join(run_dir_path, 'plots', test)) plt.show() +def out_file_exists(run_dir, out_file): + + if not os.path.isfile(os.path.join(run_dir, out_file)): + return False + return True def commandline_args(): """Parse and return command-line arguments""" @@ -327,13 +191,13 @@ def commandline_args(): Typical usage: ./run_fates_tests -f parameter_file.nc - + """ - + parser = argparse.ArgumentParser( description=description, formatter_class=argparse.RawTextHelpFormatter ) - + parser.add_argument( "-f", "--parameter-file", @@ -343,7 +207,7 @@ def commandline_args(): "If no file is specified the script will use the default .cdl file in the\n" "parameter_files directory.\n", ) - + parser.add_argument( "-b", "--build-dir", @@ -351,7 +215,7 @@ def commandline_args(): help="Directory where tests are built.\n" "Will be created if it does not exist.\n", ) - + parser.add_argument( "-r", "--run-dir", @@ -359,22 +223,22 @@ def commandline_args(): help="Directory where tests are run.\n" "Will be created if it does not exist.\n", ) - + parser.add_argument( "--make-j", type=int, default=8, help="Number of processes to use for build.", ) - + parser.add_argument( "-c", "--clean", action="store_true", - help="Clean build directory before building.\n" + help="Clean build directory before building.\n" "Removes CMake cache and runs 'make clean'.\n", ) - + parser.add_argument( "--skip-build", action="store_true", @@ -382,7 +246,7 @@ def commandline_args(): "Only do this if you already have run build.\n" "Script will check to make sure executables are present.\n", ) - + parser.add_argument( "--skip-run", action="store_true", @@ -390,7 +254,7 @@ def commandline_args(): "Only do this if you already have run the code previously.\n" "Script will check to make sure required output files are present.\n", ) - + parser.add_argument( "--save-figs", action="store_true", @@ -398,45 +262,19 @@ def commandline_args(): "Will be placed in run_dir/plots.\n" "Should probably do this on remote machines.\n", ) - - args = parser.parse_args() - - check_arg_validity(args) - - return args + parser.add_argument( + "-t", + "--test", + help="Test(s) to run. Comma-separated list of test names, or 'all'\n" + "for all tests. If not supplied, will run all tests." + ) -def check_build_exists(build_dir): - """Checks to see if the build directory and associated executables exist. - - Args: - build_dir (str): build directory - """ - - build_path = os.path.abspath(build_dir) - if not os.path.isdir(build_path): - return False - - exe_path = os.path.join(build_path, test_dir, test_exe) - if not os.path.isfile(exe_path): - return False - - return True + args = parser.parse_args() + test_list = check_arg_validity(args) -def check_out_file_exists(out_file): - """Checks to see if the required output files exist. - - Args: - out_file (str): required output file - """ - - full_path = os.path.abspath(out_file) - if not os.path.isfile(full_path): - return False - - return True - + return args, test_list def check_arg_validity(args): """Checks validity of input script arguments @@ -445,32 +283,63 @@ def check_arg_validity(args): args (parse_args): input arguments Raises: - RuntimeError: Can't find input parameter file - RuntimeError: Can't find build directory or required executables + IOError: Can't find input parameter file, or parameter file is not correct form + RuntimeError: Invalid test name or test list + RuntimeError: Can't find required build directories or executables RuntimeError: Can't find required output files for plotting """ + # check to make sure parameter file exists and is one of the correct forms if args.parameter_file is not None: if not os.path.isfile(args.parameter_file): - raise RuntimeError(f"Cannot find file {args.parameter_file}.") + raise IOError(f"Cannot find file {args.parameter_file}.") + else: + file_suffix = os.path.basename(args.parameter_file).split(".")[-1] + if not file_suffix in ['cdl', 'nc']: + raise IOError("Must supply parameter file with .cdl or .nc ending.") + + # check test names + valid_test_names = test_dict.keys() + if args.test is not None: + test_list = args.test.split(',') + for test in test_list: + if test not in valid_test_names: + raise RuntimeError("Invalid test supplied, must supply one of:\n" + f"{', '.join(valid_test_names)}\n" + "or do not supply a test name to run all tests.") + else: + test_list = valid_test_names + + # make sure build directory exists if args.skip_build: - if not check_build_exists(os.path.abspath(args.build_dir)): - raise RuntimeError("Can't find build directory or executables, run again without --skip-build") + for test in test_list: + if not build_exists(args.build_dir, test_dict[test]['test_dir'], + test_dict[test]['test_exe']): + raise RuntimeError("Build directory or executable does not exist.\n" + "Re-run script without --skip-build.") + + # make sure relevant output files exist: if args.skip_run: - if not check_out_file_exists(os.path.join(os.path.abspath(args.run_dir), out_file)): - raise RuntimeError(f"Can't find output file {out_file}, run again without --skip-run") + for test in test_list: + if test_dict[test]['out_file'] is not None: + if not out_file_exists(os.path.abspath(args.run_dir), test_dict[test]['out_file']): + raise RuntimeError(f"Required file for {test} test does not exist.\n" + "Re-run script without --skip-run.") + + return test_list def main(): """Main script + Reads in command-line arguments and then runs the tests. """ - - args = commandline_args() - + + args, test_list = commandline_args() + build = not args.skip_build run = not args.skip_run - - run_tests(args.clean, build, run, args.build_dir, args.run_dir, args.make_j, - args.parameter_file, args.save_figs) + + run_tests(args.clean, build, run, args.build_dir, args.run_dir, args.make_j, + args.parameter_file, args.save_figs, test_list) if __name__ == "__main__": - - main() \ No newline at end of file + + main() diff --git a/functional_unit_testing/utils.py b/functional_unit_testing/utils.py index 86e7038f34..025938c1d8 100644 --- a/functional_unit_testing/utils.py +++ b/functional_unit_testing/utils.py @@ -1,66 +1,75 @@ -"""Utility functions related to getting paths to various important places +"""Utility functions for file checking, math equations, etc. """ -import os -import sys import math +import os +from path_utils import add_cime_lib_to_path -# ======================================================================== -# Constants that may need to be changed if directory structures change -# ======================================================================== +add_cime_lib_to_path() -# Path to the root directory of FATES, based on the path of this file -# -# Note: It's important that this NOT end with a trailing slash; -# os.path.normpath guarantees this. -_FATES_ROOT = os.path.normpath( - os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir) -) +from CIME.utils import run_cmd_no_fail -def path_to_fates_root(): - """Returns the path to the root directory of FATES""" - return _FATES_ROOT +def round_up(num, decimals=0): + multiplier = 10**decimals + return math.ceil(num * multiplier)/multiplier -def path_to_cime(): - """Returns the path to cime, if it can be found +def truncate(num, decimals=0): + multiplier = 10**decimals + return int(num * multiplier)/multiplier - Raises a RuntimeError if it cannot be found +def create_nc_file(cdl_path, run_dir): + """Creates a netcdf file from a cdl file + Args: + cdl_path (str): full path to desired cdl file + run_dir (str): where the file should be written to """ - cime_path = os.path.join(path_to_fates_root(), "../../cime") - if os.path.isdir(cime_path): - return cime_path - raise RuntimeError("Cannot find cime.") - -def prepend_to_python_path(path): - """Adds the given path to python's sys.path if it isn't already in the path - - The path is added near the beginning, so that it takes precedence over existing - entries in the path + file_basename = os.path.basename(cdl_path).split(".")[-2] + file_nc_name = f"{file_basename}.nc" + + file_gen_command = [ + "ncgen -o", + os.path.join(run_dir, file_nc_name), + cdl_path + ] + out = run_cmd_no_fail(" ".join(file_gen_command), combine_output=True) + print(out) + + return file_nc_name + +def copy_file(file_path, dir): + """Copies a file file to a desired directory + + Args: + file_path (str): full path to file + dir (str): where the file should be copied to """ - if not path in sys.path: - # Insert at location 1 rather than 0, because 0 is special - sys.path.insert(1, path) + file_basename = os.path.basename(file_path) + + file_copy_command = [ + "cp", + os.path.abspath(file_path), + os.path.abspath(dir) + ] + run_cmd_no_fail(" ".join(file_copy_command), combine_output=True) -def add_cime_lib_to_path(): - """Adds the CIME python library to the python path, to allow importing - modules from that library + return file_basename - Returns the path to the top-level cime directory +def get_color_pallete(): + """Generate a color pallete - For documentation on standalone_only: See documentation in - path_to_cime + Returns: + real: array of colors to use in plotting """ - cime_path = path_to_cime() - prepend_to_python_path(cime_path) - cime_lib_path = os.path.join(cime_path, "CIME", "Tools") - prepend_to_python_path(cime_lib_path) - return cime_path - -def round_up(n, decimals=0): - multiplier = 10**decimals - return math.ceil(n * multiplier) / multiplier - -def truncate(n, decimals=0): - multiplier = 10**decimals - return int(n * multiplier) / multiplier \ No newline at end of file + + colors = [(31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120), + (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150), + (148, 103, 189), (197, 176, 213), (140, 86, 75), (196, 156, 148), + (227, 119, 194), (247, 182, 210), (127, 127, 127), (199, 199, 199), + (188, 189, 34), (219, 219, 141), (23, 190, 207), (158, 218, 229)] + + for i in range(len(colors)): + r, g, b = colors[i] + colors[i] = (r/255., g/255., b/255.) + + return colors \ No newline at end of file From 5163a3f43585b4275f6384c909a411a004d3ae23 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 19 Apr 2024 12:25:01 -0600 Subject: [PATCH 174/300] some pylint changes --- .gitignore | 4 + .../{AllometryUtils.py => allometry_utils.py} | 69 ++++--- .../build_fortran_tests.py | 69 ++++--- .../math_utils/MathUtils.py | 34 ---- .../math_utils/math_utils.py | 52 +++++ functional_unit_testing/run_fates_tests.py | 187 +++++++++++++----- functional_unit_testing/utils.py | 30 ++- 7 files changed, 288 insertions(+), 157 deletions(-) rename functional_unit_testing/allometry/{AllometryUtils.py => allometry_utils.py} (70%) delete mode 100644 functional_unit_testing/math_utils/MathUtils.py create mode 100644 functional_unit_testing/math_utils/math_utils.py diff --git a/.gitignore b/.gitignore index 40f2a49386..cf080967fe 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,10 @@ Thumbs.db *.dvi *.toc +# Folders created with unit/functional tests +_build/ +_run/ + # Old Files *~ diff --git a/functional_unit_testing/allometry/AllometryUtils.py b/functional_unit_testing/allometry/allometry_utils.py similarity index 70% rename from functional_unit_testing/allometry/AllometryUtils.py rename to functional_unit_testing/allometry/allometry_utils.py index ac0a285672..08814602b6 100644 --- a/functional_unit_testing/allometry/AllometryUtils.py +++ b/functional_unit_testing/allometry/allometry_utils.py @@ -20,24 +20,24 @@ def plot_allometry_var(data, varname, units, save_fig, plot_dir=None): save_fig (bool): whether or not to write out plot plot_dir (str): if saving figure, where to write to """ - df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), + data_frame = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), 'pft': np.repeat(data.pft, len(data.dbh)), data.name: data.values.flatten()}) - maxdbh = df['dbh'].max() - maxvar = round_up(df[data.name].max()) + maxdbh = data_frame['dbh'].max() + maxvar = round_up(data_frame[data.name].max()) colors = get_color_pallete() plt.figure(figsize=(7, 5)) - ax = plt.subplot(111) - ax.spines["top"].set_visible(False) - ax.spines["bottom"].set_visible(False) - ax.spines["right"].set_visible(False) - ax.spines["left"].set_visible(False) + axis = plt.subplot(111) + axis.spines["top"].set_visible(False) + axis.spines["bottom"].set_visible(False) + axis.spines["right"].set_visible(False) + axis.spines["left"].set_visible(False) - ax.get_xaxis().tick_bottom() - ax.get_yaxis().tick_left() + axis.get_xaxis().tick_bottom() + axis.get_yaxis().tick_left() plt.xlim(0.0, maxdbh) plt.ylim(0.0, maxvar) @@ -47,16 +47,16 @@ def plot_allometry_var(data, varname, units, save_fig, plot_dir=None): inc = (int(maxvar) - 0)/20 for i in range(0, 20): - y = 0.0 + i*inc + y_val = 0.0 + i*inc plt.plot(range(math.floor(0), math.ceil(maxdbh)), - [y] * len(range(math.floor(0), math.ceil(maxdbh))), + [y_val] * len(range(math.floor(0), math.ceil(maxdbh))), "--", lw=0.5, color="black", alpha=0.3) plt.tick_params(bottom=False, top=False, left=False, right=False) - pfts = np.unique(df.pft.values) + pfts = np.unique(data_frame.pft.values) for rank, pft in enumerate(pfts): - dat = df[df.pft == pft] + dat = data_frame[data_frame.pft == pft] plt.plot(dat.dbh.values, dat[data.name].values, lw=2, color=colors[rank], label=pft) @@ -66,7 +66,7 @@ def plot_allometry_var(data, varname, units, save_fig, plot_dir=None): plt.legend(loc='upper left', title='PFT') if save_fig: - fig_name = os.path.join(plot_dir, f"allometry_plot_{var}.png") + fig_name = os.path.join(plot_dir, f"allometry_plot_{data.name}.png") plt.savefig(fig_name) def plot_total_biomass(data, save_fig, plot_dir): @@ -75,7 +75,7 @@ def plot_total_biomass(data, save_fig, plot_dir): Args: data (xarray DataSet): the allometry dataset """ - df = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), + data_frame = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), 'pft': np.repeat(data.pft, len(data.dbh)), 'total_biomass_parts': data.total_biomass_parts.values.flatten(), 'total_biomass_tissues': data.total_biomass_tissues.values.flatten()}) @@ -83,16 +83,17 @@ def plot_total_biomass(data, save_fig, plot_dir): colors = get_color_pallete() plt.figure(figsize=(7, 5)) - ax = plt.subplot(111) - ax.spines["top"].set_visible(False) - ax.spines["bottom"].set_visible(False) - ax.spines["right"].set_visible(False) - ax.spines["left"].set_visible(False) + axis = plt.subplot(111) + axis.spines["top"].set_visible(False) + axis.spines["bottom"].set_visible(False) + axis.spines["right"].set_visible(False) + axis.spines["left"].set_visible(False) - ax.get_xaxis().tick_bottom() - ax.get_yaxis().tick_left() + axis.get_xaxis().tick_bottom() + axis.get_yaxis().tick_left() - maxbiomass = np.maximum(df['total_biomass_parts'].max(), df['total_biomass_tissues'].max()) + maxbiomass = np.maximum(data_frame['total_biomass_parts'].max(), + data_frame['total_biomass_tissues'].max()) plt.xlim(0.0, maxbiomass) plt.ylim(0.0, maxbiomass) @@ -101,9 +102,9 @@ def plot_total_biomass(data, save_fig, plot_dir): plt.xticks(fontsize=10) plt.tick_params(bottom=False, top=False, left=False, right=False) - pfts = np.unique(df.pft.values) + pfts = np.unique(data_frame.pft.values) for rank, pft in enumerate(pfts): - data = df[df.pft == pft] + data = data_frame[data_frame.pft == pft] plt.scatter(data.total_biomass_parts.values, data.total_biomass_parts.values, color=colors[rank], label=pft) @@ -117,6 +118,14 @@ def plot_total_biomass(data, save_fig, plot_dir): plt.savefig(fig_name) def plot_allometry_dat(run_dir, out_file, save_figs, plot_dir): + """Plots all allometry plots + + Args: + run_dir (str): run directory + out_file (str): output file name + save_figs (bool): whether or not to save the figures + plot_dir (str): plot directory to save the figures to + """ # read in allometry data allometry_dat = xr.open_dataset(os.path.join(run_dir, out_file)) @@ -172,8 +181,8 @@ def plot_allometry_dat(run_dir, out_file, save_figs, plot_dir): }, } - for plot in plot_dict: - plot_allometry_var(allometry_dat[plot], plot_dict[plot]['varname'], - plot_dict[plot]['units'], save_figs, plot_dir) + for plot, attributes in plot_dict.items(): + plot_allometry_var(allometry_dat[plot], attributes['varname'], + attributes['units'], save_figs, plot_dir) - plot_total_biomass(allometry_dat, save_figs, plot_dir) \ No newline at end of file + plot_total_biomass(allometry_dat, save_figs, plot_dir) diff --git a/functional_unit_testing/build_fortran_tests.py b/functional_unit_testing/build_fortran_tests.py index ef6d6577e9..722948ed09 100644 --- a/functional_unit_testing/build_fortran_tests.py +++ b/functional_unit_testing/build_fortran_tests.py @@ -1,18 +1,17 @@ +""" +Builds/compiles any tests within the FATES repository +""" import os -import sys import shutil - -_FATES_PYTHON = os.path.join(os.path.dirname(os.path.abspath(__file__))) -sys.path.insert(1, _FATES_PYTHON) - from utils import add_cime_lib_to_path + add_cime_lib_to_path() -from CIME.utils import get_src_root, run_cmd_no_fail, expect, stringify_bool -from CIME.build import CmakeTmpBuildDir -from CIME.XML.machines import Machines -from CIME.BuildTools.configure import configure, FakeCase -from CIME.XML.env_mach_specific import EnvMachSpecific +from CIME.utils import get_src_root, run_cmd_no_fail, expect, stringify_bool # pylint: disable=wrong-import-position,import-error,wrong-import-order +from CIME.build import CmakeTmpBuildDir # pylint: disable=wrong-import-position,import-error,wrong-import-order +from CIME.XML.machines import Machines # pylint: disable=wrong-import-position,import-error,wrong-import-order +from CIME.BuildTools.configure import configure, FakeCase # pylint: disable=wrong-import-position,import-error,wrong-import-order +from CIME.XML.env_mach_specific import EnvMachSpecific # pylint: disable=wrong-import-position,import-error,wrong-import-order _CIMEROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../cime") @@ -30,7 +29,8 @@ def run_cmake(name, test_dir, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_a print(f"Running cmake for {name}.") # directory with cmake modules - cmake_module_dir = os.path.abspath(os.path.join(_CIMEROOT, "CIME", "non_py", "src", "CMake")) + cmake_module_dir = os.path.abspath(os.path.join(_CIMEROOT, "CIME", "non_py", + "src", "CMake")) # directory with genf90 genf90_dir = os.path.join(_CIMEROOT, "CIME", "non_py", "externals", "genf90") @@ -64,7 +64,8 @@ def find_library(caseroot, cmake_args, lib_string): Args: caseroot (str): Directory with pfunit macros - cmake_args (str): The cmake args used to invoke cmake (so that we get the correct makefile vars) + cmake_args (str): The cmake args used to invoke cmake + (so that we get the correct makefile vars) """ with CmakeTmpBuildDir(macroloc=caseroot) as cmaketmp: all_vars = cmaketmp.get_makefile_vars(cmake_args=cmake_args) @@ -92,7 +93,7 @@ def prep_build_dir(build_dir, clean): # create the build directory build_dir_path = os.path.abspath(build_dir) if not os.path.isdir(build_dir_path): - os.mkdir(build_dir_path) + os.mkdir(build_dir_path) # change into that directory os.chdir(build_dir_path) @@ -116,12 +117,12 @@ def clean_cmake_files(): # Clear contents to do with cmake cache for file in cwd_contents: - if ( - file in ("Macros.cmake", "env_mach_specific.xml") - or file.startswith("Depends") - or file.startswith(".env_mach_specific") - ): - os.remove(file) + if ( + file in ("Macros.cmake", "env_mach_specific.xml") + or file.startswith("Depends") + or file.startswith(".env_mach_specific") + ): + os.remove(file) def get_extra_cmake_args(build_dir, mpilib): """Makes a fake case to grab the required cmake arguments @@ -152,23 +153,22 @@ def get_extra_cmake_args(build_dir, mpilib): os_, unit_testing=True, ) - machspecific = EnvMachSpecific(build_dir, unit_testing=True) + EnvMachSpecific(build_dir, unit_testing=True) # make a fake case - fake_case = FakeCase(compiler, mpilib, True, "nuopc", threading=False) - - cmake_args = ( - "{}-DOS={} -DMACH={} -DCOMPILER={} -DDEBUG={} -DMPILIB={} -Dcompile_threaded={} -DCASEROOT={}".format( - "", - os_, - machobj.get_machine_name(), - compiler, - stringify_bool(True), - mpilib, - stringify_bool(False), - build_dir - ) - ) + FakeCase(compiler, mpilib, True, "nuopc", threading=False) + + cmake_args_list = [ + f"-DOS={os_}", + f"-DMACH={machobj.get_machine_name()}", + f"-DCOMPILER={compiler}", + f"-DDEBUG={stringify_bool(True)}", + f"-DMPILIB={mpilib}", + f"-Dcompile_threaded={stringify_bool(False)}", + f"-DCASEROOT={build_dir}" + ] + + cmake_args = " ".join(cmake_args_list) return cmake_args @@ -246,4 +246,3 @@ def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False): # run cmake and make run_cmake(name, cmake_directory, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_args) run_make(name, make_j, clean=clean) - diff --git a/functional_unit_testing/math_utils/MathUtils.py b/functional_unit_testing/math_utils/MathUtils.py deleted file mode 100644 index 63c68ae820..0000000000 --- a/functional_unit_testing/math_utils/MathUtils.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Utility functions for allometry functional unit tests -""" -import os -import math -import xarray as xr -import pandas as pd -import numpy as np -import matplotlib -import matplotlib.pyplot as plt - -from utils import get_color_pallete - -def plot_quadratic_dat(run_dir, out_file, save_figs, plot_dir): - - # read in quadratic data - quadratic_dat = xr.open_dataset(os.path.join(run_dir, out_file)) - - # plot output - PlotQuadAndRoots(quadratic_dat.a.values, quadratic_dat.b.values, - quadratic_dat.c.values, quadratic_dat.root1.values, - quadratic_dat.root2.values) - -def PlotQuadAndRoots(a, b, c, r1, r2): - - colors = get_color_pallete() - - fig, axs = plt.subplots(ncols=1, nrows=1, figsize=(8,8)) - x = np.linspace(-10.0, 10.0, num=20) - - for i in range(0, len(a)): - y = a[i]*x**2 + b[i]*x + c[i] - plt.plot(x, y, lw=2, color=colors[i]) - plt.scatter(r1[i], r2[i], color=colors[i], s=50) - plt.axhline(y=0.0, color='k', linestyle='dotted') diff --git a/functional_unit_testing/math_utils/math_utils.py b/functional_unit_testing/math_utils/math_utils.py new file mode 100644 index 0000000000..d2ae7d743f --- /dev/null +++ b/functional_unit_testing/math_utils/math_utils.py @@ -0,0 +1,52 @@ +"""Utility functions for allometry functional unit tests +""" +import os +import math +import xarray as xr +import numpy as np +import matplotlib.pyplot as plt + +from utils import get_color_pallete + +def plot_quadratic_dat(run_dir, out_file, save_figs, plot_dir): + """Reads in and plots quadratic formula test output + + Args: + run_dir (str): run directory + out_file (str): output file + save_figs (bool): whether or not to save the figures + plot_dir (str): plot directory + """ + + # read in quadratic data + quadratic_dat = xr.open_dataset(os.path.join(run_dir, out_file)) + + # plot output + plot_quad_and_roots(quadratic_dat.a.values, quadratic_dat.b.values, + quadratic_dat.c.values, quadratic_dat.root1.values, + quadratic_dat.root2.values) + if save_figs: + fig_name = os.path.join(plot_dir, "quadratic_test.png") + plt.savefig(fig_name) + +def plot_quad_and_roots(a_coeff, b_coeff, c_coeff, root1, root2): + """Plots a set of quadratic formulas (ax**2 + bx + c) and their two roots + + Args: + a (float array): set of a coefficients + b (float array): set of b coefficients + c (float array): set of b coefficients + r1 (float array): set of first real roots + r2 (float array): set of second real roots + """ + + colors = get_color_pallete() + + plt.figure(figsize=(7, 5)) + x_vals = np.linspace(-10.0, 10.0, num=20) + + for i in range(len(a_coeff)): + y_vals = a_coeff[i]*x_vals**2 + b_coeff[i]*x_vals + c_coeff[i] + plt.plot(x_vals, y_vals, lw=2, color=colors[i]) + plt.scatter(root1[i], root2[i], color=colors[i], s=50) + plt.axhline(y=0.0, color='k', linestyle='dotted') diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index ed3e64b1bf..2ee2903554 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -10,8 +10,9 @@ - matplotlib - pandas -Though this script does not require any host land model code, it does require some CIME and shr code, -so you should still get these repositories as you normally would (i.e., manage_externals, etc.) +Though this script does not require any host land model code, it does require some CIME +and shr code, so you should still get these repositories as you normally would +(i.e., manage_externals, etc.) Additionally, this requires netcdf and netcdff as well as a fortran compiler. @@ -27,17 +28,16 @@ """ import os import argparse -import matplotlib import matplotlib.pyplot as plt from build_fortran_tests import build_unit_tests, build_exists from path_utils import add_cime_lib_to_path -from utils import round_up, copy_file, create_nc_file -from allometry.AllometryUtils import plot_allometry_dat -from math_utils.MathUtils import plot_quadratic_dat +from utils import copy_file, create_nc_file +from allometry.allometry_utils import plot_allometry_dat +from math_utils.math_utils import plot_quadratic_dat add_cime_lib_to_path() -from CIME.utils import run_cmd_no_fail +from CIME.utils import run_cmd_no_fail # pylint: disable=wrong-import-position,import-error,wrong-import-order # Constants for this script DEFAULT_CDL_PATH = os.path.abspath("../parameter_files/fates_params_default.cdl") @@ -46,6 +46,10 @@ # Dictionary with needed constants for running the executables and reading in the # output files - developers who add tests should add things here. + +# NOTE: if the functional test you write requires a parameter file read in as a +# command-line argument, this should be the *first* (or only) argument in the +# command-line argument list test_dict = { "allometry": { "test_dir": "fates_allom_test", @@ -93,6 +97,12 @@ def run_exectuables(build_dir, test_dir, test_exe, run_dir, args): print(out) def make_plotdirs(run_dir, test_list): + """Create plotting directories if they don't already exist + + Args: + run_dir (str): full path to run directory + test_list (list, str): list of test names + """ # make main plot directory plot_dir = os.path.join(run_dir, 'plots') if not os.path.isdir(plot_dir): @@ -106,6 +116,19 @@ def make_plotdirs(run_dir, test_list): os.mkdir(sub_dir) def create_param_file(param_file, run_dir): + """Creates and/or move the default or input parameter file to the run directory + Creates a netcdf file from a cdl file if a cdl file is supplied + + Args: + param_file (str): path to parmaeter file + run_dir (str): full path to run directory + + Raises: + RuntimeError: Supplied parameter file is not netcdf (.cd) or cdl (.cdl) + + Returns: + str: full path to new parameter file name/location + """ if param_file is None: print("Using default parameter file.") param_file = DEFAULT_CDL_PATH @@ -134,9 +157,7 @@ def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file, save_fi make_j (int): number of processors for the build param_file (str): input FATES parameter file save_figs (bool): whether or not to write figures to file - - Raises: - RuntimeError: Parameter file is not the correct file type + test_list(str, list): list of test names to run """ # absolute path to desired build directory @@ -156,19 +177,24 @@ def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file, save_fi # move parameter file to correct location (creates nc file if cdl supplied) param_file = create_param_file(param_file, run_dir) + # compile code if build: build_unit_tests(build_dir, NAME, CMAKE_BASE_DIR, make_j, clean=clean) + # run executables for each test in test list if run: for test in test_list: + # we don't run executables for pfunit tests if not test_dict[test]['unit_test']: + # prepend parameter file (if required) to argument list args = test_dict[test]['other_args'] if test_dict[test]['use_param_file']: args.insert(0, param_file) + # run run_exectuables(build_dir_path, test_dict[test]['test_dir'], test_dict[test]['test_exe'], run_dir_path, args) - # plot output + # plot output for relevant tests for test in test_list: if test_dict[test]['plotting_function'] is not None: test_dict[test]['plotting_function'](run_dir_path, @@ -177,11 +203,46 @@ def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file, save_fi plt.show() def out_file_exists(run_dir, out_file): + """Checks to see if the file out_file exists in the run_dir + + Args: + run_dir (str): full path to run directory + out_file (str): output file name + + Returns: + bool: yes/no file exists in correct location + """ if not os.path.isfile(os.path.join(run_dir, out_file)): return False return True +def parse_test_list(test_string): + """Parses the input test list and checks for errors + + Args: + test (str): user-supplied comma-separated list of test names + + Returns: + str, list: list of test names to run + + Raises: + RuntimeError: Invalid test name supplied + """ + valid_test_names = test_dict.keys() + + if test_string != "all": + test_list = test_string.split(',') + for test in test_list: + if test not in valid_test_names: + raise argparse.ArgumentTypeError("Invalid test supplied, must supply one of:\n" + f"{', '.join(valid_test_names)}\n" + "or do not supply a test name to run all tests.") + else: + test_list = [test for test in valid_test_names] + + return test_list + def commandline_args(): """Parse and return command-line arguments""" @@ -193,7 +254,6 @@ def commandline_args(): ./run_fates_tests -f parameter_file.nc """ - parser = argparse.ArgumentParser( description=description, formatter_class=argparse.RawTextHelpFormatter ) @@ -201,6 +261,7 @@ def commandline_args(): parser.add_argument( "-f", "--parameter-file", + type=str, default=DEFAULT_CDL_PATH, help="Parameter file to run the FATES tests with.\n" "Can be a netcdf (.nc) or cdl (.cdl) file.\n" @@ -211,6 +272,7 @@ def commandline_args(): parser.add_argument( "-b", "--build-dir", + type=str, default="../_build", help="Directory where tests are built.\n" "Will be created if it does not exist.\n", @@ -219,6 +281,7 @@ def commandline_args(): parser.add_argument( "-r", "--run-dir", + type=str, default="../_run", help="Directory where tests are run.\n" "Will be created if it does not exist.\n", @@ -265,16 +328,68 @@ def commandline_args(): parser.add_argument( "-t", - "--test", + "--test-list", + action="store", + dest="test_list", + type=parse_test_list, + default="all", help="Test(s) to run. Comma-separated list of test names, or 'all'\n" "for all tests. If not supplied, will run all tests." ) args = parser.parse_args() - test_list = check_arg_validity(args) + check_arg_validity(args) + + return args - return args, test_list +def check_param_file(param_file): + """Checks to see if param_file exists and is of the correct form (.nc or .cdl) + + Args: + param_file (str): path to parameter file + + Raises: + IOError: Parameter file is not of the correct form (.nc or .cdl) + IOError: Can't find parameter file + """ + file_suffix = os.path.basename(param_file).split(".")[-1] + if not file_suffix in ['cdl', 'nc']: + raise argparse.ArgumentError("Must supply parameter file with .cdl or .nc ending.") + if not os.path.isfile(param_file): + raise argparse.ArgumentError(f"Cannot find file {param_file}.") + +def check_build_dir(build_dir, test_list): + """Checks to see if all required build directories and executables are present + + Args: + build_dir (str): build directory + test_list (list, str): list of test names + + Raises: + RuntimeError: Can't find a required build directory or executable + """ + for test in test_list: + if not build_exists(build_dir, test_dict[test]['test_dir'], + test_dict[test]['test_exe']): + raise argparse.ArgumentError("Build directory or executable does not exist.\n" + "Re-run script without --skip-build.") + +def check_out_files(run_dir, test_list): + """Checks to see that required output files are present in the run directory + + Args: + run_dir (str): run directory + test_list (str, list): list of test names + + Raises: + RuntimeError: Can't find a required output file + """ + for test in test_list: + if test_dict[test]['out_file'] is not None: + if not out_file_exists(os.path.abspath(run_dir), test_dict[test]['out_file']): + raise argparse.ArgumentError(f"Required file for {test} test does not exist.\n" + "Re-run script without --skip-run.") def check_arg_validity(args): """Checks validity of input script arguments @@ -282,63 +397,33 @@ def check_arg_validity(args): Args: args (parse_args): input arguments - Raises: - IOError: Can't find input parameter file, or parameter file is not correct form - RuntimeError: Invalid test name or test list - RuntimeError: Can't find required build directories or executables - RuntimeError: Can't find required output files for plotting """ # check to make sure parameter file exists and is one of the correct forms if args.parameter_file is not None: - if not os.path.isfile(args.parameter_file): - raise IOError(f"Cannot find file {args.parameter_file}.") - else: - file_suffix = os.path.basename(args.parameter_file).split(".")[-1] - if not file_suffix in ['cdl', 'nc']: - raise IOError("Must supply parameter file with .cdl or .nc ending.") - - # check test names - valid_test_names = test_dict.keys() - if args.test is not None: - test_list = args.test.split(',') - for test in test_list: - if test not in valid_test_names: - raise RuntimeError("Invalid test supplied, must supply one of:\n" - f"{', '.join(valid_test_names)}\n" - "or do not supply a test name to run all tests.") + check_param_file(args.parameter_file) else: - test_list = valid_test_names + check_param_file(DEFAULT_CDL_PATH) # make sure build directory exists if args.skip_build: - for test in test_list: - if not build_exists(args.build_dir, test_dict[test]['test_dir'], - test_dict[test]['test_exe']): - raise RuntimeError("Build directory or executable does not exist.\n" - "Re-run script without --skip-build.") + check_build_dir(args.build_dir, args.test_list) # make sure relevant output files exist: if args.skip_run: - for test in test_list: - if test_dict[test]['out_file'] is not None: - if not out_file_exists(os.path.abspath(args.run_dir), test_dict[test]['out_file']): - raise RuntimeError(f"Required file for {test} test does not exist.\n" - "Re-run script without --skip-run.") - - return test_list + check_out_files(args.run_dir, args.test_list) def main(): """Main script Reads in command-line arguments and then runs the tests. """ - args, test_list = commandline_args() + args = commandline_args() build = not args.skip_build run = not args.skip_run run_tests(args.clean, build, run, args.build_dir, args.run_dir, args.make_j, - args.parameter_file, args.save_figs, test_list) + args.parameter_file, args.save_figs, args.test_list) if __name__ == "__main__": diff --git a/functional_unit_testing/utils.py b/functional_unit_testing/utils.py index 025938c1d8..4388ea5eb9 100644 --- a/functional_unit_testing/utils.py +++ b/functional_unit_testing/utils.py @@ -7,13 +7,31 @@ add_cime_lib_to_path() -from CIME.utils import run_cmd_no_fail +from CIME.utils import run_cmd_no_fail # pylint: disable=wrong-import-position,import-error,wrong-import-order def round_up(num, decimals=0): + """Rounds a number up + + Args: + num (float): number to round + decimals (int, optional): number of decimals to round to. Defaults to 0. + + Returns: + float: input number rounded up + """ multiplier = 10**decimals return math.ceil(num * multiplier)/multiplier def truncate(num, decimals=0): + """Rounds a number down + + Args: + num (float): number to round + decimals (int, optional): Decimals to round down to. Defaults to 0. + + Returns: + float: number rounded down + """ multiplier = 10**decimals return int(num * multiplier)/multiplier @@ -37,7 +55,7 @@ def create_nc_file(cdl_path, run_dir): return file_nc_name -def copy_file(file_path, dir): +def copy_file(file_path, directory): """Copies a file file to a desired directory Args: @@ -49,7 +67,7 @@ def copy_file(file_path, dir): file_copy_command = [ "cp", os.path.abspath(file_path), - os.path.abspath(dir) + os.path.abspath(directory) ] run_cmd_no_fail(" ".join(file_copy_command), combine_output=True) @@ -68,8 +86,6 @@ def get_color_pallete(): (227, 119, 194), (247, 182, 210), (127, 127, 127), (199, 199, 199), (188, 189, 34), (219, 219, 141), (23, 190, 207), (158, 218, 229)] - for i in range(len(colors)): - r, g, b = colors[i] - colors[i] = (r/255., g/255., b/255.) + colors = [(red/255.0, green/255.0, blue/255.0) for red, green, blue in colors] - return colors \ No newline at end of file + return colors From f2a805bb2e88ee2b1c59a923ae125962362a153b Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 22 Apr 2024 10:05:54 -0600 Subject: [PATCH 175/300] some pythonic updates --- ...lometry_utils.py => allometry_plotting.py} | 87 +++++----- .../build_fortran_tests.py | 6 +- .../{math_utils.py => math_plotting.py} | 22 +-- functional_unit_testing/run_fates_tests.py | 152 +++++++++--------- functional_unit_testing/utils.py | 13 +- 5 files changed, 139 insertions(+), 141 deletions(-) rename functional_unit_testing/allometry/{allometry_utils.py => allometry_plotting.py} (80%) rename functional_unit_testing/math_utils/{math_utils.py => math_plotting.py} (71%) diff --git a/functional_unit_testing/allometry/allometry_utils.py b/functional_unit_testing/allometry/allometry_plotting.py similarity index 80% rename from functional_unit_testing/allometry/allometry_utils.py rename to functional_unit_testing/allometry/allometry_plotting.py index 08814602b6..caa6cc1069 100644 --- a/functional_unit_testing/allometry/allometry_utils.py +++ b/functional_unit_testing/allometry/allometry_plotting.py @@ -7,27 +7,19 @@ import xarray as xr import matplotlib import matplotlib.pyplot as plt -from utils import get_color_pallete, round_up +from utils import get_color_palette, round_up -def plot_allometry_var(data, varname, units, save_fig, plot_dir=None): - """Plot an allometry variable +def blank_plot(x_max, x_min, y_max, y_min, draw_horizontal_lines=False): + """Generate a blank plot with set attributes Args: - data (xarray DataArray): the data array of the variable to plot - var (str): variable name (for data structure) - varname (str): variable name for plot labels - units (str): variable units for plot labels - save_fig (bool): whether or not to write out plot - plot_dir (str): if saving figure, where to write to + x_max (float): maximum x value + x_min (float): minimum x value + y_max (float): maximum y value + y_min (float): minimum y value + draw_horizontal_lines (bool, optional): whether or not to draw horizontal + lines across plot. Defaults to False. """ - data_frame = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), - 'pft': np.repeat(data.pft, len(data.dbh)), - data.name: data.values.flatten()}) - - maxdbh = data_frame['dbh'].max() - maxvar = round_up(data_frame[data.name].max()) - - colors = get_color_pallete() plt.figure(figsize=(7, 5)) axis = plt.subplot(111) @@ -39,22 +31,45 @@ def plot_allometry_var(data, varname, units, save_fig, plot_dir=None): axis.get_xaxis().tick_bottom() axis.get_yaxis().tick_left() - plt.xlim(0.0, maxdbh) - plt.ylim(0.0, maxvar) + plt.xlim(0.0, x_max) + plt.ylim(0.0, y_max) plt.yticks(fontsize=10) plt.xticks(fontsize=10) - inc = (int(maxvar) - 0)/20 - for i in range(0, 20): - y_val = 0.0 + i*inc - plt.plot(range(math.floor(0), math.ceil(maxdbh)), - [y_val] * len(range(math.floor(0), math.ceil(maxdbh))), - "--", lw=0.5, color="black", alpha=0.3) + if draw_horizontal_lines: + inc = (int(y_max) - y_min)/20 + for i in range(0, 20): + plt.plot(range(math.floor(x_min), math.ceil(x_max)), + [0.0 + i*inc] * len(range(math.floor(x_min), math.ceil(x_max))), + "--", lw=0.5, color="black", alpha=0.3) plt.tick_params(bottom=False, top=False, left=False, right=False) + return plt + +def plot_allometry_var(data, varname, units, save_fig, plot_dir=None): + """Plot an allometry variable + + Args: + data (xarray DataArray): the data array of the variable to plot + var (str): variable name (for data structure) + varname (str): variable name for plot labels + units (str): variable units for plot labels + save_fig (bool): whether or not to write out plot + plot_dir (str): if saving figure, where to write to + """ + data_frame = pd.DataFrame({'dbh': np.tile(data.dbh, len(data.pft)), + 'pft': np.repeat(data.pft, len(data.dbh)), + data.name: data.values.flatten()}) + + max_dbh = data_frame['dbh'].max() + max_var = round_up(data_frame[data.name].max()) + + blank_plot(max_dbh, 0.0, max_var, 0.0, draw_horizontal_lines=True) + pfts = np.unique(data_frame.pft.values) + colors = get_color_palette(len(pfts)) for rank, pft in enumerate(pfts): dat = data_frame[data_frame.pft == pft] plt.plot(dat.dbh.values, dat[data.name].values, lw=2, color=colors[rank], @@ -80,29 +95,13 @@ def plot_total_biomass(data, save_fig, plot_dir): 'total_biomass_parts': data.total_biomass_parts.values.flatten(), 'total_biomass_tissues': data.total_biomass_tissues.values.flatten()}) - colors = get_color_pallete() - - plt.figure(figsize=(7, 5)) - axis = plt.subplot(111) - axis.spines["top"].set_visible(False) - axis.spines["bottom"].set_visible(False) - axis.spines["right"].set_visible(False) - axis.spines["left"].set_visible(False) - - axis.get_xaxis().tick_bottom() - axis.get_yaxis().tick_left() - - maxbiomass = np.maximum(data_frame['total_biomass_parts'].max(), + max_biomass = np.maximum(data_frame['total_biomass_parts'].max(), data_frame['total_biomass_tissues'].max()) - plt.xlim(0.0, maxbiomass) - plt.ylim(0.0, maxbiomass) - - plt.yticks(fontsize=10) - plt.xticks(fontsize=10) - plt.tick_params(bottom=False, top=False, left=False, right=False) + blank_plot(max_biomass, 0.0, max_biomass, 0.0, draw_horizontal_lines=False) pfts = np.unique(data_frame.pft.values) + colors = get_color_palette(len(pfts)) for rank, pft in enumerate(pfts): data = data_frame[data_frame.pft == pft] plt.scatter(data.total_biomass_parts.values, data.total_biomass_parts.values, diff --git a/functional_unit_testing/build_fortran_tests.py b/functional_unit_testing/build_fortran_tests.py index 722948ed09..0c4cbb535f 100644 --- a/functional_unit_testing/build_fortran_tests.py +++ b/functional_unit_testing/build_fortran_tests.py @@ -15,10 +15,10 @@ _CIMEROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../../cime") -def run_cmake(name, test_dir, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_args): +def run_cmake(test_name, test_dir, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_args): """Run cmake for the fortran unit tests Arguments: - name (str) - name for output messages + test_name (str) - name for output messages test_dir (str) - directory to run Cmake in pfunit_path (str) - path to pfunit netcdf_c_path (str) - path to netcdf @@ -26,7 +26,7 @@ def run_cmake(name, test_dir, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_a clean (bool) - clean the build """ if not os.path.isfile("CMakeCache.txt"): - print(f"Running cmake for {name}.") + print(f"Running cmake for {test_name}.") # directory with cmake modules cmake_module_dir = os.path.abspath(os.path.join(_CIMEROOT, "CIME", "non_py", diff --git a/functional_unit_testing/math_utils/math_utils.py b/functional_unit_testing/math_utils/math_plotting.py similarity index 71% rename from functional_unit_testing/math_utils/math_utils.py rename to functional_unit_testing/math_utils/math_plotting.py index d2ae7d743f..4e386dbe93 100644 --- a/functional_unit_testing/math_utils/math_utils.py +++ b/functional_unit_testing/math_utils/math_plotting.py @@ -6,7 +6,7 @@ import numpy as np import matplotlib.pyplot as plt -from utils import get_color_pallete +from utils import get_color_palette def plot_quadratic_dat(run_dir, out_file, save_figs, plot_dir): """Reads in and plots quadratic formula test output @@ -26,26 +26,26 @@ def plot_quadratic_dat(run_dir, out_file, save_figs, plot_dir): quadratic_dat.c.values, quadratic_dat.root1.values, quadratic_dat.root2.values) if save_figs: - fig_name = os.path.join(plot_dir, "quadratic_test.png") - plt.savefig(fig_name) + fig_name = os.path.join(plot_dir, "quadratic_test.png") + plt.savefig(fig_name) def plot_quad_and_roots(a_coeff, b_coeff, c_coeff, root1, root2): """Plots a set of quadratic formulas (ax**2 + bx + c) and their two roots Args: - a (float array): set of a coefficients - b (float array): set of b coefficients - c (float array): set of b coefficients - r1 (float array): set of first real roots - r2 (float array): set of second real roots + a_coeff (float array): set of a coefficients + b_coeff (float array): set of b coefficients + c_coeff (float array): set of b coefficients + root1 (float array): set of first real roots + root2 (float array): set of second real roots """ - - colors = get_color_pallete() + num_equations = len(a_coeff) plt.figure(figsize=(7, 5)) x_vals = np.linspace(-10.0, 10.0, num=20) - for i in range(len(a_coeff)): + colors = get_color_palette(num_equations) + for i in range(num_equations): y_vals = a_coeff[i]*x_vals**2 + b_coeff[i]*x_vals + c_coeff[i] plt.plot(x_vals, y_vals, lw=2, color=colors[i]) plt.scatter(root1[i], root2[i], color=colors[i], s=50) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 2ee2903554..0aa53fd4a8 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -32,17 +32,17 @@ from build_fortran_tests import build_unit_tests, build_exists from path_utils import add_cime_lib_to_path from utils import copy_file, create_nc_file -from allometry.allometry_utils import plot_allometry_dat -from math_utils.math_utils import plot_quadratic_dat +from allometry.allometry_plotting import plot_allometry_dat +from math_utils.math_plotting import plot_quadratic_dat add_cime_lib_to_path() from CIME.utils import run_cmd_no_fail # pylint: disable=wrong-import-position,import-error,wrong-import-order # Constants for this script -DEFAULT_CDL_PATH = os.path.abspath("../parameter_files/fates_params_default.cdl") -CMAKE_BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../") -NAME = "fates_unit_tests" +_DEFAULT_CDL_PATH = os.path.abspath("../parameter_files/fates_params_default.cdl") +_CMAKE_BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../") +_TEST_NAME = "fates_unit_tests" # Dictionary with needed constants for running the executables and reading in the # output files - developers who add tests should add things here. @@ -50,7 +50,7 @@ # NOTE: if the functional test you write requires a parameter file read in as a # command-line argument, this should be the *first* (or only) argument in the # command-line argument list -test_dict = { +_ALL_TESTS_DICT = { "allometry": { "test_dir": "fates_allom_test", "test_exe": "FATES_allom_exe", @@ -71,8 +71,8 @@ } } -def run_exectuables(build_dir, test_dir, test_exe, run_dir, args): - """Run the generated executables +def run_fortran_exectuables(build_dir, test_dir, test_exe, run_dir, args): + """Run the generated Fortran executables Args: build_dir (str): full path to build directory @@ -92,16 +92,15 @@ def run_exectuables(build_dir, test_dir, test_exe, run_dir, args): run_command.extend(args) os.chdir(run_dir) - print("Running exectuables") out = run_cmd_no_fail(" ".join(run_command), combine_output=True) print(out) -def make_plotdirs(run_dir, test_list): +def make_plotdirs(run_dir, test_dict): """Create plotting directories if they don't already exist Args: run_dir (str): full path to run directory - test_list (list, str): list of test names + test_dict (dict): dictionary of test to run """ # make main plot directory plot_dir = os.path.join(run_dir, 'plots') @@ -109,11 +108,11 @@ def make_plotdirs(run_dir, test_list): os.mkdir(plot_dir) # make sub-plot directories - for test in test_list: - if test_dict[test]['plotting_function'] is not None: - sub_dir = os.path.join(plot_dir, test) - if not os.path.isdir(sub_dir): - os.mkdir(sub_dir) + for test in dict(filter(lambda pair: pair[1]['plotting_function'] is not None, + test_dict.items())): + sub_dir = os.path.join(plot_dir, test) + if not os.path.isdir(sub_dir): + os.mkdir(sub_dir) def create_param_file(param_file, run_dir): """Creates and/or move the default or input parameter file to the run directory @@ -131,7 +130,7 @@ def create_param_file(param_file, run_dir): """ if param_file is None: print("Using default parameter file.") - param_file = DEFAULT_CDL_PATH + param_file = _DEFAULT_CDL_PATH param_file_update = create_nc_file(param_file, run_dir) else: print(f"Using parameter file {param_file}.") @@ -145,19 +144,20 @@ def create_param_file(param_file, run_dir): return param_file_update -def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file, save_figs, test_list): +def run_tests(clean, build_tests, run_executables, build_dir, run_dir, make_j, + param_file, save_figs, test_dict): """Builds and runs the fates tests Args: clean (bool): whether or not to clean the build directory - build (bool): whether or not to build the exectuables - run (bool): whether or not to run the executables + build_tests (bool): whether or not to build the exectuables + run_executables (bool): whether or not to run the executables build_dir (str): build directory run_dir (str): run directory make_j (int): number of processors for the build param_file (str): input FATES parameter file save_figs (bool): whether or not to write figures to file - test_list(str, list): list of test names to run + test_dict (dict): dictionary of tests to run """ # absolute path to desired build directory @@ -172,34 +172,35 @@ def run_tests(clean, build, run, build_dir, run_dir, make_j, param_file, save_fi # create plot directories if we need to if save_figs: - make_plotdirs(os.path.abspath(run_dir), test_list) + make_plotdirs(os.path.abspath(run_dir), test_dict) # move parameter file to correct location (creates nc file if cdl supplied) param_file = create_param_file(param_file, run_dir) # compile code - if build: - build_unit_tests(build_dir, NAME, CMAKE_BASE_DIR, make_j, clean=clean) + if build_tests: + build_unit_tests(build_dir, _TEST_NAME, _CMAKE_BASE_DIR, make_j, clean=clean) # run executables for each test in test list - if run: - for test in test_list: - # we don't run executables for pfunit tests - if not test_dict[test]['unit_test']: - # prepend parameter file (if required) to argument list - args = test_dict[test]['other_args'] - if test_dict[test]['use_param_file']: - args.insert(0, param_file) - # run - run_exectuables(build_dir_path, test_dict[test]['test_dir'], - test_dict[test]['test_exe'], run_dir_path, args) + if run_executables: + print("Running executables") + # we don't run executables for pfunit tests + for test, attributes in dict(filter(lambda pair: not pair[1]['unit_test'], + test_dict.items())).items(): + # prepend parameter file (if required) to argument list + args = attributes['other_args'] + if attributes['use_param_file']: + args.insert(0, param_file) + # run + run_fortran_exectuables(build_dir_path, attributes['test_dir'], + attributes['test_exe'], run_dir_path, args) # plot output for relevant tests - for test in test_list: - if test_dict[test]['plotting_function'] is not None: - test_dict[test]['plotting_function'](run_dir_path, - test_dict[test]['out_file'], save_figs, - os.path.join(run_dir_path, 'plots', test)) + for test, attributes in dict(filter(lambda pair: pair[1]['plotting_function'] is not None, + test_dict.items())).items(): + attributes['plotting_function'](run_dir_path, + attributes['out_file'], save_figs, + os.path.join(run_dir_path, 'plots', test)) plt.show() def out_file_exists(run_dir, out_file): @@ -212,7 +213,6 @@ def out_file_exists(run_dir, out_file): Returns: bool: yes/no file exists in correct location """ - if not os.path.isfile(os.path.join(run_dir, out_file)): return False return True @@ -224,24 +224,26 @@ def parse_test_list(test_string): test (str): user-supplied comma-separated list of test names Returns: - str, list: list of test names to run + dictionary: filtered dictionary of tests to run Raises: RuntimeError: Invalid test name supplied """ - valid_test_names = test_dict.keys() + valid_test_names = _ALL_TESTS_DICT.keys() if test_string != "all": test_list = test_string.split(',') for test in test_list: if test not in valid_test_names: - raise argparse.ArgumentTypeError("Invalid test supplied, must supply one of:\n" + raise argparse.ArgumentTypeError("Invalid test supplied, \n" + "must supply one of:\n" f"{', '.join(valid_test_names)}\n" "or do not supply a test name to run all tests.") + test_dict = {key: _ALL_TESTS_DICT[key] for key in test_list} else: - test_list = [test for test in valid_test_names] + test_dict = _ALL_TESTS_DICT - return test_list + return test_dict def commandline_args(): """Parse and return command-line arguments""" @@ -262,7 +264,7 @@ def commandline_args(): "-f", "--parameter-file", type=str, - default=DEFAULT_CDL_PATH, + default=_DEFAULT_CDL_PATH, help="Parameter file to run the FATES tests with.\n" "Can be a netcdf (.nc) or cdl (.cdl) file.\n" "If no file is specified the script will use the default .cdl file in the\n" @@ -311,7 +313,7 @@ def commandline_args(): ) parser.add_argument( - "--skip-run", + "--skip-run-executables", action="store_true", help="Skip running test code executables.\n" "Only do this if you already have run the code previously.\n" @@ -330,7 +332,7 @@ def commandline_args(): "-t", "--test-list", action="store", - dest="test_list", + dest="test_dict", type=parse_test_list, default="all", help="Test(s) to run. Comma-separated list of test names, or 'all'\n" @@ -350,16 +352,16 @@ def check_param_file(param_file): param_file (str): path to parameter file Raises: - IOError: Parameter file is not of the correct form (.nc or .cdl) - IOError: Can't find parameter file + argparse.ArgumentError: Parameter file is not of the correct form (.nc or .cdl) + argparse.ArgumentError: Can't find parameter file """ file_suffix = os.path.basename(param_file).split(".")[-1] if not file_suffix in ['cdl', 'nc']: - raise argparse.ArgumentError("Must supply parameter file with .cdl or .nc ending.") + raise argparse.ArgumentError(None, "Must supply parameter file with .cdl or .nc ending.") if not os.path.isfile(param_file): - raise argparse.ArgumentError(f"Cannot find file {param_file}.") + raise argparse.ArgumentError(None, f"Cannot find file {param_file}.") -def check_build_dir(build_dir, test_list): +def check_build_dir(build_dir, test_dict): """Checks to see if all required build directories and executables are present Args: @@ -367,50 +369,45 @@ def check_build_dir(build_dir, test_list): test_list (list, str): list of test names Raises: - RuntimeError: Can't find a required build directory or executable + argparse.ArgumentError: Can't find a required build directory or executable """ - for test in test_list: - if not build_exists(build_dir, test_dict[test]['test_dir'], - test_dict[test]['test_exe']): - raise argparse.ArgumentError("Build directory or executable does not exist.\n" + for test, attributes in test_dict.items(): + if not build_exists(build_dir, attributes['test_dir'], attributes['test_exe']): + raise argparse.ArgumentError(None, "Build directory or executable does not exist.\n" "Re-run script without --skip-build.") -def check_out_files(run_dir, test_list): +def check_out_files(run_dir, test_dict): """Checks to see that required output files are present in the run directory Args: run_dir (str): run directory - test_list (str, list): list of test names + test_dict (dict): dictionary of tests to run Raises: - RuntimeError: Can't find a required output file + argparse.ArgumentError: Can't find a required output file """ - for test in test_list: - if test_dict[test]['out_file'] is not None: - if not out_file_exists(os.path.abspath(run_dir), test_dict[test]['out_file']): - raise argparse.ArgumentError(f"Required file for {test} test does not exist.\n" - "Re-run script without --skip-run.") + for test, attributes in dict(filter(lambda pair: pair[1]['out_file'] is not None, + test_dict.items())).items(): + if not out_file_exists(os.path.abspath(run_dir), attributes['out_file']): + raise argparse.ArgumentError(None, f"Required file for {test} test does not exist.\n" + "Re-run script without --skip-run.") def check_arg_validity(args): """Checks validity of input script arguments Args: args (parse_args): input arguments - """ # check to make sure parameter file exists and is one of the correct forms - if args.parameter_file is not None: - check_param_file(args.parameter_file) - else: - check_param_file(DEFAULT_CDL_PATH) + check_param_file(args.parameter_file) # make sure build directory exists if args.skip_build: - check_build_dir(args.build_dir, args.test_list) + check_build_dir(args.build_dir, args.test_dict) # make sure relevant output files exist: - if args.skip_run: - check_out_files(args.run_dir, args.test_list) + if args.skip_run_executables: + check_out_files(args.run_dir, args.test_dict) def main(): """Main script @@ -420,11 +417,10 @@ def main(): args = commandline_args() build = not args.skip_build - run = not args.skip_run + run = not args.skip_run_executables run_tests(args.clean, build, run, args.build_dir, args.run_dir, args.make_j, - args.parameter_file, args.save_figs, args.test_list) + args.parameter_file, args.save_figs, args.test_dict) if __name__ == "__main__": - main() diff --git a/functional_unit_testing/utils.py b/functional_unit_testing/utils.py index 4388ea5eb9..aa6079757d 100644 --- a/functional_unit_testing/utils.py +++ b/functional_unit_testing/utils.py @@ -1,4 +1,4 @@ -"""Utility functions for file checking, math equations, etc. +"""Utility functions for plotting, file checking, math equations, etc. """ import math @@ -73,12 +73,15 @@ def copy_file(file_path, directory): return file_basename -def get_color_pallete(): +def get_color_palette(number): """Generate a color pallete - + Args: + number: number of colors to get - must be <= 20 Returns: - real: array of colors to use in plotting + float: array of colors to use in plotting """ + if number > 20: + raise RuntimeError("get_color_palette: number must be <=20") colors = [(31, 119, 180), (174, 199, 232), (255, 127, 14), (255, 187, 120), (44, 160, 44), (152, 223, 138), (214, 39, 40), (255, 152, 150), @@ -88,4 +91,4 @@ def get_color_pallete(): colors = [(red/255.0, green/255.0, blue/255.0) for red, green, blue in colors] - return colors + return colors[:number] From 79b7369ddbdcc1e86b029a62ab99dfdb16b59ea8 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 22 Apr 2024 10:07:16 -0600 Subject: [PATCH 176/300] check for executable instead of unit test --- functional_unit_testing/run_fates_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 0aa53fd4a8..ecbddbb094 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -184,8 +184,8 @@ def run_tests(clean, build_tests, run_executables, build_dir, run_dir, make_j, # run executables for each test in test list if run_executables: print("Running executables") - # we don't run executables for pfunit tests - for test, attributes in dict(filter(lambda pair: not pair[1]['unit_test'], + # we don't run executables for only pfunit tests + for test, attributes in dict(filter(lambda pair: pair[1]['test_exe'] is not None, test_dict.items())).items(): # prepend parameter file (if required) to argument list args = attributes['other_args'] From ac21898dbbb4d0ef405c01b39b4aa150241d63d7 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 22 Apr 2024 10:07:51 -0600 Subject: [PATCH 177/300] more clear dictionary key --- functional_unit_testing/run_fates_tests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index ecbddbb094..0884bcf54a 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -55,7 +55,7 @@ "test_dir": "fates_allom_test", "test_exe": "FATES_allom_exe", "out_file": "allometry_out.nc", - "unit_test": False, + "has_unit_test": False, "use_param_file": True, "other_args": [], "plotting_function": plot_allometry_dat, @@ -64,7 +64,7 @@ "test_dir": "fates_math_test", "test_exe": "FATES_math_exe", "out_file": "quad_out.nc", - "unit_test": False, + "has_unit_test": False, "use_param_file": False, "other_args": [], "plotting_function": plot_quadratic_dat, From af5cb131d3774493117b766da01d4a2eba4d6cc5 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 22 Apr 2024 10:26:15 -0600 Subject: [PATCH 178/300] upading dict lambdas --- functional_unit_testing/run_fates_tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 0884bcf54a..6bae07e2b3 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -185,8 +185,8 @@ def run_tests(clean, build_tests, run_executables, build_dir, run_dir, make_j, if run_executables: print("Running executables") # we don't run executables for only pfunit tests - for test, attributes in dict(filter(lambda pair: pair[1]['test_exe'] is not None, - test_dict.items())).items(): + for attributes in dict(filter(lambda pair: pair[1]['test_exe'] is not None, + test_dict.items())).values(): # prepend parameter file (if required) to argument list args = attributes['other_args'] if attributes['use_param_file']: @@ -371,7 +371,7 @@ def check_build_dir(build_dir, test_dict): Raises: argparse.ArgumentError: Can't find a required build directory or executable """ - for test, attributes in test_dict.items(): + for attributes in test_dict.values(): if not build_exists(build_dir, attributes['test_dir'], attributes['test_exe']): raise argparse.ArgumentError(None, "Build directory or executable does not exist.\n" "Re-run script without --skip-build.") From 62d800462429b023629ace064a592a48ddd3bcfd Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 23 Apr 2024 10:40:44 -0400 Subject: [PATCH 179/300] Removed redundant history variables, updated some text to explain unit conversions better --- main/FatesHistoryInterfaceMod.F90 | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 763bf5c34c..96fb8d9078 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5014,6 +5014,8 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) if_notnew: if ( .not. ccohort%isnew ) then ! scale up cohort fluxes to the site level + ! these fluxes have conversions of [kg/plant/timestep] -> [kg/m2/s] + hio_npp_si(io_si) = hio_npp_si(io_si) + & ccohort%npp_tstep * n_perm2 * dt_tstep_inv @@ -5065,9 +5067,9 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) * n_perm2 ! accumulate fluxes on canopy- and understory- separated fluxes + ! these fluxes have conversions of [kg/plant/timestep] -> [kg/m2/s] if (ccohort%canopy_layer .eq. 1) then - ! bulk fluxes are in gC / m2 / s hio_gpp_canopy_si(io_si) = hio_gpp_canopy_si(io_si) + & ccohort%gpp_tstep * n_perm2 * dt_tstep_inv @@ -5076,7 +5078,6 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) else - ! bulk fluxes are in gC / m2 / s hio_gpp_understory_si(io_si) = hio_gpp_understory_si(io_si) + & ccohort%gpp_tstep * n_perm2 * dt_tstep_inv @@ -8488,10 +8489,6 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & ivar=ivar, initialize=initialize_variables, index = ih_nir_rad_err_si) - call this%set_history_var(vname='FATES_AR', units='gC/m^2/s', & - long='autotrophic respiration', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & - ivar=ivar, initialize=initialize_variables, index = ih_aresp_si ) ! Ecosystem Carbon Fluxes (updated rapidly, upfreq=group_hifr_simple) call this%set_history_var(vname='FATES_NPP', units='kg m-2 s-1', & @@ -8554,16 +8551,6 @@ subroutine define_history_vars(this, initialize_variables) upfreq=group_hifr_simple, ivar=ivar, initialize=initialize_variables, & index = ih_maint_resp_secondary_si) - call this%set_history_var(vname='FATES_AR_CANOPY', units='gC/m^2/s', & - long='autotrophic respiration of canopy plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & - ivar=ivar, initialize=initialize_variables, index = ih_ar_canopy_si ) - - call this%set_history_var(vname='FATES_AR_UNDERSTORY', units='gC/m^2/s', & - long='autotrophic respiration of understory plants', use_default='active', & - avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_hifr_simple, & - ivar=ivar, initialize=initialize_variables, index = ih_ar_understory_si ) - ! fast fluxes separated canopy/understory call this%set_history_var(vname='FATES_GPP_CANOPY', units='kg m-2 s-1', & long='gross primary production of canopy plants in kg carbon per m2 per second', & From 397dbe7e666c6fe5259508e93296343462587873 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 23 Apr 2024 10:53:01 -0400 Subject: [PATCH 180/300] fix to crown area normalized height diagnostic --- main/FatesHistoryInterfaceMod.F90 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 96fb8d9078..cee46b8529 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2927,6 +2927,10 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_lai_secondary_si(io_si) = 0._r8 end if + ! Normalize crown-area weighted height + if(site_ca>nearzero)then + hio_ca_weighted_height_si(io_si) = hio_ca_weighted_height_si(io_si)/site_ca + end if ! divide basal-area-weighted height by basal area to get mean if ( site_ba .gt. nearzero ) then From 0e9867165cf839786f97834ade30962e7c3af221 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 23 Apr 2024 09:06:07 -0600 Subject: [PATCH 181/300] fix need to call 2 separate registervar subroutines --- .../allometry/FatesTestAllometry.F90 | 33 ++-- .../math_utils/FatesTestMathUtils.F90 | 15 +- unit_test_shr/FatesUnitTestIOMod.F90 | 157 +++++++----------- 3 files changed, 86 insertions(+), 119 deletions(-) diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index 7ee85b7675..1d0c433d9f 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -52,7 +52,7 @@ subroutine WriteAllometryData(out_file, ndbh, numpft, dbh, height, bagw, blmax, total_biom_parts, total_biom_tissues) use FatesUnitTestIOMod, only : OpenNCFile, RegisterNCDims, CloseNCFile - use FatesUnitTestIOMod, only : RegisterVar1D, WriteVar, RegisterVar2D + use FatesUnitTestIOMod, only : WriteVar, RegisterVar use FatesUnitTestIOMod, only : type_double, type_int use FatesConstantsMod, only : r8 => fates_r8 implicit none @@ -152,7 +152,8 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height, bagw, blmax ! use FatesConstantsMod, only : r8 => fates_r8 use FatesUnitTestIOMod, only : OpenNCFile, RegisterNCDims, CloseNCFile - use FatesUnitTestIOMod, only : RegisterVar1D, WriteVar, RegisterVar2D + use FatesUnitTestIOMod, only : WriteVar + use FatesUnitTestIOMod, only : RegisterVar use FatesUnitTestIOMod, only : EndNCDef use FatesUnitTestIOMod, only : type_double, type_int @@ -206,83 +207,83 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height, bagw, blmax call RegisterNCDims(ncid, dim_names, (/numdbh, numpft/), 2, dimIDs) ! register dbh - call RegisterVar1D(ncid, dim_names(1), dimIDs(1), type_double, & + call RegisterVar(ncid, dim_names(1), dimIDs(1:1), type_double, & [character(len=20) :: 'units', 'long_name'], & [character(len=150) :: 'cm', 'diameter at breast height'], 2, dbhID) ! register pft - call RegisterVar1D(ncid, dim_names(2), dimIDs(2), type_int, & + call RegisterVar(ncid, dim_names(2), dimIDs(2:2), type_int, & [character(len=20) :: 'units', 'long_name'], & [character(len=150) :: '', 'plant functional type'], 2, pftID) ! register height - call RegisterVar2D(ncid, 'height', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'height', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'm', 'plant height'], & 3, heightID) ! register aboveground biomass - call RegisterVar2D(ncid, 'bagw', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'bagw', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'kgC', 'plant aboveground woody biomass'], & 3, bagwID) ! register leaf biomass - call RegisterVar2D(ncid, 'blmax', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'blmax', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'kgC', 'plant maximum leaf biomass'], & 3, blmaxID) ! register crown area - call RegisterVar2D(ncid, 'crown_area', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'crown_area', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'm2', 'plant crown area per cohort'], & 3, c_areaID) ! register sapwood area - call RegisterVar2D(ncid, 'sapwood_area', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'sapwood_area', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'm2', 'plant cross section area sapwood at reference height'], & 3, sapwoodareaID) ! register sapwood biomass - call RegisterVar2D(ncid, 'bsap', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'bsap', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'kgC', 'plant sapwood biomass'], & 3, bsapID) ! register belowground woody biomass - call RegisterVar2D(ncid, 'bbgw', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'bbgw', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'kgC', 'plant belowground woody biomass'], & 3, bbgwID) ! register fineroot biomass - call RegisterVar2D(ncid, 'fineroot_biomass', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'fineroot_biomass', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'kgC', 'plant fineroot biomass'], & 3, finerootID) ! register storage biomass - call RegisterVar2D(ncid, 'bstore', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'bstore', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'kgC', 'plant storage biomass'], & 3, bstoreID) ! register structural biomass - call RegisterVar2D(ncid, 'bdead', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'bdead', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'kgC', 'plant deadwood (structural/heartwood) biomass'], & 3, bdeadID) ! register total biomass (parts) - call RegisterVar2D(ncid, 'total_biomass_parts', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'total_biomass_parts', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'kgC', 'plant total biomass calculated from parts'], & 3, totbiomID1) ! register total biomass (tissues) - call RegisterVar2D(ncid, 'total_biomass_tissues', dimIDs(1:2), type_double, & + call RegisterVar(ncid, 'total_biomass_tissues', dimIDs(1:2), type_double, & [character(len=20) :: 'coordinates', 'units', 'long_name'], & [character(len=150) :: 'pft dbh', 'kgC', 'plant total biomass calculated from tissues'], & 3, totbiomID2) diff --git a/functional_unit_testing/math_utils/FatesTestMathUtils.F90 b/functional_unit_testing/math_utils/FatesTestMathUtils.F90 index f13b888d47..2eae197f57 100644 --- a/functional_unit_testing/math_utils/FatesTestMathUtils.F90 +++ b/functional_unit_testing/math_utils/FatesTestMathUtils.F90 @@ -22,7 +22,7 @@ program FatesTestQuadSolvers subroutine WriteQuadData(out_file, n, a, b, c, root1, root2) use FatesUnitTestIOMod, only : OpenNCFile, RegisterNCDims, CloseNCFile - use FatesUnitTestIOMod, only : RegisterVar1D, WriteVar, RegisterVar2D + use FatesUnitTestIOMod, only : WriteVar, RegisterVar use FatesUnitTestIOMod, only : type_double, type_int use FatesConstantsMod, only : r8 => fates_r8 implicit none @@ -59,7 +59,8 @@ subroutine WriteQuadData(out_file, n, a, b, c, root1, root2) ! use FatesConstantsMod, only : r8 => fates_r8 use FatesUnitTestIOMod, only : OpenNCFile, RegisterNCDims, CloseNCFile - use FatesUnitTestIOMod, only : RegisterVar1D, WriteVar, RegisterVar2D + use FatesUnitTestIOMod, only : WriteVar + use FatesUnitTestIOMod, only : RegisterVar use FatesUnitTestIOMod, only : EndNCDef use FatesUnitTestIOMod, only : type_double, type_int @@ -98,27 +99,27 @@ subroutine WriteQuadData(out_file, n, a, b, c, root1, root2) call RegisterNCDims(ncid, dim_names, (/n/), 1, dimIDs) ! register a - call RegisterVar1D(ncid, 'a', dimIDs(1), type_double, & + call RegisterVar(ncid, 'a', dimIDs(1:1), type_double, & [character(len=20) :: 'units', 'long_name'], & [character(len=150) :: '', 'coefficient a'], 2, aID) ! register b - call RegisterVar1D(ncid, 'b', dimIDs(1), type_double, & + call RegisterVar(ncid, 'b', dimIDs(1:1), type_double, & [character(len=20) :: 'units', 'long_name'], & [character(len=150) :: '', 'coefficient b'], 2, bID) ! register c - call RegisterVar1D(ncid, 'c', dimIDs(1), type_double, & + call RegisterVar(ncid, 'c', dimIDs(1:1), type_double, & [character(len=20) :: 'units', 'long_name'], & [character(len=150) :: '', 'coefficient c'], 2, cID) ! register root1 - call RegisterVar1D(ncid, 'root1', dimIDs(1), type_double, & + call RegisterVar(ncid, 'root1', dimIDs(1:1), type_double, & [character(len=20) :: 'units', 'long_name'], & [character(len=150) :: '', 'root 1'], 2, root1ID) ! register root2 - call RegisterVar1D(ncid, 'root2', dimIDs(1), type_double, & + call RegisterVar(ncid, 'root2', dimIDs(1:1), type_double, & [character(len=20) :: 'units', 'long_name'], & [character(len=150) :: '', 'root 2'], 2, root2ID) diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 index d1428ea3ec..c6cccbd11a 100644 --- a/unit_test_shr/FatesUnitTestIOMod.F90 +++ b/unit_test_shr/FatesUnitTestIOMod.F90 @@ -3,12 +3,12 @@ module FatesUnitTestIOMod use FatesGlobals, only : fates_endrun use shr_kind_mod, only : SHR_KIND_CL use netcdf - + implicit none private ! LOCALS - integer, public, parameter :: type_double = 1 ! type + integer, public, parameter :: type_double = 1 ! type integer, public, parameter :: type_int = 2 ! type interface GetVar @@ -28,16 +28,21 @@ module FatesUnitTestIOMod module procedure WriteVar2DInt end interface + ! interface RegisterVar + ! !module procedure RegisterVar1D + ! module procedure RegisterVar_all + ! end interface + public :: OpenNCFile public :: CloseNCFile public :: GetDimID public :: GetDimLen public :: GetVar public :: RegisterNCDims - public :: RegisterVar2D, RegisterVar1D + public :: RegisterVar public :: WriteVar public :: EndNCDef - + contains !======================================================================================= @@ -56,7 +61,7 @@ logical function CheckFile(filename, fmode) character(len=len(filename)) :: fname ! Local filename (trimmed) integer :: ios ! I/O status logical :: file_exists ! Does the file exist? - + ! trim filename of whitespace fname = trim(adjustl(filename)) @@ -65,26 +70,26 @@ logical function CheckFile(filename, fmode) select case (fmode) case('read') - - if (.not. file_exists) then + + if (.not. file_exists) then write(*,'(a,a,a)') "File ", fname(1:len_trim(fname)), " does not exist. Can't read." CheckFile = .false. - else + else CheckFile = .true. end if case('readwrite') CheckFile = .true. - - case('write') - if (file_exists) then + + case('write') + if (file_exists) then write(*, '(a, a, a)') "File ", fname(1:len_trim(fname)), " exists. Cannot open write only." - else + else CheckFile = .true. CheckFile = .false. - end if - case default + end if + case default write(*,'(a)') "Invalid file mode." CheckFile = .false. end select @@ -97,13 +102,13 @@ subroutine Check(status) ! ! DESCRIPTION: ! Checks status of netcdf operations - + ! ARGUMENTS: integer, intent(in) :: status ! return status code from a netcdf procedure - - if (status /= nf90_noerr) then + + if (status /= nf90_noerr) then write(*,*) trim(nf90_strerror(status)) - stop + stop end if end subroutine Check @@ -114,7 +119,7 @@ subroutine OpenNCFile(nc_file, ncid, fmode) ! ! DESCRIPTION: ! Opens a netcdf file - + ! ARGUMENTS: character(len=*), intent(in) :: nc_file ! file name integer, intent(out) :: ncid ! netcdf file unit number @@ -133,10 +138,10 @@ subroutine OpenNCFile(nc_file, ncid, fmode) write(*,*) 'Need to specify read, write, or readwrite' stop end select - else + else write(*,*) 'Problem reading file' stop - end if + end if end subroutine OpenNCFile @@ -146,7 +151,7 @@ subroutine CloseNCFile(ncid) ! ! DESCRIPTION: ! Closes a netcdf file - + ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file unit number @@ -161,7 +166,7 @@ subroutine GetDimID(ncid, var_name, dim_id) ! DESCRIPTION: ! Gets dimension IDs for a variable ID ! - + ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file unit number character(len=*), intent(in) :: var_name ! variable name @@ -189,7 +194,7 @@ subroutine GetDimLen(ncid, dim_id, dim_len) end subroutine GetDimLen !======================================================================================= - + subroutine GetDims(ncid, varID, dim_lens) ! ! DESCRIPTION: @@ -206,7 +211,7 @@ subroutine GetDims(ncid, varID, dim_lens) integer, allocatable :: dimIDs(:) ! dimension IDs integer :: i ! looping index - ! find dimensions of data + ! find dimensions of data call Check(nf90_inquire_variable(ncid, varID, ndims=numDims)) ! allocate data to grab dimension information @@ -238,7 +243,7 @@ subroutine GetVarScalarReal(ncid, var_name, data) ! LOCALS: integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths + integer, allocatable :: dim_lens(:) ! dimension lengths ! find variable ID first call Check(nf90_inq_varid(ncid, var_name, varID)) @@ -263,7 +268,7 @@ subroutine GetVar1DReal(ncid, var_name, data) ! LOCALS: integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths + integer, allocatable :: dim_lens(:) ! dimension lengths ! find variable ID first call Check(nf90_inq_varid(ncid, var_name, varID)) @@ -292,7 +297,7 @@ subroutine GetVar1DInt(ncid, var_name, data) ! LOCALS: integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths + integer, allocatable :: dim_lens(:) ! dimension lengths ! find variable ID first call Check(nf90_inq_varid(ncid, var_name, varID)) @@ -321,7 +326,7 @@ subroutine GetVar2DReal(ncid, var_name, data) ! LOCALS: integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths + integer, allocatable :: dim_lens(:) ! dimension lengths ! find variable ID first call Check(nf90_inq_varid(ncid, var_name, varID)) @@ -350,7 +355,7 @@ subroutine GetVar2DInt(ncid, var_name, data) ! LOCALS: integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths + integer, allocatable :: dim_lens(:) ! dimension lengths ! find variable ID first call Check(nf90_inq_varid(ncid, var_name, varID)) @@ -379,7 +384,7 @@ subroutine GetVar3DReal(ncid, var_name, data) ! LOCALS: integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths + integer, allocatable :: dim_lens(:) ! dimension lengths ! find variable ID first call Check(nf90_inq_varid(ncid, var_name, varID)) @@ -408,7 +413,7 @@ subroutine GetVar3DInt(ncid, var_name, data) ! LOCALS: integer :: varID ! variable ID - integer, allocatable :: dim_lens(:) ! dimension lengths + integer, allocatable :: dim_lens(:) ! dimension lengths ! find variable ID first call Check(nf90_inq_varid(ncid, var_name, varID)) @@ -427,10 +432,10 @@ end subroutine GetVar3DInt subroutine RegisterNCDims(ncid, dim_names, dim_lens, num_dims, dim_IDs) ! ! DESCRIPTION: - ! Defines variables and dimensions + ! Defines variables and dimensions ! - ! ARGUMENTS: + ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file id character(len=*), intent(in) :: dim_names(num_dims) ! dimension names integer, intent(in) :: dim_lens(num_dims) ! dimension lengths @@ -440,27 +445,27 @@ subroutine RegisterNCDims(ncid, dim_names, dim_lens, num_dims, dim_IDs) ! LOCALS: integer :: i ! looping index - do i = 1, num_dims + do i = 1, num_dims call Check(nf90_def_dim(ncid, dim_names(i), dim_lens(i), dim_IDs(i))) - end do + end do end subroutine RegisterNCDims !===================================================================================== - subroutine RegisterVar1D(ncid, var_name, dimID, type, att_names, atts, num_atts, varID) + subroutine RegisterVar(ncid, var_name, dimID, type, att_names, atts, num_atts, varID) ! ! DESCRIPTION: - ! Defines variables and dimensions + ! Defines variables and dimensions ! - ! ARGUMENTS: + ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file id character(len=*), intent(in) :: var_name ! variable name - integer, intent(in) :: dimID ! dimension ID + integer, intent(in) :: dimID(:) ! dimension IDs integer, intent(in) :: type ! type: int or double character(len=*), intent(in) :: att_names(num_atts) ! attribute names - character(len=*), intent(in) :: atts(num_atts) ! attribute values + character(len=*), intent(in) :: atts(num_atts) ! attribute values integer, intent(in) :: num_atts ! number of attributes integer, intent(out) :: varID ! variable ID @@ -469,62 +474,22 @@ subroutine RegisterVar1D(ncid, var_name, dimID, type, att_names, atts, num_atts, integer :: i ! looping index integer :: nc_type ! netcdf type - if (type == type_double) then + if (type == type_double) then nc_type = NF90_DOUBLE - else if (type == type_int) then + else if (type == type_int) then nc_type = NF90_INT else write(*, *) "Must pick correct type" stop - end if + end if call Check(nf90_def_var(ncid, var_name, nc_type, dimID, varID)) - do i = 1, num_atts + do i = 1, num_atts call Check(nf90_put_att(ncid, varID, att_names(i), atts(i))) end do - - end subroutine RegisterVar1D - - !===================================================================================== - - subroutine RegisterVar2D(ncid, var_name, dimID, type, att_names, atts, num_atts, varID) - ! - ! DESCRIPTION: - ! Defines variables and dimensions - ! - - ! ARGUMENTS: - integer, intent(in) :: ncid ! netcdf file id - character(len=*), intent(in) :: var_name ! variable name - integer, intent(in) :: dimID(1:2) ! dimension ID - integer, intent(in) :: type ! type: int or double - character(len=*), intent(in) :: att_names(num_atts) ! attribute names - character(len=*), intent(in) :: atts(num_atts) ! attribute values - integer, intent(in) :: num_atts ! number of attributes - integer, intent(out) :: varID ! variable ID - - ! LOCALS: - integer :: i ! looping index - integer :: nc_type ! netcdf type - - if (type == type_double) then - nc_type = NF90_DOUBLE - else if (type == type_int) then - nc_type = NF90_INT - else - write(*, *) "Must pick correct type" - stop - end if - - call Check(nf90_def_var(ncid, var_name, nc_type, dimID, varID)) - - do i = 1, num_atts - call Check(nf90_put_att(ncid, varID, att_names(i), atts(i))) - end do - - end subroutine RegisterVar2D + end subroutine RegisterVar ! ===================================================================================== @@ -534,11 +499,11 @@ subroutine EndNCDef(ncid) ! End defining of netcdf dimensions and variables ! - ! ARGUMENTS: + ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file id call Check(nf90_enddef(ncid)) - + end subroutine EndNCDef ! ===================================================================================== @@ -549,13 +514,13 @@ subroutine WriteVar1DReal(ncid, varID, data) ! Write 1D real data ! - ! ARGUMENTS: + ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file id integer, intent(in) :: varID ! variable ID real(r8), intent(in) :: data(:) ! data to write call Check(nf90_put_var(ncid, varID, data(:))) - + end subroutine WriteVar1DReal ! ===================================================================================== @@ -566,13 +531,13 @@ subroutine WriteVar2DReal(ncid, varID, data) ! Write 2D real data ! - ! ARGUMENTS: + ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file id integer, intent(in) :: varID ! variable ID real(r8), intent(in) :: data(:,:) ! data to write call Check(nf90_put_var(ncid, varID, data(:,:))) - + end subroutine WriteVar2DReal ! ===================================================================================== @@ -583,13 +548,13 @@ subroutine WriteVar1DInt(ncid, varID, data) ! Write 1D integer data ! - ! ARGUMENTS: + ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file id integer, intent(in) :: varID ! variable ID integer, intent(in) :: data(:) ! data to write call Check(nf90_put_var(ncid, varID, data(:))) - + end subroutine WriteVar1DInt ! ===================================================================================== @@ -600,13 +565,13 @@ subroutine WriteVar2DInt(ncid, varID, data) ! Write 2D integer data ! - ! ARGUMENTS: + ! ARGUMENTS: integer, intent(in) :: ncid ! netcdf file id integer, intent(in) :: varID ! variable ID integer, intent(in) :: data(:,:) ! data to write call Check(nf90_put_var(ncid, varID, data(:,:))) - + end subroutine WriteVar2DInt ! ===================================================================================== From b25df0eae4fa384fd5dc885119356d3ba86f23c6 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 23 Apr 2024 09:26:47 -0600 Subject: [PATCH 182/300] clean up --- .../math_utils/FatesTestMathUtils.F90 | 1 - unit_test_shr/FatesUnitTestIOMod.F90 | 11 +++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/functional_unit_testing/math_utils/FatesTestMathUtils.F90 b/functional_unit_testing/math_utils/FatesTestMathUtils.F90 index 2eae197f57..627eb2713b 100644 --- a/functional_unit_testing/math_utils/FatesTestMathUtils.F90 +++ b/functional_unit_testing/math_utils/FatesTestMathUtils.F90 @@ -10,7 +10,6 @@ program FatesTestQuadSolvers integer, parameter :: n = 4 ! number of points to test character(len=*), parameter :: out_file = 'quad_out.nc' ! output file - ! LOCALS: integer :: i ! looping index real(r8) :: a(n), b(n), c(n) ! coefficients for quadratic solvers diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_test_shr/FatesUnitTestIOMod.F90 index c6cccbd11a..8f6ea1141a 100644 --- a/unit_test_shr/FatesUnitTestIOMod.F90 +++ b/unit_test_shr/FatesUnitTestIOMod.F90 @@ -1,7 +1,7 @@ module FatesUnitTestIOMod - use FatesConstantsMod, only : r8 => fates_r8 - use FatesGlobals, only : fates_endrun - use shr_kind_mod, only : SHR_KIND_CL + use FatesConstantsMod, only : r8 => fates_r8 + use FatesGlobals, only : fates_endrun + use shr_kind_mod, only : SHR_KIND_CL use netcdf implicit none @@ -28,11 +28,6 @@ module FatesUnitTestIOMod module procedure WriteVar2DInt end interface - ! interface RegisterVar - ! !module procedure RegisterVar1D - ! module procedure RegisterVar_all - ! end interface - public :: OpenNCFile public :: CloseNCFile public :: GetDimID From c611b0d25c2bc610e83ad988bb2cafaad89f62b3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 23 Apr 2024 13:06:18 -0400 Subject: [PATCH 183/300] syntax style updates --- biogeochem/FatesLandUseChangeMod.F90 | 31 +++++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index c244f7267b..3ef66cf75c 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -101,7 +101,8 @@ subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, lan urban_fraction = bc_in%hlm_luh_states(FindIndex(bc_in%hlm_luh_state_names,'urban')) end if - !!TODO: may need some logic here to ask whether or not ot perform land use change on this timestep. current code occurs every day. + !!TODO: may need some logic here to ask whether or not ot perform land use change on this + ! timestep. current code occurs every day. !!If not doing transition every day, need to update units. transitions_loop: do i_luh2_transitions = 1, hlm_num_luh2_transitions @@ -170,15 +171,19 @@ end function GetLUCategoryFromStateName subroutine get_landusechange_rules(clearing_matrix) - ! the purpose of this is to define a ruleset for when to clear the vegetation in transitioning from one land use type to another + ! the purpose of this is to define a ruleset for when to clear the + ! vegetation in transitioning from one land use type to another logical, intent(out) :: clearing_matrix(n_landuse_cats,n_landuse_cats) - ! default value of ruleset 4 above means that plants are not cleared during land use change transitions to rangeland, whereas plants are + ! default value of ruleset 4 above means that plants are not cleared during + ! land use change transitions to rangeland, whereas plants are ! cleared in transitions to pasturelands and croplands. - integer, parameter :: ruleset = 4 ! ruleset to apply from table 1 of Ma et al (2020) https://doi.org/10.5194/gmd-13-3203-2020 + integer, parameter :: ruleset = 4 ! ruleset to apply from table 1 of Ma et al + ! (2020) https://doi.org/10.5194/gmd-13-3203-2020 - ! clearing matrix applies from the donor to the receiver land use type of the newly-transferred patch area + ! clearing matrix applies from the donor to the receiver land use + ! type of the newly-transferred patch area ! values of clearing matrix: false => do not clear; true => clear clearing_matrix(:,:) = .false. @@ -187,8 +192,9 @@ subroutine get_landusechange_rules(clearing_matrix) case(1) - ! note that this ruleset isnt exactly what is in Ma et al. rulesets 1 and 2, because FATES does not make the distinction - ! between forested and non-forested lands from a land use/land cover perspective. + ! note that this ruleset isnt exactly what is in Ma et al. rulesets 1 and 2, + ! because FATES does not make the distinction between forested and non-forested + ! lands from a land use/land cover perspective. clearing_matrix(:,cropland) = .true. clearing_matrix(:,pastureland) = .true. clearing_matrix(primaryland,rangeland) = .true. @@ -310,6 +316,10 @@ subroutine get_luh_statedata(bc_in, state_vector) state_vector(primaryland) = 1._r8 endif else + + ! If we are using potential vegetation, that means + ! our only land classification is primary land + state_vector(primaryland) = 1._r8 end if @@ -326,8 +336,8 @@ subroutine CheckLUHData(luh_vector,modified_flag) ! Check to see if the incoming luh2 vector is NaN. ! This suggests that there is a discepency where the HLM and LUH2 states - ! there is vegetated ground. E.g. LUH2 data is missing for glacier-margin regions such as Antarctica. - ! In this case, states should be Nan. If so, + ! there is vegetated ground. E.g. LUH2 data is missing for glacier-margin + ! regions such as Antarctica. In this case, states should be Nan. If so, ! set the current state to be all primary forest, and all transitions to be zero. ! If only a portion of the vector is NaN, there is something amiss with ! the data, so end the run. @@ -340,7 +350,8 @@ subroutine CheckLUHData(luh_vector,modified_flag) luh_vector(primaryland) = 1._r8 end if modified_flag = .true. - !write(fates_log(),*) 'WARNING: land use state is all NaN; setting state as all primary forest.' ! GL DIAG + !write(fates_log(),*) 'WARNING: land use state is all NaN; + !setting state as all primary forest.' ! GL DIAG else if (any(isnan(luh_vector))) then if (any(.not. isnan(luh_vector))) then write(fates_log(),*) 'ERROR: land use vector has NaN' From ad20bfd1d6eca8d936868b4a43ef667d3924c6fa Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 23 Apr 2024 13:09:01 -0400 Subject: [PATCH 184/300] update long name of vertical resp scaling to inform proportionality with leaf N --- parameter_files/fates_params_default.cdl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 018d714191..ad2c9a9b6a 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -389,10 +389,10 @@ variables: fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; double fates_maintresp_leaf_vert_scaler_coeff1(fates_pft) ; fates_maintresp_leaf_vert_scaler_coeff1:units = "unitless" ; - fates_maintresp_leaf_vert_scaler_coeff1:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the default value of 0.00963." ; + fates_maintresp_leaf_vert_scaler_coeff1:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the same value as fates_leafn_vert_scaler_coeff1." ; double fates_maintresp_leaf_vert_scaler_coeff2(fates_pft) ; fates_maintresp_leaf_vert_scaler_coeff2:units = "unitless" ; - fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the default value of 2.43." ; + fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the same value as fates_leafn_vert_scaler_coeff2." ; double fates_leafn_vert_scaler_coeff1(fates_pft) ; fates_leafn_vert_scaler_coeff1:units = "unitless" ; fates_leafn_vert_scaler_coeff1:long_name = "Coefficient one for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010. " ; From f4ef11bf0d00e79dfc88f5f5afff0a4498e98c20 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 23 Apr 2024 17:41:15 -0400 Subject: [PATCH 185/300] adding in ncalers and unifying vert scaler code --- biogeochem/EDPhysiologyMod.F90 | 7 +++-- biogeochem/FatesAllometryMod.F90 | 30 ++++++++++++++-------- biogeophys/FatesPlantRespPhotosynthMod.F90 | 18 ++++++------- main/EDPftvarcon.F90 | 19 +------------- parteh/PRTParametersMod.F90 | 5 ++++ parteh/PRTParamsFATESMod.F90 | 18 +++++++++++++ 6 files changed, 58 insertions(+), 39 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 727aaa7370..e25a722f7a 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -45,7 +45,7 @@ module EDPhysiologyMod use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai use FatesAllometryMod , only : leafc_from_treelai - use FatesAllometryMod , only : decay_coeff_kn + use FatesAllometryMod , only : decay_coeff_vcmax use FatesLitterMod , only : litter_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : numlevsoil_max @@ -765,7 +765,10 @@ subroutine trim_canopy( currentSite ) ! Calculate sla_levleaf following the sla profile with overlying leaf area ! Scale for leaf nitrogen profile - kn = decay_coeff_kn(ipft,currentCohort%vcmax25top) + kn = decay_coeff_vcmax(currentCohort%vcmax25top, & + prt_params%leafn_vert_scaler_coeff1(ipft), & + prt_params%leafn_vert_scaler_coeff2(ipft)) + ! Nscaler value at leaf level z nscaler_levleaf = exp(-kn * cumulative_lai) ! Sla value at leaf level z after nitrogen profile scaling (m2/gC) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 6cccde4422..1aa1cc4525 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -118,7 +118,7 @@ module FatesAllometryMod public :: bdead_allom ! Generic bdead wrapper public :: carea_allom ! Generic crown area wrapper public :: bstore_allom ! Generic maximum storage carbon wrapper - public :: decay_coeff_kn + public :: decay_coeff_vcmax ! vertical canopy decay rate, scaled on vcmax public :: ForceDBH ! Method to set DBH to sync with structure ! or fineroot biomass public :: CheckIntegratedAllometries @@ -710,8 +710,10 @@ real(r8) function tree_lai( leaf_c, pft, c_area, nplant, cl, canopy_lai, vcmax25 end if ! Coefficient for exponential decay of 1/sla with canopy depth: - kn = decay_coeff_kn(pft,vcmax25top) - + kn = decay_coeff_vcmax(vcmax25top, & + prt_params%leafn_vert_scaler_coeff1(pft), & + prt_params%leafn_vert_scaler_coeff2(pft)) + ! take PFT-level maximum SLA value, even if under a thick canopy (which has units of m2/gC), ! and put into units of m2/kgC sla_max = g_per_kg*prt_params%slamax(pft) @@ -904,8 +906,11 @@ real(r8) function leafc_from_treelai( treelai, pft, c_area, nplant, cl, vcmax25t ! convert PFT-level canopy top and maximum SLA values and convert from m2/gC to m2/kgC slat = g_per_kg * prt_params%slatop(pft) sla_max = g_per_kg * prt_params%slamax(pft) + ! Coefficient for exponential decay of 1/sla with canopy depth: - kn = decay_coeff_kn(pft,vcmax25top) + kn = decay_coeff_vcmax(vcmax25top, & + prt_params%leafn_vert_scaler_coeff1(pft), & + prt_params%leafn_vert_scaler_coeff2(pft)) if(treelai > 0.0_r8)then ! Leafc_per_unitarea at which sla_max is reached due to exponential sla profile in canopy: @@ -2743,7 +2748,7 @@ end subroutine jackson_beta_root_profile ! ===================================================================================== - real(r8) function decay_coeff_kn(pft,vcmax25top) + real(r8) function decay_coeff_vcmax(vcmax25top,slope_param,intercept_param) ! --------------------------------------------------------------------------------- ! This function estimates the decay coefficient used to estimate vertical @@ -2751,13 +2756,16 @@ real(r8) function decay_coeff_kn(pft,vcmax25top) ! ! Decay coefficient (kn) is a function of vcmax25top for each pft. ! - ! Currently, this decay is applied to vcmax attenuation, and SLA (optionally) + ! Currently, this decay is applied to vcmax attenuation, SLA (optionally) + ! and leaf respiration (optionally w/ Atkin) ! ! --------------------------------------------------------------------------------- !ARGUMENTS - integer, intent(in) :: pft + real(r8),intent(in) :: vcmax25top + real(r8),intent(in) :: slope_param ! multiplies vcmax25top + real(r8),intent(in) :: intercept_param ! adds to vcmax25top !LOCAL VARIABLES @@ -2766,12 +2774,14 @@ real(r8) function decay_coeff_kn(pft,vcmax25top) ! Bonan et al (2011) JGR, 116, doi:10.1029/2010JG001593 used ! kn = 0.11. Here, we derive kn from vcmax25 as in Lloyd et al ! (2010) Biogeosciences, 7, 1833-1859 + ! This function is also used to vertically scale leaf maintenance + ! respiration. - decay_coeff_kn = exp(0.00963_r8 * vcmax25top - 2.43_r8) + decay_coeff_vcmax = exp(slope_param * vcmax25top - intercept_param) return - end function decay_coeff_kn - + end function decay_coeff_vcmax + ! ===================================================================================== subroutine ForceDBH( ipft, crowndamage, canopy_trim, elongf_leaf, elongf_stem, d, h, bdead, bl ) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index ae639ebb6e..dee03c4b36 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -146,7 +146,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use FatesAllometryMod, only : bleaf, bstore_allom use FatesAllometryMod, only : storage_fraction_of_target use FatesAllometryMod, only : set_root_fraction - use FatesAllometryMod, only : decay_coeff_kn + use FatesAllometryMod, only : decay_coeff_vcmax use DamageMainMod, only : GetCrownReduction @@ -544,7 +544,9 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! kn = 0.11. Here, derive kn from vcmax25 as in Lloyd et al ! (2010) Biogeosciences, 7, 1833-1859 - kn = decay_coeff_kn(ft,currentCohort%vcmax25top) + kn = decay_coeff_vcmax(currentCohort%vcmax25top, & + prt_params%leafn_vert_scaler_coeff1(ft), & + prt_params%leafn_vert_scaler_coeff2(ft)) ! Scale for leaf nitrogen profile nscaler = exp(-kn * cumulative_lai) @@ -2219,8 +2221,6 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & real(r8) :: rdark_scaler ! negative exponential scaling of rdark real(r8) :: kn ! decay coefficient - real(r8) :: rdark_vert_scaler1 ! determines rate of rdark decay through canopy - real(r8) :: rdark_vert_scaler2 ! determines rate of rdark decay through canopy ! parameter values of r_0 as listed in Atkin et al 2017: (umol CO2/m**2/s) ! Broad-leaved trees 1.7560 @@ -2233,9 +2233,6 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! all figs in Atkin et al 2017 stop at zero Celsius so we will assume acclimation is fixed below that r_0 = EDPftvarcon_inst%maintresp_leaf_atkin2017_baserate(ft) - rdark_vert_scaler1 = EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff1(ft) - rdark_vert_scaler2 = EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff2(ft) - ! This code uses the relationship between leaf N and respiration from Atkin et al ! for the top of the canopy, but then scales through the canopy based on a rdark_scaler. ! To assume proportionality with N through the canopy following Lloyd et al. 2010, use the @@ -2243,8 +2240,11 @@ subroutine LeafLayerMaintenanceRespiration_Atkin_etal_2017(lnc_top, & ! being proportional through the canopy. To have a steeper decrease in respiration than photosynthesis ! this number can be smaller. There is some observational evidence for this being the case ! in Lamour et al. 2023. - - kn = exp(rdark_vert_scaler1 * vcmax25top - rdark_vert_scaler2) + + kn = decay_coeff_vcmax(vcmax25top, & + EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff1(ft), & + EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff2(ft)) + rdark_scaler = exp(-kn * cumulative_lai) r_t_ref = max(0._r8, rdark_scaler * (r_0 + lmr_r_1 * lnc_top + lmr_r_2 * max(0._r8, (tgrowth - tfrz) )) ) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index bc821c0204..9d57655b54 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -92,8 +92,7 @@ module EDPftvarcon real(r8), allocatable :: maintresp_leaf_ryan1991_baserate(:) ! leaf maintenance respiration per Ryan et al 1991 - real(r8), allocatable :: leafn_vert_scaler_coeff1(:) ! Coefficient one for decrease of leaf N through the canopy - real(r8), allocatable :: leafn_vert_scaler_coeff2(:) ! Coefficient two for decrease of leaf N through the canopy + real(r8), allocatable :: maintresp_leaf_vert_scaler_coeff1(:) ! leaf maintenance respiration decrease through the canopy param 1 ! only with Atkin et al. 2017 respiration model @@ -478,13 +477,7 @@ subroutine Register_PFT(this, fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_leafn_vert_scaler_coeff1' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_leafn_vert_scaler_coeff2' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) name = 'fates_maintresp_leaf_vert_scaler_coeff1' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & @@ -935,14 +928,6 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=this%maintresp_leaf_ryan1991_baserate) - name = 'fates_leafn_vert_scaler_coeff1' - call fates_params%RetrieveParameterAllocate(name=name, & - data=this%leafn_vert_scaler_coeff1) - - name = 'fates_leafn_vert_scaler_coeff2' - call fates_params%RetrieveParameterAllocate(name=name, & - data=this%leafn_vert_scaler_coeff2) - name = 'fates_maintresp_leaf_vert_scaler_coeff1' call fates_params%RetrieveParameterAllocate(name=name, & data=this%maintresp_leaf_vert_scaler_coeff1) @@ -1776,8 +1761,6 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'hydro_vg_alpha_node = ',EDPftvarcon_inst%hydr_vg_alpha_node write(fates_log(),fmt0) 'hydro_vg_m_node = ',EDPftvarcon_inst%hydr_vg_m_node write(fates_log(),fmt0) 'hydro_vg_n_node = ',EDPftvarcon_inst%hydr_vg_n_node - write(fates_log(),fmt0) 'leafn_vert_scaler_coeff1 = ',EDPftvarcon_inst%leafn_vert_scaler_coeff1 - write(fates_log(),fmt0) 'leafn_vert_scaler_coeff2 = ',EDPftvarcon_inst%leafn_vert_scaler_coeff2 write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff1 = ',EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff1 write(fates_log(),fmt0) 'maintresp_leaf_vert_scaler_coeff2 = ',EDPftvarcon_inst%maintresp_leaf_vert_scaler_coeff2 write(fates_log(),*) '-------------------------------------------------' diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index bb3f98f6be..febd4a3b55 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -60,6 +60,11 @@ module PRTParametersMod real(r8), allocatable :: turnover_nitr_retrans(:,:) ! nitrogen re-translocation fraction (pft x organ) real(r8), allocatable :: turnover_phos_retrans(:,:) ! phosphorus re-translocation fraction (pft x organ) ! Parameters dimensioned by PFT and leaf age + + ! These vertical n profile scalers affect crown allometry and sla, thus they + ! are here in the PRT module + real(r8), allocatable :: leafn_vert_scaler_coeff1(:) ! Coefficient one for decrease of leaf N through the canopy + real(r8), allocatable :: leafn_vert_scaler_coeff2(:) ! Coefficient two for decrease of leaf N through the canopy real(r8), allocatable :: grperc(:) ! Growth respiration per unit Carbon gained ! One value for whole plant diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 381546f1d9..3a3c624926 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -237,6 +237,14 @@ subroutine PRTRegisterPFT(fates_params) call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_leafn_vert_scaler_coeff1' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + + name = 'fates_leafn_vert_scaler_coeff2' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_recruit_seed_alloc_mature' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -540,6 +548,14 @@ subroutine PRTReceivePFT(fates_params) call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%root_long) + name = 'fates_leafn_vert_scaler_coeff1' + call fates_params%RetrieveParameterAllocate(name=name, & + data=leafn_vert_scaler_coeff1) + + name = 'fates_leafn_vert_scaler_coeff2' + call fates_params%RetrieveParameterAllocate(name=name, & + data=leafn_vert_scaler_coeff2) + name = 'fates_recruit_seed_alloc_mature' call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%seed_alloc_mature) @@ -1040,6 +1056,8 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmti) 'organ_id = ',prt_params%organ_id write(fates_log(),fmt0) 'nitr_store_ratio = ',prt_params%nitr_store_ratio write(fates_log(),fmt0) 'phos_store_ratio = ',prt_params%phos_store_ratio + write(fates_log(),fmt0) 'leafn_vert_scaler_coeff1 = ',prt_params%leafn_vert_scaler_coeff1 + write(fates_log(),fmt0) 'leafn_vert_scaler_coeff2 = ',prt_params%leafn_vert_scaler_coeff2 write(fates_log(),*) '-------------------------------------------------' end if From b1329afd9c2830b0c55aa71a6aad1e26dbe949bf Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 23 Apr 2024 17:59:44 -0400 Subject: [PATCH 186/300] fix location of module and parameter name --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 5 +++-- parteh/PRTParamsFATESMod.F90 | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index dee03c4b36..b768176310 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -72,7 +72,8 @@ module FATESPlantRespPhotosynthMod use FatesRadiationMemMod, only : ipar use FatesTwoStreamUtilsMod, only : FatesGetCohortAbsRad use FatesAllometryMod , only : VegAreaLayer - + use FatesAllometryMod, only : decay_coeff_vcmax + ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -146,7 +147,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) use FatesAllometryMod, only : bleaf, bstore_allom use FatesAllometryMod, only : storage_fraction_of_target use FatesAllometryMod, only : set_root_fraction - use FatesAllometryMod, only : decay_coeff_vcmax + use DamageMainMod, only : GetCrownReduction diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 3a3c624926..d586237778 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -550,11 +550,11 @@ subroutine PRTReceivePFT(fates_params) name = 'fates_leafn_vert_scaler_coeff1' call fates_params%RetrieveParameterAllocate(name=name, & - data=leafn_vert_scaler_coeff1) + data=prt_params%leafn_vert_scaler_coeff1) name = 'fates_leafn_vert_scaler_coeff2' call fates_params%RetrieveParameterAllocate(name=name, & - data=leafn_vert_scaler_coeff2) + data=prt_params%leafn_vert_scaler_coeff2) name = 'fates_recruit_seed_alloc_mature' call fates_params%RetrieveParameterAllocate(name=name, & From c00d711e150fe022b09970c2c8733e10f2202e19 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 23 Apr 2024 18:01:21 -0400 Subject: [PATCH 187/300] merged up parameter file in main to vert scaler branch --- parameter_files/fates_params_default.cdl | 143 +++++++++++++---------- 1 file changed, 82 insertions(+), 61 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index ad2c9a9b6a..2eaeb875fe 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,4 +1,4 @@ -netcdf fates_params_default { +netcdf tmp { dimensions: fates_NCWD = 4 ; fates_history_age_bins = 7 ; @@ -8,12 +8,12 @@ dimensions: fates_history_size_bins = 13 ; fates_hlm_pftno = 14 ; fates_hydr_organs = 4 ; + fates_landuseclass = 5 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; fates_plant_organs = 4 ; fates_string_length = 60 ; - fates_landuseclass = 5 ; variables: double fates_history_ageclass_bin_edges(fates_history_age_bins) ; fates_history_ageclass_bin_edges:units = "yr" ; @@ -84,9 +84,6 @@ variables: double fates_allom_cmode(fates_pft) ; fates_allom_cmode:units = "index" ; fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; double fates_allom_d2bl1(fates_pft) ; fates_allom_d2bl1:units = "variable" ; fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; @@ -114,6 +111,9 @@ variables: double fates_allom_dbh_maxheight(fates_pft) ; fates_allom_dbh_maxheight:units = "cm" ; fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_dmode(fates_pft) ; + fates_allom_dmode:units = "index" ; + fates_allom_dmode:long_name = "crown depth allometry function index" ; double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; @@ -129,6 +129,12 @@ variables: double fates_allom_frbstor_repro(fates_pft) ; fates_allom_frbstor_repro:units = "fraction" ; fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_h2cd1(fates_pft) ; + fates_allom_h2cd1:units = "variable" ; + fates_allom_h2cd1:long_name = "Parameter 1 for h2cd allometry (exp(log-intercept) or scaling). If allom_dmode=1; this is the same as former crown_depth_frac parameter" ; + double fates_allom_h2cd2(fates_pft) ; + fates_allom_h2cd2:units = "variable" ; + fates_allom_h2cd2:long_name = "Parameter 2 for h2cd allometry (log-slope or exponent). If allom_dmode=1; this is not needed (as exponent is assumed 1)" ; double fates_allom_hmode(fates_pft) ; fates_allom_hmode:units = "index" ; fates_allom_hmode:long_name = "height allometry function index." ; @@ -173,7 +179,7 @@ variables: fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; double fates_cnp_eca_alpha_ptase(fates_pft) ; fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; + fates_cnp_eca_alpha_ptase:long_name = "(INACTIVE, KEEP AT 0) fraction of P from ptase activity sent directly to plant (ECA)" ; double fates_cnp_eca_decompmicc(fates_pft) ; fates_cnp_eca_decompmicc:units = "gC/m3" ; fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; @@ -191,7 +197,7 @@ variables: fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; double fates_cnp_eca_lambda_ptase(fates_pft) ; fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; + fates_cnp_eca_lambda_ptase:long_name = "(INACTIVE, KEEP AT 0) critical value for biochemical production (ECA)" ; double fates_cnp_eca_vmax_ptase(fates_pft) ; fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; @@ -381,24 +387,24 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leafn_vert_scaler_coeff1(fates_pft) ; + fates_leafn_vert_scaler_coeff1:units = "unitless" ; + fates_leafn_vert_scaler_coeff1:long_name = "Coefficient one for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010." ; + double fates_leafn_vert_scaler_coeff2(fates_pft) ; + fates_leafn_vert_scaler_coeff2:units = "unitless" ; + fates_leafn_vert_scaler_coeff2:long_name = "Coefficient two for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010." ; double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; - double fates_maintresp_leaf_vert_scaler_coeff1(fates_pft) ; - fates_maintresp_leaf_vert_scaler_coeff1:units = "unitless" ; - fates_maintresp_leaf_vert_scaler_coeff1:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the same value as fates_leafn_vert_scaler_coeff1." ; - double fates_maintresp_leaf_vert_scaler_coeff2(fates_pft) ; - fates_maintresp_leaf_vert_scaler_coeff2:units = "unitless" ; - fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy use the same value as fates_leafn_vert_scaler_coeff2." ; - double fates_leafn_vert_scaler_coeff1(fates_pft) ; - fates_leafn_vert_scaler_coeff1:units = "unitless" ; - fates_leafn_vert_scaler_coeff1:long_name = "Coefficient one for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010. " ; - double fates_leafn_vert_scaler_coeff2(fates_pft) ; - fates_leafn_vert_scaler_coeff2:units = "unitless" ; - fates_leafn_vert_scaler_coeff2:long_name = "Coefficient two for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010. " ; + double fates_maintresp_leaf_vert_scaler_coeff1(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff1:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff1:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff1." ; + double fates_maintresp_leaf_vert_scaler_coeff2(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff2:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff2." ; double fates_maintresp_reduction_curvature(fates_pft) ; fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; @@ -485,7 +491,7 @@ variables: fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; double fates_phen_stress_decid(fates_pft) ; fates_phen_stress_decid:units = "logical flag" ; - fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; + fates_phen_stress_decid:long_name = "Flag for stress/drought-deciduous leaf habit. 0 - not stress deciduous; 1 - default drought deciduous (two target states only, fully flushed or fully abscised); 2 - semi-deciduous" ; double fates_prescribed_npp_canopy(fates_pft) ; fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; @@ -708,6 +714,9 @@ variables: double fates_damage_event_code ; fates_damage_event_code:units = "unitless" ; fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_daylength_factor_switch ; + fates_daylength_factor_switch:units = "unitless" ; + fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters (ie scale vcmax and jmax)" ; double fates_dev_arbitrary ; fates_dev_arbitrary:units = "unknown" ; fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; @@ -834,6 +843,9 @@ variables: double fates_maxcohort ; fates_maxcohort:units = "count" ; fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_mort_cstarvation_model ; + fates_mort_cstarvation_model:units = "unitless" ; + fates_mort_cstarvation_model:long_name = "switch defining the carbon starvation model ( 1) Linear or 2) Exponential) in the mortality_rates function." ; double fates_mort_disturb_frac ; fates_mort_disturb_frac:units = "fraction" ; fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; @@ -970,11 +982,11 @@ data: fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + fates_allom_agb1 = 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, + 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; + fates_allom_agb2 = 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, + 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94 ; @@ -985,42 +997,43 @@ data: fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6 ; - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, + 0, 0, 0, 0, 0 ; fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07 ; - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; + fates_allom_d2bl2 = 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, + 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55 ; - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, + fates_allom_d2ca_coefficient_max = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464 ; - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; + fates_allom_d2h1 = 78.4087704, 306.842667, 106.8745821, 104.3586841, + 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; + fates_allom_d2h2 = 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, + 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; + fates_allom_d2h3 = 47.6666164, 196.6865691, 93.9790461, 160.6835089, + 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; + fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, + 0.35, 0.35, 0.35 ; - fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; + fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1032,7 +1045,11 @@ data: fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_h2cd1 = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; + + fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1041,7 +1058,7 @@ data: fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 ; fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; @@ -1065,8 +1082,7 @@ data: fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; + fates_cnp_eca_alpha_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; @@ -1082,7 +1098,7 @@ data: fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_eca_lambda_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; @@ -1315,6 +1331,12 @@ data: fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; + fates_leafn_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; + + fates_leafn_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43 ; + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; @@ -1322,17 +1344,12 @@ data: 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06 ; - fates_maintresp_leaf_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, 0.00963, - 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; - - fates_maintresp_leaf_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, - 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; + fates_maintresp_leaf_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963 ; - fates_leafn_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, 0.00963, - 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; - - fates_leafn_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, - 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; + fates_maintresp_leaf_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; @@ -1580,8 +1597,8 @@ data: fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; + fates_wood_density = 0.548327, 0.44235, 0.454845, 0.754336, 0.548327, + 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; @@ -1637,6 +1654,8 @@ data: fates_damage_event_code = 1 ; + fates_daylength_factor_switch = 1 ; + fates_dev_arbitrary = _ ; fates_fire_active_crown_fire = 0 ; @@ -1721,6 +1740,8 @@ data: fates_maxcohort = 100 ; + fates_mort_cstarvation_model = 1 ; + fates_mort_disturb_frac = 1 ; fates_mort_understorey_death = 0.55983 ; From b105d56f6594efba5740e70ac27d567ad1df4c93 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Tue, 23 Apr 2024 15:21:31 -0700 Subject: [PATCH 188/300] PascalCase --- biogeochem/EDLoggingMortalityMod.F90 | 8 +++---- biogeochem/EDPatchDynamicsMod.F90 | 22 ++++++++--------- biogeochem/FatesLandUseChangeMod.F90 | 36 ++++++++++++++-------------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index c80244e392..caf55d7f74 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -71,8 +71,8 @@ module EDLoggingMortalityMod use FatesConstantsMod , only : hlm_harvest_carbon use FatesConstantsMod, only : fates_check_param_set use FatesInterfaceTypesMod , only : numpft - use FatesLandUseChangeMod, only : get_init_landuse_harvest_rate - use FatesLandUseChangeMod, only : get_luh_statedata + use FatesLandUseChangeMod, only : GetInitLanduseHarvestRate + use FatesLandUseChangeMod, only : GetLUHStatedata implicit none private @@ -249,7 +249,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, ! todo: eventually set up distinct harvest practices, each with a set of input paramaeters ! todo: implement harvested carbon inputs - call get_luh_statedata(bc_in, state_vector) + call GetLUHStatedata(bc_in, state_vector) site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. currentSite%min_allowed_landuse_fraction) & .and. (.not. currentSite%landuse_vector_gt_min(secondaryland)) @@ -368,7 +368,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, endif else - call get_init_landuse_harvest_rate(bc_in, currentSite%min_allowed_landuse_fraction, & + call GetInitLanduseHarvestRate(bc_in, currentSite%min_allowed_landuse_fraction, & harvest_rate, currentSite%landuse_vector_gt_min) if(prt_params%woody(pft_i) == itrue)then lmort_direct = harvest_rate diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 9d4da65b53..86a2e197c4 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -72,7 +72,7 @@ module EDPatchDynamicsMod use EDLoggingMortalityMod, only : get_harvest_rate_carbon use EDLoggingMortalityMod, only : get_harvestable_carbon use EDLoggingMortalityMod, only : get_harvest_debt - use FatesLandUseChangeMod, only : get_init_landuse_harvest_rate + use FatesLandUseChangeMod, only : GetInitLanduseHarvestRate use EDParamsMod , only : fates_mortality_disturbance_fraction use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : set_root_fraction @@ -84,9 +84,9 @@ module EDPatchDynamicsMod use FatesConstantsMod , only : primaryland, secondaryland, pastureland, rangeland, cropland use FatesConstantsMod , only : nocomp_bareground_land use FatesConstantsMod , only : n_landuse_cats - use FatesLandUseChangeMod, only : get_landuse_transition_rates - use FatesLandUseChangeMod, only : get_init_landuse_transition_rates - use FatesLandUseChangeMod, only : get_luh_statedata + use FatesLandUseChangeMod, only : GetLanduseTransitionRates + use FatesLandUseChangeMod, only : GetInitLanduseTransitionRates + use FatesLandUseChangeMod, only : GetLUHStatedata use FatesConstantsMod , only : fates_unset_r8 use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : hlm_harvest_carbon @@ -288,10 +288,10 @@ subroutine disturbance_rates( site_in, bc_in) if ( hlm_use_luh .eq. itrue ) then if(.not. site_in%transition_landuse_from_off_to_on) then - call get_landuse_transition_rates(bc_in, site_in%min_allowed_landuse_fraction, & + call GetLanduseTransitionRates(bc_in, site_in%min_allowed_landuse_fraction, & site_in%landuse_transition_matrix, site_in%landuse_vector_gt_min) else - call get_init_landuse_transition_rates(bc_in, site_in%min_allowed_landuse_fraction, & + call GetInitLanduseTransitionRates(bc_in, site_in%min_allowed_landuse_fraction, & site_in%landuse_transition_matrix, site_in%landuse_vector_gt_min) endif else @@ -317,7 +317,7 @@ subroutine disturbance_rates( site_in, bc_in) end do ! get some info needed to determine whether or not to apply land use change - call get_luh_statedata(bc_in, state_vector) + call GetLUHStatedata(bc_in, state_vector) site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. site_in%min_allowed_landuse_fraction) & .and. (.not. site_in%landuse_vector_gt_min(secondaryland)) @@ -407,7 +407,7 @@ subroutine disturbance_rates( site_in, bc_in) harvest_rate = 0._r8 end if else - call get_init_landuse_harvest_rate(bc_in, site_in%min_allowed_landuse_fraction, & + call GetInitLanduseHarvestRate(bc_in, site_in%min_allowed_landuse_fraction, & harvest_rate, site_in%landuse_vector_gt_min) endif @@ -495,7 +495,7 @@ subroutine spawn_patches( currentSite, bc_in) use EDParamsMod , only : ED_val_understorey_death, logging_coll_under_frac use EDCohortDynamicsMod , only : terminate_cohorts use FatesConstantsMod , only : rsnbl_math_prec - use FatesLandUseChangeMod, only : get_landusechange_rules + use FatesLandUseChangeMod, only : GetLanduseChangeRules ! ! !ARGUMENTS: type (ed_site_type), intent(inout) :: currentSite @@ -564,7 +564,7 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%disturbance_rates(:,:,:) = 0._r8 ! get rules for vegetation clearing during land use change - call get_landusechange_rules(clearing_matrix) + call GetLanduseChangeRules(clearing_matrix) ! in the nocomp cases, since every patch has a PFT identity, it can only receive patch area from patches ! that have the same identity. In order to allow this, we have this very high level loop over nocomp PFTs @@ -3558,7 +3558,7 @@ subroutine terminate_patches(currentSite, bc_in) call get_current_landuse_statevector(currentSite, state_vector_internal) write(fates_log(),*) 'current landuse state vector: ', state_vector_internal write(fates_log(),*) 'current landuse state vector (not including bare gruond): ', state_vector_internal/(1._r8-currentSite%area_bareground) - call get_luh_statedata(bc_in, state_vector_driver) + call GetLUHStatedata(bc_in, state_vector_driver) write(fates_log(),*) 'driver data landuse state vector: ', state_vector_driver write(fates_log(),*) 'min_allowed_landuse_fraction: ', currentSite%min_allowed_landuse_fraction write(fates_log(),*) 'landuse_vector_gt_min: ', currentSite%landuse_vector_gt_min diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index c244f7267b..b30ee74288 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -28,11 +28,11 @@ module FatesLandUseChangeMod character(len=*), parameter :: sourcefile = __FILE__ - public :: get_landuse_transition_rates - public :: get_landusechange_rules - public :: get_luh_statedata - public :: get_init_landuse_transition_rates - public :: get_init_landuse_harvest_rate + public :: GetLanduseTransitionRates + public :: GetLanduseChangeRules + public :: GetLUHStatedata + public :: GetInitLanduseTransitionRates + public :: GetInitLanduseHarvestRate ! module data integer, parameter :: max_luh2_types_per_fates_lu_type = 5 @@ -62,7 +62,7 @@ module FatesLandUseChangeMod contains ! ============================================================================ - subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, landuse_vector_gt_min) + subroutine GetLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, landuse_vector_gt_min) ! The purpose of this routine is to ingest the land use transition rate information that the host model has read in from a dataset, @@ -128,7 +128,7 @@ subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, lan ! and otherwise if this is the first timestep where the minimum was exceeded, ! then apply all transitions from primary to this type and reset the flag ! note that the flag resetting should not happen for secondary lands, as this is handled in the logging logic - call get_luh_statedata(bc_in, state_vector) + call GetLUHStatedata(bc_in, state_vector) do i_lu = secondaryland, n_landuse_cats if ( state_vector(i_lu) .le. min_allowed_landuse_fraction ) then landuse_transition_matrix(:,i_lu) = 0._r8 @@ -140,7 +140,7 @@ subroutine get_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, lan end do end if - end subroutine get_landuse_transition_rates + end subroutine GetLanduseTransitionRates !---------------------------------------------------------------------------------------------------- @@ -168,7 +168,7 @@ end function GetLUCategoryFromStateName !---------------------------------------------------------------------------------------------------- - subroutine get_landusechange_rules(clearing_matrix) + subroutine GetLanduseChangeRules(clearing_matrix) ! the purpose of this is to define a ruleset for when to clear the vegetation in transitioning from one land use type to another @@ -253,11 +253,11 @@ subroutine get_landusechange_rules(clearing_matrix) end select - end subroutine get_landusechange_rules + end subroutine GetLanduseChangeRules !---------------------------------------------------------------------------------------------------- - subroutine get_luh_statedata(bc_in, state_vector) + subroutine GetLUHStatedata(bc_in, state_vector) type(bc_in_type) , intent(in) :: bc_in real(r8), intent(out) :: state_vector(n_landuse_cats) ! [m2/m2] @@ -313,7 +313,7 @@ subroutine get_luh_statedata(bc_in, state_vector) state_vector(primaryland) = 1._r8 end if - end subroutine get_luh_statedata + end subroutine GetLUHStatedata !---------------------------------------------------------------------------------------------------- @@ -351,7 +351,7 @@ subroutine CheckLUHData(luh_vector,modified_flag) end subroutine CheckLUHData - subroutine get_init_landuse_harvest_rate(bc_in, min_allowed_landuse_fraction, harvest_rate, landuse_vector_gt_min) + subroutine GetInitLanduseHarvestRate(bc_in, min_allowed_landuse_fraction, harvest_rate, landuse_vector_gt_min) ! the purpose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for @@ -367,7 +367,7 @@ subroutine get_init_landuse_harvest_rate(bc_in, min_allowed_landuse_fraction, ha ! LOCALS real(r8) :: state_vector(n_landuse_cats) ! [m2/m2] - call get_luh_statedata(bc_in, state_vector) + call GetLUHStatedata(bc_in, state_vector) ! only do this if the state vector exceeds the minimum viable patch size, and if so, note that in the ! landuse_vector_gt_min flag (which will be coming in as .false. because of the use_potentialveg logic). @@ -376,9 +376,9 @@ subroutine get_init_landuse_harvest_rate(bc_in, min_allowed_landuse_fraction, ha landuse_vector_gt_min(secondaryland) = .true. endif - end subroutine get_init_landuse_harvest_rate + end subroutine GetInitLanduseHarvestRate - subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, landuse_vector_gt_min) + subroutine GetInitLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, landuse_vector_gt_min) ! The purpose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. This is for @@ -396,7 +396,7 @@ subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction landuse_transition_matrix(:,:) = 0._r8 - call get_luh_statedata(bc_in, state_vector) + call GetLUHStatedata(bc_in, state_vector) ! only do this if the state vector exceeds the minimum viable patch size, and if so, note that in the ! landuse_vector_gt_min flag (which will be coming in as .false. because of the use_potentialveg logic). @@ -407,6 +407,6 @@ subroutine get_init_landuse_transition_rates(bc_in, min_allowed_landuse_fraction end if end do - end subroutine get_init_landuse_transition_rates + end subroutine GetInitLanduseTransitionRates end module FatesLandUseChangeMod From 34dcc5f79478db4d7c95941dbbc789e784c5304b Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Tue, 23 Apr 2024 21:54:36 -0700 Subject: [PATCH 189/300] shortening line lengths --- biogeochem/FatesLandUseChangeMod.F90 | 69 +++++++++++++++++----------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index b30ee74288..69d06e26f5 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -62,12 +62,13 @@ module FatesLandUseChangeMod contains ! ============================================================================ - subroutine GetLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, landuse_vector_gt_min) + subroutine GetLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, & + landuse_vector_gt_min) - ! The purpose of this routine is to ingest the land use transition rate information that the host model has read in from a dataset, - ! aggregate land use types to those being used in the simulation, and output a transition matrix that can be used to drive patch - ! disturbance rates. + ! The purpose of this routine is to ingest the land use transition rate information that the host + ! model has read in from a dataset,aggregate land use types to those being used in the simulation, + ! and output a transition matrix that can be used to drive patch disturbance rates. ! !ARGUMENTS: type(bc_in_type) , intent(in) :: bc_in @@ -101,8 +102,8 @@ subroutine GetLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, landus urban_fraction = bc_in%hlm_luh_states(FindIndex(bc_in%hlm_luh_state_names,'urban')) end if - !!TODO: may need some logic here to ask whether or not ot perform land use change on this timestep. current code occurs every day. - !!If not doing transition every day, need to update units. + !! TODO: may need some logic here to ask whether or not ot perform land use change on this timestep. + !! current code occurs every day. If not doing transition every day, need to update units. transitions_loop: do i_luh2_transitions = 1, hlm_num_luh2_transitions @@ -117,9 +118,11 @@ subroutine GetLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, landus ! Avoid transitions with 'urban' as those are handled seperately ! Also ignore diagonal elements of transition matrix. - if (.not.(i_donor .eq. fates_unset_int .or. i_receiver .eq. fates_unset_int .or. i_donor .eq. i_receiver)) then + if (.not.(i_donor .eq. fates_unset_int .or. i_receiver .eq. fates_unset_int .or. & + i_donor .eq. i_receiver)) then landuse_transition_matrix(i_donor,i_receiver) = & - landuse_transition_matrix(i_donor,i_receiver) + temp_vector(i_luh2_transitions) * years_per_day / (1._r8 - urban_fraction) + landuse_transition_matrix(i_donor,i_receiver) + temp_vector(i_luh2_transitions) & + * years_per_day / (1._r8 - urban_fraction) end if end do transitions_loop @@ -127,7 +130,8 @@ subroutine GetLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, landus ! zero all transitions where the state vector is less than the minimum allowed, ! and otherwise if this is the first timestep where the minimum was exceeded, ! then apply all transitions from primary to this type and reset the flag - ! note that the flag resetting should not happen for secondary lands, as this is handled in the logging logic + ! note that the flag resetting should not happen for secondary lands, as this is handled in the + ! logging logic call GetLUHStatedata(bc_in, state_vector) do i_lu = secondaryland, n_landuse_cats if ( state_vector(i_lu) .le. min_allowed_landuse_fraction ) then @@ -170,16 +174,18 @@ end function GetLUCategoryFromStateName subroutine GetLanduseChangeRules(clearing_matrix) - ! the purpose of this is to define a ruleset for when to clear the vegetation in transitioning from one land use type to another + ! the purpose of this is to define a ruleset for when to clear the vegetation in transitioning + ! from one land use type to another logical, intent(out) :: clearing_matrix(n_landuse_cats,n_landuse_cats) - ! default value of ruleset 4 above means that plants are not cleared during land use change transitions to rangeland, whereas plants are - ! cleared in transitions to pasturelands and croplands. - integer, parameter :: ruleset = 4 ! ruleset to apply from table 1 of Ma et al (2020) https://doi.org/10.5194/gmd-13-3203-2020 + ! default value of ruleset 4 above means that plants are not cleared during land use change + ! transitions to rangeland, whereas plants are cleared in transitions to pasturelands and croplands. + integer, parameter :: ruleset = 4 ! ruleset to apply from table 1 of Ma et al (2020) + ! https://doi.org/10.5194/gmd-13-3203-2020 - ! clearing matrix applies from the donor to the receiver land use type of the newly-transferred patch area - ! values of clearing matrix: false => do not clear; true => clear + ! clearing matrix applies from the donor to the receiver land use type of the newly-transferred + ! patch area values of clearing matrix: false => do not clear; true => clear clearing_matrix(:,:) = .false. @@ -187,8 +193,9 @@ subroutine GetLanduseChangeRules(clearing_matrix) case(1) - ! note that this ruleset isnt exactly what is in Ma et al. rulesets 1 and 2, because FATES does not make the distinction - ! between forested and non-forested lands from a land use/land cover perspective. + ! note that this ruleset isnt exactly what is in Ma et al. rulesets 1 and 2, because FATES + ! does not make the distinction between forested and non-forested lands from a land use/land + ! cover perspective. clearing_matrix(:,cropland) = .true. clearing_matrix(:,pastureland) = .true. clearing_matrix(primaryland,rangeland) = .true. @@ -351,12 +358,15 @@ subroutine CheckLUHData(luh_vector,modified_flag) end subroutine CheckLUHData - subroutine GetInitLanduseHarvestRate(bc_in, min_allowed_landuse_fraction, harvest_rate, landuse_vector_gt_min) + subroutine GetInitLanduseHarvestRate(bc_in, min_allowed_landuse_fraction, harvest_rate, & + landuse_vector_gt_min) - ! the purpose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use - ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. this is for - ! the hrvest rate from primary lands, i.e. the transition from primary to secondary lands. thus instead of using the harvest - ! dataset tself, it only uses the state vector for what land use compositoin we want to achieve, and log the forests accordingly. + ! the purpose of this subroutine is, only under the case where we are transitioning from a spinup + ! run that did not have land use to a run that does, to apply the land-use changes needed to get + ! to the state vector in a single daily instance. this is for the hrvest rate from primary lands, + ! i.e. the transition from primary to secondary lands. thus instead of using the harvest dataset + ! itself, it only uses the state vector for what land use compositoin we want to achieve, and log + ! the forests accordingly. ! !ARGUMENTS: type(bc_in_type) , intent(in) :: bc_in @@ -378,11 +388,13 @@ subroutine GetInitLanduseHarvestRate(bc_in, min_allowed_landuse_fraction, harves end subroutine GetInitLanduseHarvestRate - subroutine GetInitLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, landuse_transition_matrix, landuse_vector_gt_min) + subroutine GetInitLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, & + landuse_transition_matrix, landuse_vector_gt_min) - ! The purpose of this subroutine is, only under the case where we are transitioning from a spinup run that did not have land use - ! to a run that does, to apply the land-use changes needed to get to the state vector in a single daily instance. This is for - ! the transitions other than harvest, i.e. from primary lands to all other categories aside from secondary lands. + ! The purpose of this subroutine is, only under the case where we are transitioning from a spinup + ! run that did not have land use to a run that does, to apply the land-use changes needed to get + ! to the state vector in a single daily instance. This is for the transitions other than harvest, + ! i.e. from primary lands to all other categories aside from secondary lands. ! !ARGUMENTS: type(bc_in_type) , intent(in) :: bc_in @@ -398,8 +410,9 @@ subroutine GetInitLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, la call GetLUHStatedata(bc_in, state_vector) - ! only do this if the state vector exceeds the minimum viable patch size, and if so, note that in the - ! landuse_vector_gt_min flag (which will be coming in as .false. because of the use_potentialveg logic). + ! only do this if the state vector exceeds the minimum viable patch size, and if so, note that + ! in the landuse_vector_gt_min flag (which will be coming in as .false. because of the + ! use_potentialveg logic). do i = secondaryland+1,n_landuse_cats if ( state_vector(i) .gt. min_allowed_landuse_fraction) then landuse_transition_matrix(primaryland,i) = state_vector(i) From a9b5230768353334446b7769c039963ee7e8159c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 26 Apr 2024 06:40:26 -0600 Subject: [PATCH 190/300] reverting to parameter file from main, because daylength factor switch was already in there --- parameter_files/fates_params_default.cdl | 3 --- 1 file changed, 3 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 8a2997c300..2eaeb875fe 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -255,9 +255,6 @@ variables: double fates_damage_recovery_scalar(fates_pft) ; fates_damage_recovery_scalar:units = "unitless" ; fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; - double fates_daylength_factor_switch ; - fates_daylength_factor_switch:units = "unitless" ; - fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters" ; double fates_dev_arbitrary_pft(fates_pft) ; fates_dev_arbitrary_pft:units = "unknown" ; fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; From cc34d1b6be6094e725ee3ed7857ad2984863de80 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Sat, 27 Apr 2024 14:10:00 -0400 Subject: [PATCH 191/300] removed unnecessary zeroing in site-level history output --- main/FatesHistoryInterfaceMod.F90 | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index cee46b8529..c80186a58b 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2435,6 +2435,9 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) site_ba = 0._r8 site_ca = 0._r8 + + ! This should be removed from the interface and put here (RGK 04-24) + ! call this%zero_site_hvars(sites(s),upfreq_in=group_dyna_simple) ! set the fates fraction to one, since it is zero on non-fates columns, & ! the average is the total gridcell fates fraction @@ -2569,13 +2572,6 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) sum(flux_diags_c%root_litter_input(:))) * & AREA_INV * days_per_sec - hio_litter_out_si(io_si) = 0._r8 - hio_seed_bank_si(io_si) = 0._r8 - hio_ungerm_seed_bank_si(io_si) = 0._r8 - hio_seedling_pool_si(io_si) = 0._r8 - hio_seeds_in_si(io_si) = 0._r8 - hio_seeds_in_local_si(io_si) = 0._r8 - ! Loop through patches to sum up diagonistics ipa = 0 cpatch => sites(s)%oldest_patch @@ -2923,8 +2919,6 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! divide secondary plant leaf area by secondary forest area to get the secondary forest LAI if (hio_fraction_secondary_forest_si(io_si) .gt. nearzero) then hio_lai_secondary_si(io_si) = hio_lai_secondary_si(io_si) / (hio_fraction_secondary_forest_si(io_si)*AREA) - else - hio_lai_secondary_si(io_si) = 0._r8 end if ! Normalize crown-area weighted height @@ -2934,9 +2928,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! divide basal-area-weighted height by basal area to get mean if ( site_ba .gt. nearzero ) then - hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si) / site_ba - else - hio_ba_weighted_height_si(io_si) = 0._r8 + hio_ba_weighted_height_si(io_si) = hio_ba_weighted_height_si(io_si)/site_ba endif elloop2: do el = 1, num_elements From 25fb73aa1f2b46f7fc806260198463f2b17f5066 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 29 Apr 2024 11:23:52 -0400 Subject: [PATCH 192/300] Updated some comments in low water potential protections --- biogeophys/FatesHydroWTFMod.F90 | 2 +- functional_unit_testing/hydro/HydroUTestDriver.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/biogeophys/FatesHydroWTFMod.F90 b/biogeophys/FatesHydroWTFMod.F90 index f83aa4d5d9..69c7fce9aa 100644 --- a/biogeophys/FatesHydroWTFMod.F90 +++ b/biogeophys/FatesHydroWTFMod.F90 @@ -51,7 +51,7 @@ module FatesHydroWTFMod !real(r8), parameter :: min_theta_cch = 0.05_r8 ! Minimum theta (matches ctsm) - real(r8), parameter :: min_psi_cch = -15.0_r8 ! Minimum theta (matches ctsm) + real(r8), parameter :: min_psi_cch = -15.0_r8 ! Minimum suction (MPa) ! Generic class that can be extended to describe ! specific water retention functions diff --git a/functional_unit_testing/hydro/HydroUTestDriver.py b/functional_unit_testing/hydro/HydroUTestDriver.py index 98c38a63c2..0d210d119c 100644 --- a/functional_unit_testing/hydro/HydroUTestDriver.py +++ b/functional_unit_testing/hydro/HydroUTestDriver.py @@ -162,7 +162,12 @@ def OMParams(zsoi): return(om_watsat,om_sucsat,om_bsw) def CCHParmsCosby84T5(zsoi,om_frac,sand_frac,clay_frac): - + + # Cosby, B.J., Hornberger, G.M., Clapp, R.B., and Ginn, T.R. 1984. + # A statistical exploration of the relationships of soil moisture + # characteristics to the physical properties of soils. Water Resour. + # Res. 20:682-690. + # cosby_1984_table5 # Get pedotransfer for soil matrix From a5d9fd953e0b76dd98c56d5874d662b3089b3256 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 29 Apr 2024 11:34:30 -0400 Subject: [PATCH 193/300] update to comments in hydro flux disaggregation code --- biogeophys/FatesPlantHydraulicsMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 874ab80a94..8263b98937 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -2763,7 +2763,7 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) if(rootflux_disagg == soilk_disagg)then if(qflx_soil2root_rhiz>0._r8 )then ! Weight disaggregation by K*dz, but only for flux - ! into the root, othersize weight by depth + ! into the root, othersize weight by root length ! h2osoi_liqvol: [kg/m2] / [m] / [kg/m3] = [m3/m3] eff_por = bc_in(s)%eff_porosity_sl(j_bc) h2osoi_liqvol = min(eff_por, bc_in(s)%h2o_liq_sisl(j_bc)/(bc_in(s)%dz_sisl(j_bc)*denh2o)) @@ -2787,8 +2787,8 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) ! Note: It is possible that the soil is so dry there is no conductance ! In these cases, solver error may create some non-zero, yet - ! trivially small fluxes. The conductances are exactly zero - ! so we need to renormalize the weighting function + ! trivially small fluxes. Lets create a simple weighting + ! function based on root length and available water. if(sumweight < nearzero)then sumweight = 0._r8 do j_bc = j_t,j_b From fd80f6ab3b270d8d1bacd734485deeb7d40826e0 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 30 Apr 2024 10:33:46 -0600 Subject: [PATCH 194/300] trying to fix ldflags --- .../allometry/CMakeLists.txt | 3 ++- .../allometry/FatesTestAllometry.F90 | 1 - .../build_fortran_tests.py | 5 ++-- functional_unit_testing/run_fates_tests.py | 25 +++++++++++++------ 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/functional_unit_testing/allometry/CMakeLists.txt b/functional_unit_testing/allometry/CMakeLists.txt index 0a48161e49..c2c453e93a 100644 --- a/functional_unit_testing/allometry/CMakeLists.txt +++ b/functional_unit_testing/allometry/CMakeLists.txt @@ -6,13 +6,14 @@ set(NETCDF_FORTRAN_DIR ${NETCDF_F_PATH}) FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) + include_directories(${NETCDF_C_DIR}/include ${NETCDF_FORTRAN_DIR}/include) link_directories(${NETCDF_C_DIR}/lib ${NETCDF_FORTRAN_DIR}/lib ${PFUNIT_TOP_DIR}/lib) - + add_executable(FATES_allom_exe ${allom_sources}) target_link_libraries(FATES_allom_exe diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/functional_unit_testing/allometry/FatesTestAllometry.F90 index 1d0c433d9f..91ee4df2cf 100644 --- a/functional_unit_testing/allometry/FatesTestAllometry.F90 +++ b/functional_unit_testing/allometry/FatesTestAllometry.F90 @@ -288,7 +288,6 @@ subroutine WriteAllometryData(out_file, numdbh, numpft, dbh, height, bagw, blmax [character(len=150) :: 'pft dbh', 'kgC', 'plant total biomass calculated from tissues'], & 3, totbiomID2) - ! finish defining variables call EndNCDef(ncid) diff --git a/functional_unit_testing/build_fortran_tests.py b/functional_unit_testing/build_fortran_tests.py index 0c4cbb535f..7943640f89 100644 --- a/functional_unit_testing/build_fortran_tests.py +++ b/functional_unit_testing/build_fortran_tests.py @@ -216,7 +216,7 @@ def build_exists(build_dir, test_dir, test_exe=None): return True -def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False): +def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False, verbose=False): """Build the unit test executables Args: @@ -225,6 +225,7 @@ def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False): cmake_directory (str): directory where the make CMakeLists.txt file is make_j (int): number of processes to use for make clean (bool, optional): whether or not to clean the build first. Defaults to False. + verbose (bool, optional): whether or not to run make with verbose output. Defaults to False. """ # create the build directory full_build_path = prep_build_dir(build_dir, clean=clean) @@ -245,4 +246,4 @@ def build_unit_tests(build_dir, name, cmake_directory, make_j, clean=False): # run cmake and make run_cmake(name, cmake_directory, pfunit_path, netcdf_c_path, netcdf_f_path, cmake_args) - run_make(name, make_j, clean=clean) + run_make(name, make_j, clean=clean, verbose=verbose) diff --git a/functional_unit_testing/run_fates_tests.py b/functional_unit_testing/run_fates_tests.py index 6bae07e2b3..9c260276ff 100755 --- a/functional_unit_testing/run_fates_tests.py +++ b/functional_unit_testing/run_fates_tests.py @@ -144,12 +144,13 @@ def create_param_file(param_file, run_dir): return param_file_update -def run_tests(clean, build_tests, run_executables, build_dir, run_dir, make_j, - param_file, save_figs, test_dict): +def run_tests(clean, verbose_make, build_tests, run_executables, build_dir, run_dir, + make_j, param_file, save_figs, test_dict): """Builds and runs the fates tests Args: clean (bool): whether or not to clean the build directory + verbose_make (bool): whether or not to run make with verbose output build_tests (bool): whether or not to build the exectuables run_executables (bool): whether or not to run the executables build_dir (str): build directory @@ -179,7 +180,8 @@ def run_tests(clean, build_tests, run_executables, build_dir, run_dir, make_j, # compile code if build_tests: - build_unit_tests(build_dir, _TEST_NAME, _CMAKE_BASE_DIR, make_j, clean=clean) + build_unit_tests(build_dir, _TEST_NAME, _CMAKE_BASE_DIR, make_j, clean=clean, + verbose=verbose_make) # run executables for each test in test list if run_executables: @@ -213,9 +215,7 @@ def out_file_exists(run_dir, out_file): Returns: bool: yes/no file exists in correct location """ - if not os.path.isfile(os.path.join(run_dir, out_file)): - return False - return True + return os.path.isfile(os.path.join(run_dir, out_file)) def parse_test_list(test_string): """Parses the input test list and checks for errors @@ -327,6 +327,12 @@ def commandline_args(): "Will be placed in run_dir/plots.\n" "Should probably do this on remote machines.\n", ) + + parser.add_argument( + "--verbose-make", + action="store_true", + help="Run make with verbose output." + ) parser.add_argument( "-t", @@ -403,6 +409,9 @@ def check_arg_validity(args): # make sure build directory exists if args.skip_build: + if args.verbose_make: + raise argparse.ArgumentError(None, f"Can't run verbose make and skip build.\n" + "Re-run script without --skip-build") check_build_dir(args.build_dir, args.test_dict) # make sure relevant output files exist: @@ -419,8 +428,8 @@ def main(): build = not args.skip_build run = not args.skip_run_executables - run_tests(args.clean, build, run, args.build_dir, args.run_dir, args.make_j, - args.parameter_file, args.save_figs, args.test_dict) + run_tests(args.clean, args.verbose_make, build, run, args.build_dir, args.run_dir, + args.make_j, args.parameter_file, args.save_figs, args.test_dict) if __name__ == "__main__": main() From fb610acf44bae3a0892734f7fab531083d25f29d Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 30 Apr 2024 10:37:30 -0600 Subject: [PATCH 195/300] push cmakelists --- CMakeLists.txt | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b8b7b12a08..3961a6780d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,15 @@ cmake_minimum_required(VERSION 3.4) list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) + +FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) +FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) +MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") +MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") + +string(APPEND LDFLAGS " -L${NETCDF_FORTRAN_DIR}/lib -lnetcdff") +string(APPEND LDFLAGS " -L${NETCDF_C_DIR}/lib -lnetcdf") + include(CIME_initial_setup) project(FATES_tests Fortran C) @@ -68,11 +77,6 @@ include_directories(${HLM_ROOT}/share/include) set(NETCDF_C_DIR ${NETCDF_C_PATH}) set(NETCDF_FORTRAN_DIR ${NETCDF_F_PATH}) -FIND_PATH(NETCDFC_FOUND libnetcdf.a ${NETCDF_C_DIR}/lib) -FIND_PATH(NETCDFF_FOUND libnetcdff.a ${NETCDF_FORTRAN_DIR}/lib) -MESSAGE(" NETCDFC_FOUND = ${NETCDFC_FOUND}") -MESSAGE(" NETCDFF_FOUND = ${NETCDFF_FOUND}") - include_directories(${NETCDF_C_DIR}/include ${NETCDF_FORTRAN_DIR}/include) link_directories(${NETCDF_C_DIR}/lib @@ -82,6 +86,8 @@ link_directories(${NETCDF_C_DIR}/lib include_directories(${CMAKE_CURRENT_BINARY_DIR}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) + + # Add the test directories # Note: it's possible that these could be added by each source directory that # has tests in it. However, it appears that the order needs to be done From 5a5dea1102dd64e6b5a00ee3489ddda2d4f67685 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Tue, 30 Apr 2024 11:18:01 -0700 Subject: [PATCH 196/300] vasrious changes in response to review comments --- biogeochem/EDLoggingMortalityMod.F90 | 37 ++++--- biogeochem/EDPatchDynamicsMod.F90 | 128 +++++++++++++---------- biogeochem/FatesLandUseChangeMod.F90 | 6 +- main/FatesInterfaceTypesMod.F90 | 1 + main/FatesRestartInterfaceMod.F90 | 6 +- parameter_files/fates_params_default.cdl | 2 +- 6 files changed, 101 insertions(+), 79 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index caf55d7f74..4708c31c21 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -253,13 +253,22 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. currentSite%min_allowed_landuse_fraction) & .and. (.not. currentSite%landuse_vector_gt_min(secondaryland)) + ! The transition_landuse_from_off_to_on is for handling the special case of the first timestep after leaving potential + ! vegetation mode. In this case, all prior historical land-use, including harvest, needs to be applied on that first day. + ! So logging rates on that day are what is required to deforest exactly the amount of primary lands that will give the + ! amount of secondary lands dictated by the land use state vector for that year, rather than whatever the continuous + ! logging rate for that year is supposed to be according to the land use transition matrix. if (.not. currentSite%transition_landuse_from_off_to_on) then + + ! if the total intended area of secondary lands are less than what we can consider without having too-small patches, + ! or if that was the case until just now, then there is special logic if (site_secondaryland_first_exceeding_min) then - - ! if the total intended area of secondary lands are less than what we can consider without having too-small patches, - ! or if that was the case until just now, then there is special logic - harvest_rate = state_vector(secondaryland) / sum(state_vector(:)) - write(fates_log(), *) 'applying state_vector(secondaryland) to plants.', pft_i + if ( patch_land_use_label .eq. primaryland) then + harvest_rate = state_vector(secondaryland) / state_vector(primaryland) + write(fates_log(), *) 'applying state_vector(secondaryland) to plants.', pft_i + else + harvest_rate = 0._r8 + endif ! For area-based harvest, harvest_tag shall always be 2 (not applicable). harvest_tag = 2 @@ -370,20 +379,14 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, else call GetInitLanduseHarvestRate(bc_in, currentSite%min_allowed_landuse_fraction, & harvest_rate, currentSite%landuse_vector_gt_min) + lmort_direct = 0.0_r8 + lmort_collateral = 0.0_r8 + lmort_infra = 0.0_r8 + l_degrad = 0.0_r8 if(prt_params%woody(pft_i) == itrue)then lmort_direct = harvest_rate - lmort_collateral = 0.0_r8 - lmort_infra = 0.0_r8 - l_degrad = 0.0_r8 - else - lmort_direct = 0.0_r8 - lmort_collateral = 0.0_r8 - lmort_infra = 0.0_r8 - if (canopy_layer .eq. 1) then - l_degrad = harvest_rate - else - l_degrad = 0.0_r8 - endif + else if (canopy_layer .eq. 1) then + l_degrad = harvest_rate endif endif diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 86a2e197c4..268b443a4f 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -330,13 +330,14 @@ subroutine disturbance_rates( site_in, bc_in) dist_rate_ldist_notharvested = 0.0_r8 - ! transitin matrix has units of area transitioned per unit area of the whole gridcell per time; + ! transition matrix has units of area transitioned per unit area of the whole gridcell per time; ! need to change to area transitioned per unit area of that land-use type per time; ! because the land use state vector sums to one minus area bareground, need to also divide by that ! (or rather, multiply since it is in the denominator of the denominator) - ! Avoid this calculation to avoid NaN due to division by zero result if luh is not used or applying to bare ground - ! note that an alternative here might be to use what LUH thinks the state vector should be instead of what the FATES state vector is, - ! in order to not amplify small deviations between the two... + ! Avoid this calculation to avoid NaN due to division by zero result if luh is not used or applying + ! to bare ground note that an alternative here might be to use what LUH thinks the state vector + ! should be instead of what the FATES state vector is, in order to not amplify small deviations + ! between the two... if (hlm_use_luh .eq. itrue .and. currentPatch%land_use_label .gt. nocomp_bareground_land) then currentPatch%landuse_transition_rates(1:n_landuse_cats) = min(1._r8, & site_in%landuse_transition_matrix(currentPatch%land_use_label,1:n_landuse_cats) & @@ -397,11 +398,13 @@ subroutine disturbance_rates( site_in, bc_in) currentPatch%age_since_anthro_disturbance, harvest_rate) end if - ! if the total intended area of secondary lands are less than what we can consider without having too-small patches, - ! or if that was the case until just now, then there is special logic + ! if the total intended area of secondary lands are less than what we can consider + ! without having too-small patches, or if that was the case until just now, + ! then there is special logic if (state_vector(secondaryland) .le. site_in%min_allowed_landuse_fraction) then harvest_rate = 0._r8 - else if (currentPatch%land_use_label .eq. primaryland .and. .not. site_in%landuse_vector_gt_min(secondaryland)) then + else if (currentPatch%land_use_label .eq. primaryland .and. .not. & + site_in%landuse_vector_gt_min(secondaryland)) then harvest_rate = state_vector(secondaryland) / sum(state_vector(:)) else harvest_rate = 0._r8 @@ -440,15 +443,19 @@ subroutine disturbance_rates( site_in, bc_in) call FatesWarn(msg,index=2) endif - ! if the sum of all disturbance rates is such that they will exceed total patch area on this day, then reduce them all proportionally. + ! if the sum of all disturbance rates is such that they will exceed total patch area on this day, + ! then reduce them all proportionally. + if ( (sum(currentPatch%disturbance_rates(:)) + sum(currentPatch%landuse_transition_rates(1:n_landuse_cats))) .gt. & max_daily_disturbance_rate ) then tempsum = sum(currentPatch%disturbance_rates(:)) + sum(currentPatch%landuse_transition_rates(1:n_landuse_cats)) do i_dist = 1,N_DIST_TYPES - currentPatch%disturbance_rates(i_dist) = max_daily_disturbance_rate * currentPatch%disturbance_rates(i_dist) / tempsum + currentPatch%disturbance_rates(i_dist) = max_daily_disturbance_rate * currentPatch%disturbance_rates(i_dist) & + / tempsum end do do i_dist = 1,n_landuse_cats - currentPatch%landuse_transition_rates(i_dist) = max_daily_disturbance_rate * currentPatch%landuse_transition_rates(i_dist) / tempsum + currentPatch%landuse_transition_rates(i_dist) = max_daily_disturbance_rate * & + currentPatch%landuse_transition_rates(i_dist) / tempsum end do endif @@ -456,17 +463,21 @@ subroutine disturbance_rates( site_in, bc_in) enddo !patch loop - ! if the area of secondary land has just exceeded the minimum below which we ignore things, set the flag to keep track of that. - if ( (state_vector(secondaryland) .gt. site_in%min_allowed_landuse_fraction) .and. (.not. site_in%landuse_vector_gt_min(secondaryland)) ) then + ! if the area of secondary land has just exceeded the minimum below which we ignore things, + ! set the flag to keep track of that. + if ( (state_vector(secondaryland) .gt. site_in%min_allowed_landuse_fraction) .and. & + (.not. site_in%landuse_vector_gt_min(secondaryland)) ) then site_in%landuse_vector_gt_min(secondaryland) = .true. write(fates_log(),*) 'setting site_in%landuse_vector_gt_min(secondaryland) = .true.' - - currentPatch => site_in%oldest_patch - do while (associated(currentPatch)) - write(fates_log(),*) 'cpatch area, LU, distrates(ilog): ', currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label, currentPatch%disturbance_rates(dtype_ilog), currentPatch%area - currentPatch%total_canopy_area - currentPatch => currentPatch%younger - end do - + if (debug) then + currentPatch => site_in%oldest_patch + do while (associated(currentPatch)) + write(fates_log(),*) 'cpatch area, LU, distrates(ilog): ', currentPatch%area, currentPatch%land_use_label, & + currentPatch%nocomp_pft_label, currentPatch%disturbance_rates(dtype_ilog), & + currentPatch%area - currentPatch%total_canopy_area + currentPatch => currentPatch%younger + end do + end if end if end subroutine disturbance_rates @@ -575,7 +586,8 @@ subroutine spawn_patches( currentSite, bc_in) ! we want at the second-outermost loop to go through all disturbance types, because we resolve each of these separately disturbance_type_loop: do i_disturbance_type = 1,N_DIST_TYPES - ! the next loop level is to go through patches that have a specific land-use type. the reason to do this is because the combination of + ! the next loop level is to go through patches that have a specific land-use type. the reason to do this + ! is because the combination of ! disturbance type and donor land-use type uniquly define the land-use type of the receiver patch. landuse_donortype_loop: do i_donorpatch_landuse_type = 1, n_landuse_cats @@ -584,7 +596,8 @@ subroutine spawn_patches( currentSite, bc_in) ! for fire and treefall disturbance, receiver land-use type is whatever the donor land-use type is. ! for logging disturbance, receiver land-use type is always secondary lands - ! for land-use-change disturbance, we need to loop over all possible transition types for land-use-change from the current land-use type. + ! for land-use-change disturbance, we need to loop over all possible transition types for land-use-change from + ! the current land-use type. select case(i_disturbance_type) case(dtype_ifire) @@ -597,7 +610,8 @@ subroutine spawn_patches( currentSite, bc_in) start_receiver_lulabel = secondaryland end_receiver_lulabel = secondaryland case(dtype_ilandusechange) - start_receiver_lulabel = 1 ! this could actually maybe be 2, as primaryland column of matrix should all be zeros, but leave as 1 for now + start_receiver_lulabel = 1 ! this could actually maybe be 2, as primaryland column of matrix should + ! all be zeros, but leave as 1 for now end_receiver_lulabel = n_landuse_cats case default write(fates_log(),*) 'unknown disturbance mode?' @@ -607,19 +621,24 @@ subroutine spawn_patches( currentSite, bc_in) ! next loop level is the set of possible receiver patch land use types. ! for disturbance types other than land use change, this is sort of a dummy loop, per the above logic. - landusechange_receiverpatchlabel_loop: do i_landusechange_receiverpatchlabel = start_receiver_lulabel, end_receiver_lulabel + landusechange_receiverpatchlabel_loop: do i_landusechange_receiverpatchlabel = start_receiver_lulabel, & + end_receiver_lulabel ! now we want to begin resolving all of the disturbance given the above categorical criteria of: - ! nocomp-PFT, disturbance type, donor patch land use label, and receiver patch land use label. All of the disturbed area that meets these - ! criteria (if any) will be put into a new patch whose area and properties are taken from one or more donor patches. + ! nocomp-PFT, disturbance type, donor patch land use label, and receiver patch land use label. + ! All of the disturbed area that meets these criteria (if any) will be put into a new patch whose area and + ! properties are taken from one or more donor patches. - ! calculate area of disturbed land that meets the above criteria, in this timestep, by summing contributions from each existing patch. + ! calculate area of disturbed land that meets the above criteria, in this timestep, by summing contributions + ! from each existing patch. currentPatch => currentSite%youngest_patch - ! this variable site_areadis holds all the newly disturbed area from all patches for all disturbance being resolved now. + ! this variable site_areadis holds all the newly disturbed area from all patches for all disturbance being + ! resolved now. site_areadis = 0.0_r8 - ! loop over all patches to figure out the total patch area generated as a result of all disturbance being resolved now. + ! loop over all patches to figure out the total patch area generated as a result of all disturbance being + ! resolved now. patchloop_areadis: do while(associated(currentPatch)) cp_nocomp_matches_1_if: if ( hlm_use_nocomp .eq. ifalse .or. & @@ -751,7 +770,8 @@ subroutine spawn_patches( currentSite, bc_in) call logging_litter_fluxes(currentSite, currentPatch, & newPatch, patch_site_areadis,bc_in) - ! if transitioning from primary to secondary, then may need to change nocomp pft, so tag as having transitioned LU + ! if transitioning from primary to secondary, then may need to change nocomp pft, + ! so tag as having transitioned LU if ( i_disturbance_type .eq. dtype_ilog .and. i_donorpatch_landuse_type .eq. primaryland) then newPatch%changed_landuse_this_ts = .true. end if @@ -838,7 +858,8 @@ subroutine spawn_patches( currentSite, bc_in) store_c = currentCohort%prt%GetState(store_organ, carbon12_element) total_c = sapw_c + struct_c + leaf_c + fnrt_c + store_c - ! survivorship of plants in both the disturbed and undisturbed cohorts depends on what type of disturbance is happening. + ! survivorship of plants in both the disturbed and undisturbed cohorts depends on what type of + ! disturbance is happening. disttype_case: select case(i_disturbance_type) @@ -1478,7 +1499,7 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch => currentPatch%younger end do - if ( buffer_patch_used ) then + buffer_patch_used_if: if ( buffer_patch_used ) then ! at this point, lets check that the total patch area remaining to be relabelled equals what we think that it is. if (abs(sum(nocomp_pft_area_vector(:)) - sum(nocomp_pft_area_vector_filled(:)) - buffer_patch%area) .gt. rsnbl_math_prec) then write(fates_log(),*) 'midway through patch reallocation and things are already not adding up.', i_land_use_label @@ -1489,7 +1510,7 @@ subroutine spawn_patches( currentSite, bc_in) write(fates_log(),*) nocomp_pft_area_vector write(fates_log(),*) '-----' write(fates_log(),*) buffer_patch%area, buffer_patch%land_use_label, buffer_patch%nocomp_pft_label - write(fates_log(),*) sum(nocomp_pft_area_vector(:)), sum(nocomp_pft_area_vector_filled(:)), buffer_patch%area + write(fates_log(+),*) sum(nocomp_pft_area_vector(:)), sum(nocomp_pft_area_vector_filled(:)), buffer_patch%area currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) write(fates_log(),*) currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label @@ -1526,9 +1547,6 @@ subroutine spawn_patches( currentSite, bc_in) ! put the new patch into the linked list call InsertPatch(currentSite, temp_patch) - ! now that the patch that temp_patch points to is in the site linked list, we want to null temp_patch so that it can be - ! refilled the next time through the loop. - else ! give the buffer patch the intended nocomp PFT label buffer_patch%nocomp_pft_label = i_pft @@ -1547,26 +1565,26 @@ subroutine spawn_patches( currentSite, bc_in) end if end do nocomp_pft_loop_2 - ! now we want to make sure that either the buffer_patch either has zero area (presumably it was never used), in which case it should be deallocated, - ! or else it does have area but it has been put into the site linked list, and so buffer patch should be nulled before next pass through outer loop. - ! if either of those, that means everything worked properly, if not, then something has gone wrong. - if (buffer_patch_in_linked_list) then - buffer_patch => null() - else if (buffer_patch%area .lt. rsnbl_math_prec) then - ! here we need to deallocate the buffer patch so that we don't get a memory leak. - call buffer_patch%FreeMemory(regeneration_model, numpft) - deallocate(buffer_patch, stat=istat, errmsg=smsg) - if (istat/=0) then - write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - else - write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' - write(fates_log(),*) 'buffer_patch%area', buffer_patch%area - write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)), sum(nocomp_pft_area_vector(:)) - write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:)) + ! now we want to make sure that either the buffer_patch has zero area (presumably it was never used), + ! in which case it should be deallocated, or else it does have area but it has been put into the site + ! linked list. if either of those, that means everything worked properly, if not, then something has gone wrong. + if ( .not. buffer_patch_in_linked_list) then + if (buffer_patch%area .lt. rsnbl_math_prec) then + ! here we need to deallocate the buffer patch so that we don't get a memory leak. + call buffer_patch%FreeMemory(regeneration_model, numpft) + deallocate(buffer_patch, stat=istat, errmsg=smsg) + if (istat/=0) then + write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + else + write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' + write(fates_log(),*) 'buffer_patch%area', buffer_patch%area + write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)), sum(nocomp_pft_area_vector(:)) + write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:)) - call endrun(msg=errMsg(sourcefile, __LINE__)) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if end if else ! buffer patch was never even used. deallocate. @@ -1576,7 +1594,7 @@ subroutine spawn_patches( currentSite, bc_in) write(fates_log(),*) 'dealloc: fail on deallocate(dp):'//trim(smsg) call endrun(msg=errMsg(sourcefile, __LINE__)) endif - end if + end if buffer_patch_used_if ! check that the area we have added is the same as the area we have taken away. if not, crash. if ( abs(sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:))) .gt. rsnbl_math_prec) then diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index 69d06e26f5..cb8fcd740c 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -282,7 +282,9 @@ subroutine GetLUHStatedata(bc_in, state_vector) state_vector(:) = 0._r8 urban_fraction = 0._r8 - if (hlm_use_potentialveg .eq. ifalse) then + if (hlm_use_potentialveg .eq. itrue) then + state_vector(primaryland) = 1._r8 + else ! Check to see if the incoming state vector is NaN. temp_vector = bc_in%hlm_luh_states call CheckLUHData(temp_vector,modified_flag) @@ -316,8 +318,6 @@ subroutine GetLUHStatedata(bc_in, state_vector) else state_vector(primaryland) = 1._r8 endif - else - state_vector(primaryland) = 1._r8 end if end subroutine GetLUHStatedata diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index dd672e3bcb..c124499e6b 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -125,6 +125,7 @@ module FatesInterfaceTypesMod integer, public :: hlm_use_luh ! flag to signal whether or not to use luh2 drivers integer, public :: hlm_use_potentialveg ! flag to signal whether or not to use potential vegetation only + ! (i.e., no land use and instead force all lands to be primary) integer, public :: hlm_num_luh2_states ! number of land use state types provided in LUH2 forcing dataset integer, public :: hlm_num_luh2_transitions ! number of land use transition types provided in LUH2 forcing dataset diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index f4225bc259..829ce56b60 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -713,15 +713,15 @@ subroutine define_restart_vars(this, initialize_variables) hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_gdd_si ) call this%set_restart_var(vname='fates_min_allowed_landuse_fraction_site', vtype=site_r8, & - long_name='minimum allowed land use fraction at each site', units='degC days', flushval = flushzero, & + long_name='minimum allowed land use fraction at each site', units='fraction', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_min_allowed_landuse_fraction_si ) call this%set_restart_var(vname='fates_landuse_vector_gt_min_site', vtype=cohort_int, & - long_name='minimum allowed land use fraction at each site', units='degC days', flushval = flushzero, & + long_name='minimum allowed land use fraction at each site', units='logical', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_landuse_vector_gt_min_si ) call this%set_restart_var(vname='fates_area_bareground_site', vtype=site_r8, & - long_name='minimum allowed land use fraction at each site', units='degC days', flushval = flushzero, & + long_name='minimum allowed land use fraction at each site', units='fraction', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_area_bareground_si ) call this%set_restart_var(vname='fates_snow_depth_site', vtype=site_r8, & diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index cbee915175..fe5bfdb086 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1626,7 +1626,7 @@ data: fates_landuse_crop_lu_pft_vector = -999, -999, -999, -999, 11 ; - fates_max_nocomp_pfts_by_landuse = 4, 4, 2, 2, 1 ; + fates_max_nocomp_pfts_by_landuse = 4, 4, 1, 1, 1 ; fates_maxpatches_by_landuse = 9, 4, 1, 1, 1 ; From 530c99d37fcf56e16f65546a015be39c03cb5576 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Tue, 30 Apr 2024 11:21:12 -0700 Subject: [PATCH 197/300] Update biogeochem/FatesLandUseChangeMod.F90 Co-authored-by: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> --- biogeochem/FatesLandUseChangeMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/FatesLandUseChangeMod.F90 b/biogeochem/FatesLandUseChangeMod.F90 index cb8fcd740c..c523c8788a 100644 --- a/biogeochem/FatesLandUseChangeMod.F90 +++ b/biogeochem/FatesLandUseChangeMod.F90 @@ -127,7 +127,7 @@ subroutine GetLanduseTransitionRates(bc_in, min_allowed_landuse_fraction, landus end if end do transitions_loop - ! zero all transitions where the state vector is less than the minimum allowed, + ! zero all transitions where the receiving land use type state vector is less than the minimum allowed, ! and otherwise if this is the first timestep where the minimum was exceeded, ! then apply all transitions from primary to this type and reset the flag ! note that the flag resetting should not happen for secondary lands, as this is handled in the From d5b06403bdedd8c072c8725509afa247591ed251 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Tue, 30 Apr 2024 17:27:39 -0700 Subject: [PATCH 198/300] Update main/FatesInterfaceMod.F90 Co-authored-by: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> --- main/FatesInterfaceMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index a445bfab51..55298127e3 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -566,7 +566,7 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats, if ( hlm_use_fixed_biogeog .eq. itrue) then if (hlm_use_luh .eq. itrue ) then - allocate(bc_in%pft_areafrac_lu(size( EDPftvarcon_inst%hlm_pft_map,2),num_luh2_states-n_crop_lu_types)) + allocate(bc_in%pft_areafrac_lu(size( EDPftvarcon_inst%hlm_pft_map,2),n_landuse_cats-n_crop_lu_types)) else allocate(bc_in%pft_areafrac(surfpft_lb:surfpft_ub)) endif From 5f79a10ed740822ff56d55071663c268e5d0be1c Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Wed, 1 May 2024 10:56:22 -0600 Subject: [PATCH 199/300] Update fire/SFMainMod.F90 Co-authored-by: Charlie Koven --- fire/SFMainMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index b5b9ad0ce6..adc4b63293 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -75,7 +75,7 @@ module SFMainMod subroutine fire_model(currentSite, bc_in) ! ! DESCRIPTION: - ! Runs the daily fire weather model + ! Runs the daily fire model ! ARGUMENTS: type(ed_site_type), intent(inout), target :: currentSite ! site object From 0538d93fde922ce055459de81859a9f8f2715f06 Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Wed, 1 May 2024 10:56:37 -0600 Subject: [PATCH 200/300] Update fire/SFNesterovMod.F90 Co-authored-by: Charlie Koven --- fire/SFNesterovMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fire/SFNesterovMod.F90 b/fire/SFNesterovMod.F90 index 860a2ec6f9..a93b956b20 100644 --- a/fire/SFNesterovMod.F90 +++ b/fire/SFNesterovMod.F90 @@ -16,7 +16,7 @@ module SFNesterovMod end type nesterov_index - real(r8), parameter :: min_precip_thresh = 3.0_r8 ! threshold for precipitation above which to 0.0 NI + real(r8), parameter :: min_precip_thresh = 3.0_r8 ! threshold for precipitation above which to zero NI [mm/day] contains From a99035f26e364039ef04b613384a4862b6ee8cc1 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 1 May 2024 12:02:21 -0600 Subject: [PATCH 201/300] comment updates --- CMakeLists.txt | 3 +++ biogeochem/CMakeLists.txt | 1 + fire/CMakeLists.txt | 1 + radiation/CMakeLists.txt | 2 ++ 4 files changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00544cc654..e84fbfb711 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,6 @@ +# This file helps to build unit test programs to test FATES, but is not used in +# production runs + cmake_minimum_required(VERSION 3.4) list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) diff --git a/biogeochem/CMakeLists.txt b/biogeochem/CMakeLists.txt index 692e22d9dc..876739a894 100644 --- a/biogeochem/CMakeLists.txt +++ b/biogeochem/CMakeLists.txt @@ -1,3 +1,4 @@ +# This file is required for unit testing, but is not used for production runs list(APPEND fates_sources FatesLitterMod.F90 ) diff --git a/fire/CMakeLists.txt b/fire/CMakeLists.txt index 2cd6b992d1..e0dde25c67 100644 --- a/fire/CMakeLists.txt +++ b/fire/CMakeLists.txt @@ -1,3 +1,4 @@ +# This file is required for unit testing, but is not used for production runs list(APPEND fates_sources SFParamsMod.F90 SFFireWeatherMod.F90 diff --git a/radiation/CMakeLists.txt b/radiation/CMakeLists.txt index 7cb7a324c2..cf092060ea 100644 --- a/radiation/CMakeLists.txt +++ b/radiation/CMakeLists.txt @@ -1,3 +1,5 @@ +# This file is required for unit testing, but is not used for production runs + list(APPEND fates_sources TwoStreamMLPEMod.F90 ) From d864fac68b70cbe2989c0cb3ef63f29c06a39152 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Wed, 1 May 2024 13:50:54 -0600 Subject: [PATCH 202/300] remove dewpoint constants --- fire/SFNesterovMod.F90 | 63 +++++++++++-------- fire/SFParamsMod.F90 | 12 ---- .../fire_weather_test/test_FireWeather.pf | 3 - main/FatesConstantsMod.F90 | 4 ++ parameter_files/fates_params_default.cdl | 10 --- 5 files changed, 40 insertions(+), 52 deletions(-) diff --git a/fire/SFNesterovMod.F90 b/fire/SFNesterovMod.F90 index a93b956b20..85d1d94396 100644 --- a/fire/SFNesterovMod.F90 +++ b/fire/SFNesterovMod.F90 @@ -12,8 +12,7 @@ module SFNesterovMod procedure, public :: Init => init_nesterov_fire_weather procedure, public :: Update => update_nesterov_index - procedure :: calc_nesterov_index - + end type nesterov_index real(r8), parameter :: min_precip_thresh = 3.0_r8 ! threshold for precipitation above which to zero NI [mm/day] @@ -46,50 +45,60 @@ subroutine update_nesterov_index(this, temp_C, precip, rh, wind) real(r8), intent(in) :: precip ! daily precipitation [mm] real(r8), intent(in) :: rh ! daily relative humidity [%] real(r8), intent(in) :: wind ! daily wind speed [m/min] + + ! LOCALS: + real(r8) :: t_dew ! dewpoint temperature [degrees C] if (precip > min_precip_thresh) then ! rezero NI if it rains this%fire_weather_index = 0.0_r8 else + + ! Calculate dewpoint temperature + t_dew = dewpoint(temp_c, rh) + ! Accumulate Nesterov index over fire season. - this%fire_weather_index = this%fire_weather_index + & - this%calc_nesterov_index(temp_C, precip, rh) + this%fire_weather_index = this%fire_weather_index + calc_nesterov_index(temp_C, t_dew) end if end subroutine update_nesterov_index !------------------------------------------------------------------------------------- - real(r8) function calc_nesterov_index(this, temp_C, precip, rh) + real(r8) function calc_nesterov_index(temp_C, t_dew) ! ! DESCRIPTION: ! Calculates current day's Nesterov Index for a given input values - - use SFParamsMod, only : SF_val_fdi_a, SF_val_fdi_b ! ARGUMENTS: - class(nesterov_index), intent(in) :: this ! nesterov index extended class - real(r8), intent(in) :: temp_C ! daily averaged temperature [degrees C] - real(r8), intent(in) :: precip ! daily precipitation [mm] - real(r8), intent(in) :: rh ! daily relative humidity [rh] - - ! LOCALS: - real(r8) :: yipsolon ! intermediate variable for dewpoint calculation - real(r8) :: dewpoint ! dewpoint - - if (precip > min_precip_thresh) then ! NI is 0.0 if it rains - calc_nesterov_index = 0.0_r8 - else - ! Calculate dewpoint temperature - yipsolon = (SF_val_fdi_a*temp_C)/(SF_val_fdi_b + temp_C) + log(max(1.0_r8, rh)/100.0_r8) - dewpoint = (SF_val_fdi_b*yipsolon)/(SF_val_fdi_a - yipsolon) - - ! Nesterov 1968. Eq 5, Thonicke et al. 2010 - calc_nesterov_index = (temp_C - dewpoint)*temp_C - if (calc_nesterov_index < 0.0_r8) calc_nesterov_index = 0.0_r8 ! can't be negative - endif + real(r8), intent(in) :: temp_C ! daily averaged temperature [degrees C] + real(r8), intent(in) :: t_dew ! daily dewpoint temperature [degrees C] + + ! Nesterov 1968. Eq 5, Thonicke et al. 2010 + calc_nesterov_index = (temp_C - t_dew)*temp_C + if (calc_nesterov_index < 0.0_r8) calc_nesterov_index = 0.0_r8 ! can't be negative end function calc_nesterov_index !------------------------------------------------------------------------------------- + + real(r8) function dewpoint(temp_C, rh) + ! + ! DESCRIPTION: + ! Calculates dewpoint from input air temperature and relative humidity + ! Uses Equation 8 from Lawrence 2005, https://doi.org/10.1175/BAMS-86-2-225 + + use FatesConstantsMod, only : dewpoint_a, dewpoint_b + + ! ARGUMENTS + real(r8), intent(in) :: temp_C ! temperature [degrees C] + real(r8), intent(in) :: rh ! relative humidity [%] + + ! LOCALS + real(r8) :: yipsolon ! intermediate value for dewpoint calculation + + yipsolon = log(max(1.0_r8, rh)/100.0_r8) + (dewpoint_a*temp_C)/(dewpoint_b + temp_C) + dewpoint = (dewpoint_b*yipsolon)/(dewpoint_a - yipsolon) + + end function dewpoint end module SFNesterovMod \ No newline at end of file diff --git a/fire/SFParamsMod.F90 b/fire/SFParamsMod.F90 index e07777f25d..5ecd269692 100644 --- a/fire/SFParamsMod.F90 +++ b/fire/SFParamsMod.F90 @@ -18,9 +18,6 @@ module SFParamsMod ! ! this is what the user can use for the actual values ! - - real(r8), public :: SF_val_fdi_a - real(r8), public :: SF_val_fdi_b real(r8),protected, public :: SF_val_fdi_alpha real(r8),protected, public :: SF_val_miner_total real(r8),protected, public :: SF_val_fuel_energy @@ -148,8 +145,6 @@ subroutine SpitFireParamsInit() implicit none - SF_val_fdi_a = nan - SF_val_fdi_b = nan SF_val_fdi_alpha = nan SF_val_miner_total = nan SF_val_fuel_energy = nan @@ -258,13 +253,6 @@ subroutine SpitFireReceiveScalars(fates_params) class(fates_parameters_type), intent(inout) :: fates_params real(r8) :: tmp_real - - - call fates_params%RetrieveParameter(name=SF_name_fdi_a, & - data=SF_val_fdi_a) - - call fates_params%RetrieveParameter(name=SF_name_fdi_b, & - data=SF_val_fdi_b) call fates_params%RetrieveParameter(name=SF_name_fdi_alpha, & data=SF_val_fdi_alpha) diff --git a/fire/test/fire_weather_test/test_FireWeather.pf b/fire/test/fire_weather_test/test_FireWeather.pf index 21338b5f90..c5111394bc 100644 --- a/fire/test/fire_weather_test/test_FireWeather.pf +++ b/fire/test/fire_weather_test/test_FireWeather.pf @@ -6,7 +6,6 @@ module test_FireWeather use FatesConstantsMod, only : r8 => fates_r8 use SFFireWeatherMod, only : fire_weather use SFNesterovMod, only : nesterov_index - use SFParamsMod, only : SF_val_fdi_a, SF_val_fdi_b use funit implicit none @@ -29,8 +28,6 @@ module test_FireWeather class(TestFireWeather), intent(inout) :: this allocate(nesterov_index :: this%fireWeatherNesterov) call this%fireWeatherNesterov%Init() - SF_val_fdi_a = 17.62_r8 - SF_val_fdi_b = 243.12_r8 end subroutine setUp subroutine tearDown(this) diff --git a/main/FatesConstantsMod.F90 b/main/FatesConstantsMod.F90 index 350979b7c4..b531957096 100644 --- a/main/FatesConstantsMod.F90 +++ b/main/FatesConstantsMod.F90 @@ -277,6 +277,10 @@ module FatesConstantsMod real(fates_r8), parameter, public :: J_per_kJ = 1000.0_fates_r8 ! Physical constants + + ! dewpoint calculation + real(fates_r8), parameter, public :: dewpoint_a = 17.62_fates_r8 + real(fates_r8), parameter, public :: dewpoint_b = 243.12_fates_r8 ![degrees C] ! universal gas constant [J/K/kmol] real(fates_r8), parameter, public :: rgas_J_K_kmol = 8314.4598_fates_r8 diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 2eaeb875fe..2a909ee340 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -732,15 +732,9 @@ variables: double fates_fire_durat_slope ; fates_fire_durat_slope:units = "NA" ; fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; - double fates_fire_fdi_a ; - fates_fire_fdi_a:units = "NA" ; - fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; double fates_fire_fdi_alpha ; fates_fire_fdi_alpha:units = "NA" ; fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; - double fates_fire_fdi_b ; - fates_fire_fdi_b:units = "NA" ; - fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; double fates_fire_fuel_energy ; fates_fire_fuel_energy:units = "kJ/kg" ; fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; @@ -1666,12 +1660,8 @@ data: fates_fire_durat_slope = -11.06 ; - fates_fire_fdi_a = 17.62 ; - fates_fire_fdi_alpha = 0.00037 ; - fates_fire_fdi_b = 243.12 ; - fates_fire_fuel_energy = 18000 ; fates_fire_max_durat = 240 ; From b49d1abcd1d29849a49d60aa743e112ebaf23910 Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Wed, 1 May 2024 14:46:28 -0600 Subject: [PATCH 203/300] fix need to clean builds --- functional_unit_testing/build_fortran_tests.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/functional_unit_testing/build_fortran_tests.py b/functional_unit_testing/build_fortran_tests.py index 7943640f89..b495f25020 100644 --- a/functional_unit_testing/build_fortran_tests.py +++ b/functional_unit_testing/build_fortran_tests.py @@ -131,7 +131,7 @@ def get_extra_cmake_args(build_dir, mpilib): mpilib (str): MPI library name """ # get the machine objects file - machobj = Machines() + machobj = Machines() # this is different? # get compiler compiler = machobj.get_default_compiler() @@ -153,11 +153,11 @@ def get_extra_cmake_args(build_dir, mpilib): os_, unit_testing=True, ) - EnvMachSpecific(build_dir, unit_testing=True) + machspecific = EnvMachSpecific(build_dir, unit_testing=True) # make a fake case - FakeCase(compiler, mpilib, True, "nuopc", threading=False) - + fake_case = FakeCase(compiler, mpilib, True, "nuopc", threading=False) + machspecific.load_env(fake_case) cmake_args_list = [ f"-DOS={os_}", f"-DMACH={machobj.get_machine_name()}", From ec2720740693bf2507a8319aff460d726994a7b3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 1 May 2024 15:03:20 -0600 Subject: [PATCH 204/300] disaggregating fluxes based on root length only when sumweights is zero, to enable first time-step issues in ctsm --- biogeophys/FatesPlantHydraulicsMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 8263b98937..454bf5d28d 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -2788,11 +2788,11 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) ! Note: It is possible that the soil is so dry there is no conductance ! In these cases, solver error may create some non-zero, yet ! trivially small fluxes. Lets create a simple weighting - ! function based on root length and available water. + ! function based on root length. if(sumweight < nearzero)then sumweight = 0._r8 do j_bc = j_t,j_b - weight_sl(j_bc) = csite_hydr%rootl_sl(j_bc)*bc_in(s)%h2o_liq_sisl(j_bc) + weight_sl(j_bc) = csite_hydr%rootl_sl(j_bc) sumweight = sumweight + weight_sl(j_bc) end do end if From 5d5d205616ea4471a1896f59d63b0c46fe4686cd Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 1 May 2024 17:59:41 -0400 Subject: [PATCH 205/300] migrating unit testing to folder unit_testing --- CMakeLists.txt | 6 +++--- .../allometry/CMakeLists.txt | 0 .../allometry/FatesTestAllometry.F90 | 0 .../allometry/allometry_plotting.py | 0 .../build_fortran_tests.py | 0 .../math_utils/CMakeLists.txt | 0 .../math_utils/FatesTestMathUtils.F90 | 0 .../math_utils/math_plotting.py | 0 {functional_unit_testing => unit_testing}/path_utils.py | 0 .../run_fates_tests.py | 0 .../unit_test_shr}/CMakeLists.txt | 0 .../unit_test_shr}/FatesUnitTestIOMod.F90 | 0 .../unit_test_shr}/FatesUnitTestParamReaderMod.F90 | 0 {functional_unit_testing => unit_testing}/utils.py | 0 14 files changed, 3 insertions(+), 3 deletions(-) rename {functional_unit_testing => unit_testing}/allometry/CMakeLists.txt (100%) rename {functional_unit_testing => unit_testing}/allometry/FatesTestAllometry.F90 (100%) rename {functional_unit_testing => unit_testing}/allometry/allometry_plotting.py (100%) rename {functional_unit_testing => unit_testing}/build_fortran_tests.py (100%) rename {functional_unit_testing => unit_testing}/math_utils/CMakeLists.txt (100%) rename {functional_unit_testing => unit_testing}/math_utils/FatesTestMathUtils.F90 (100%) rename {functional_unit_testing => unit_testing}/math_utils/math_plotting.py (100%) rename {functional_unit_testing => unit_testing}/path_utils.py (100%) rename {functional_unit_testing => unit_testing}/run_fates_tests.py (100%) rename {unit_test_shr => unit_testing/unit_test_shr}/CMakeLists.txt (100%) rename {unit_test_shr => unit_testing/unit_test_shr}/FatesUnitTestIOMod.F90 (100%) rename {unit_test_shr => unit_testing/unit_test_shr}/FatesUnitTestParamReaderMod.F90 (100%) rename {functional_unit_testing => unit_testing}/utils.py (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3961a6780d..4b5a8cdc0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ add_subdirectory(${HLM_ROOT}/src/fates/biogeophys fates_biogeophys) add_subdirectory(${HLM_ROOT}/src/fates/parteh fates_parteh) add_subdirectory(${HLM_ROOT}/src/fates/fire fates_fire) add_subdirectory(${HLM_ROOT}/src/fates/radiation fates_radiation) -add_subdirectory(${HLM_ROOT}/src/fates/unit_test_shr unit_share) +add_subdirectory(${HLM_ROOT}/src/fates/unit_testing/unit_test_shr unit_share) # Remove shr_mpi_mod from share_sources. # This is needed because we want to use the mock shr_mpi_mod in place of the real one @@ -93,5 +93,5 @@ link_directories(${CMAKE_CURRENT_BINARY_DIR}) # has tests in it. However, it appears that the order needs to be done # carefully: for example, include_directories and link_directories needs to be # done before adding the tests themselves. -add_subdirectory(${HLM_ROOT}/src/fates/functional_unit_testing/allometry fates_allom_test) -add_subdirectory(${HLM_ROOT}/src/fates/functional_unit_testing/math_utils fates_math_test) \ No newline at end of file +add_subdirectory(${HLM_ROOT}/src/fates/unit_testing/allometry fates_allom_test) +add_subdirectory(${HLM_ROOT}/src/fates/unit_testing/math_utils fates_math_test) diff --git a/functional_unit_testing/allometry/CMakeLists.txt b/unit_testing/allometry/CMakeLists.txt similarity index 100% rename from functional_unit_testing/allometry/CMakeLists.txt rename to unit_testing/allometry/CMakeLists.txt diff --git a/functional_unit_testing/allometry/FatesTestAllometry.F90 b/unit_testing/allometry/FatesTestAllometry.F90 similarity index 100% rename from functional_unit_testing/allometry/FatesTestAllometry.F90 rename to unit_testing/allometry/FatesTestAllometry.F90 diff --git a/functional_unit_testing/allometry/allometry_plotting.py b/unit_testing/allometry/allometry_plotting.py similarity index 100% rename from functional_unit_testing/allometry/allometry_plotting.py rename to unit_testing/allometry/allometry_plotting.py diff --git a/functional_unit_testing/build_fortran_tests.py b/unit_testing/build_fortran_tests.py similarity index 100% rename from functional_unit_testing/build_fortran_tests.py rename to unit_testing/build_fortran_tests.py diff --git a/functional_unit_testing/math_utils/CMakeLists.txt b/unit_testing/math_utils/CMakeLists.txt similarity index 100% rename from functional_unit_testing/math_utils/CMakeLists.txt rename to unit_testing/math_utils/CMakeLists.txt diff --git a/functional_unit_testing/math_utils/FatesTestMathUtils.F90 b/unit_testing/math_utils/FatesTestMathUtils.F90 similarity index 100% rename from functional_unit_testing/math_utils/FatesTestMathUtils.F90 rename to unit_testing/math_utils/FatesTestMathUtils.F90 diff --git a/functional_unit_testing/math_utils/math_plotting.py b/unit_testing/math_utils/math_plotting.py similarity index 100% rename from functional_unit_testing/math_utils/math_plotting.py rename to unit_testing/math_utils/math_plotting.py diff --git a/functional_unit_testing/path_utils.py b/unit_testing/path_utils.py similarity index 100% rename from functional_unit_testing/path_utils.py rename to unit_testing/path_utils.py diff --git a/functional_unit_testing/run_fates_tests.py b/unit_testing/run_fates_tests.py similarity index 100% rename from functional_unit_testing/run_fates_tests.py rename to unit_testing/run_fates_tests.py diff --git a/unit_test_shr/CMakeLists.txt b/unit_testing/unit_test_shr/CMakeLists.txt similarity index 100% rename from unit_test_shr/CMakeLists.txt rename to unit_testing/unit_test_shr/CMakeLists.txt diff --git a/unit_test_shr/FatesUnitTestIOMod.F90 b/unit_testing/unit_test_shr/FatesUnitTestIOMod.F90 similarity index 100% rename from unit_test_shr/FatesUnitTestIOMod.F90 rename to unit_testing/unit_test_shr/FatesUnitTestIOMod.F90 diff --git a/unit_test_shr/FatesUnitTestParamReaderMod.F90 b/unit_testing/unit_test_shr/FatesUnitTestParamReaderMod.F90 similarity index 100% rename from unit_test_shr/FatesUnitTestParamReaderMod.F90 rename to unit_testing/unit_test_shr/FatesUnitTestParamReaderMod.F90 diff --git a/functional_unit_testing/utils.py b/unit_testing/utils.py similarity index 100% rename from functional_unit_testing/utils.py rename to unit_testing/utils.py From c348a7dafcdba4f62b7cc26a4bee43826a79c2a9 Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Thu, 2 May 2024 14:53:54 -0700 Subject: [PATCH 206/300] aded error check if trying to go back into potential veg mode --- main/FatesRestartInterfaceMod.F90 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 829ce56b60..3d1f71a963 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -3696,6 +3696,12 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! restart run that did not include land use. if (rio_landuse_config_si(io_idx_si) .eq. itrue .and. hlm_use_potentialveg .eq. ifalse) then sites(s)%transition_landuse_from_off_to_on = .true. + else if ( rio_landuse_config_si(io_idx_si) .ne. hlm_use_potentialveg ) then + ! can't go back into potential vegetation mode, it is a one-way thing. + write(fates_log(),*) 'this combination of rio_landuse_config_si(io_idx_si) and hlm_use_potentialveg is not permitted' + write(fates_log(),*) 'rio_landuse_config_si(io_idx_si)', rio_landuse_config_si(io_idx_si) + write(fates_log(),*) 'hlm_use_potentialveg', hlm_use_potentialveg + call endrun(msg=errMsg(sourcefile, __LINE__)) endif end do From 9775af6ba2a324e9b9c54fcaf3ec384cb8be6d4c Mon Sep 17 00:00:00 2001 From: adrifoster Date: Thu, 2 May 2024 17:18:08 -0600 Subject: [PATCH 207/300] remove old cmakelists --- functional_unit_testing/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 functional_unit_testing/CMakeLists.txt diff --git a/functional_unit_testing/CMakeLists.txt b/functional_unit_testing/CMakeLists.txt deleted file mode 100644 index 1ab61abfc2..0000000000 --- a/functional_unit_testing/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -add_subdirectory(allometry) -add_subdirectory(math_utils) \ No newline at end of file From 1a5c1987ea96c3154807ae57efe53550b298edf9 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Fri, 3 May 2024 09:04:02 -0600 Subject: [PATCH 208/300] fix merge conflict --- fire/SFParamsMod.F90 | 8 -------- 1 file changed, 8 deletions(-) diff --git a/fire/SFParamsMod.F90 b/fire/SFParamsMod.F90 index 5ecd269692..c2dbc3fcd6 100644 --- a/fire/SFParamsMod.F90 +++ b/fire/SFParamsMod.F90 @@ -38,8 +38,6 @@ module SFParamsMod real(r8),protected, public :: SF_val_mid_moisture_Coeff(NFSC) real(r8),protected, public :: SF_val_mid_moisture_Slope(NFSC) - character(len=param_string_length),parameter :: SF_name_fdi_a = "fates_fire_fdi_a" - character(len=param_string_length),parameter :: SF_name_fdi_b = "fates_fire_fdi_b" character(len=param_string_length),parameter :: SF_name_fdi_alpha = "fates_fire_fdi_alpha" character(len=param_string_length),parameter :: SF_name_miner_total = "fates_fire_miner_total" character(len=param_string_length),parameter :: SF_name_fuel_energy = "fates_fire_fuel_energy" @@ -209,12 +207,6 @@ subroutine SpitFireRegisterScalars(fates_params) character(len=param_string_length), parameter :: dim_names_scalar(1) = (/dimension_name_scalar/) - call fates_params%RegisterParameter(name=SF_name_fdi_a, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - - call fates_params%RegisterParameter(name=SF_name_fdi_b, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=SF_name_fdi_alpha, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) From f61c792cc795b14fefc5268c2b350b75fa180da7 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 6 May 2024 11:30:04 -0400 Subject: [PATCH 209/300] Finally named that constant defining fraction of energy going to photosystem 2 --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 0aad6eb977..c5ffac2884 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1301,6 +1301,11 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! Fraction of light absorbed by non-photosynthetic pigments real(r8),parameter :: fnps = 0.15_r8 + ! term accounting that two photons are needed to fully transport a single + ! electron to the thylakoid-membrane-bound NADP reductase (see Farquhar 1980) + ! ie only have the energy enters photosystem 2 + real(r8), parameter :: photon_to_e_nadp = 0.5_r8 + ! For plants with no leaves, a miniscule amount of conductance ! can happen through the stems, at a partial rate of cuticular conductance real(r8),parameter :: stem_cuticle_loss_frac = 0.1_r8 @@ -1372,7 +1377,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in if(( laisun_lsl * canopy_area_lsl) > min_la_to_solve)then qabs = parsun_lsl / (laisun_lsl * canopy_area_lsl ) - qabs = qabs * 0.5_r8 * (1._r8 - fnps) * 4.6_r8 + qabs = qabs * photon_to_e_nadp * (1._r8 - fnps) * 4.6_r8 else qabs = 0.0_r8 @@ -1382,7 +1387,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in if( (parsha_lsl>nearzero) .and. (laisha_lsl * canopy_area_lsl) > min_la_to_solve ) then qabs = parsha_lsl / (laisha_lsl * canopy_area_lsl) - qabs = qabs * 0.5_r8 * (1._r8 - fnps) * 4.6_r8 + qabs = qabs * photon_to_e_nadp * (1._r8 - fnps) * 4.6_r8 else ! The radiative transfer schemes are imperfect ! they can sometimes generate negative values here From 35cd29786c8abbc3e9fb08da7d048b36370ee736 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 6 May 2024 11:35:57 -0400 Subject: [PATCH 210/300] cleaned up description a tad --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index c5ffac2884..482372470b 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1303,7 +1303,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! term accounting that two photons are needed to fully transport a single ! electron to the thylakoid-membrane-bound NADP reductase (see Farquhar 1980) - ! ie only have the energy enters photosystem 2 + ! ie only half the energy from a photon enters photosystem 2 real(r8), parameter :: photon_to_e_nadp = 0.5_r8 ! For plants with no leaves, a miniscule amount of conductance From 4a34bd5fe346babff096b23e8b7d595b4399088d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 6 May 2024 15:18:49 -0600 Subject: [PATCH 211/300] remove defunct use calls to fire_fdi_a and b --- fire/SFMainMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index 2000c45261..f1e7de14ea 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -115,7 +115,6 @@ subroutine UpdateFireWeather(currentSite, bc_in) ! DESCRIPTION: ! Updates the site's fire weather index - use SFParamsMod, only : SF_val_fdi_a, SF_val_fdi_b use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm use FatesConstantsMod, only : sec_per_day From d076c0719214d88095ab33db07bb152645a2556e Mon Sep 17 00:00:00 2001 From: Adrianna Foster Date: Mon, 6 May 2024 15:33:13 -0600 Subject: [PATCH 212/300] Update main/EDTypesMod.F90 Co-authored-by: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> --- main/EDTypesMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index c3f71d6ff8..9c92871f1f 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -32,7 +32,6 @@ module EDTypesMod use FatesConstantsMod, only : n_dbh_bins, n_dist_types use shr_log_mod, only : errMsg => shr_log_errMsg use SFFireWeatherMod, only : fire_weather - use SFNesterovMod, only : nesterov_index implicit none private ! By default everything is private From ebdb992051a30b65a51c884549678a4a773b575d Mon Sep 17 00:00:00 2001 From: adrifoster Date: Mon, 6 May 2024 16:01:49 -0600 Subject: [PATCH 213/300] updated directory structure --- CMakeLists.txt | 13 +++---------- testing/CMakeLists.txt | 3 +++ {unit_testing => testing}/build_fortran_tests.py | 0 .../functional_testing}/allometry/CMakeLists.txt | 0 .../allometry/FatesTestAllometry.F90 | 0 .../allometry/allometry_plotting.py | 0 .../functional_testing}/math_utils/CMakeLists.txt | 0 .../math_utils/FatesTestMathUtils.F90 | 0 .../functional_testing}/math_utils/math_plotting.py | 0 {unit_testing => testing}/path_utils.py | 0 {unit_testing => testing}/run_fates_tests.py | 9 +++++---- .../testing_shr}/CMakeLists.txt | 0 .../testing_shr}/FatesUnitTestIOMod.F90 | 0 .../testing_shr}/FatesUnitTestParamReaderMod.F90 | 0 testing/unit_testing/README_unit_testing | 1 + {unit_testing => testing}/utils.py | 0 16 files changed, 12 insertions(+), 14 deletions(-) create mode 100644 testing/CMakeLists.txt rename {unit_testing => testing}/build_fortran_tests.py (100%) rename {unit_testing => testing/functional_testing}/allometry/CMakeLists.txt (100%) rename {unit_testing => testing/functional_testing}/allometry/FatesTestAllometry.F90 (100%) rename {unit_testing => testing/functional_testing}/allometry/allometry_plotting.py (100%) rename {unit_testing => testing/functional_testing}/math_utils/CMakeLists.txt (100%) rename {unit_testing => testing/functional_testing}/math_utils/FatesTestMathUtils.F90 (100%) rename {unit_testing => testing/functional_testing}/math_utils/math_plotting.py (100%) rename {unit_testing => testing}/path_utils.py (100%) rename {unit_testing => testing}/run_fates_tests.py (98%) rename {unit_testing/unit_test_shr => testing/testing_shr}/CMakeLists.txt (100%) rename {unit_testing/unit_test_shr => testing/testing_shr}/FatesUnitTestIOMod.F90 (100%) rename {unit_testing/unit_test_shr => testing/testing_shr}/FatesUnitTestParamReaderMod.F90 (100%) create mode 100644 testing/unit_testing/README_unit_testing rename {unit_testing => testing}/utils.py (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b5a8cdc0b..9760a39c1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,7 @@ add_subdirectory(${HLM_ROOT}/src/fates/biogeophys fates_biogeophys) add_subdirectory(${HLM_ROOT}/src/fates/parteh fates_parteh) add_subdirectory(${HLM_ROOT}/src/fates/fire fates_fire) add_subdirectory(${HLM_ROOT}/src/fates/radiation fates_radiation) -add_subdirectory(${HLM_ROOT}/src/fates/unit_testing/unit_test_shr unit_share) +add_subdirectory(${HLM_ROOT}/src/fates/testing/testing_shr test_share) # Remove shr_mpi_mod from share_sources. # This is needed because we want to use the mock shr_mpi_mod in place of the real one @@ -86,12 +86,5 @@ link_directories(${NETCDF_C_DIR}/lib include_directories(${CMAKE_CURRENT_BINARY_DIR}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) - - -# Add the test directories -# Note: it's possible that these could be added by each source directory that -# has tests in it. However, it appears that the order needs to be done -# carefully: for example, include_directories and link_directories needs to be -# done before adding the tests themselves. -add_subdirectory(${HLM_ROOT}/src/fates/unit_testing/allometry fates_allom_test) -add_subdirectory(${HLM_ROOT}/src/fates/unit_testing/math_utils fates_math_test) +# Add the main test directory +add_subdirectory(${HLM_ROOT}/src/fates/testing) diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt new file mode 100644 index 0000000000..ac3ac02d18 --- /dev/null +++ b/testing/CMakeLists.txt @@ -0,0 +1,3 @@ +# This is where you add specific test directories +add_subdirectory(functional_testing/allometry fates_allom_test) +add_subdirectory(functional_testing/math_utils fates_math_test) \ No newline at end of file diff --git a/unit_testing/build_fortran_tests.py b/testing/build_fortran_tests.py similarity index 100% rename from unit_testing/build_fortran_tests.py rename to testing/build_fortran_tests.py diff --git a/unit_testing/allometry/CMakeLists.txt b/testing/functional_testing/allometry/CMakeLists.txt similarity index 100% rename from unit_testing/allometry/CMakeLists.txt rename to testing/functional_testing/allometry/CMakeLists.txt diff --git a/unit_testing/allometry/FatesTestAllometry.F90 b/testing/functional_testing/allometry/FatesTestAllometry.F90 similarity index 100% rename from unit_testing/allometry/FatesTestAllometry.F90 rename to testing/functional_testing/allometry/FatesTestAllometry.F90 diff --git a/unit_testing/allometry/allometry_plotting.py b/testing/functional_testing/allometry/allometry_plotting.py similarity index 100% rename from unit_testing/allometry/allometry_plotting.py rename to testing/functional_testing/allometry/allometry_plotting.py diff --git a/unit_testing/math_utils/CMakeLists.txt b/testing/functional_testing/math_utils/CMakeLists.txt similarity index 100% rename from unit_testing/math_utils/CMakeLists.txt rename to testing/functional_testing/math_utils/CMakeLists.txt diff --git a/unit_testing/math_utils/FatesTestMathUtils.F90 b/testing/functional_testing/math_utils/FatesTestMathUtils.F90 similarity index 100% rename from unit_testing/math_utils/FatesTestMathUtils.F90 rename to testing/functional_testing/math_utils/FatesTestMathUtils.F90 diff --git a/unit_testing/math_utils/math_plotting.py b/testing/functional_testing/math_utils/math_plotting.py similarity index 100% rename from unit_testing/math_utils/math_plotting.py rename to testing/functional_testing/math_utils/math_plotting.py diff --git a/unit_testing/path_utils.py b/testing/path_utils.py similarity index 100% rename from unit_testing/path_utils.py rename to testing/path_utils.py diff --git a/unit_testing/run_fates_tests.py b/testing/run_fates_tests.py similarity index 98% rename from unit_testing/run_fates_tests.py rename to testing/run_fates_tests.py index 9c260276ff..7a6b8cc296 100755 --- a/unit_testing/run_fates_tests.py +++ b/testing/run_fates_tests.py @@ -32,8 +32,8 @@ from build_fortran_tests import build_unit_tests, build_exists from path_utils import add_cime_lib_to_path from utils import copy_file, create_nc_file -from allometry.allometry_plotting import plot_allometry_dat -from math_utils.math_plotting import plot_quadratic_dat +from functional_testing.allometry.allometry_plotting import plot_allometry_dat +from functional_testing.math_utils.math_plotting import plot_quadratic_dat add_cime_lib_to_path() @@ -42,7 +42,8 @@ # Constants for this script _DEFAULT_CDL_PATH = os.path.abspath("../parameter_files/fates_params_default.cdl") _CMAKE_BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../") -_TEST_NAME = "fates_unit_tests" +_TEST_NAME = "fates_tests" +_TEST_SUB_DIR = "testing" # Dictionary with needed constants for running the executables and reading in the # output files - developers who add tests should add things here. @@ -83,7 +84,7 @@ def run_fortran_exectuables(build_dir, test_dir, test_exe, run_dir, args): """ # move executable to run directory - exe_path = os.path.join(build_dir, test_dir, test_exe) + exe_path = os.path.join(build_dir, _TEST_SUB_DIR, test_dir, test_exe) copy_file(exe_path, run_dir) # run the executable diff --git a/unit_testing/unit_test_shr/CMakeLists.txt b/testing/testing_shr/CMakeLists.txt similarity index 100% rename from unit_testing/unit_test_shr/CMakeLists.txt rename to testing/testing_shr/CMakeLists.txt diff --git a/unit_testing/unit_test_shr/FatesUnitTestIOMod.F90 b/testing/testing_shr/FatesUnitTestIOMod.F90 similarity index 100% rename from unit_testing/unit_test_shr/FatesUnitTestIOMod.F90 rename to testing/testing_shr/FatesUnitTestIOMod.F90 diff --git a/unit_testing/unit_test_shr/FatesUnitTestParamReaderMod.F90 b/testing/testing_shr/FatesUnitTestParamReaderMod.F90 similarity index 100% rename from unit_testing/unit_test_shr/FatesUnitTestParamReaderMod.F90 rename to testing/testing_shr/FatesUnitTestParamReaderMod.F90 diff --git a/testing/unit_testing/README_unit_testing b/testing/unit_testing/README_unit_testing new file mode 100644 index 0000000000..1df3d0220a --- /dev/null +++ b/testing/unit_testing/README_unit_testing @@ -0,0 +1 @@ +Nothing here yet - but we will put some tests here eventually. \ No newline at end of file diff --git a/unit_testing/utils.py b/testing/utils.py similarity index 100% rename from unit_testing/utils.py rename to testing/utils.py From b2e4194d26c68b918506240182749aa8a275d9a7 Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Mon, 6 May 2024 22:18:17 -0600 Subject: [PATCH 214/300] add grass specific agw,sap,leaf allometry --- biogeochem/FatesAllometryMod.F90 | 166 ++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 1aa1cc4525..646df53f05 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1036,6 +1036,35 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,elongf_stem, sapw_area,bsap end if end if + case(2) ! this is a 'sapwood' function specifically for grass PFT that do not produce + ! dead woody biomass. So bsap = bagw. Might remove the bsap and bdead for grass + ! in the future as there is no need to distinguish the two for grass above- and belowground biomass + + call bagw_allom(d,ipft,crowndamage,elongf_stem,bagw,dbagwdd) + call bbgw_allom(d,bagw,dbagwdd,ipft,bbgw,dbbgwdd) + bsap = bagw + bbgw + + ! replicate the crown damage code + ! Do we really need this for grass? I would think this can be helpful for + ! grazing in the future. --XLG + if(crowndamage > 1)then + call GetCrownReduction(crowndamage, crown_reduction) + bsap = elongf_stem * (bsap - (bsap * agb_frac * branch_frac * crown_reduction)) + if(present(dbsapdd))then + dbsapdd = elongf_stem * & + (dbagwdd + dbbgwdd - ((dbagwdd + dbbgwdd) * agb_frac * branch_frac * crown_reduction)) + end if + else + bsap = elongf_stem * bsap + if (present(dbsapdd))then + dbsapdd = elongf_stem * (dbagwdd + dbbgwdd) + end if + end if + + if(present(dbsapdd))then + dbsapdd = dbagwdd + dbbgwdd + end if + case DEFAULT write(fates_log(),*) 'An undefined sapwood allometry was specified: ', & prt_params%allom_smode(ipft) @@ -1228,7 +1257,7 @@ subroutine bdead_allom(bagw,bbgw,bsap,ipft,bdead,dbagwdd,dbbgwdd,dbsapdd,dbdeadd dbdeaddd = dbagwdd/agb_fraction end if - case(2,3,4) + case(2,3,4,5) bdead = bagw + bbgw - bsap if(present(dbagwdd) .and. present(dbbgwdd) .and. & @@ -1631,6 +1660,78 @@ subroutine dh2blmax_3pwr(d,h,dhdd,p1,p2,p3,slatop,dbh_maxh,c2b,blmax,dblmaxdd) end subroutine dh2blmax_3pwr + + ! ========================================================================= + + subroutine dh2blmax_3pwr_grass(d,p1,p2,p3,h,dhdd,c2b,blmax,dblmaxdd) + !------------------------------------------------------------------------ + ! + ! This function calculates the maximum leaf biomass using diameter (basal + ! diameter for grass) and plant height based on grass leaf allometry developed + ! in Gao et al. 2024 + ! + !------------------- + ! References + !------------------- + ! Gao X., Koven C., and Kueppers L. 2024. Allometric relationships and trade-offs + ! in 11 common Mediterranean-climate grasses. Ecological Applications. + ! https://esajournals.onlinelibrary.wiley.com/doi/10.1002/eap.2976 + + !------------------ + ! Input arguments + !------------------ + ! d -- Basal diameter for grass or any herbaceous plants [ cm] + ! h -- Plant height [ m] + ! dhdd -- Height derivative with dbh [ m/cm] + ! p1 -- Parameter 1 (log-intercept) [ --] + ! p2 -- Parameter 2 (log-slope associated with d) [ --] + ! p3 -- Parameter 3 (log-slope associated with h) [ --] + ! dbh_maxh -- DBH at maximum height [ cm] + ! c2b -- Carbon to biomass multiplier ~ 2 [ kg/kgC] + ! + !----------------- + ! Output arguments + !----------------- + ! blmax -- Leaf biomass [ kgC] + ! dblmaxdd -- Leaf biomass derivative [ kgC/cm] + ! + !----------------- + ! Default parameters have been updated for three FATES grass PFTs according to Gao et al. 2024 + !--------------------------------------------------------------------------------------------- + + !-----Arguments + real(r8), intent(in) :: d ! plant diameter [ cm] + real(r8), intent(in) :: h ! plant height [ m] + real(r8), intent(in) :: dhdd ! height derivative [ m/cm] + real(r8), intent(in) :: p1 ! log-intercept parameter [ -] + real(r8), intent(in) :: p2 ! log-slope associated with d [ -] + real(r8), intent(in) :: p3 ! log-slope associated with h [ -] + real(r8), intent(in) :: c2b ! carbon to biomass multiplier [kg/kgC] +! real(r8), intent(in) :: dbh_maxh ! diameter at maximum height [ cm] + real(r8), intent(out) :: blmax ! leaf biomass [ kgC] + real(r8), intent(out), optional :: dblmaxdd ! leaf biomass derivative [kgC/cm] + !----Local variables +! real(r8) :: duse + + + !----Cap diameter +! duse = min(d, dbh_maxh) + + !----Calculate leaf biomass + blmax = p1 * d**p2 * h**p3 / c2b + + !----Calculate leaf biomass derivative if needed + + if (present(dblmaxdd))then + dblmaxdd = p1 * (p2 * d**(p2 - 1.0_r8) * h**p3 + p3 * h**(p3 - 1.0_r8) * dhdd * d**p2) / c2b + end if + + return + end subroutine dh2blmax_3pwr_grass + + + + ! ========================================================================= ! Diameter to height (D2H) functions ! ========================================================================= @@ -2015,6 +2116,69 @@ end subroutine dh2bagw_3pwr ! ============================================================================ + subroutine dh2bagw_3pwr_grass(d,h,dhdd,p1,p2,p3,c2b,bagw,dbagwdd) + !--------------------------------------------------------------------------- + ! + ! This function calculates aboveground biomass (excluding leaf biomass) using + ! basal diamerer (cm) and plant height (m) as size references, specifically + ! for grass or herbaceous plants (can be used for other PFTs if supported by data) + ! + !---------------- + ! Reference + !---------------- + ! Gao X., Koven C., and Kueppers L. 2024. Allometric relationships and trade-offs in 11 + ! common Mediterranean-climate grasses. Ecological Applications. + ! https://esajournals.onlinelibrary.wiley.com/doi/10.1002/eap.2976 + ! + !---------------- + ! Input arguments + !---------------- + ! d -- Basal diameter [ cm] + ! h -- Plant height [ m] + ! dhdd -- Height derivative with diameter [ m/cm] + ! p1 -- Log-intercept [ -] + ! p2 -- Log-slope associated with d [ -] + ! p3 -- Log-slope associated with h [ -] + ! c2b -- Carbon to biomass multiplier [kg/kgC] + ! + !---------------- + ! Output variables + !---------------- + ! bagw -- Aboveground biomass [ kgC] + ! dbagwdd -- Aboveground biomass derivative [kgC/cm] + ! + !--------------------------------------------------------------------------- + + + !----Arguments + real(r8), intent(in) :: d ! plant diameter [ cm] + real(r8), intent(in) :: h ! plant height [ m] + real(r8), intent(in) :: dhdd ! height derivative w/ diameter [ m/cm] + real(r8), intent(in) :: p1 ! log-intercept [ -] + real(r8), intent(in) :: p2 ! log-slope associated with d [ -] + real(r8), intent(in) :: p3 ! log-slope associated with h [ -] + real(r8), intent(in) :: c2b ! biomass to carbon multiplier [kg/kgC] + real(r8), intent(out) :: bagw ! aboveground biomass excluding leaf [ kgC] + real(r8), intent(out) :: dbagwdd ! aboveground biomass derivative [kgC/cm] + + !----Calculate aboveground biomass + + bagw = p1 * (d**p2) * (h**p3) / c2b + + !----Compute the aboveground biomass derivative with basal diameter if needed + if (present(dbagwdd)) then + dbagwdd = p1 * (p2 * d**(p2 - 1.0_r8) * h**p3 + p3 * h**(p3 - 1.0_r8) * dhdd * d**p2) / c2b + end if + + return + end subroutine dh2bagw_3pwr_grass + + + + ! ============================================================================ + + + subroutine d2bagw_2pwr(d,p1,p2,c2b,bagw,dbagwdd) ! ========================================================================= From dce7256bbedb83cc4cd7ca330f7fff17fc45c1df Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Mon, 6 May 2024 22:18:45 -0600 Subject: [PATCH 215/300] update default allometry params for grass PFTs --- parameter_files/fates_params_default.cdl | 34 ++++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 2eaeb875fe..e6f126c526 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -983,55 +983,55 @@ data: 0.8, 0.8, 0.8, 0.8 ; fates_allom_agb1 = 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, - 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + 0.0728698, 0.06896, 0.06896, 0.06896, 0.001, 0.001, 0.003 ; fates_allom_agb2 = 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, - 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; + 0.572, 0.572, 0.572, 1.6592, 1.6592, 1.3456 ; fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; + 1.248, 1.248, 1.869 ; fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; + 0.931, -999.9, -999.9, -999.9 ; - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 1, + 1, 1 ; fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, - 0, 0, 0, 0, 0 ; + 0, 0, -0.487, -0.487, -0.259 ; fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; + 0.0004, 0.0004, 0.0012 ; fates_allom_d2bl2 = 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, - 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; + 1.3998939, 1.3, 1.3, 1.3, 1.7092, 1.7092, 1.5879 ; fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; + 0.3417, 0.3417, 0.9948 ; fates_allom_d2ca_coefficient_max = 0.2715891, 0.3693718, 1.0787259, 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; + 0.0408, 0.0408, 0.0862 ; fates_allom_d2ca_coefficient_min = 0.2715891, 0.3693718, 1.0787259, 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; + 0.6568464, 0.0408, 0.0862 ; fates_allom_d2h1 = 78.4087704, 306.842667, 106.8745821, 104.3586841, - 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; + 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.1812, 0.1812, 0.3353 ; fates_allom_d2h2 = 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, - 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; + 0.9734088, 0.37, 0.37, 0.37, 0.6384, 0.6384, 0.4235 ; fates_allom_d2h3 = 47.6666164, 196.6865691, 93.9790461, 160.6835089, 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, - 0.35, 0.35, 0.35 ; + 10, 10, 10 ; fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1049,9 +1049,9 @@ data: fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 3, 3, 3 ; - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.67, 0.67, 1.41 ; fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; From 5ee5750d93041f2429ccec32a6bd849213012450 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 7 May 2024 09:16:21 -0600 Subject: [PATCH 216/300] move pfunit test to new testing dir --- CMakeLists.txt | 79 ------------------- fire/test/CMakeLists.txt | 1 - radiation/CMakeLists.txt | 1 + testing/CMakeLists.txt | 9 ++- testing/run_fates_tests.py | 25 +++++- testing/unit_testing/README_unit_testing | 1 - .../fire_weather_test/CMakeLists.txt | 0 .../fire_weather_test/test_FireWeather.pf | 0 8 files changed, 31 insertions(+), 85 deletions(-) delete mode 100644 fire/test/CMakeLists.txt delete mode 100644 testing/unit_testing/README_unit_testing rename {fire/test => testing/unit_testing}/fire_weather_test/CMakeLists.txt (100%) rename {fire/test => testing/unit_testing}/fire_weather_test/test_FireWeather.pf (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 063e5ce4f6..9760a39c1d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,3 @@ -<<<<<<< HEAD cmake_minimum_required(VERSION 3.4) list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) @@ -89,81 +88,3 @@ link_directories(${CMAKE_CURRENT_BINARY_DIR}) # Add the main test directory add_subdirectory(${HLM_ROOT}/src/fates/testing) -||||||| e2621983 -======= -# This file helps to build unit test programs to test FATES, but is not used in -# production runs - -cmake_minimum_required(VERSION 3.4) - -list(APPEND CMAKE_MODULE_PATH ${CIME_CMAKE_MODULE_DIRECTORY}) -include(CIME_initial_setup) - -project(FATES_tests Fortran C) - -include(CIME_utils) - -set(HLM_ROOT "../../") - -# Add source directories from other share code (csm_share, etc.) -add_subdirectory(${HLM_ROOT}/share/src csm_share) -add_subdirectory(${HLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) - -# Add FATES source directories -add_subdirectory(${HLM_ROOT}/src/fates/main fates_main) -add_subdirectory(${HLM_ROOT}/src/fates/biogeochem fates_biogeochem) -add_subdirectory(${HLM_ROOT}/src/fates/fire fates_fire) -add_subdirectory(${HLM_ROOT}/src/fates/radiation fates_radiation) - -# Remove shr_mpi_mod from share_sources. -# This is needed because we want to use the mock shr_mpi_mod in place of the real one -# -# TODO: this should be moved into a general-purpose function in Sourcelist_utils. -# Then this block of code could be replaced with a single call, like: -# remove_source_file(${share_sources} "shr_mpi_mod.F90") -foreach (sourcefile ${share_sources}) - string(REGEX MATCH "shr_mpi_mod.F90" match_found ${sourcefile}) - if(match_found) - list(REMOVE_ITEM share_sources ${sourcefile}) - endif() -endforeach() - -# Remove shr_cal_mod from share_sources. -# -# shr_cal_mod depends on ESMF (or the lightweight esmf wrf timemgr, at -# least). Since CTSM doesn't currently use shr_cal_mod, we're avoiding -# the extra overhead of including esmf_wrf_timemgr sources in this -# build. -# -# TODO: like above, this should be moved into a general-purpose function -# in Sourcelist_utils. Then this block of code could be replaced with a -# single call, like: remove_source_file(${share_sources} -# "shr_cal_mod.F90") -foreach (sourcefile ${share_sources}) - string(REGEX MATCH "shr_cal_mod.F90" match_found ${sourcefile}) - if(match_found) - list(REMOVE_ITEM share_sources ${sourcefile}) - endif() -endforeach() - -# Build libraries containing stuff needed for the unit tests. -# Eventually, these add_library calls should probably be distributed into the correct location, rather than being in this top-level CMakeLists.txt file. -add_library(csm_share ${share_sources}) -declare_generated_dependencies(csm_share "${share_genf90_sources}") -add_library(fates ${fates_sources}) -add_dependencies(fates csm_share) - -# We need to look for header files here, in order to pick up shr_assert.h -include_directories(${HLM_ROOT}/share/include) - -# Tell cmake to look for libraries & mod files here, because this is where we built libraries -include_directories(${CMAKE_CURRENT_BINARY_DIR}) -link_directories(${CMAKE_CURRENT_BINARY_DIR}) - -# Add the test directories -# Note: it's possible that these could be added by each source directory that -# has tests in it. However, it appears that the order needs to be done -# carefully: for example, include_directories and link_directories needs to be -# done before adding the tests themselves. -add_subdirectory(${HLM_ROOT}/src/fates/fire/test fates_fire_test) ->>>>>>> main diff --git a/fire/test/CMakeLists.txt b/fire/test/CMakeLists.txt deleted file mode 100644 index 4dcfa244d4..0000000000 --- a/fire/test/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(fire_weather_test) \ No newline at end of file diff --git a/radiation/CMakeLists.txt b/radiation/CMakeLists.txt index abd2b99a94..74d625b12d 100644 --- a/radiation/CMakeLists.txt +++ b/radiation/CMakeLists.txt @@ -1,6 +1,7 @@ # This file is required for unit testing, but is not used for production runs list(APPEND fates_sources TwoStreamMLPEMod.F90 + FatesRadiationMemMod.F90 ) sourcelist_to_parent(fates_sources) diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index ac3ac02d18..d59509c73d 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -1,3 +1,8 @@ # This is where you add specific test directories -add_subdirectory(functional_testing/allometry fates_allom_test) -add_subdirectory(functional_testing/math_utils fates_math_test) \ No newline at end of file + +## Functional tests +add_subdirectory(functional_testing/allometry fates_allom_ftest) +add_subdirectory(functional_testing/math_utils fates_math_ftest) + +## Unit tests +add_subdirectory(unit_testing/fire_weather_test fates_fire_weather_utest) \ No newline at end of file diff --git a/testing/run_fates_tests.py b/testing/run_fates_tests.py index 7a6b8cc296..6816e034ad 100755 --- a/testing/run_fates_tests.py +++ b/testing/run_fates_tests.py @@ -53,7 +53,7 @@ # command-line argument list _ALL_TESTS_DICT = { "allometry": { - "test_dir": "fates_allom_test", + "test_dir": "fates_allom_ftest", "test_exe": "FATES_allom_exe", "out_file": "allometry_out.nc", "has_unit_test": False, @@ -62,13 +62,22 @@ "plotting_function": plot_allometry_dat, }, "quadratic": { - "test_dir": "fates_math_test", + "test_dir": "fates_math_ftest", "test_exe": "FATES_math_exe", "out_file": "quad_out.nc", "has_unit_test": False, "use_param_file": False, "other_args": [], "plotting_function": plot_quadratic_dat, + }, + "fire_weather":{ + "test_dir": "fates_fire_weather_utest", + "test_exe": None, + "out_file": None, + "has_unit_test": True, + "use_param_file": False, + "other_args": [], + "plotting_function": None, } } @@ -197,6 +206,17 @@ def run_tests(clean, verbose_make, build_tests, run_executables, build_dir, run_ # run run_fortran_exectuables(build_dir_path, attributes['test_dir'], attributes['test_exe'], run_dir_path, args) + + # run unit tests + for test, attributes in dict(filter(lambda pair: pair[1]['has_unit_test'], + test_dict.items())).items(): + print(f"Running unit tests for {test}.") + + test_dir = os.path.join(build_dir_path, _TEST_SUB_DIR, attributes['test_dir']) + ctest_command = ["ctest", "--output-on-failure"] + output = run_cmd_no_fail(" ".join(ctest_command), from_dir=test_dir, + combine_output=True) + print(output) # plot output for relevant tests for test, attributes in dict(filter(lambda pair: pair[1]['plotting_function'] is not None, @@ -204,6 +224,7 @@ def run_tests(clean, verbose_make, build_tests, run_executables, build_dir, run_ attributes['plotting_function'](run_dir_path, attributes['out_file'], save_figs, os.path.join(run_dir_path, 'plots', test)) + # show plots plt.show() def out_file_exists(run_dir, out_file): diff --git a/testing/unit_testing/README_unit_testing b/testing/unit_testing/README_unit_testing deleted file mode 100644 index 1df3d0220a..0000000000 --- a/testing/unit_testing/README_unit_testing +++ /dev/null @@ -1 +0,0 @@ -Nothing here yet - but we will put some tests here eventually. \ No newline at end of file diff --git a/fire/test/fire_weather_test/CMakeLists.txt b/testing/unit_testing/fire_weather_test/CMakeLists.txt similarity index 100% rename from fire/test/fire_weather_test/CMakeLists.txt rename to testing/unit_testing/fire_weather_test/CMakeLists.txt diff --git a/fire/test/fire_weather_test/test_FireWeather.pf b/testing/unit_testing/fire_weather_test/test_FireWeather.pf similarity index 100% rename from fire/test/fire_weather_test/test_FireWeather.pf rename to testing/unit_testing/fire_weather_test/test_FireWeather.pf From 797798df6a792b9b788d6b53428b066c86a11613 Mon Sep 17 00:00:00 2001 From: adrifoster Date: Tue, 7 May 2024 09:17:47 -0600 Subject: [PATCH 217/300] small pylint fix --- testing/run_fates_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/run_fates_tests.py b/testing/run_fates_tests.py index 6816e034ad..ea2cf5b0b1 100755 --- a/testing/run_fates_tests.py +++ b/testing/run_fates_tests.py @@ -432,7 +432,7 @@ def check_arg_validity(args): # make sure build directory exists if args.skip_build: if args.verbose_make: - raise argparse.ArgumentError(None, f"Can't run verbose make and skip build.\n" + raise argparse.ArgumentError(None, "Can't run verbose make and skip build.\n" "Re-run script without --skip-build") check_build_dir(args.build_dir, args.test_dict) From 0b415cfb1d4eceb7a1e19946f6c96eab2ef379e1 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 7 May 2024 14:27:37 -0700 Subject: [PATCH 218/300] minor typo and renaming corrections --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- main/EDInitMod.F90 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 268b443a4f..b9d60ed926 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1510,7 +1510,7 @@ subroutine spawn_patches( currentSite, bc_in) write(fates_log(),*) nocomp_pft_area_vector write(fates_log(),*) '-----' write(fates_log(),*) buffer_patch%area, buffer_patch%land_use_label, buffer_patch%nocomp_pft_label - write(fates_log(+),*) sum(nocomp_pft_area_vector(:)), sum(nocomp_pft_area_vector_filled(:)), buffer_patch%area + write(fates_log(),*) sum(nocomp_pft_area_vector(:)), sum(nocomp_pft_area_vector_filled(:)), buffer_patch%area currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) write(fates_log(),*) currentPatch%area, currentPatch%land_use_label, currentPatch%nocomp_pft_label diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index b8862705a7..1c04deaef8 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -623,7 +623,7 @@ subroutine init_patches( nsites, sites, bc_in) use FatesPlantHydraulicsMod, only : updateSizeDepRhizHydProps use FatesInventoryInitMod, only : initialize_sites_by_inventory - use FatesLandUseChangeMod, only : get_luh_statedata + use FatesLandUseChangeMod, only : GetLUHStatedata ! ! !ARGUMENTS @@ -720,7 +720,7 @@ subroutine init_patches( nsites, sites, bc_in) ! This could be updated in the future to allow a variable number of ! categories based on which states are zero n_active_landuse_cats = n_landuse_cats - call get_luh_statedata(bc_in(s), state_vector) + call GetLUHStatedata(bc_in(s), state_vector) ! if the land use state vector is greater than the minimum value, set landuse_vector_gt_min flag to true ! otherwise set to false. From 153b0bda9c96f18e8d2a93887a082bc7a31b574b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 7 May 2024 16:08:42 -0700 Subject: [PATCH 219/300] add landuse mode checks for setting site_secondarylands... --- biogeochem/EDLoggingMortalityMod.F90 | 15 ++++++++++----- biogeochem/EDPatchDynamicsMod.F90 | 9 ++++++--- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 4708c31c21..1b1200037e 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -54,6 +54,7 @@ module EDLoggingMortalityMod use FatesInterfaceTypesMod , only : hlm_num_lu_harvest_cats use FatesInterfaceTypesMod , only : hlm_use_logging use FatesInterfaceTypesMod , only : hlm_use_planthydro + use FatesInterfaceTypesMod , only : hlm_use_luh use FatesConstantsMod , only : itrue,ifalse use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : fates_log @@ -249,17 +250,21 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, ! todo: eventually set up distinct harvest practices, each with a set of input paramaeters ! todo: implement harvested carbon inputs - call GetLUHStatedata(bc_in, state_vector) - site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. currentSite%min_allowed_landuse_fraction) & - .and. (.not. currentSite%landuse_vector_gt_min(secondaryland)) - ! The transition_landuse_from_off_to_on is for handling the special case of the first timestep after leaving potential ! vegetation mode. In this case, all prior historical land-use, including harvest, needs to be applied on that first day. ! So logging rates on that day are what is required to deforest exactly the amount of primary lands that will give the ! amount of secondary lands dictated by the land use state vector for that year, rather than whatever the continuous ! logging rate for that year is supposed to be according to the land use transition matrix. if (.not. currentSite%transition_landuse_from_off_to_on) then - + + ! Check if the secondaryland exceeds the minimum if in landuse mode + site_secondaryland_first_exceeding_min = .false. + if (hlm_use_luh .eq. itrue) then + call GetLUHStatedata(bc_in, state_vector) + site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. currentSite%min_allowed_landuse_fraction) & + .and. (.not. currentSite%landuse_vector_gt_min(secondaryland)) + end if + ! if the total intended area of secondary lands are less than what we can consider without having too-small patches, ! or if that was the case until just now, then there is special logic if (site_secondaryland_first_exceeding_min) then diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index b9d60ed926..60f5927541 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -317,9 +317,12 @@ subroutine disturbance_rates( site_in, bc_in) end do ! get some info needed to determine whether or not to apply land use change - call GetLUHStatedata(bc_in, state_vector) - site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. site_in%min_allowed_landuse_fraction) & - .and. (.not. site_in%landuse_vector_gt_min(secondaryland)) + site_secondaryland_first_exceeding_min = .false. + if (hlm_use_luh .eq. itrue) then + call GetLUHStatedata(bc_in, state_vector) + site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. site_in%min_allowed_landuse_fraction) & + .and. (.not. site_in%landuse_vector_gt_min(secondaryland)) + end if currentPatch => site_in%oldest_patch do while (associated(currentPatch)) From 25d3d525d43a489012f09e079bf7178f7e4f15b9 Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Tue, 7 May 2024 17:48:06 -0600 Subject: [PATCH 220/300] edit generic allom subrountine for grass PFT --- biogeochem/FatesAllometryMod.F90 | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 646df53f05..9e3d196054 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -412,6 +412,9 @@ subroutine bagw_allom(d,ipft,crowndamage, elongf_stem, bagw,dbagwdd) case (4) ! 3par_pwr call h_allom(d,ipft,h,dhdd) call dh2bagw_3pwr(d,h,dhdd,p1,p2,p3,wood_density,c2b,bagw,dbagwdd) + case (5) ! 3par_pwr_grass + call h_allom(d,ipft,h,dhdd) + call dh2bagw_3pwr_grass(d,h,dhdd,p1,p2,p3,c2b,bagw,dbagwdd) case DEFAULT write(fates_log(),*) 'An undefined AGB allometry was specified: ',allom_amode write(fates_log(),*) 'Aborting' @@ -471,6 +474,9 @@ subroutine blmax_allom(d,ipft,blmax,dblmaxdd) case(4) ! dh2blmax_3pwr call h_allom(d,ipft,h,dhdd) call dh2blmax_3pwr(d,h,dhdd,p1,p2,p3,slatop,dbh_maxh,c2b,blmax,dblmaxdd) + case (5) ! dh2blmax_3pwr_grass + call h_allom(d,ipft,h,dhdd) + call dh2blmax_3pwr_grass(d,h,dhdd,p1,p2,p3,c2b,blmax,dblmaxdd) case DEFAULT write(fates_log(),*) 'An undefined leaf allometry was specified: ', & allom_lmode @@ -1663,7 +1669,7 @@ end subroutine dh2blmax_3pwr ! ========================================================================= - subroutine dh2blmax_3pwr_grass(d,p1,p2,p3,h,dhdd,c2b,blmax,dblmaxdd) + subroutine dh2blmax_3pwr_grass(d,h,dhdd,p1,p2,p3,c2b,blmax,dblmaxdd) !------------------------------------------------------------------------ ! ! This function calculates the maximum leaf biomass using diameter (basal From 838de5643c134d3bd5f0c5050b9e87ea8c14089f Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Tue, 7 May 2024 17:49:31 -0600 Subject: [PATCH 221/300] update default allom mode for grass PFT in param file --- parameter_files/fates_params_default.cdl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index e6f126c526..90f931356a 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -997,7 +997,7 @@ data: fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 1, 1, 1 ; - fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; + fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 5, 5, 5 ; fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, 0, 0, -0.487, -0.487, -0.259 ; @@ -1058,12 +1058,12 @@ data: fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 ; + fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 5, 5 ; fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2 ; fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; From e36df6621e51b45c5c7a983b782ede14df5ad42b Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 7 May 2024 22:52:56 -0700 Subject: [PATCH 222/300] fix missing end subroutine --- biogeochem/EDPatchDynamicsMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index c46540170f..1b16d30e0c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -3951,5 +3951,6 @@ subroutine CopyPatchMeansTimers(dp, rp) enddo end if + end subroutine CopyPatchMeansTimers end module EDPatchDynamicsMod From e622877a3fd537623d4f3328a8cbe3d01df6d123 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 8 May 2024 11:04:43 -0400 Subject: [PATCH 223/300] Added watt to mole conversion and fixed the photon to electron conversion --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 482372470b..ffbac10bdd 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1302,9 +1302,11 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in real(r8),parameter :: fnps = 0.15_r8 ! term accounting that two photons are needed to fully transport a single - ! electron to the thylakoid-membrane-bound NADP reductase (see Farquhar 1980) - ! ie only half the energy from a photon enters photosystem 2 - real(r8), parameter :: photon_to_e_nadp = 0.5_r8 + ! electron in photosystem 2 + real(r8), parameter :: photon_to_e = 0.5_r8 + + ! Unit conversion of w/m2 to umol photons m-2 s-1 + real(r8), parameter :: wm2_to_umolm2s = 4.6_r8 ! For plants with no leaves, a miniscule amount of conductance ! can happen through the stems, at a partial rate of cuticular conductance @@ -1369,7 +1371,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in do sunsha = 1,2 ! Electron transport rate for C3 plants. - ! Convert par from W/m2 to umol photons/m**2/s using the factor 4.6 + ! Convert par from W/m2 to umol photons/m**2/s ! Convert from units of par absorbed per unit ground area to par ! absorbed per unit leaf area. @@ -1377,7 +1379,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in if(( laisun_lsl * canopy_area_lsl) > min_la_to_solve)then qabs = parsun_lsl / (laisun_lsl * canopy_area_lsl ) - qabs = qabs * photon_to_e_nadp * (1._r8 - fnps) * 4.6_r8 + qabs = qabs * photon_to_e * (1._r8 - fnps) * wm2_to_umolm2s else qabs = 0.0_r8 @@ -1387,7 +1389,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in if( (parsha_lsl>nearzero) .and. (laisha_lsl * canopy_area_lsl) > min_la_to_solve ) then qabs = parsha_lsl / (laisha_lsl * canopy_area_lsl) - qabs = qabs * photon_to_e_nadp * (1._r8 - fnps) * 4.6_r8 + qabs = qabs * photon_to_e * (1._r8 - fnps) * wm2_to_umolm2s else ! The radiative transfer schemes are imperfect ! they can sometimes generate negative values here @@ -1443,14 +1445,14 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in if(sunsha == 1)then !sunlit !guard against /0's in the night. if((laisun_lsl * canopy_area_lsl) > 0.0000000001_r8) then - aj = quant_eff(c3c4_path_index) * parsun_lsl * 4.6_r8 + aj = quant_eff(c3c4_path_index) * parsun_lsl * wm2_to_umolm2s !convert from per cohort to per m2 of leaf) aj = aj / (laisun_lsl * canopy_area_lsl) else aj = 0._r8 end if else - aj = quant_eff(c3c4_path_index) * parsha_lsl * 4.6_r8 + aj = quant_eff(c3c4_path_index) * parsha_lsl * wm2_to_umolm2s aj = aj / (laisha_lsl * canopy_area_lsl) end if From 19e0b167c78cdef8fe8366fad05962e1fe65fdda Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 8 May 2024 09:39:39 -0700 Subject: [PATCH 224/300] remove target and fix missing indexing definition --- biogeochem/EDPatchDynamicsMod.F90 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 1b16d30e0c..54dee697fe 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1621,8 +1621,8 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) ! ! !ARGUMENTS: type(ed_site_type),intent(inout) :: currentSite - type(fates_patch_type) , intent(inout), target :: currentPatch ! Donor Patch - type(fates_patch_type) , intent(inout), target :: new_patch ! New Patch + type(fates_patch_type) , intent(inout), pointer :: currentPatch ! Donor Patch + type(fates_patch_type) , intent(inout), pointer :: new_patch ! New Patch real(r8), intent(in) :: fraction_to_keep ! fraction of currentPatch to keep, the rest goes to newpatch ! ! !LOCAL VARIABLES: @@ -3937,6 +3937,9 @@ subroutine CopyPatchMeansTimers(dp, rp) type (fates_patch_type) , pointer :: dp ! Donor Patch type (fates_patch_type) , target, intent(inout) :: rp ! Recipient Patch + ! LOCAL: + integer :: ipft ! pft index + call rp%tveg24%CopyFromDonor(dp%tveg24) call rp%tveg_lpa%CopyFromDonor(dp%tveg_lpa) call rp%tveg_longterm%CopyFromDonor(dp%tveg_longterm) @@ -3945,9 +3948,9 @@ subroutine CopyPatchMeansTimers(dp, rp) call rp%seedling_layer_par24%CopyFromDonor(dp%seedling_layer_par24) call rp%sdlng_mort_par%CopyFromDonor(dp%sdlng_mort_par) call rp%sdlng2sap_par%CopyFromDonor(dp%sdlng2sap_par) - do pft = 1,numpft - call rp%sdlng_emerg_smp(pft)%p%CopyFromDonor(dp%sdlng_emerg_smp(pft)%p) - call rp%sdlng_mdd(pft)%p%CopyFromDonor(dp%sdlng_mdd(pft)%p) + do ipft = 1,numpft + call rp%sdlng_emerg_smp(ipft)%p%CopyFromDonor(dp%sdlng_emerg_smp(ipft)%p) + call rp%sdlng_mdd(ipft)%p%CopyFromDonor(dp%sdlng_mdd(ipft)%p) enddo end if From 69558bc5175a70d7261cb080186b3f291c917462 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 8 May 2024 10:20:28 -0700 Subject: [PATCH 225/300] fix patch name typo --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 54dee697fe..028c69cf9a 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1411,7 +1411,7 @@ subroutine spawn_patches( currentSite, bc_in) buffer_patch%tallest => null() buffer_patch%shortest => null() - call CopyPatchMeansTimers(buffer_patch, currentPatch) + call CopyPatchMeansTimers(buffer_patch, copyPatch) ! make a note that this buffer patch has not been put into the linked list buffer_patch_in_linked_list = .false. From affe544a9070941c23d9ea7a7fb699032926afc4 Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Wed, 8 May 2024 13:34:16 -0600 Subject: [PATCH 226/300] bug fix --- biogeochem/FatesAllometryMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 9e3d196054..cfbc28674c 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1047,7 +1047,7 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,elongf_stem, sapw_area,bsap ! in the future as there is no need to distinguish the two for grass above- and belowground biomass call bagw_allom(d,ipft,crowndamage,elongf_stem,bagw,dbagwdd) - call bbgw_allom(d,bagw,dbagwdd,ipft,bbgw,dbbgwdd) + call bbgw_allom(d,ipft, elongf_stem,bbgw,dbbgwdd) bsap = bagw + bbgw ! replicate the crown damage code @@ -2165,7 +2165,7 @@ subroutine dh2bagw_3pwr_grass(d,h,dhdd,p1,p2,p3,c2b,bagw,dbagwdd) real(r8), intent(in) :: p3 ! log-slope associated with h [ -] real(r8), intent(in) :: c2b ! biomass to carbon multiplier [kg/kgC] real(r8), intent(out) :: bagw ! aboveground biomass excluding leaf [ kgC] - real(r8), intent(out) :: dbagwdd ! aboveground biomass derivative [kgC/cm] + real(r8), intent(out),optional :: dbagwdd ! aboveground biomass derivative [kgC/cm] !----Calculate aboveground biomass From c090218c60416b9cc2a99fbd91925eeaa1691aaa Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 8 May 2024 13:48:04 -0700 Subject: [PATCH 227/300] fix incorrect argument order for new subroutine --- biogeochem/EDPatchDynamicsMod.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 028c69cf9a..f2621a2bba 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -764,7 +764,7 @@ subroutine spawn_patches( currentSite, bc_in) currentPatch%burnt_frac_litter(:) = 0._r8 end if - call CopyPatchMeansTimers(newPatch, currentPatch) + call CopyPatchMeansTimers(currentPatch, newPatch) call TransLitterNewPatch( currentSite, currentPatch, newPatch, patch_site_areadis) @@ -1411,7 +1411,7 @@ subroutine spawn_patches( currentSite, bc_in) buffer_patch%tallest => null() buffer_patch%shortest => null() - call CopyPatchMeansTimers(buffer_patch, copyPatch) + call CopyPatchMeansTimers(copyPatch, buffer_patch) ! make a note that this buffer patch has not been put into the linked list buffer_patch_in_linked_list = .false. @@ -1654,7 +1654,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) new_patch%tallest => null() new_patch%shortest => null() - call CopyPatchMeansTimers(new_patch, currentPatch) + call CopyPatchMeansTimers(currentPatch, new_patch) call TransLitterNewPatch( currentSite, currentPatch, new_patch, currentPatch%area * (1.-fraction_to_keep)) @@ -3934,8 +3934,8 @@ subroutine CopyPatchMeansTimers(dp, rp) ! -------------------------------------------------------------------------- ! ! !ARGUMENTS: - type (fates_patch_type) , pointer :: dp ! Donor Patch - type (fates_patch_type) , target, intent(inout) :: rp ! Recipient Patch + type (fates_patch_type), intent(in) :: dp ! Donor Patch + type (fates_patch_type), intent(inout) :: rp ! Recipient Patch ! LOCAL: integer :: ipft ! pft index From 3594045428ada92e68c59a428a8ef3fc288bd284 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 8 May 2024 14:46:44 -0700 Subject: [PATCH 228/300] fix procedure declaration --- main/EDTypesMod.F90 | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 18498230f6..5644fb8295 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -4,6 +4,7 @@ module EDTypesMod use FatesGlobals, only : endrun => fates_endrun use FatesConstantsMod, only : ifalse use FatesConstantsMod, only : itrue + use FatesConstantsMod, only : nocomp_bareground_land use FatesGlobals, only : fates_log use FatesHydraulicsMemMod, only : ed_cohort_hydr_type use FatesHydraulicsMemMod, only : ed_site_hydr_type @@ -440,7 +441,7 @@ module EDTypesMod contains - public :: get_current_landuse_statevector + procedure, public :: get_current_landuse_statevector end type ed_site_type @@ -545,8 +546,6 @@ function get_current_landuse_statevector(this) result(current_state_vector) currentPatch => currentPatch%younger end do - end subroutine get_current_landuse_statevector - - + end function get_current_landuse_statevector end module EDTypesMod From 805d302143a1c4e78194e07c6751ad7c1d2d5023 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 9 May 2024 12:20:36 -0400 Subject: [PATCH 229/300] Added note on quadratic solves for conductance --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 23 ++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index ffbac10bdd..f583e6cbff 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1495,6 +1495,29 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! With an <= 0, then gs_mol = stomatal_intercept_btran leaf_co2_ppress = can_co2_ppress- h2o_co2_bl_diffuse_ratio/gb_mol * a_gs * can_press leaf_co2_ppress = max(leaf_co2_ppress,1.e-06_r8) + + ! A note about the use of the quadratic equations for calculating stomatal conductance + ! ------------------------------------------------------------------------------------ + ! These two following models calculate the conductance between the intercellular leaf + ! space and the leaf surface, not the canopy air space. Transport between the leaf + ! surface and the canopy air space is governed by the leaf boundary layer conductance. + ! However, we need to estimate the properties at the surface of the leaf to solve for + ! the stomatal conductance. We do this by using Fick's law (gradient resistance + ! approximation of diffusion). + ! + ! e_s = (e_i g_s + e_c g_b)/(g_b + g_s) + ! + ! The leaf surface humidity (e_s) then becomes an expression of canopy humidity (e_c), + ! intercellular humidity (e_i), boundary layer conductance (g_b) (these are known) + ! and stomatal conductance (g_s) (this is still unknown). This expression is + ! substituted into the stomatal conductance equation. The resulting form of these + ! equations becomes a quadratic. + ! + ! For a detailed explanation, see the FATES technical note, section + ! "1.11 Stomatal Conductance" + ! + ! ------------------------------------------------------------------------------------ + if ( stomatal_model == medlyn_model ) then !stomatal conductance calculated from Medlyn et al. (2011), the numerical & From dc3198b7a58053557b1596953e0d1b08b4b7f6f6 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 9 May 2024 12:23:19 -0400 Subject: [PATCH 230/300] Updated text about quadratic solvers --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index f583e6cbff..722e25e275 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1503,11 +1503,13 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! surface and the canopy air space is governed by the leaf boundary layer conductance. ! However, we need to estimate the properties at the surface of the leaf to solve for ! the stomatal conductance. We do this by using Fick's law (gradient resistance - ! approximation of diffusion). + ! approximation of diffusion) to estimate the flux of water vapor across the + ! leaf boundary layer, and balancing that with the flux across the stomata. It + ! results in the following equation for leaf surface humidity: ! ! e_s = (e_i g_s + e_c g_b)/(g_b + g_s) ! - ! The leaf surface humidity (e_s) then becomes an expression of canopy humidity (e_c), + ! The leaf surface humidity (e_s) becomes an expression of canopy humidity (e_c), ! intercellular humidity (e_i), boundary layer conductance (g_b) (these are known) ! and stomatal conductance (g_s) (this is still unknown). This expression is ! substituted into the stomatal conductance equation. The resulting form of these From d01e236759ed5dc55984ceaf62420e240293b7cf Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Thu, 9 May 2024 12:17:55 -0600 Subject: [PATCH 231/300] crown area allometry bug fix --- biogeochem/FatesAllometryMod.F90 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index cfbc28674c..c712e8b4c6 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -547,6 +547,10 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) call carea_3pwr(dbh_eff,height,ipft,dbh_maxh, site_spread,d2bl_p2, & d2bl_ediff, d2ca_min,d2ca_max,crowndamage, c_area, do_inverse) capped_allom = .true. + case(5) + call carea_2pwr(dbh,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & + crowndamage, c_area, do_inverse) + capped_allom = .false. case DEFAULT write(fates_log(),*) 'An undefined leaf allometry was specified: ', & allom_lmode From 589c97297aa2b2c587c7eedf9a004eee70125e65 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 9 May 2024 15:08:11 -0400 Subject: [PATCH 232/300] updated comment on intercellular e_i --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 722e25e275..4f3df22449 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -1510,10 +1510,10 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! e_s = (e_i g_s + e_c g_b)/(g_b + g_s) ! ! The leaf surface humidity (e_s) becomes an expression of canopy humidity (e_c), - ! intercellular humidity (e_i), boundary layer conductance (g_b) (these are known) - ! and stomatal conductance (g_s) (this is still unknown). This expression is - ! substituted into the stomatal conductance equation. The resulting form of these - ! equations becomes a quadratic. + ! intercellular humidity (e_i, which is the saturation humidity at leaf temperature), + ! boundary layer conductance (g_b) (these are all known) and stomatal conductance + ! (g_s) (this is still unknown). This expression is substituted into the stomatal + ! conductance equation. The resulting form of these equations becomes a quadratic. ! ! For a detailed explanation, see the FATES technical note, section ! "1.11 Stomatal Conductance" From 8a7c384d0e53e36e30e17e43a5e072e320aeffcf Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Thu, 9 May 2024 21:39:50 -0600 Subject: [PATCH 233/300] cap leaf and crown area allometry --- biogeochem/FatesAllometryMod.F90 | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index c712e8b4c6..e908bfd86e 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -476,7 +476,7 @@ subroutine blmax_allom(d,ipft,blmax,dblmaxdd) call dh2blmax_3pwr(d,h,dhdd,p1,p2,p3,slatop,dbh_maxh,c2b,blmax,dblmaxdd) case (5) ! dh2blmax_3pwr_grass call h_allom(d,ipft,h,dhdd) - call dh2blmax_3pwr_grass(d,h,dhdd,p1,p2,p3,c2b,blmax,dblmaxdd) + call dh2blmax_3pwr_grass(d,h,dhdd,p1,p2,p3,dbh_maxh,c2b,blmax,dblmaxdd) case DEFAULT write(fates_log(),*) 'An undefined leaf allometry was specified: ', & allom_lmode @@ -548,9 +548,10 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) d2bl_ediff, d2ca_min,d2ca_max,crowndamage, c_area, do_inverse) capped_allom = .true. case(5) - call carea_2pwr(dbh,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & + dbh_eff = min(dbh,dbh_maxh) + call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & crowndamage, c_area, do_inverse) - capped_allom = .false. + capped_allom = .true. case DEFAULT write(fates_log(),*) 'An undefined leaf allometry was specified: ', & allom_lmode @@ -1673,7 +1674,7 @@ end subroutine dh2blmax_3pwr ! ========================================================================= - subroutine dh2blmax_3pwr_grass(d,h,dhdd,p1,p2,p3,c2b,blmax,dblmaxdd) + subroutine dh2blmax_3pwr_grass(d,h,dhdd,p1,p2,p3,dbh_maxh,c2b,blmax,dblmaxdd) !------------------------------------------------------------------------ ! ! This function calculates the maximum leaf biomass using diameter (basal @@ -1717,23 +1718,27 @@ subroutine dh2blmax_3pwr_grass(d,h,dhdd,p1,p2,p3,c2b,blmax,dblmaxdd) real(r8), intent(in) :: p2 ! log-slope associated with d [ -] real(r8), intent(in) :: p3 ! log-slope associated with h [ -] real(r8), intent(in) :: c2b ! carbon to biomass multiplier [kg/kgC] -! real(r8), intent(in) :: dbh_maxh ! diameter at maximum height [ cm] + real(r8), intent(in) :: dbh_maxh ! diameter at maximum height [ cm] real(r8), intent(out) :: blmax ! leaf biomass [ kgC] real(r8), intent(out), optional :: dblmaxdd ! leaf biomass derivative [kgC/cm] !----Local variables -! real(r8) :: duse + real(r8) :: duse !----Cap diameter -! duse = min(d, dbh_maxh) + duse = min(d, dbh_maxh) !----Calculate leaf biomass - blmax = p1 * d**p2 * h**p3 / c2b + blmax = p1 * duse**p2 * h**p3 / c2b !----Calculate leaf biomass derivative if needed if (present(dblmaxdd))then - dblmaxdd = p1 * (p2 * d**(p2 - 1.0_r8) * h**p3 + p3 * h**(p3 - 1.0_r8) * dhdd * d**p2) / c2b + if(d .ge. dbh_maxh)then + dblmaxdd = 0._r8 + else + dblmaxdd = p1 * (p2 * duse**(p2 - 1.0_r8) * h**p3 + p3 * h**(p3 - 1.0_r8) * dhdd * duse**p2) / c2b + end if end if return From 2951856f7818dba89bec9d8f5771f69962b7f5ea Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Thu, 9 May 2024 21:46:57 -0600 Subject: [PATCH 234/300] update dbh_maxheight for c3 and c4 grass --- parameter_files/fates_params_default.cdl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 90f931356a..f231d7f314 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1031,7 +1031,7 @@ data: 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, - 10, 10, 10 ; + 20, 20, 30 ; fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; From e1fb8190fd288f8e0b611077b408a61ea221b360 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 10 May 2024 11:01:24 -0400 Subject: [PATCH 235/300] removing dependency on small nclmax --- biogeochem/EDCanopyStructureMod.F90 | 174 +++++---------------- biogeochem/EDPatchDynamicsMod.F90 | 1 - biogeochem/EDPhysiologyMod.F90 | 2 +- biogeochem/FatesAllometryMod.F90 | 5 +- biogeochem/FatesCohortMod.F90 | 3 +- biogeochem/FatesPatchMod.F90 | 50 +++--- biogeophys/FatesPlantRespPhotosynthMod.F90 | 13 +- main/EDParamsMod.F90 | 3 +- main/FatesRestartInterfaceMod.F90 | 2 +- radiation/FatesNormanRadMod.F90 | 2 +- radiation/FatesTwoStreamUtilsMod.F90 | 3 - 11 files changed, 87 insertions(+), 171 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 3fbd7b78bd..b38c371c18 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -85,8 +85,6 @@ module EDCanopyStructureMod real(r8), parameter :: similar_height_tol = 1.0E-3_r8 ! I think trees that differ by 1mm ! can be roughly considered the same right? - logical, parameter :: preserve_b4b = .true. - ! 10/30/09: Created by Rosie Fisher ! 2017/2018: Modifications and updates by Ryan Knox ! ============================================================================ @@ -1546,6 +1544,21 @@ subroutine leaf_area_profile( currentSite ) currentPatch => currentSite%oldest_patch do while(associated(currentPatch)) + ! If the large patch arrays are not new, deallocate them + if(associated(currentPatch%tlai_profile)) then + deallocate(currentPatch%tlai_profile,currentPatch%tsai_profile) + deallocate(currentPatch%elai_profile,currentPatch%esai_profile) + end if + + ! Evaluate required array sizes and possibly re-allocate + + max_leaf_layer = maxval(currentPatch%nrad(:,:)) + allocate(currentPatch%tlai_profile(currentPatch%NCL_p,numpft,max_leaf_layer)) + allocate(currentPatch%tsai_profile(currentPatch%NCL_p,numpft,max_leaf_layer)) + allocate(currentPatch%elai_profile(currentPatch%NCL_p,numpft,max_leaf_layer)) + allocate(currentPatch%esai_profile(currentPatch%NCL_p,numpft,max_leaf_layer)) + allocate(currentPatch%canopy_area_profile(currentPatch%NCL_p,numpft,max_leaf_layer)) + ! -------------------------------------------------------------------------------- ! Calculate tree and canopy areas. ! calculate tree lai and sai. @@ -1587,136 +1600,35 @@ subroutine leaf_area_profile( currentSite ) ! How much of each tree is stem area index? Assuming that there is ! This may indeed be zero if there is a sensecent grass ! ---------------------------------------------------------------- - ! preserve_b4b will be removed soon. This is kept here to prevent - ! round off errors in the baseline tests for the two-stream code (RGK 12-27-23) - if_preserve_b4b: if(preserve_b4b) then - lai = currentCohort%treelai * currentCohort%c_area/currentPatch%total_canopy_area - sai = currentCohort%treesai * currentCohort%c_area/currentPatch%total_canopy_area - if( (currentCohort%treelai+currentCohort%treesai) > nearzero)then - - ! See issue: https://github.com/NGEET/fates/issues/899 - ! fleaf = currentCohort%treelai / (currentCohort%treelai + currentCohort%treesai) - fleaf = lai / (lai+sai) - else - fleaf = 0._r8 - endif - - currentPatch%nrad(cl,ft) = currentPatch%ncan(cl,ft) - - if (currentPatch%nrad(cl,ft) > nlevleaf ) then - write(fates_log(), *) 'Number of radiative leaf layers is larger' - write(fates_log(), *) ' than the maximum allowed.' - write(fates_log(), *) ' cl: ',cl - write(fates_log(), *) ' ft: ',ft - write(fates_log(), *) ' nlevleaf: ',nlevleaf - write(fates_log(), *) ' currentPatch%nrad(cl,ft): ', currentPatch%nrad(cl,ft) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - !---~--- - ! Find current crown depth using the allometric function. - !---~--- - call CrownDepth(currentCohort%height,currentCohort%pft,crown_depth) - !---~--- - - - ! -------------------------------------------------------------------------- - ! Whole layers. Make a weighted average of the leaf area in each layer - ! before dividing it by the total area. Fill up layer for whole layers. - ! -------------------------------------------------------------------------- - - do iv = 1,currentCohort%NV - - ! This loop builds the arrays that define the effective (not snow covered) - ! and total (includes snow covered) area indices for leaves and stems - ! We calculate the absolute elevation of each layer to help determine if the layer - ! is obscured by snow. - - layer_top_height = currentCohort%height - & - ( real(iv-1,r8)/currentCohort%NV * crown_depth ) - - layer_bottom_height = currentCohort%height - & - ( real(iv,r8)/currentCohort%NV * crown_depth ) - - fraction_exposed = 1.0_r8 - if(currentSite%snow_depth > layer_top_height)then - fraction_exposed = 0._r8 - endif - if(currentSite%snow_depth < layer_bottom_height)then - fraction_exposed = 1._r8 - endif - if(currentSite%snow_depth >= layer_bottom_height .and. & - currentSite%snow_depth <= layer_top_height) then !only partly hidden... - fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_height)/ & - (layer_top_height-layer_bottom_height )))) - endif - - if(iv==currentCohort%NV) then - remainder = (currentCohort%treelai + currentCohort%treesai) - & - (dlower_vai(iv) - dinc_vai(iv)) - if(remainder > dinc_vai(iv) )then - write(fates_log(), *)'ED: issue with remainder', & - currentCohort%treelai,currentCohort%treesai,dinc_vai(iv), & - currentCohort%NV,remainder - - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - else - remainder = dinc_vai(iv) - end if - - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & - remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area - - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & - remainder * fleaf * currentCohort%c_area/currentPatch%total_canopy_area * & - fraction_exposed - - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & - remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area - - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & - remainder * (1._r8 - fleaf) * currentCohort%c_area/currentPatch%total_canopy_area * & - fraction_exposed - - currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & - currentCohort%c_area/currentPatch%total_canopy_area - - - end do - - else !if_preserve_b4b - - do iv = 1,currentCohort%NV - - call VegAreaLayer(currentCohort%treelai, & - currentCohort%treesai, & - currentCohort%height, & - iv,currentCohort%nv,currentCohort%pft, & - currentSite%snow_depth, & - vai_top,vai_bot, & - elai_layer,esai_layer,tlai_layer,tsai_layer) - - - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & - tlai_layer * currentCohort%c_area/currentPatch%total_canopy_area - - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & - elai_layer * currentCohort%c_area/currentPatch%total_canopy_area - - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & - tsai_layer * currentCohort%c_area/currentPatch%total_canopy_area - - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & - esai_layer * currentCohort%c_area/currentPatch%total_canopy_area - - currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & - currentCohort%c_area/currentPatch%total_canopy_area - - end do - - end if if_preserve_b4b - + do iv = 1,currentCohort%NV + + call VegAreaLayer(currentCohort%treelai, & + currentCohort%treesai, & + currentCohort%height, & + iv,currentCohort%nv,currentCohort%pft, & + currentSite%snow_depth, & + vai_top,vai_bot, & + elai_layer,esai_layer,tlai_layer,tsai_layer) + + + currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & + tlai_layer * currentCohort%c_area/currentPatch%total_canopy_area + + currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & + elai_layer * currentCohort%c_area/currentPatch%total_canopy_area + + currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & + tsai_layer * currentCohort%c_area/currentPatch%total_canopy_area + + currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & + esai_layer * currentCohort%c_area/currentPatch%total_canopy_area + + currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & + currentCohort%c_area/currentPatch%total_canopy_area + + end do + currentCohort => currentCohort%taller enddo !cohort diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 140c108d66..f9e684022d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -29,7 +29,6 @@ module EDPatchDynamicsMod use EDTypesMod , only : site_fluxdiags_type use EDTypesMod , only : min_patch_area use EDTypesMod , only : min_patch_area_forced - use EDParamsMod , only : nclmax use EDParamsMod , only : regeneration_model use FatesInterfaceTypesMod, only : numpft use FatesConstantsMod , only : dtype_ifall diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index e25a722f7a..b13e8e4ee4 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -3301,7 +3301,7 @@ subroutine UpdateRecruitL2FR(csite) end do ! Find the daily mean for each PFT weighted by number and add it to the running mean - do cl = 1,nclmax + do cl = 1,cpatch%ncl_p do ft = 1,numpft if(rec_n(ft,cl)>nearzero)then rec_l2fr0(ft,cl) = rec_l2fr0(ft,cl) / rec_n(ft,cl) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 1aa1cc4525..7aaf415719 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -98,7 +98,6 @@ module FatesAllometryMod use FatesGlobals , only : endrun => fates_endrun use FatesGlobals , only : FatesWarn,N2S,A2S,I2S use EDParamsMod , only : nlevleaf,dinc_vai,dlower_vai - use EDParamsMod , only : nclmax use DamageMainMod , only : GetCrownReduction implicit none @@ -670,7 +669,7 @@ real(r8) function tree_lai( leaf_c, pft, c_area, nplant, cl, canopy_lai, vcmax25 real(r8), intent(in) :: c_area ! areal extent of canopy (m2) real(r8), intent(in) :: nplant ! number of individuals in cohort per ha integer, intent(in) :: cl ! canopy layer index - real(r8), intent(in) :: canopy_lai(nclmax) ! total leaf area index of + real(r8), intent(in) :: canopy_lai(:) ! total leaf area index of ! each canopy layer real(r8), intent(in) :: vcmax25top ! maximum carboxylation rate at canopy ! top, ref 25C @@ -803,7 +802,7 @@ real(r8) function tree_sai(pft, dbh, crowndamage, canopy_trim, elongf_stem, c_ar real(r8), intent(in) :: c_area ! crown area (m2) real(r8), intent(in) :: nplant ! number of plants integer, intent(in) :: cl ! canopy layer index - real(r8), intent(in) :: canopy_lai(nclmax) ! total leaf area index of + real(r8), intent(in) :: canopy_lai(:) ! total leaf area index of ! each canopy layer real(r8), intent(in) :: treelai ! tree LAI for checking purposes only real(r8), intent(in) :: vcmax25top ! maximum carboxylation rate at top of crown diff --git a/biogeochem/FatesCohortMod.F90 b/biogeochem/FatesCohortMod.F90 index e98c4a345a..6dc6f515da 100644 --- a/biogeochem/FatesCohortMod.F90 +++ b/biogeochem/FatesCohortMod.F90 @@ -6,7 +6,6 @@ module FatesCohortMod use FatesConstantsMod, only : nearzero use FatesConstantsMod, only : ican_upper, ican_ustory use EDParamsMod, only : nlevleaf - use EDParamsMod, only : nclmax use FatesGlobals, only : endrun => fates_endrun use FatesGlobals, only : fates_log use PRTGenericMod, only : max_nleafage @@ -560,7 +559,7 @@ subroutine Create(this, prt, pft, nn, height, coage, dbh, status, & real(r8), intent(in) :: ctrim ! fraction of the maximum leaf biomass real(r8), intent(in) :: spread ! how spread crowns are in horizontal space real(r8), intent(in) :: carea ! area of cohort, for SP mode [m2] - real(r8), intent(in) :: can_tlai(nclmax) ! patch-level total LAI of each leaf layer + real(r8), intent(in) :: can_tlai(:) ! patch-level total LAI of each canopy layer real(r8), intent(in) :: elongf_leaf ! leaf elongation factor [fraction] real(r8), intent(in) :: elongf_fnrt ! fine-root "elongation factor" [fraction] real(r8), intent(in) :: elongf_stem ! stem "elongation factor" [fraction] diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index d86e5c5d51..773b6c409a 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -99,21 +99,27 @@ module FatesPatchMod real(r8) :: total_canopy_area ! area that is covered by vegetation [m2] real(r8) :: total_tree_area ! area that is covered by woody vegetation [m2] real(r8) :: zstar ! height of smallest canopy tree, only meaningful in "strict PPA" mode [m] - real(r8) :: elai_profile(nclmax,maxpft,nlevleaf) ! exposed leaf area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] - real(r8) :: esai_profile(nclmax,maxpft,nlevleaf) ! exposed stem area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] - real(r8) :: tlai_profile(nclmax,maxpft,nlevleaf) - real(r8) :: tsai_profile(nclmax,maxpft,nlevleaf) - real(r8) :: canopy_area_profile(nclmax,maxpft,nlevleaf) ! fraction of crown area per canopy area in each layer - ! they will sum to 1.0 in the fully closed canopy layers - ! but only in leaf-layers that contain contributions - ! from all cohorts that donate to canopy_area + + ! exposed leaf area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] + real(r8), allocatable :: elai_profile(:,:,:) ! nclmax,maxpft,nlevleaf) + ! exposed stem area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] + real(r8), allocatable :: esai_profile(:,:,:) ! nclmax,maxpft,nlevleaf) + ! total leaf area (includes that which is under snow-pack) + real(r8), allocatable :: tlai_profile(:,:,:) ! nclmax,maxpft,nlevleaf) + ! total stem area (includes that which is under snow-pack) + real(r8), allocatable :: tsai_profile(:,:,:) ! nclmax,maxpft,nlevleaf) + + real(r8), allocatable :: canopy_area_profile(:,:,:) ! nclmax,maxpft,nlevleaf) ! fraction of crown area per canopy area in each layer + ! they will sum to 1.0 in the fully closed canopy layers + ! but only in leaf-layers that contain contributions + ! from all cohorts that donate to canopy_area + integer :: canopy_mask(nclmax,maxpft) ! is there any of this pft in this canopy layer? integer :: nrad(nclmax,maxpft) ! number of exposed leaf layers for each canopy layer and pft integer :: ncan(nclmax,maxpft) ! number of total leaf layers for each canopy layer and pft real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] - real(r8) :: psn_z(nclmax,maxpft,nlevleaf) real(r8) :: nrmlzd_parprof_pft_dir_z(num_rad_stream_types,nclmax,maxpft,nlevleaf) real(r8) :: nrmlzd_parprof_pft_dif_z(num_rad_stream_types,nclmax,maxpft,nlevleaf) @@ -129,20 +135,20 @@ module FatesPatchMod ! organized by canopy layer, pft, and leaf layer - real(r8) :: fabd_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of direct light absorbed [0-1] - real(r8) :: fabd_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of direct light absorbed [0-1] - real(r8) :: fabi_sun_z(nclmax,maxpft,nlevleaf) ! sun fraction of indirect light absorbed [0-1] - real(r8) :: fabi_sha_z(nclmax,maxpft,nlevleaf) ! shade fraction of indirect light absorbed [0-1] - real(r8) :: ed_parsun_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the sun [W/m2] - real(r8) :: ed_parsha_z(nclmax,maxpft,nlevleaf) ! PAR absorbed in the shade [W/m2] - real(r8) :: f_sun(nclmax,maxpft,nlevleaf) ! fraction of leaves in the sun [0-1] - real(r8) :: ed_laisun_z(nclmax,maxpft,nlevleaf) - real(r8) :: ed_laisha_z(nclmax,maxpft,nlevleaf) + real(r8),allocatable :: fabd_sun_z(:,:,:) !nclmax,maxpft,nlevleaf) ! sun fraction of direct light absorbed [0-1] + real(r8),allocatable :: fabd_sha_z(:,:,:) !nclmax,maxpft,nlevleaf) ! shade fraction of direct light absorbed [0-1] + real(r8),allocatable :: fabi_sun_z(:,:,:) !nclmax,maxpft,nlevleaf) ! sun fraction of indirect light absorbed [0-1] + real(r8),allocatable :: fabi_sha_z(:,:,:) !nclmax,maxpft,nlevleaf) ! shade fraction of indirect light absorbed [0-1] + real(r8),allocatable :: ed_parsun_z(:,:,:) !nclmax,maxpft,nlevleaf) ! PAR absorbed in the sun [W/m2] + real(r8),allocatable :: ed_parsha_z(:,:,:) !nclmax,maxpft,nlevleaf) ! PAR absorbed in the shade [W/m2] + real(r8),allocatable :: f_sun(:,:,:) !nclmax,maxpft,nlevleaf) ! fraction of leaves in the sun [0-1] + real(r8),allocatable :: ed_laisun_z(:,:,:) !nclmax,maxpft,nlevleaf) + real(r8),allocatable :: ed_laisha_z(:,:,:) !nclmax,maxpft,nlevleaf) ! radiation profiles for comparison against observations - real(r8) :: parprof_pft_dir_z(nclmax,maxpft,nlevleaf) ! direct-beam PAR profile through canopy, by canopy, PFT, leaf level [W/m2] - real(r8) :: parprof_pft_dif_z(nclmax,maxpft,nlevleaf) ! diffuse PAR profile through canopy, by canopy, PFT, leaf level [W/m2] + real(r8),allocatable :: parprof_pft_dir_z(:,:,:) !nclmax,maxpft,nlevleaf) ! direct-beam PAR profile through canopy, by canopy, PFT, leaf level [W/m2] + real(r8),allocatable :: parprof_pft_dif_z(:,:,:) !nclmax,maxpft,nlevleaf) ! diffuse PAR profile through canopy, by canopy, PFT, leaf level [W/m2] real(r8), allocatable :: tr_soil_dir(:) ! fraction of incoming direct radiation transmitted to the soil as direct, by numSWB [0-1] real(r8), allocatable :: tr_soil_dif(:) ! fraction of incoming diffuse radiation that is transmitted to the soil as diffuse [0-1] @@ -321,7 +327,7 @@ subroutine NanValues(this) this%c_stomata = nan this%c_lblayer = nan - this%psn_z(:,:,:) = nan + !this%psn_z(:,:,:) = nan this%nrmlzd_parprof_pft_dir_z(:,:,:,:) = nan this%nrmlzd_parprof_pft_dif_z(:,:,:,:) = nan @@ -412,7 +418,7 @@ subroutine ZeroValues(this) this%elai_profile(:,:,:) = 0.0_r8 this%c_stomata = 0.0_r8 this%c_lblayer = 0.0_r8 - this%psn_z(:,:,:) = 0.0_r8 + ! this%psn_z(:,:,:) = 0.0_r8 this%nrmlzd_parprof_pft_dir_z(:,:,:,:) = 0.0_r8 this%nrmlzd_parprof_pft_dif_z(:,:,:,:) = 0.0_r8 diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 0aad6eb977..673e19bce6 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -186,13 +186,16 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! leaf maintenance (dark) respiration [umol CO2/m**2/s] real(r8) :: lmr_z(nlevleaf,maxpft,nclmax) - + ! stomatal resistance [s/m] real(r8) :: rs_z(nlevleaf,maxpft,nclmax) ! net leaf photosynthesis averaged over sun and shade leaves. [umol CO2/m**2/s] real(r8) :: anet_av_z(nlevleaf,maxpft,nclmax) + ! Photosynthesis [umol /m2 /s] + real(r8) :: psn_z(nlevleaf,maxpft,nclmax) + ! Mask used to determine which leaf-layer biophysical rates have been ! used already logical :: rate_mask_z(nlevleaf,maxpft,nclmax) @@ -723,7 +726,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) lmr_z(iv,ft,cl), & ! in leaf_psi, & ! in bc_in(s)%rb_pa(ifp), & ! in - currentPatch%psn_z(cl,ft,iv), & ! out + psn_z(iv,ft,cl), & ! out rs_z(iv,ft,cl), & ! out anet_av_z(iv,ft,cl), & ! out c13disc_z(cl,ft,iv)) ! out @@ -755,7 +758,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) if(radiation_model.eq.norman_solver) then call ScaleLeafLayerFluxToCohort(nv, & !in - currentPatch%psn_z(cl,ft,1:nv), & !in + psn_z(1:nv,ft,cl), & !in lmr_z(1:nv,ft,cl), & !in rs_z(1:nv,ft,cl), & !in currentPatch%elai_profile(cl,ft,1:nv), & !in @@ -773,7 +776,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) else call ScaleLeafLayerFluxToCohort(nv, & !in - currentPatch%psn_z(cl,ft,1:nv), & !in + psn_z(1:nv,ft,cl), & !in lmr_z(1:nv,ft,cl), & !in rs_z(1:nv,ft,cl), & !in cohort_layer_elai(1:nv), & !in @@ -1991,7 +1994,7 @@ subroutine UpdateCanopyNCanNRadPresent(currentPatch) currentPatch%nrad = currentPatch%ncan ! Now loop through and identify which layer and pft combo has scattering elements - do cl = 1,nclmax + do cl = 1,currentPatch%ncl_p do ft = 1,numpft currentPatch%canopy_mask(cl,ft) = 0 do iv = 1, currentPatch%nrad(cl,ft); diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 1389e1c489..4ce1babcdb 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -104,7 +104,8 @@ module EDParamsMod real(r8), parameter, public :: soil_tfrz_thresh = -2.0_r8 ! Soil temperature threshold below which hydraulic failure mortality is off (non-hydro only) in degrees C - integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers + integer, parameter, public :: nclmax = 8 ! Maximum number of canopy layers (used only for scratch arrays) + ! For large arrays at patch level we use dynamic allocation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in each canopy layer diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index ffef39eb6f..cb808cf379 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -3688,7 +3688,7 @@ subroutine update_3dpatch_radiation(this, nsites, sites, bc_out) currentpatch => sites(s)%oldest_patch do while (associated(currentpatch)) ifp = ifp+1 - + currentPatch%f_sun (:,:,:) = 0._r8 currentPatch%fabd_sun_z (:,:,:) = 0._r8 currentPatch%fabd_sha_z (:,:,:) = 0._r8 diff --git a/radiation/FatesNormanRadMod.F90 b/radiation/FatesNormanRadMod.F90 index 24cf38fbb7..ae73748a42 100644 --- a/radiation/FatesNormanRadMod.F90 +++ b/radiation/FatesNormanRadMod.F90 @@ -189,7 +189,7 @@ subroutine PatchNormanRadiation (currentPatch, & tau_layer(:,:,:,:)=0.0_r8 f_abs(:,:,:,:)=0.0_r8 f_abs_leaf(:,:,:,:)=0._r8 - do L = 1,nclmax + do L = 1,currentPatch%ncl_p do ft = 1,numpft currentPatch%canopy_mask(L,ft) = 0 do iv = 1, currentPatch%nrad(L,ft) diff --git a/radiation/FatesTwoStreamUtilsMod.F90 b/radiation/FatesTwoStreamUtilsMod.F90 index 5a87ff24b0..3abe0ce849 100644 --- a/radiation/FatesTwoStreamUtilsMod.F90 +++ b/radiation/FatesTwoStreamUtilsMod.F90 @@ -87,9 +87,6 @@ subroutine FatesConstructRadElements(site,fcansno_pa,coszen_pa) !real(r8), parameter :: init_max_vai_diff_per_elem = 0.2_r8 !type(fates_cohort_type), pointer :: elem_co_ptrs(ncl*max_el_per_layer,100) - - - max_elements = -1 ifp=0 patch => site%oldest_patch From 5fb8e974802e6647cf178192cde8d7b6c5b45465 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 10 May 2024 13:25:50 -0400 Subject: [PATCH 236/300] final pass at the first version of dynamic patch arrays --- biogeochem/EDCanopyStructureMod.F90 | 223 ++++++++++++++++++--------- biogeochem/FatesPatchMod.F90 | 4 +- main/EDParamsMod.F90 | 8 +- radiation/FatesRadiationDriveMod.F90 | 2 +- 4 files changed, 157 insertions(+), 80 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index b38c371c18..1b3474e961 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -49,6 +49,7 @@ module EDCanopyStructureMod use PRTGenericMod, only : carbon12_element use FatesTwoStreamUtilsMod, only : FatesConstructRadElements use FatesRadiationMemMod , only : twostr_solver + use FatesRadiationMemMod , only : num_rad_stream_types ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg @@ -1514,13 +1515,19 @@ subroutine leaf_area_profile( currentSite ) ! ! !LOCAL VARIABLES: - type (fates_patch_type) , pointer :: currentPatch + type (fates_patch_type) , pointer :: cpatch type (fates_cohort_type) , pointer :: currentCohort real(r8) :: remainder !Thickness of layer at bottom of canopy. real(r8) :: fleaf ! fraction of cohort incepting area that is leaves. integer :: ft ! Plant functional type index. integer :: iv ! Vertical leaf layer index integer :: cl ! Canopy layer index + logical :: re_allocate ! Should we re-allocate the patch arrays? + integer :: prev_nveg ! Previous number of vegetation layers + integer :: nveg ! Number of vegetation layers + integer :: ncan ! Number of canopy layers + integer :: prev_ncan ! Number of canopy layers previously + ! as defined in the allocation space real(r8) :: fraction_exposed ! how much of this layer is not covered by snow? real(r8) :: frac_canopy(N_HEIGHT_BINS) ! amount of canopy in each height class real(r8) :: minh(N_HEIGHT_BINS) ! minimum height in height class (m) @@ -1541,49 +1548,113 @@ subroutine leaf_area_profile( currentSite ) ! leaf area index above it, irrespective of PFT identity... ! Each leaf is defined by how deep in the canopy it is, in terms of LAI units. (FIX(RF,032414), GB) - currentPatch => currentSite%oldest_patch - do while(associated(currentPatch)) - + cpatch => currentSite%oldest_patch + do while(associated(cpatch)) + + cpatch%ncan(:,:) = 0 + ! This routine updates the %ncan array + call UpdatePatchLAI(cpatch) + + + ! Perform allocations and re-allocations of potentially large patch arrays + ! + ! Note that this routine is called at the very end of dynamics, after trimming + ! and after canopy structure. This is important because we want to allocate + ! the array spaces for leaf area and radiation scattering based on the most + ! updated values. Note, that this routine is also called before we re-initialize + ! radiation scattering during restarts. + ! ------------------------------------------------------------------------ + + ncan = cpatch%ncl_p + nveg = maxval(cpatch%ncan(:,:)) + + ! Assume we will need to allocate, unless the + ! arrays already are allocated and require the same size + re_allocate = .true. + ! If the large patch arrays are not new, deallocate them - if(associated(currentPatch%tlai_profile)) then - deallocate(currentPatch%tlai_profile,currentPatch%tsai_profile) - deallocate(currentPatch%elai_profile,currentPatch%esai_profile) + if(associated(cpatch%tlai_profile)) then + + prev_ncan = ubound(cpatch%tlai_profile,1) + prev_nveg = ubound(cpatch%tlai_profile,3) + + ! We re-allocate if the number of canopy layers has changed, or + ! if the number of vegetation layers is larger than previously. + ! However, we also re-allocate if the number of vegetation layers + ! is not just smaller than previously allocated, but A GOOD BIT smaller + ! than previously allocated. Why? + ! We do this so that we are not always re-allocating. + + if( prev_ncan .ne. ncan .or. (nveg>prev_nveg) .or. (nveg nearzero ) then - - call UpdatePatchLAI(currentPatch) - - currentPatch%nrad(:,:) = currentPatch%ncan(:,:) + if_any_canopy_area: if (cpatch%total_canopy_area > nearzero ) then ! ----------------------------------------------------------------------------- ! Standard canopy layering model. @@ -1591,7 +1662,7 @@ subroutine leaf_area_profile( currentSite ) ! and canopy area to the accumulators. ! ----------------------------------------------------------------------------- - currentCohort => currentPatch%shortest + currentCohort => cpatch%shortest do while(associated(currentCohort)) ft = currentCohort%pft cl = currentCohort%canopy_layer @@ -1612,20 +1683,20 @@ subroutine leaf_area_profile( currentSite ) elai_layer,esai_layer,tlai_layer,tsai_layer) - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) + & - tlai_layer * currentCohort%c_area/currentPatch%total_canopy_area + cpatch%tlai_profile(cl,ft,iv) = cpatch%tlai_profile(cl,ft,iv) + & + tlai_layer * currentCohort%c_area/cpatch%total_canopy_area - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) + & - elai_layer * currentCohort%c_area/currentPatch%total_canopy_area + cpatch%elai_profile(cl,ft,iv) = cpatch%elai_profile(cl,ft,iv) + & + elai_layer * currentCohort%c_area/cpatch%total_canopy_area - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) + & - tsai_layer * currentCohort%c_area/currentPatch%total_canopy_area + cpatch%tsai_profile(cl,ft,iv) = cpatch%tsai_profile(cl,ft,iv) + & + tsai_layer * currentCohort%c_area/cpatch%total_canopy_area - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) + & - esai_layer * currentCohort%c_area/currentPatch%total_canopy_area + cpatch%esai_profile(cl,ft,iv) = cpatch%esai_profile(cl,ft,iv) + & + esai_layer * currentCohort%c_area/cpatch%total_canopy_area - currentPatch%canopy_area_profile(cl,ft,iv) = currentPatch%canopy_area_profile(cl,ft,iv) + & - currentCohort%c_area/currentPatch%total_canopy_area + cpatch%canopy_area_profile(cl,ft,iv) = cpatch%canopy_area_profile(cl,ft,iv) + & + currentCohort%c_area/cpatch%total_canopy_area end do @@ -1639,20 +1710,20 @@ subroutine leaf_area_profile( currentSite ) ! should have a value of exactly 1.0 in its top leaf layer ! -------------------------------------------------------------------------- - if ( (currentPatch%NCL_p > 1) .and. & - (sum(currentPatch%canopy_area_profile(1,:,1)) < 0.9999 )) then + if ( (cpatch%NCL_p > 1) .and. & + (sum(cpatch%canopy_area_profile(1,:,1)) < 0.9999 )) then write(fates_log(), *) 'FATES: canopy_area_profile was less than 1 at the canopy top' write(fates_log(), *) 'cl: ',1 write(fates_log(), *) 'iv: ',1 write(fates_log(), *) 'sum(cpatch%canopy_area_profile(1,:,1)): ', & - sum(currentPatch%canopy_area_profile(1,:,1)) - currentCohort => currentPatch%shortest + sum(cpatch%canopy_area_profile(1,:,1)) + currentCohort => cpatch%shortest do while(associated(currentCohort)) if(currentCohort%canopy_layer==1)then write(fates_log(), *) 'FATES: cohorts',currentCohort%dbh,currentCohort%c_area, & - currentPatch%total_canopy_area,currentPatch%area + cpatch%total_canopy_area,cpatch%area write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & - currentCohort%c_area/currentPatch%total_canopy_area + currentCohort%c_area/cpatch%total_canopy_area endif currentCohort => currentCohort%taller enddo !currentCohort @@ -1672,24 +1743,24 @@ subroutine leaf_area_profile( currentSite ) ! It should never be larger than 1 or less than 0. ! -------------------------------------------------------------------------- - do cl = 1,currentPatch%NCL_p - do iv = 1,currentPatch%ncan(cl,ft) + do cl = 1,cpatch%NCL_p + do iv = 1,cpatch%ncan(cl,ft) - if( debug .and. sum(currentPatch%canopy_area_profile(cl,:,iv)) > 1.0001_r8 ) then + if( debug .and. sum(cpatch%canopy_area_profile(cl,:,iv)) > 1.0001_r8 ) then write(fates_log(), *) 'FATES: A canopy_area_profile exceeded 1.0' write(fates_log(), *) 'cl: ',cl write(fates_log(), *) 'iv: ',iv write(fates_log(), *) 'sum(cpatch%canopy_area_profile(cl,:,iv)): ', & - sum(currentPatch%canopy_area_profile(cl,:,iv)) - currentCohort => currentPatch%shortest + sum(cpatch%canopy_area_profile(cl,:,iv)) + currentCohort => cpatch%shortest do while(associated(currentCohort)) if(currentCohort%canopy_layer==cl)then write(fates_log(), *) 'FATES: cohorts in layer cl = ',cl, & currentCohort%dbh,currentCohort%c_area, & - currentPatch%total_canopy_area,currentPatch%area + cpatch%total_canopy_area,cpatch%area write(fates_log(), *) 'ED: fracarea', currentCohort%pft, & - currentCohort%c_area/currentPatch%total_canopy_area + currentCohort%c_area/cpatch%total_canopy_area endif currentCohort => currentCohort%taller enddo !currentCohort @@ -1698,21 +1769,21 @@ subroutine leaf_area_profile( currentSite ) end do do ft = 1,numpft - do iv = 1,currentPatch%ncan(cl,ft) + do iv = 1,cpatch%ncan(cl,ft) - if( currentPatch%canopy_area_profile(cl,ft,iv) > nearzero ) then + if( cpatch%canopy_area_profile(cl,ft,iv) > nearzero ) then - currentPatch%tlai_profile(cl,ft,iv) = currentPatch%tlai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + cpatch%tlai_profile(cl,ft,iv) = cpatch%tlai_profile(cl,ft,iv) / & + cpatch%canopy_area_profile(cl,ft,iv) - currentPatch%tsai_profile(cl,ft,iv) = currentPatch%tsai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + cpatch%tsai_profile(cl,ft,iv) = cpatch%tsai_profile(cl,ft,iv) / & + cpatch%canopy_area_profile(cl,ft,iv) - currentPatch%elai_profile(cl,ft,iv) = currentPatch%elai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + cpatch%elai_profile(cl,ft,iv) = cpatch%elai_profile(cl,ft,iv) / & + cpatch%canopy_area_profile(cl,ft,iv) - currentPatch%esai_profile(cl,ft,iv) = currentPatch%esai_profile(cl,ft,iv) / & - currentPatch%canopy_area_profile(cl,ft,iv) + cpatch%esai_profile(cl,ft,iv) = cpatch%esai_profile(cl,ft,iv) / & + cpatch%canopy_area_profile(cl,ft,iv) end if enddo @@ -1728,23 +1799,23 @@ subroutine leaf_area_profile( currentSite ) ! Leaving this for the time being. ! -------------------------------------------------------------------------- - currentPatch%canopy_mask(:,:) = 0 + cpatch%canopy_mask(:,:) = 0 ! preserve_b4b will be removed soon. This is kept here to prevent ! round off errors in the baseline tests for the two-stream code (RGK 12-27-23) if(preserve_b4b) then - do cl = 1,currentPatch%NCL_p + do cl = 1,cpatch%NCL_p do ft = 1,numpft - do iv = 1, currentPatch%nrad(cl,ft) - if(currentPatch%canopy_area_profile(cl,ft,iv) > 0._r8)then - currentPatch%canopy_mask(cl,ft) = 1 + do iv = 1, cpatch%nrad(cl,ft) + if(cpatch%canopy_area_profile(cl,ft,iv) > 0._r8)then + cpatch%canopy_mask(cl,ft) = 1 endif end do !iv end do end do else - do cl = 1,currentPatch%NCL_p + do cl = 1,cpatch%NCL_p do ft = 1,numpft - if(currentPatch%canopy_area_profile(cl,ft,1) > 0._r8 ) currentPatch%canopy_mask(cl,ft) = 1 + if(cpatch%canopy_area_profile(cl,ft,1) > 0._r8 ) cpatch%canopy_mask(cl,ft) = 1 end do end do end if @@ -1752,7 +1823,7 @@ subroutine leaf_area_profile( currentSite ) end if if_any_canopy_area - currentPatch => currentPatch%younger + cpatch => cpatch%younger enddo !patch @@ -2099,21 +2170,25 @@ subroutine UpdatePatchLAI(currentPatch) type(fates_cohort_type), pointer :: currentCohort integer :: cl ! Canopy layer index integer :: ft ! Plant functional type index - + + integer :: ncl_p + ! Calculate LAI of layers above. Because it is possible for some understory cohorts ! to be taller than cohorts in the top canopy layer, we must iterate through the ! patch by canopy layer first. Given that canopy_layer_tlai is a patch level variable ! we could iterate through each cohort in any direction as long as we go down through ! the canopy layers. - + + currentPatch%ncl_p = 0 canopyloop: do cl = 1,nclmax currentCohort => currentPatch%tallest cohortloop: do while(associated(currentCohort)) ! Only update the current cohort tree lai if lai of the above layers have been calculated if (currentCohort%canopy_layer .eq. cl) then - ft = currentCohort%pft + ft = currentCohort%pft + currentPatch%ncl_p = max(currentPatch%ncl_p,cl) ! Update the cohort level lai and related variables call UpdateCohortLAI(currentCohort,currentPatch%canopy_layer_tlai, & currentPatch%total_canopy_area) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 773b6c409a..4eed088dc8 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -120,8 +120,8 @@ module FatesPatchMod real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] - real(r8) :: nrmlzd_parprof_pft_dir_z(num_rad_stream_types,nclmax,maxpft,nlevleaf) - real(r8) :: nrmlzd_parprof_pft_dif_z(num_rad_stream_types,nclmax,maxpft,nlevleaf) + real(r8),allocatable :: nrmlzd_parprof_pft_dir_z(:,:,:,:) !num_rad_stream_types,nclmax,maxpft,nlevleaf) + real(r8),allocatable :: nrmlzd_parprof_pft_dif_z(:,:,:,:) !num_rad_stream_types,nclmax,maxpft,nlevleaf) !--------------------------------------------------------------------------- diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 4ce1babcdb..69d48ed53d 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -104,11 +104,13 @@ module EDParamsMod real(r8), parameter, public :: soil_tfrz_thresh = -2.0_r8 ! Soil temperature threshold below which hydraulic failure mortality is off (non-hydro only) in degrees C - integer, parameter, public :: nclmax = 8 ! Maximum number of canopy layers (used only for scratch arrays) - ! For large arrays at patch level we use dynamic allocation + integer, parameter, public :: nclmax = 5 ! Maximum number of canopy layers (used only for scratch arrays) + ! We would make this even higher, but making this + ! a little lower keeps the size down on some output arrays + ! For large arrays at patch level we use dynamic allocation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in each canopy layer + integer, parameter, public :: nlevleaf = 50 ! number of leaf+stem layers in each canopy layer real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins diff --git a/radiation/FatesRadiationDriveMod.F90 b/radiation/FatesRadiationDriveMod.F90 index cb642c1289..e8170a74a9 100644 --- a/radiation/FatesRadiationDriveMod.F90 +++ b/radiation/FatesRadiationDriveMod.F90 @@ -471,7 +471,7 @@ subroutine FatesSunShadeFracs(nsites, sites,bc_in,bc_out) end do do_icol do ft = 1,numpft - do_iv: do iv = 1, nlevleaf + do_iv: do iv = 1, cpatch%ncan(cl,ft)! nlevleaf if(area_vlpfcl(iv,ft,cl) Date: Fri, 10 May 2024 13:40:50 -0400 Subject: [PATCH 237/300] Added ncl_p protections --- biogeochem/EDCanopyStructureMod.F90 | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 1b3474e961..b1d5b203ec 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -306,9 +306,19 @@ subroutine canopy_structure( currentSite , bc_in ) enddo ! do while(area_not_balanced) - ! Set current canopy layer occupancy indicator. - currentPatch%NCL_p = min(nclmax,z) - + ! Save number of canopy layers to the patch structure + + if(z > nclmax) then + write(fates_log(),*) 'FATES generated more canopy layers than scratch-space allows' + write(fates_log(),*) 'Predicted: ',z + write(fates_log(),*) 'Scratch space (nclmax, see EDParamsMod.F90): ',nclmax + write(fates_log(),*) 'Consider increasing nclmax if this value is to low' + write(fates_log(),*) 'and you think this number of canopy layers is reasonable.' + call endrun(msg=errMsg(sourcefile, __LINE__)) + else + currentPatch%NCL_p = z + end if + ! ------------------------------------------------------------------------------------------- ! if we are using "strict PPA", then calculate a z_star value as ! the height of the smallest tree in the canopy From d9f25a003686c2702443dd393150e44e2d59e228 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 10 May 2024 14:03:12 -0400 Subject: [PATCH 238/300] Reverted some changes where we update ncl_p, but it doesn't need to be updated in that spot --- biogeochem/EDCanopyStructureMod.F90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index b1d5b203ec..fec424299f 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -2181,15 +2181,12 @@ subroutine UpdatePatchLAI(currentPatch) integer :: cl ! Canopy layer index integer :: ft ! Plant functional type index - integer :: ncl_p - ! Calculate LAI of layers above. Because it is possible for some understory cohorts ! to be taller than cohorts in the top canopy layer, we must iterate through the ! patch by canopy layer first. Given that canopy_layer_tlai is a patch level variable ! we could iterate through each cohort in any direction as long as we go down through ! the canopy layers. - currentPatch%ncl_p = 0 canopyloop: do cl = 1,nclmax currentCohort => currentPatch%tallest cohortloop: do while(associated(currentCohort)) @@ -2198,7 +2195,6 @@ subroutine UpdatePatchLAI(currentPatch) if (currentCohort%canopy_layer .eq. cl) then ft = currentCohort%pft - currentPatch%ncl_p = max(currentPatch%ncl_p,cl) ! Update the cohort level lai and related variables call UpdateCohortLAI(currentCohort,currentPatch%canopy_layer_tlai, & currentPatch%total_canopy_area) From 6dc21d1904049de29d4097afb07bd698689c57d7 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 10 May 2024 14:12:16 -0400 Subject: [PATCH 239/300] Revert some removed b4b code, will re-remove later under its own changeset --- biogeochem/EDCanopyStructureMod.F90 | 143 ++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 19 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index fec424299f..4e1a5f1a05 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -86,6 +86,8 @@ module EDCanopyStructureMod real(r8), parameter :: similar_height_tol = 1.0E-3_r8 ! I think trees that differ by 1mm ! can be roughly considered the same right? + logical, parameter :: preserve_b4b = .true. + ! 10/30/09: Created by Rosie Fisher ! 2017/2018: Modifications and updates by Ryan Knox ! ============================================================================ @@ -1682,33 +1684,136 @@ subroutine leaf_area_profile( currentSite ) ! This may indeed be zero if there is a sensecent grass ! ---------------------------------------------------------------- - do iv = 1,currentCohort%NV + ! preserve_b4b will be removed soon. This is kept here to prevent + ! round off errors in the baseline tests for the two-stream code (RGK 12-27-23) + if_preserve_b4b: if(preserve_b4b) then - call VegAreaLayer(currentCohort%treelai, & - currentCohort%treesai, & - currentCohort%height, & - iv,currentCohort%nv,currentCohort%pft, & - currentSite%snow_depth, & - vai_top,vai_bot, & - elai_layer,esai_layer,tlai_layer,tsai_layer) + lai = currentCohort%treelai * currentCohort%c_area/cpatch%total_canopy_area + sai = currentCohort%treesai * currentCohort%c_area/cpatch%total_canopy_area + if( (currentCohort%treelai+currentCohort%treesai) > nearzero)then + ! See issue: https://github.com/NGEET/fates/issues/899 + ! fleaf = currentCohort%treelai / (currentCohort%treelai + currentCohort%treesai) + fleaf = lai / (lai+sai) + else + fleaf = 0._r8 + endif - cpatch%tlai_profile(cl,ft,iv) = cpatch%tlai_profile(cl,ft,iv) + & - tlai_layer * currentCohort%c_area/cpatch%total_canopy_area + cpatch%nrad(cl,ft) = cpatch%ncan(cl,ft) - cpatch%elai_profile(cl,ft,iv) = cpatch%elai_profile(cl,ft,iv) + & - elai_layer * currentCohort%c_area/cpatch%total_canopy_area + if (cpatch%nrad(cl,ft) > nlevleaf ) then + write(fates_log(), *) 'Number of radiative leaf layers is larger' + write(fates_log(), *) ' than the maximum allowed.' + write(fates_log(), *) ' cl: ',cl + write(fates_log(), *) ' ft: ',ft + write(fates_log(), *) ' nlevleaf: ',nlevleaf + write(fates_log(), *) ' cpatch%nrad(cl,ft): ', cpatch%nrad(cl,ft) + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - cpatch%tsai_profile(cl,ft,iv) = cpatch%tsai_profile(cl,ft,iv) + & - tsai_layer * currentCohort%c_area/cpatch%total_canopy_area + !---~--- + ! Find current crown depth using the allometric function. + !---~--- + call CrownDepth(currentCohort%height,currentCohort%pft,crown_depth) + !---~--- - cpatch%esai_profile(cl,ft,iv) = cpatch%esai_profile(cl,ft,iv) + & - esai_layer * currentCohort%c_area/cpatch%total_canopy_area - cpatch%canopy_area_profile(cl,ft,iv) = cpatch%canopy_area_profile(cl,ft,iv) + & - currentCohort%c_area/cpatch%total_canopy_area + ! -------------------------------------------------------------------------- + ! Whole layers. Make a weighted average of the leaf area in each layer + ! before dividing it by the total area. Fill up layer for whole layers. + ! -------------------------------------------------------------------------- - end do + do iv = 1,currentCohort%NV + + ! This loop builds the arrays that define the effective (not snow covered) + ! and total (includes snow covered) area indices for leaves and stems + ! We calculate the absolute elevation of each layer to help determine if the layer + ! is obscured by snow. + + layer_top_height = currentCohort%height - & + ( real(iv-1,r8)/currentCohort%NV * crown_depth ) + + layer_bottom_height = currentCohort%height - & + ( real(iv,r8)/currentCohort%NV * crown_depth ) + + fraction_exposed = 1.0_r8 + if(currentSite%snow_depth > layer_top_height)then + fraction_exposed = 0._r8 + endif + if(currentSite%snow_depth < layer_bottom_height)then + fraction_exposed = 1._r8 + endif + if(currentSite%snow_depth >= layer_bottom_height .and. & + currentSite%snow_depth <= layer_top_height) then !only partly hidden... + fraction_exposed = 1._r8 - max(0._r8,(min(1.0_r8,(currentSite%snow_depth -layer_bottom_height)/ & + (layer_top_height-layer_bottom_height )))) + endif + + if(iv==currentCohort%NV) then + remainder = (currentCohort%treelai + currentCohort%treesai) - & + (dlower_vai(iv) - dinc_vai(iv)) + if(remainder > dinc_vai(iv) )then + write(fates_log(), *)'ED: issue with remainder', & + currentCohort%treelai,currentCohort%treesai,dinc_vai(iv), & + currentCohort%NV,remainder + + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + else + remainder = dinc_vai(iv) + end if + + cpatch%tlai_profile(cl,ft,iv) = cpatch%tlai_profile(cl,ft,iv) + & + remainder * fleaf * currentCohort%c_area/cpatch%total_canopy_area + + cpatch%elai_profile(cl,ft,iv) = cpatch%elai_profile(cl,ft,iv) + & + remainder * fleaf * currentCohort%c_area/cpatch%total_canopy_area * & + fraction_exposed + + cpatch%tsai_profile(cl,ft,iv) = cpatch%tsai_profile(cl,ft,iv) + & + remainder * (1._r8 - fleaf) * currentCohort%c_area/cpatch%total_canopy_area + + cpatch%esai_profile(cl,ft,iv) = cpatch%esai_profile(cl,ft,iv) + & + remainder * (1._r8 - fleaf) * currentCohort%c_area/cpatch%total_canopy_area * & + fraction_exposed + + cpatch%canopy_area_profile(cl,ft,iv) = cpatch%canopy_area_profile(cl,ft,iv) + & + currentCohort%c_area/cpatch%total_canopy_area + + + end do + + else !if_preserve_b4b + + do iv = 1,currentCohort%NV + + call VegAreaLayer(currentCohort%treelai, & + currentCohort%treesai, & + currentCohort%height, & + iv,currentCohort%nv,currentCohort%pft, & + currentSite%snow_depth, & + vai_top,vai_bot, & + elai_layer,esai_layer,tlai_layer,tsai_layer) + + + cpatch%tlai_profile(cl,ft,iv) = cpatch%tlai_profile(cl,ft,iv) + & + tlai_layer * currentCohort%c_area/cpatch%total_canopy_area + + cpatch%elai_profile(cl,ft,iv) = cpatch%elai_profile(cl,ft,iv) + & + elai_layer * currentCohort%c_area/cpatch%total_canopy_area + + cpatch%tsai_profile(cl,ft,iv) = cpatch%tsai_profile(cl,ft,iv) + & + tsai_layer * currentCohort%c_area/cpatch%total_canopy_area + + cpatch%esai_profile(cl,ft,iv) = cpatch%esai_profile(cl,ft,iv) + & + esai_layer * currentCohort%c_area/cpatch%total_canopy_area + + cpatch%canopy_area_profile(cl,ft,iv) = cpatch%canopy_area_profile(cl,ft,iv) + & + currentCohort%c_area/cpatch%total_canopy_area + + end do + + end if if_preserve_b4b currentCohort => currentCohort%taller From f7dd5393bbe47cee26571ecf93c07d4cf6a7cf28 Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Fri, 10 May 2024 12:52:38 -0600 Subject: [PATCH 240/300] tunned some PFT params for grasses to make the default params producing reasonable results, tested only at vaira ranch tho --- parameter_files/fates_params_default.cdl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index f231d7f314..1d255a4aec 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1306,10 +1306,10 @@ data: 495 ; fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; + 0.03, 0.03, 0.05, 0.05, 0.05 ; fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; + 0.03, 0.05, 0.05, 0.05 ; fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 40000 ; @@ -1463,7 +1463,7 @@ data: 0.001, 0.001, 0.12, 0.12, 0.12 ; fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, - 0.125, 0.125, 0.125 ; + 0.2, 0.2, 0.2 ; fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; @@ -1471,14 +1471,14 @@ data: fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 ; - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, + 0, 0 ; - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, - 0.9 ; + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.25, 0.25, + 0.2 ; fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, - 0.35, 0.35, 0.35 ; + 3, 3, 3 ; fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; From 6b4f3f9e62068ae681727202d5ed4f5bcfcc03ef Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 10 May 2024 17:29:00 -0400 Subject: [PATCH 241/300] Update tools/make_unstruct_grid/MakeUnstructGrid.py Co-authored-by: Gregory Lemieux <7565064+glemieux@users.noreply.github.com> --- tools/make_unstruct_grid/MakeUnstructGrid.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/make_unstruct_grid/MakeUnstructGrid.py b/tools/make_unstruct_grid/MakeUnstructGrid.py index 159fb92f8b..dfde3d8e03 100644 --- a/tools/make_unstruct_grid/MakeUnstructGrid.py +++ b/tools/make_unstruct_grid/MakeUnstructGrid.py @@ -68,6 +68,8 @@ def TransferData(da_key,ds_base,ds_unst,minis,minjs,dset_type): dtype_out = np.float64 elif(ds_base[da_key].dtype == 'int32'): dtype_out = np.int32 + elif(ds_base[da_key].dtype == 'float32'): + dtype_out = np.float32 else: print('unknown data type: {}.\n Exiting'.format(ds_base[da_key].dtype)) exit(2) From 6080ab6032814c5e70547bcf82cd39a028e5253f Mon Sep 17 00:00:00 2001 From: Charlie Koven Date: Fri, 10 May 2024 16:58:44 -0700 Subject: [PATCH 242/300] fixing error in harvest rate calculations --- biogeochem/EDLoggingMortalityMod.F90 | 22 +++++++++---- biogeochem/EDPatchDynamicsMod.F90 | 6 +++- main/EDTypesMod.F90 | 47 +++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 1b1200037e..6d373e995a 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -242,6 +242,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, real(r8) :: harvest_rate ! the final harvest rate to apply to this cohort today real(r8) :: state_vector(n_landuse_cats) logical :: site_secondaryland_first_exceeding_min + real(r8) :: secondary_young_fraction ! what fraction of secondary land is young secondary land ! todo: probably lower the dbhmin default value to 30 cm ! todo: change the default logging_event_code to 1 september (-244) @@ -302,9 +303,11 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, ! HARVEST_SH2 = harvest from secondary young forest ! HARVEST_SH3 = harvest from secondary non-forest (assume this is young for biomass) + secondary_young_fraction = currentSite%get_secondary_young_fraction() + ! Get the area-based harvest rates based on info passed to FATES from the boundary condition call get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, & - hlm_harvest_rates, frac_site_primary, frac_site_secondary, secondary_age, harvest_rate) + hlm_harvest_rates, frac_site_primary, frac_site_secondary, secondary_young_fraction, secondary_age, harvest_rate) ! For area-based harvest, harvest_tag shall always be 2 (not applicable). harvest_tag = 2 @@ -401,13 +404,13 @@ end subroutine LoggingMortality_frac ! ============================================================================ subroutine get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, hlm_harvest_rates, & - frac_site_primary, frac_site_secondary, secondary_age, harvest_rate) + frac_site_primary, frac_site_secondary, secondary_young_fraction, secondary_age, harvest_rate) ! ------------------------------------------------------------------------------------------- ! ! DESCRIPTION: - ! get the area-based harvest rates based on info passed to FATES from the bioundary conditions in. + ! get the area-based harvest rates based on info passed to FATES from the boundary conditions in. ! assumes logging_time == true ! Arguments @@ -417,6 +420,7 @@ subroutine get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, hl real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance real(r8), intent(in) :: frac_site_primary real(r8), intent(in) :: frac_site_secondary + real(r8), intent(in) :: secondary_young_fraction ! what fraction of secondary land is young secondary land real(r8), intent(out) :: harvest_rate ! Local Variables @@ -449,15 +453,21 @@ subroutine get_harvest_rate_area (patch_land_use_label, hlm_harvest_catnames, hl ! Normalize by site-level primary or secondary forest fraction ! since harvest_rate is specified as a fraction of the gridcell ! also need to put a cap so as not to harvest more primary or secondary area than there is in a gridcell + ! For secondary, also need to normalize by the young/old fraction. if (patch_land_use_label .eq. primaryland) then if (frac_site_primary .gt. fates_tiny) then - harvest_rate = min((harvest_rate / frac_site_primary),frac_site_primary) + harvest_rate = min((harvest_rate / frac_site_primary),1._r8) else harvest_rate = 0._r8 endif else if (patch_land_use_label .eq. secondaryland) then - if (frac_site_secondary .gt. fates_tiny) then - harvest_rate = min((harvest_rate / frac_site_secondary), frac_site_secondary) + ! the .gt. -0.5 in the next line is because frac_site_secondary returns -1 if no secondary area. + if (frac_site_secondary .gt. fates_tiny .and. frac_site_secondary .gt. -0.5_r8) then + if (secondary_age .lt. secondary_age_threshold) then + harvest_rate = min((harvest_rate / (frac_site_secondary * secondary_young_fraction)), 1._r8) + else + harvest_rate = min((harvest_rate / (frac_site_secondary * (1._r8 - secondary_young_fraction))), 1._r8) + endif else harvest_rate = 0._r8 endif diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 7536cbdf3a..3998569800 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -216,6 +216,7 @@ subroutine disturbance_rates( site_in, bc_in) real(r8) :: state_vector(n_landuse_cats) real(r8), parameter :: max_daily_disturbance_rate = 0.999_r8 logical :: site_secondaryland_first_exceeding_min + real(r8) :: secondary_young_fraction ! what fraction of secondary land is young secondary land !---------------------------------------------------------------------------------------------- ! Calculate Mortality Rates (these were previously calculated during growth derivatives) ! And the same rates in understory plants have already been applied to %dndt @@ -224,6 +225,9 @@ subroutine disturbance_rates( site_in, bc_in) ! first calculate the fraction of the site that is primary land current_fates_landuse_state_vector = site_in%get_current_landuse_statevector() + ! and get the fraction of secondary land that is young secondary land + secondary_young_fraction = currentSite%get_secondary_young_fraction() + ! check status of transition_landuse_from_off_to_on flag, and do some error checking on it if(site_in%transition_landuse_from_off_to_on) then if (sum(current_fates_landuse_state_vector(secondaryland:cropland)) .gt. nearzero) then @@ -396,7 +400,7 @@ subroutine disturbance_rates( site_in, bc_in) else call get_harvest_rate_area (currentPatch%land_use_label, bc_in%hlm_harvest_catnames, & bc_in%hlm_harvest_rates, current_fates_landuse_state_vector(primaryland), & - current_fates_landuse_state_vector(secondaryland), & + current_fates_landuse_state_vector(secondaryland), secondary_young_fraction, & currentPatch%age_since_anthro_disturbance, harvest_rate) end if diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 5644fb8295..f1790b130f 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -5,6 +5,8 @@ module EDTypesMod use FatesConstantsMod, only : ifalse use FatesConstantsMod, only : itrue use FatesConstantsMod, only : nocomp_bareground_land + use FatesConstantsMod, only : secondaryland + use FatesConstantsMod, only : secondary_age_threshold use FatesGlobals, only : fates_log use FatesHydraulicsMemMod, only : ed_cohort_hydr_type use FatesHydraulicsMemMod, only : ed_site_hydr_type @@ -547,5 +549,48 @@ function get_current_landuse_statevector(this) result(current_state_vector) end do end function get_current_landuse_statevector - + + ! ===================================================================================== + + function get_secondary_young_fraction(this) result(secondary_young_fraction) + + ! + ! !DESCRIPTION: + ! Calculate how much of the secondary area is "young", i.e. below the age threshold. + ! If no seconday patch area at all, return -1. + ! + ! !USES: + ! + ! !ARGUMENTS: + class(ed_site_type) :: this + real(r8) :: secondary_young_fraction + real(r8) :: secondary_young_area + real(r8) :: secondary_old_area + + ! !LOCAL VARIABLES: + type(fates_patch_type), pointer :: currentPatch + + secondary_young_area = 0._r8 + secondary_old_area = 0._r8 + + currentPatch => this%oldest_patch + do while (associated(currentPatch)) + if (currentPatch%land_use_label .eq. secondaryland) then + if ( currentPatch%age .ge. secondary_age_threshold ) then + secondary_old_area = secondary_old_area + currentPatch%area + else + secondary_young_area = secondary_young_area + currentPatch%area + end if + end if + currentPatch => currentPatch%younger + end do + + if ( (secondary_young_area + secondary_old_area) .gt. fates_tiny) then + secondary_young_fraction = secondary_young_area / (secondary_young_area + secondary_old_area) + else + secondary_young_fraction = -1._r8 + endif + + end function get_secondary_young_fraction + end module EDTypesMod From 827ab3f1d63f710f8819d4329253d0a7d75a4bed Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 14 May 2024 14:54:03 -0700 Subject: [PATCH 243/300] minor build fixes --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- main/EDTypesMod.F90 | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3998569800..208560975d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -226,7 +226,7 @@ subroutine disturbance_rates( site_in, bc_in) current_fates_landuse_state_vector = site_in%get_current_landuse_statevector() ! and get the fraction of secondary land that is young secondary land - secondary_young_fraction = currentSite%get_secondary_young_fraction() + secondary_young_fraction = site_in%get_secondary_young_fraction() ! check status of transition_landuse_from_off_to_on flag, and do some error checking on it if(site_in%transition_landuse_from_off_to_on) then diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index f1790b130f..8f2e8ad570 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -7,6 +7,7 @@ module EDTypesMod use FatesConstantsMod, only : nocomp_bareground_land use FatesConstantsMod, only : secondaryland use FatesConstantsMod, only : secondary_age_threshold + use FatesConstantsMod, only : fates_tiny use FatesGlobals, only : fates_log use FatesHydraulicsMemMod, only : ed_cohort_hydr_type use FatesHydraulicsMemMod, only : ed_site_hydr_type @@ -444,6 +445,7 @@ module EDTypesMod contains procedure, public :: get_current_landuse_statevector + procedure, public :: get_secondary_young_fraction end type ed_site_type From 556edd48452459b7ffbe248adfb921b45205af53 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 16 May 2024 12:55:42 -0600 Subject: [PATCH 244/300] nclmax nlevleaf: reverting for b4b testing --- biogeochem/EDCanopyStructureMod.F90 | 24 +++++++++++++++--------- biogeochem/FatesPatchMod.F90 | 2 +- main/EDParamsMod.F90 | 4 ++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 4e1a5f1a05..a0facdbd7c 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1599,17 +1599,24 @@ subroutine leaf_area_profile( currentSite ) if( prev_ncan .ne. ncan .or. (nveg>prev_nveg) .or. (nveg Date: Fri, 17 May 2024 09:28:45 -0600 Subject: [PATCH 245/300] bug fixes from luhv2 merge --- biogeochem/EDPatchDynamicsMod.F90 | 6 +++--- main/EDInitMod.F90 | 2 +- main/EDTypesMod.F90 | 6 ++++-- main/FatesHistoryInterfaceMod.F90 | 1 - main/FatesRestartInterfaceMod.F90 | 1 - 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 0a0ac19e3a..a6e05617be 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -226,7 +226,7 @@ subroutine disturbance_rates( site_in, bc_in) current_fates_landuse_state_vector = site_in%get_current_landuse_statevector() ! and get the fraction of secondary land that is young secondary land - secondary_young_fraction = currentSite%get_secondary_young_fraction() + secondary_young_fraction = site_in%get_secondary_young_fraction() ! check status of transition_landuse_from_off_to_on flag, and do some error checking on it if(site_in%transition_landuse_from_off_to_on) then @@ -1399,7 +1399,7 @@ subroutine spawn_patches( currentSite, bc_in) allocate(buffer_patch) call buffer_patch%Create(0._r8, 0._r8, i_land_use_label, 0, & - hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & + num_swb, numpft, currentSite%nlevsoil, hlm_current_tod, & regeneration_model) ! Initialize the litter pools to zero @@ -1641,7 +1641,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) ! first we need to make the new patch call new_patch%Create(0._r8, & currentPatch%area * (1._r8 - fraction_to_keep), currentPatch%land_use_label, currentPatch%nocomp_pft_label, & - hlm_numSWb, numpft, currentSite%nlevsoil, hlm_current_tod, & + num_swb, numpft, currentSite%nlevsoil, hlm_current_tod, & regeneration_model) ! Initialize the litter pools to zero, these diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index c6cb008bd3..efef68aae4 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -762,7 +762,7 @@ subroutine init_patches( nsites, sites, bc_in) allocate(newp) call newp%Create(age, newparea, nocomp_bareground_land, nocomp_bareground, & - hlm_numSWb, numpft, sites(s)%nlevsoil, hlm_current_tod, & + num_swb, numpft, sites(s)%nlevsoil, hlm_current_tod, & regeneration_model) ! set pointers for first patch (or only patch, if nocomp is false) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 0307cd6518..ec6ed4dc44 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -7,6 +7,7 @@ module EDTypesMod use FatesConstantsMod, only : nocomp_bareground_land use FatesConstantsMod, only : secondaryland use FatesConstantsMod, only : secondary_age_threshold + use FatesConstantsMod, only : nearzero use FatesGlobals, only : fates_log use FatesHydraulicsMemMod, only : ed_cohort_hydr_type use FatesHydraulicsMemMod, only : ed_site_hydr_type @@ -462,7 +463,8 @@ module EDTypesMod contains procedure, public :: get_current_landuse_statevector - + procedure, public :: get_secondary_young_fraction + end type ed_site_type ! Make public necessary subroutines and functions @@ -603,7 +605,7 @@ function get_secondary_young_fraction(this) result(secondary_young_fraction) currentPatch => currentPatch%younger end do - if ( (secondary_young_area + secondary_old_area) .gt. fates_tiny) then + if ( (secondary_young_area + secondary_old_area) .gt. nearzero ) then secondary_young_fraction = secondary_young_area / (secondary_young_area + secondary_old_area) else secondary_young_fraction = -1._r8 diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c2014b75e2..d9f7d7ac4a 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2390,7 +2390,6 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) hio_fire_disturbance_rate_si => this%hvars(ih_fire_disturbance_rate_si)%r81d, & hio_logging_disturbance_rate_si => this%hvars(ih_logging_disturbance_rate_si)%r81d, & hio_fall_disturbance_rate_si => this%hvars(ih_fall_disturbance_rate_si)%r81d, & - hio_harvest_carbonflux_si => this%hvars(ih_harvest_carbonflux_si)%r81d, & hio_harvest_debt_si => this%hvars(ih_harvest_debt_si)%r81d, & hio_harvest_debt_sec_si => this%hvars(ih_harvest_debt_sec_si)%r81d, & hio_npp_leaf_si => this%hvars(ih_npp_leaf_si)%r81d, & diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 3d1219a55a..57b0bd6ea9 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -3049,7 +3049,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) integer :: i_landuse,i_pflu ! loop counter for land use class integer :: i_lu_donor, i_lu_receiver, i_dist ! loop counters for land use and disturbance integer :: i_term_type ! loop counter for termination type - integer :: i_lu_donor, i_lu_receiver, i_dist ! loop counters for land use and disturbance associate( rio_npatch_si => this%rvars(ir_npatch_si)%int1d, & rio_cd_status_si => this%rvars(ir_cd_status_si)%int1d, & From d00ece6bd6cff548483977f40c0be683a698b2f1 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 17 May 2024 15:59:29 -0400 Subject: [PATCH 246/300] added parameter file patch for api 36 --- .../archive/api36.0.0_051724_patch_params.xml | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 parameter_files/archive/api36.0.0_051724_patch_params.xml diff --git a/parameter_files/archive/api36.0.0_051724_patch_params.xml b/parameter_files/archive/api36.0.0_051724_patch_params.xml new file mode 100644 index 0000000000..938bd4bd78 --- /dev/null +++ b/parameter_files/archive/api36.0.0_051724_patch_params.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + archive/api36.0.0_051724_params_default.xml + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_landuse_harvest_pprod10 + fates_pft + fraction + fraction of harvest wood product that goes to 10-year product pool (remainder goes to 100-year pool) + 1, 0.75, 0.75, 0.75, 1, 0.75, 1, 1, 1, 1, 1, 1 + + + fates_landuse_luc_frac_burned + fates_pft + fraction + fraction of land use change-generated and not-exported material that is burned (the remainder goes to litter) + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 + + + fates_landuse_luc_frac_exported + fates_pft + fraction + fraction of land use change-generated wood material that is exported to wood product (the remainder is either burned or goes to litter) + 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.2, 0.2, 0.2, 0, 0, 0 + + + fates_landuse_luc_pprod10 + fates_pft + fraction + fraction of land use change wood product that goes to 10-year product pool (remainder goes to 100-year pool) + 1, 0.75, 0.75, 0.75, 1, 0.75, 1, 1, 1, 1, 1, 1 + + + fates_landuse_crop_lu_pft_vector + fates_landuse_class + NA + the FATES PFT index to use on a given crop land-use type (dummy value of -999 for non-crop types) + 999, -999, -999, -999, 11 + + + fates_max_nocomp_pfts_by_landuse + fates_landuse_class + count + maximum number of nocomp PFTs on each land use type (only used in nocomp mode) + 4, 4, 1, 1, 1 + + + fates_landuse_pprodharv10_forest_mean + + + + + fates_landuse_harvest_pprod10:units = "fraction" ; + fates_landuse_harvest_pprod10:long_name = "fraction of harvest wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; + double fates_landuse_luc_frac_burned(fates_pft) ; + fates_landuse_luc_frac_burned:units = "fraction" ; + fates_landuse_luc_frac_burned:long_name = "fraction of land use change-generated and not-exported material that is burned (the remainder goes to litter)" ; + + double fates_landuse_luc_frac_exported(fates_pft) ; + fates_landuse_luc_frac_exported:units = "fraction" ; + fates_landuse_luc_frac_exported:long_name = "fraction of land use change-generated wood material that is exported to wood product (the remainder is either burned or goes to litter)" ; + + double fates_landuse_luc_pprod10(fates_pft) ; + fates_landuse_luc_pprod10:units = "fraction" ; + fates_landuse_luc_pprod10:long_name = "fraction of land use change wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; + +double fates_landuse_crop_lu_pft_vector(fates_landuseclass) ; + fates_landuse_crop_lu_pft_vector:units = "NA" ; + fates_landuse_crop_lu_pft_vector:long_name = "What FATES PFT index to use on a given crop land-use type? (dummy value of -999 for non-crop types)" ; + double fates_max_nocomp_pfts_by_landuse(fates_landuseclass) ; + fates_max_nocomp_pfts_by_landuse:units = "count" ; + fates_max_nocomp_pfts_by_landuse:long_name = "maximum number of nocomp PFTs on each land use type (only used in nocomp mode)" ; + + + + From 7084c0d11214f38090e4611ac17e7a817988abae Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 20 May 2024 10:12:58 -0400 Subject: [PATCH 247/300] updated parameter api update xml --- .../api36.0.0_051724_params_default.cdl | 1776 +++++++++++++++++ .../archive/api36.0.0_051724_patch_params.xml | 31 +- parameter_files/fates_params_default.cdl | 6 +- 3 files changed, 1781 insertions(+), 32 deletions(-) create mode 100644 parameter_files/archive/api36.0.0_051724_params_default.cdl diff --git a/parameter_files/archive/api36.0.0_051724_params_default.cdl b/parameter_files/archive/api36.0.0_051724_params_default.cdl new file mode 100644 index 0000000000..2a909ee340 --- /dev/null +++ b/parameter_files/archive/api36.0.0_051724_params_default.cdl @@ -0,0 +1,1776 @@ +netcdf tmp { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_landuseclass = 5 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + char fates_landuseclass_name(fates_landuseclass, fates_string_length) ; + fates_landuseclass_name:units = "unitless - string" ; + fates_landuseclass_name:long_name = "Name of the land use classes, for variables associated with dimension fates_landuseclass" ; + char fates_litterclass_name(fates_litterclass, fates_string_length) ; + fates_litterclass_name:units = "unitless - string" ; + fates_litterclass_name:long_name = "Name of the litter classes, for variables associated with dimension fates_litterclass" ; + double fates_alloc_organ_priority(fates_plant_organs, fates_pft) ; + fates_alloc_organ_priority:units = "index" ; + fates_alloc_organ_priority:long_name = "Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_dmode(fates_pft) ; + fates_allom_dmode:units = "index" ; + fates_allom_dmode:long_name = "crown depth allometry function index" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_h2cd1(fates_pft) ; + fates_allom_h2cd1:units = "variable" ; + fates_allom_h2cd1:long_name = "Parameter 1 for h2cd allometry (exp(log-intercept) or scaling). If allom_dmode=1; this is the same as former crown_depth_frac parameter" ; + double fates_allom_h2cd2(fates_pft) ; + fates_allom_h2cd2:units = "variable" ; + fates_allom_h2cd2:long_name = "Parameter 2 for h2cd allometry (log-slope or exponent). If allom_dmode=1; this is not needed (as exponent is assumed 1)" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "(INACTIVE, KEEP AT 0) fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "(INACTIVE, KEEP AT 0) critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + double fates_damage_recovery_scalar(fates_pft) ; + fates_damage_recovery_scalar:units = "unitless" ; + fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; + double fates_dev_arbitrary_pft(fates_pft) ; + fates_dev_arbitrary_pft:units = "unknown" ; + fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + double fates_hydro_vg_n_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_n_node:units = "unitless" ; + fates_hydro_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leafn_vert_scaler_coeff1(fates_pft) ; + fates_leafn_vert_scaler_coeff1:units = "unitless" ; + fates_leafn_vert_scaler_coeff1:long_name = "Coefficient one for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010." ; + double fates_leafn_vert_scaler_coeff2(fates_pft) ; + fates_leafn_vert_scaler_coeff2:units = "unitless" ; + fates_leafn_vert_scaler_coeff2:long_name = "Coefficient two for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010." ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_leaf_vert_scaler_coeff1(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff1:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff1:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff1." ; + double fates_maintresp_leaf_vert_scaler_coeff2(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff2:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff2." ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_maintresp_reduction_upthresh(fates_pft) ; + fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; + fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_mort_upthresh_cstarvation(fates_pft) ; + fates_mort_upthresh_cstarvation:units = "unitless" ; + fates_mort_upthresh_cstarvation:long_name = "threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_drought_threshold(fates_pft) ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; + double fates_phen_mindaysoff(fates_pft) ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; + double fates_phen_moist_threshold(fates_pft) ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Flag for stress/drought-deciduous leaf habit. 0 - not stress deciduous; 1 - default drought deciduous (two target states only, fully flushed or fully abscised); 2 - semi-deciduous" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_seed_dispersal_fraction(fates_pft) ; + fates_seed_dispersal_fraction:units = "fraction" ; + fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; + double fates_seed_dispersal_max_dist(fates_pft) ; + fates_seed_dispersal_max_dist:units = "m" ; + fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; + double fates_seed_dispersal_pdf_scale(fates_pft) ; + fates_seed_dispersal_pdf_scale:units = "unitless" ; + fates_seed_dispersal_pdf_scale:long_name = "seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016" ; + double fates_seed_dispersal_pdf_shape(fates_pft) ; + fates_seed_dispersal_pdf_shape:units = "unitless" ; + fates_seed_dispersal_pdf_shape:long_name = "seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_trs_repro_alloc_a(fates_pft) ; + fates_trs_repro_alloc_a:units = "fraction" ; + fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_alloc_b(fates_pft) ; + fates_trs_repro_alloc_b:units = "fraction" ; + fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_frac_seed(fates_pft) ; + fates_trs_repro_frac_seed:units = "fraction" ; + fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; + double fates_trs_seedling_a_emerg(fates_pft) ; + fates_trs_seedling_a_emerg:units = "day -1" ; + fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; + double fates_trs_seedling_b_emerg(fates_pft) ; + fates_trs_seedling_b_emerg:units = "day -1" ; + fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; + double fates_trs_seedling_background_mort(fates_pft) ; + fates_trs_seedling_background_mort:units = "yr-1" ; + fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; + double fates_trs_seedling_h2o_mort_a(fates_pft) ; + fates_trs_seedling_h2o_mort_a:units = "-" ; + fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_b(fates_pft) ; + fates_trs_seedling_h2o_mort_b:units = "-" ; + fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_c(fates_pft) ; + fates_trs_seedling_h2o_mort_c:units = "-" ; + fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_light_mort_a(fates_pft) ; + fates_trs_seedling_light_mort_a:units = "-" ; + fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_mort_b(fates_pft) ; + fates_trs_seedling_light_mort_b:units = "-" ; + fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_rec_a(fates_pft) ; + fates_trs_seedling_light_rec_a:units = "-" ; + fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_light_rec_b(fates_pft) ; + fates_trs_seedling_light_rec_b:units = "-" ; + fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_mdd_crit(fates_pft) ; + fates_trs_seedling_mdd_crit:units = "mm H2O day" ; + fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; + double fates_trs_seedling_par_crit_germ(fates_pft) ; + fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; + fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; + double fates_trs_seedling_psi_crit(fates_pft) ; + fates_trs_seedling_psi_crit:units = "mm H2O" ; + fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; + double fates_trs_seedling_psi_emerg(fates_pft) ; + fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; + fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; + double fates_trs_seedling_root_depth(fates_pft) ; + fates_trs_seedling_root_depth:units = "m" ; + fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + double fates_frag_cwd_frac(fates_NCWD) ; + fates_frag_cwd_frac:units = "fraction" ; + fates_frag_cwd_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_maxpatches_by_landuse(fates_landuseclass) ; + fates_maxpatches_by_landuse:units = "count" ; + fates_maxpatches_by_landuse:long_name = "maximum number of patches per site on each land use type" ; + double fates_canopy_closure_thresh ; + fates_canopy_closure_thresh:units = "unitless" ; + fates_canopy_closure_thresh:long_name = "tree canopy coverage at which crown area allometry changes from savanna to forest value" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_daylength_factor_switch ; + fates_daylength_factor_switch:units = "unitless" ; + fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters (ie scale vcmax and jmax)" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + double fates_hydro_solver ; + fates_hydro_solver:units = "unitless" ; + fates_hydro_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard, 3 = 2D Newton (deprecated)" ; + double fates_landuse_logging_coll_under_frac ; + fates_landuse_logging_coll_under_frac:units = "fraction" ; + fates_landuse_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_thome_time ; + fates_leaf_photo_temp_acclim_thome_time:units = "years" ; + fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_mort_cstarvation_model ; + fates_mort_cstarvation_model:units = "unitless" ; + fates_mort_cstarvation_model:long_name = "switch defining the carbon starvation model ( 1) Linear or 2) Exponential) in the mortality_rates function." ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_rad_model ; + fates_rad_model:units = "unitless" ; + fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; + double fates_regeneration_model ; + fates_regeneration_model:units = "-" ; + fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_trs_seedling2sap_par_timescale ; + fates_trs_seedling2sap_par_timescale:units = "days" ; + fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; + double fates_trs_seedling_emerg_h2o_timescale ; + fates_trs_seedling_emerg_h2o_timescale:units = "days" ; + fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; + double fates_trs_seedling_mdd_timescale ; + fates_trs_seedling_mdd_timescale:units = "days" ; + fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; + double fates_trs_seedling_mort_par_timescale ; + fates_trs_seedling_mort_par_timescale:units = "days" ; + fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_landuseclass_name = + "primaryland", + "secondaryland", + "rangeland", + "pastureland", + "cropland" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + fates_alloc_organ_priority = + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, + 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, + 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, + 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, + 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2h1 = 78.4087704, 306.842667, 106.8745821, 104.3586841, + 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, + 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = 47.6666164, 196.6865691, 93.9790461, 160.6835089, + 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_h2cd1 = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; + + fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; + + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_leafn_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; + + fates_leafn_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43 ; + + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; + + fates_maintresp_leaf_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963 ; + + fates_maintresp_leaf_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_upthresh_cstarvation = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_scale = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_shape = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, + 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; + + fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, + -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; + + fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, + 0.24, 0.24, 0.24, 0.24 ; + + fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, + 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; + + fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371 ; + + fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; + + fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; + + fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; + + fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; + + fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063 ; + + fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, + 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; + + fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, + 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; + + fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, + 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; + + fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, + 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; + + fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7 ; + + fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65 ; + + fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.06, 0.06, 0.06, 0.06 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.548327, 0.44235, 0.454845, 0.754336, 0.548327, + 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_maxpatches_by_landuse = 9, 4, 1, 1, 1 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_daylength_factor_switch = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_thome_time = 30 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; + + fates_maxcohort = 100 ; + + fates_mort_cstarvation_model = 1 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindayson = 90 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_rad_model = 1 ; + + fates_regeneration_model = 1 ; + + fates_soil_salinity = 0.4 ; + + fates_trs_seedling2sap_par_timescale = 32 ; + + fates_trs_seedling_emerg_h2o_timescale = 7 ; + + fates_trs_seedling_mdd_timescale = 126 ; + + fates_trs_seedling_mort_par_timescale = 32 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/archive/api36.0.0_051724_patch_params.xml b/parameter_files/archive/api36.0.0_051724_patch_params.xml index 938bd4bd78..3af518bde2 100644 --- a/parameter_files/archive/api36.0.0_051724_patch_params.xml +++ b/parameter_files/archive/api36.0.0_051724_patch_params.xml @@ -52,14 +52,14 @@ fates_landuse_crop_lu_pft_vector - fates_landuse_class + fates_landuseclass NA the FATES PFT index to use on a given crop land-use type (dummy value of -999 for non-crop types) - 999, -999, -999, -999, 11 + -999, -999, -999, -999, 11 fates_max_nocomp_pfts_by_landuse - fates_landuse_class + fates_landuseclass count maximum number of nocomp PFTs on each land use type (only used in nocomp mode) 4, 4, 1, 1, 1 @@ -67,30 +67,5 @@ fates_landuse_pprodharv10_forest_mean - - - - fates_landuse_harvest_pprod10:units = "fraction" ; - fates_landuse_harvest_pprod10:long_name = "fraction of harvest wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; - double fates_landuse_luc_frac_burned(fates_pft) ; - fates_landuse_luc_frac_burned:units = "fraction" ; - fates_landuse_luc_frac_burned:long_name = "fraction of land use change-generated and not-exported material that is burned (the remainder goes to litter)" ; - - double fates_landuse_luc_frac_exported(fates_pft) ; - fates_landuse_luc_frac_exported:units = "fraction" ; - fates_landuse_luc_frac_exported:long_name = "fraction of land use change-generated wood material that is exported to wood product (the remainder is either burned or goes to litter)" ; - - double fates_landuse_luc_pprod10(fates_pft) ; - fates_landuse_luc_pprod10:units = "fraction" ; - fates_landuse_luc_pprod10:long_name = "fraction of land use change wood product that goes to 10-year product pool (remainder goes to 100-year pool)" ; - -double fates_landuse_crop_lu_pft_vector(fates_landuseclass) ; - fates_landuse_crop_lu_pft_vector:units = "NA" ; - fates_landuse_crop_lu_pft_vector:long_name = "What FATES PFT index to use on a given crop land-use type? (dummy value of -999 for non-crop types)" ; - double fates_max_nocomp_pfts_by_landuse(fates_landuseclass) ; - fates_max_nocomp_pfts_by_landuse:units = "count" ; - fates_max_nocomp_pfts_by_landuse:long_name = "maximum number of nocomp PFTs on each land use type (only used in nocomp mode)" ; - - diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 19f4234436..b66336bbf2 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -704,7 +704,7 @@ variables: fates_frag_cwd_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; double fates_landuse_crop_lu_pft_vector(fates_landuseclass) ; fates_landuse_crop_lu_pft_vector:units = "NA" ; - fates_landuse_crop_lu_pft_vector:long_name = "What FATES PFT index to use on a given crop land-use type? (dummy value of -999 for non-crop types)" ; + fates_landuse_crop_lu_pft_vector:long_name = "the FATES PFT index to use on a given crop land-use type (dummy value of -999 for non-crop types)" ; double fates_max_nocomp_pfts_by_landuse(fates_landuseclass) ; fates_max_nocomp_pfts_by_landuse:units = "count" ; fates_max_nocomp_pfts_by_landuse:long_name = "maximum number of nocomp PFTs on each land use type (only used in nocomp mode)" ; @@ -920,9 +920,7 @@ variables: fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; // global attributes: - :history = "This file was generated by BatchPatchParams.py:\n", - "CDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\n", - "XML patch file = archive/api24.1.0_101722_patch_params.xml" ; + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; data: fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; From 37f02457bb2f52609eb0923510103f696d5a964a Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 20 May 2024 12:31:02 -0600 Subject: [PATCH 248/300] fixed logic on when to initialize patches when not in nocomp-fixedbio --- main/EDInitMod.F90 | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index efef68aae4..49099b7ddf 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -795,7 +795,16 @@ subroutine init_patches( nsites, sites, bc_in) end_landuse_idx = 1 endif - not_all_bareground_if: if ((1._r8 - sites(s)%area_bareground) .gt. nearzero) then + + ! not_all_bareground_if: if ((1._r8 - sites(s)%area_bareground) .gt. nearzero) then + + ! Next, create the non-bareground patches. We do this for either of two scenarios: + ! If 1) we are not doing both nocomp & fixed-biogeo + ! 2) we are, but there is some non-zero bare-ground area + + not_all_bare_if: if( ((1._r8 - sites(s)%area_bareground) > nearzero) .or. & + (.not.(hlm_use_nocomp.eq.itrue .and. hlm_use_fixed_biogeog.eq.itrue)) ) then + ! now make one or more vegetated patches based on nocomp and land use logic luh_state_loop: do i_lu_state = 1, end_landuse_idx lu_state_present_if: if (state_vector(i_lu_state) .gt. nearzero) then @@ -876,7 +885,7 @@ subroutine init_patches( nsites, sites, bc_in) end do new_patch_nocomp_loop end if lu_state_present_if end do luh_state_loop - end if not_all_bareground_if + end if not_all_bare_if ! if we had to skip small patches above, resize things accordingly if ( area_error .gt. nearzero) then @@ -907,7 +916,9 @@ subroutine init_patches( nsites, sites, bc_in) end do else !this is a big error not just a precision error. - write(fates_log(),*) 'issue with patch area in EDinit', area_diff, total + write(fates_log(),*) 'issue with patch area in EDinit', area_diff, total,sites(s)%lat,sites(s)%lon + write(fates_log(),*) 'hlm_use_nocomp: ',hlm_use_nocomp + write(fates_log(),*) 'hlm_use_fixed_biogeog: ',hlm_use_fixed_biogeog newp => sites(s)%oldest_patch do while (associated(newp)) write(fates_log(),*) newp%area, newp%nocomp_pft_label, newp%land_use_label From a997af58f38db8ffda259e11f3abcc65478a4903 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 22 May 2024 11:14:10 -0600 Subject: [PATCH 249/300] updated parameter check to ignore SP --- main/EDPftvarcon.F90 | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 32c7800249..8e10ebdcf7 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -2237,8 +2237,11 @@ subroutine FatesCheckParams(is_master) ! if nocomp is enabled, check to make sure the max number of nocomp PFTs per land use is - ! less than or equal to the max number of patches per land use. - if ( hlm_use_nocomp .eq. itrue ) then + ! less than or equal to the max number of patches per land use. (unless this is an + ! SP run, then all PFTS are tracked on the primary LU and the others are allocated + ! zero patch space + + if ( hlm_use_nocomp .eq. itrue .and. hlm_use_sp.eq.ifalse) then do i_lu = 1, n_landuse_cats if (max_nocomp_pfts_by_landuse(i_lu) .gt. maxpatches_by_landuse(i_lu)) then write(fates_log(),*) 'The max number of nocomp PFTs must all be less than or equal to the number of patches, for a given land use type' From b4ab2836a2f7b387a7dae91959b102ec5ea867db Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 22 May 2024 11:58:16 -0600 Subject: [PATCH 250/300] added memory cleanup to new patch allocated arrays --- biogeochem/FatesPatchMod.F90 | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 8901bfdd41..a8cd18322f 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -316,6 +316,7 @@ subroutine NanValues(this) this%total_canopy_area = nan this%total_tree_area = nan this%zstar = nan + this%elai_profile(:,:,:) = nan this%esai_profile(:,:,:) = nan this%tlai_profile(:,:,:) = nan @@ -679,6 +680,33 @@ subroutine FreeMemory(this, regeneration_model, numpft) this%fragmentation_scaler, & stat=istat, errmsg=smsg) + ! These arrays are allocated in EDCanopyStructureMod + ! while determining how many canopy and leaf layers + ! the patch has. Its possible that patches may + ! be spawned and destroyed before ever reaching + ! that routine, thus we must check to see + ! if the they are already allocated. + if(associated(this%tlai_profile)) then + deallocate(this%tlai_profile) + deallocate(this%tsai_profile) + deallocate(this%elai_profile) + deallocate(this%esai_profile) + deallocate(this%f_sun) + deallocate(this%fabd_sun_z) + deallocate(this%fabd_sha_z) + deallocate(this%fabi_sun_z) + deallocate(this%fabi_sha_z) + deallocate(this%nrmlzd_parprof_pft_dir_z) + deallocate(this%nrmlzd_parprof_pft_dif_z) + deallocate(this%ed_parsun_z) + deallocate(this%ed_parsha_z) + deallocate(this%ed_laisun_z) + deallocate(this%ed_laisha_z) + deallocate(this%parprof_pft_dir_z) + deallocate(this%parprof_pft_dif_z) + deallocate(this%canopy_area_profile) + end if + if (istat/=0) then write(fates_log(),*) 'dealloc009: fail on deallocate patch vectors:'//trim(smsg) call endrun(msg=errMsg(sourcefile, __LINE__)) From 40e67cfc5386220a1df22496c2180b429a92b4b5 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 23 May 2024 11:24:13 -0400 Subject: [PATCH 251/300] Moved patch dynamic reallocations, zeroing and nanning into FatesPatchMod --- biogeochem/EDCanopyStructureMod.F90 | 94 ++----------- biogeochem/FatesPatchMod.F90 | 204 ++++++++++++++++++++++------ 2 files changed, 173 insertions(+), 125 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index a0facdbd7c..d944017198 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1534,12 +1534,7 @@ subroutine leaf_area_profile( currentSite ) integer :: ft ! Plant functional type index. integer :: iv ! Vertical leaf layer index integer :: cl ! Canopy layer index - logical :: re_allocate ! Should we re-allocate the patch arrays? - integer :: prev_nveg ! Previous number of vegetation layers - integer :: nveg ! Number of vegetation layers - integer :: ncan ! Number of canopy layers - integer :: prev_ncan ! Number of canopy layers previously - ! as defined in the allocation space + real(r8) :: fraction_exposed ! how much of this layer is not covered by snow? real(r8) :: frac_canopy(N_HEIGHT_BINS) ! amount of canopy in each height class real(r8) :: minh(N_HEIGHT_BINS) ! minimum height in height class (m) @@ -1568,86 +1563,15 @@ subroutine leaf_area_profile( currentSite ) call UpdatePatchLAI(cpatch) - ! Perform allocations and re-allocations of potentially large patch arrays - ! - ! Note that this routine is called at the very end of dynamics, after trimming - ! and after canopy structure. This is important because we want to allocate - ! the array spaces for leaf area and radiation scattering based on the most - ! updated values. Note, that this routine is also called before we re-initialize - ! radiation scattering during restarts. - ! ------------------------------------------------------------------------ - - ncan = cpatch%ncl_p - nveg = maxval(cpatch%ncan(:,:)) - - ! Assume we will need to allocate, unless the - ! arrays already are allocated and require the same size - re_allocate = .true. - - ! If the large patch arrays are not new, deallocate them - if(associated(cpatch%tlai_profile)) then - - prev_ncan = ubound(cpatch%tlai_profile,1) - prev_nveg = ubound(cpatch%tlai_profile,3) - - ! We re-allocate if the number of canopy layers has changed, or - ! if the number of vegetation layers is larger than previously. - ! However, we also re-allocate if the number of vegetation layers - ! is not just smaller than previously allocated, but A GOOD BIT smaller - ! than previously allocated. Why? - ! We do this so that we are not always re-allocating. - - if( prev_ncan .ne. ncan .or. (nveg>prev_nveg) .or. (nveg shr_infnan_nan, assignment(=) use shr_log_mod, only : errMsg => shr_log_errMsg @@ -105,7 +106,7 @@ module FatesPatchMod ! exposed stem area in each canopy layer, pft, and leaf layer [m2 leaf/m2 contributing crown area] real(r8), allocatable :: esai_profile(:,:,:) ! nclmax,maxpft,nlevleaf) ! total leaf area (includes that which is under snow-pack) - real(r8), pointer :: tlai_profile(:,:,:) ! nclmax,maxpft,nlevleaf) + real(r8), allocatable :: tlai_profile(:,:,:) ! nclmax,maxpft,nlevleaf) ! total stem area (includes that which is under snow-pack) real(r8), allocatable :: tsai_profile(:,:,:) ! nclmax,maxpft,nlevleaf) @@ -231,8 +232,11 @@ module FatesPatchMod contains procedure :: Init - procedure :: NanValues + procedure :: NanValues + procedure :: NanDynamics procedure :: ZeroValues + procedure :: ZeroDynamics + procedure :: ReAllocateDynamics procedure :: InitRunningMeans procedure :: InitLitter procedure :: Create @@ -278,6 +282,137 @@ end subroutine Init !=========================================================================== + subroutine ReAllocateDynamics(this) + + ! ------------------------------------------------------------------------ + ! Perform allocations and re-allocations of potentially large patch arrays + ! + ! Note that this routine is called at the very end of dynamics, after trimming + ! and after canopy structure. This is important because we want to allocate + ! the array spaces for leaf area and radiation scattering based on the most + ! updated values. Note, that this routine is also called before we re-initialize + ! radiation scattering during restarts. + ! ------------------------------------------------------------------------ + + ! arguments + class(fates_patch_type), intent(inout) :: this ! patch object + + ! locals + logical :: re_allocate ! Should we re-allocate the patch arrays? + integer :: prev_nveg ! Previous number of vegetation layers + integer :: nveg ! Number of vegetation layers + integer :: ncan ! Number of canopy layers + integer :: prev_ncan ! Number of canopy layers previously + ! as defined in the allocation space + + ncan = this%ncl_p + nveg = maxval(this%ncan(:,:)) + + ! Assume we will need to allocate, unless the + ! arrays already are allocated and require the same size + re_allocate = .true. + + ! If the large patch arrays are not new, deallocate them + if(allocated(this%elai_profile)) then + + prev_ncan = ubound(this%tlai_profile,1) + prev_nveg = ubound(this%tlai_profile,3) + + ! We re-allocate if the number of canopy layers has changed, or + ! if the number of vegetation layers is larger than previously. + ! However, we also re-allocate if the number of vegetation layers + ! is not just smaller than previously allocated, but A GOOD BIT smaller + ! than previously allocated. Why? + ! We do this so that we are not always re-allocating. + + if( prev_ncan .ne. ncan .or. (nveg>prev_nveg) .or. (nveg Date: Thu, 23 May 2024 15:23:55 -0400 Subject: [PATCH 252/300] Updated nclmax and nlevleaf --- biogeochem/EDCanopyStructureMod.F90 | 4 ++-- main/EDParamsMod.F90 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index d944017198..a101065cf6 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -311,9 +311,9 @@ subroutine canopy_structure( currentSite , bc_in ) ! Save number of canopy layers to the patch structure if(z > nclmax) then - write(fates_log(),*) 'FATES generated more canopy layers than scratch-space allows' + write(fates_log(),*) 'Termination should have ensured number of canopy layers was not larger than nclmax' write(fates_log(),*) 'Predicted: ',z - write(fates_log(),*) 'Scratch space (nclmax, see EDParamsMod.F90): ',nclmax + write(fates_log(),*) 'nclmax: ',nclmax write(fates_log(),*) 'Consider increasing nclmax if this value is to low' write(fates_log(),*) 'and you think this number of canopy layers is reasonable.' call endrun(msg=errMsg(sourcefile, __LINE__)) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index e89257a3f6..a125c81413 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -104,13 +104,13 @@ module EDParamsMod real(r8), parameter, public :: soil_tfrz_thresh = -2.0_r8 ! Soil temperature threshold below which hydraulic failure mortality is off (non-hydro only) in degrees C - integer, parameter, public :: nclmax = 2 !5 ! Maximum number of canopy layers (used only for scratch arrays) + integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers (used only for scratch arrays) ! We would make this even higher, but making this ! a little lower keeps the size down on some output arrays ! For large arrays at patch level we use dynamic allocation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 30 !50 ! number of leaf+stem layers in each canopy layer + integer, parameter, public :: nlevleaf = 60 ! number of leaf+stem layers in each canopy layer real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins From 1889a9ffb11862eb9cb1ab1ef1c10e07e0ce9eb9 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 23 May 2024 16:00:44 -0400 Subject: [PATCH 253/300] Updates and fixes to zeroing and flushing --- main/EDMainMod.F90 | 6 ---- main/FatesHistoryInterfaceMod.F90 | 49 ++++++++++++------------------- main/FatesIOVariableKindMod.F90 | 26 ++++++++++++++-- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 159e942c6a..06e4b74c80 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -166,12 +166,6 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) call currentSite%flux_diags(el)%ZeroFluxDiags() end do - ! zero dynamics (upfreq_in = 1) output history variables - call fates_hist%zero_site_hvars(currentSite,upfreq_in=1) - - ! zero nutrient fluxes (upfreq_in=5) output hist variables - call fates_hist%zero_site_hvars(currentSite,upfreq_in=5) - ! 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/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index fdd459f9c3..45cd3b8a3f 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -33,6 +33,7 @@ module FatesHistoryInterfaceMod use FatesIOVariableKindMod , only : group_dyna_simple, group_dyna_complx use FatesIOVariableKindMod , only : group_hifr_simple, group_hifr_complx use FatesIOVariableKindMod , only : group_hydr_simple, group_hydr_complx + use FatesIOVariableKindMod , only : group_nflx_simple, group_nflx_complx use FatesConstantsMod , only : N_DIST_TYPES use FatesConstantsMod , only : dtype_ifall use FatesConstantsMod , only : dtype_ifire @@ -2093,6 +2094,9 @@ subroutine update_history_nutrflux(this,csite) ! history site index io_si = csite%h_gid + ! zero nutrient fluxes + call this%zero_site_hvars(csite,upfreq_in=group_nflx_simple) + cpatch => csite%youngest_patch do while(associated(cpatch)) @@ -2178,10 +2182,11 @@ subroutine update_history_nutrflux(this,csite) if_dynam2: if(hlm_hist_level_dynam>1) then - ! history site index io_si = csite%h_gid + call this%zero_site_hvars(csite,upfreq_in=group_nflx_complx) + cpatch => csite%youngest_patch do while(associated(cpatch)) @@ -2429,6 +2434,8 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! Loop through the FATES scale hierarchy and fill the history IO arrays ! --------------------------------------------------------------------------------- + call this%flush_hvars(nc,upfreq_in=group_dyna_simple) + siteloop: do s = 1,nsites io_si = sites(s)%h_gid @@ -2436,8 +2443,7 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) site_ba = 0._r8 site_ca = 0._r8 - ! This should be removed from the interface and put here (RGK 04-24) - ! call this%zero_site_hvars(sites(s),upfreq_in=group_dyna_simple) + call this%zero_site_hvars(sites(s),upfreq_in=group_dyna_simple) ! set the fates fraction to one, since it is zero on non-fates columns, & ! the average is the total gridcell fates fraction @@ -3269,10 +3275,14 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! Loop through the FATES scale hierarchy and fill the history IO arrays ! --------------------------------------------------------------------------------- + call this%flush_hvars(nc,upfreq_in=group_dyna_complx) + siteloop: do s = 1,nsites io_si = sites(s)%h_gid + call this%zero_site_hvars(sites(s),upfreq_in=group_dyna_complx) + ! These are weighting factors storen_canopy_scpf(:) = 0._r8 storen_understory_scpf(:) = 0._r8 @@ -3328,7 +3338,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) end if end do - ! Loop through patches to sum up diagonistics ipa = 0 cpatch => sites(s)%oldest_patch @@ -4518,8 +4527,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! Diagnostics discretized by element type ! ------------------------------------------------------------------------------ - hio_cwd_elcwd(io_si,:) = 0._r8 - do el = 1, num_elements flux_diags => sites(s)%flux_diags(el) @@ -4529,17 +4536,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) 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_cwd_ag_elem(io_si,el) = 0._r8 - hio_cwd_bg_elem(io_si,el) = 0._r8 - hio_fines_ag_elem(io_si,el) = 0._r8 - hio_fines_bg_elem(io_si,el) = 0._r8 - - hio_seed_bank_elem(io_si,el) = 0._r8 - hio_seed_germ_elem(io_si,el) = 0._r8 - hio_seed_decay_elem(io_si,el) = 0._r8 - hio_seeds_in_local_elem(io_si,el) = 0._r8 - hio_seed_in_extern_elem(io_si,el) = 0._r8 - hio_litter_out_elem(io_si,el) = 0._r8 ! Plant multi-element states and fluxes ! Zero states, and set the fluxes @@ -4867,10 +4863,6 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) type(fates_cohort_type),pointer :: ccohort - ! This routine is only called for hlm_hist_level_hifrq >= 1 - if(hlm_hist_level_hifrq<1) return - - associate( hio_gpp_si => this%hvars(ih_gpp_si)%r81d, & hio_gpp_secondary_si => this%hvars(ih_gpp_secondary_si)%r81d, & hio_npp_si => this%hvars(ih_npp_si)%r81d, & @@ -4899,9 +4891,8 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_tveg => this%hvars(ih_tveg_si)%r81d) - ! Flush the relevant history variables call this%flush_hvars(nc,upfreq_in=group_hifr_simple) - + dt_tstep_inv = 1.0_r8/dt_tstep allocate(age_area_rad(size(ED_val_history_ageclass_bin_edges,1)+1)) @@ -5142,9 +5133,6 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) type(fates_cohort_type),pointer :: ccohort real(r8) :: dt_tstep_inv ! Time step in frequency units (/s) - ! This routine is only called for hlm_hist_level_hifrq >= 1 - if(hlm_hist_level_hifrq<2) return - associate( hio_ar_si_scpf => this%hvars(ih_ar_si_scpf)%r82d, & hio_ar_grow_si_scpf => this%hvars(ih_ar_grow_si_scpf)%r82d, & hio_ar_maint_si_scpf => this%hvars(ih_ar_maint_si_scpf)%r82d, & @@ -5187,13 +5175,15 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_laisun_si_can => this%hvars(ih_laisun_si_can)%r82d, & hio_laisha_si_can => this%hvars(ih_laisha_si_can)%r82d ) - ! Flush the relevant history variables - call this%flush_hvars(nc,upfreq_in=group_hifr_complx) + call this%flush_hvars(nc,upfreq_in=group_hifr_complx) + dt_tstep_inv = 1.0_r8/dt_tstep do_sites: do s = 1,nsites + call this%zero_site_hvars(sites(s), upfreq_in=group_hifr_complx) + site_area_veg_inv = 0._r8 cpatch => sites(s)%oldest_patch do while(associated(cpatch)) @@ -5617,7 +5607,6 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) if_hifrq0: if(hlm_hist_level_hifrq>0) then - ! Flush the relevant history variables call this%flush_hvars(nc,upfreq_in=group_hydr_simple) associate( hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d, & @@ -5810,8 +5799,6 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) hio_rootuptake10_scpf(io_si,iscpf) = site_hydr%rootuptake10_scpf(iscls,ipft) * ha_per_m2 hio_rootuptake50_scpf(io_si,iscpf) = site_hydr%rootuptake50_scpf(iscls,ipft) * ha_per_m2 hio_rootuptake100_scpf(io_si,iscpf) = site_hydr%rootuptake100_scpf(iscls,ipft) * ha_per_m2 - hio_iterh1_scpf(io_si,iscpf) = 0._r8 - hio_iterh2_scpf(io_si,iscpf) = 0._r8 end do end do diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index 61e2c93c9d..75ea7dbe57 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -51,16 +51,36 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_elcwd_r8 = 'SI_ELEMCWD_R8' character(*), parameter, public :: site_elage_r8 = 'SI_ELEMAGE_R8' - + ! ------------------------------------------------------------------ + ! + ! History Variable Groups + ! ! These are group indices for output variables. We use ! these groups to do things like zero-ing and initializing - + ! + ! These groups are updated at the dynamics (daily) step + ! so they are turned on and off with dimlevel(2) + ! + ! active when dimlevel(2)>0 integer, parameter, public :: group_dyna_simple = 1 + integer, parameter, public :: group_nflx_simple = 7 + + ! active when dimlevel(2)>1 integer, parameter, public :: group_dyna_complx = 2 + integer, parameter, public :: group_nflx_complx = 8 + + ! These groups are updated at the fast step + ! so they are turned on and off with dimlevel(1) + ! + ! active when dimlevel(1)>0 integer, parameter, public :: group_hifr_simple = 3 - integer, parameter, public :: group_hifr_complx = 4 integer, parameter, public :: group_hydr_simple = 5 + + ! active when dimlevel(1)>1 + integer, parameter, public :: group_hifr_complx = 4 integer, parameter, public :: group_hydr_complx = 6 + + ! ------------------------------------------------------------------- ! NOTE(RGK, 2016) %active is not used yet. Was intended as a check on the HLM->FATES ! control parameter passing to ensure all active dimension types received all From 7d0876d93708a2865b674cb68b4302e132611a35 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 23 May 2024 16:16:29 -0400 Subject: [PATCH 254/300] updated the group_nflx_ specifications for the variables --- main/FatesHistoryInterfaceMod.F90 | 40 ++++++++++++++++++------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 45cd3b8a3f..62680890b4 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2165,7 +2165,9 @@ subroutine update_history_nutrflux(this,csite) ! 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 @@ -6366,31 +6368,31 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_NH4UPTAKE', units='kg m-2 s-1', & long='ammonium uptake rate by plants in kg NH4 per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_nh4uptake_si) call this%set_history_var(vname='FATES_NO3UPTAKE', units='kg m-2 s-1', & long='nitrate uptake rate by plants in kg NO3 per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_no3uptake_si) call this%set_history_var(vname='FATES_NEFFLUX', units='kg m-2 s-1', & long='nitrogen effluxed from plant in kg N per m2 per second (unused)', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_dyna_simple, ivar=ivar, initialize=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_dyna_simple, ivar=ivar, initialize=initialize_variables, & + 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', & - upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_nfix_si) call this%set_history_var(vname='FATES_STOREN', units='kg m-2', & @@ -6475,19 +6477,19 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='FATES_PUPTAKE', units='kg m-2 s-1', & long='mineralized phosphorus uptake rate of plants in kg P per m2 per second', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_puptake_si) call this%set_history_var(vname='FATES_PEFFLUX', units='kg m-2 s-1', & long='phosphorus effluxed from plant in kg P per m2 per second (unused)', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_dyna_simple, ivar=ivar, initialize=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_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_pdemand_si) end if phosphorus_active_if0 @@ -6583,11 +6585,15 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_r8, hlms='CLM:ALM', upfreq=group_dyna_simple, & ivar=ivar, initialize=initialize_variables, index = ih_harvest_debt_sec_si ) + ! Nutrient flux variables (dynamics call frequency) + ! ---------------------------------------------------- call this%set_history_var(vname='FATES_EXCESS_RESP', units='kg m-2 s-1', & long='respiration of un-allocatable carbon gain', & use_default='active', avgflag='A', vtype=site_r8, hlms='CLM:ALM', & - upfreq=group_dyna_simple, ivar=ivar, initialize=initialize_variables, & + upfreq=group_nflx_simple, ivar=ivar, initialize=initialize_variables, & index = ih_excess_resp_si) + + ! slow carbon fluxes associated with mortality from or transfer betweeen canopy and understory call this%set_history_var(vname='FATES_DEMOTION_CARBONFLUX', & @@ -7098,32 +7104,32 @@ subroutine define_history_vars(this, initialize_variables) units='kg m-2 s-1', & long='ammonium uptake rate by plants by size-class x pft in kg NH4 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & initialize=initialize_variables, index = ih_nh4uptake_scpf) call this%set_history_var(vname='FATES_NO3UPTAKE_SZPF', & units='kg m-2 s-1', & long='nitrate uptake rate by plants by size-class x pft in kg NO3 per m2 per second', & use_default='inactive', avgflag='A', vtype=site_size_pft_r8, & - hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & initialize=initialize_variables, index = ih_no3uptake_scpf) call this%set_history_var(vname='FATES_NEFFLUX_SZPF', units='kg m-2 s-1', & long='nitrogen efflux, root to soil, 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_dyna_complx, ivar=ivar, & + 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_dyna_complx, ivar=ivar, & + 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, & - hlms='CLM:ALM', upfreq=group_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & initialize=initialize_variables, index = ih_nfix_scpf) call this%set_history_var(vname='FATES_VEGN_SZPF', units='kg m-2', & @@ -7235,20 +7241,20 @@ subroutine define_history_vars(this, initialize_variables) units='kg m-2 s-1', & long='phosphorus uptake rate by plants, 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_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & initialize=initialize_variables, index = ih_puptake_scpf) call this%set_history_var(vname='FATES_PEFFLUX_SZPF', & units='kg m-2 s-1', & long='phosphorus efflux, root to soil, 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_dyna_complx, ivar=ivar, & + 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_dyna_complx, ivar=ivar, & + hlms='CLM:ALM', upfreq=group_nflx_complx, ivar=ivar, & initialize=initialize_variables, index = ih_pdemand_scpf) end if phosphorus_active_if1 From c82918fb5c25a7d96af77d6aa7884f65854c27da Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 28 May 2024 12:17:36 -0600 Subject: [PATCH 255/300] Removed unnecessary dynamics flushing --- main/FatesHistoryInterfaceMod.F90 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 62680890b4..8defbcb3dd 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2436,8 +2436,6 @@ subroutine update_history_dyn1(this,nc,nsites,sites,bc_in) ! Loop through the FATES scale hierarchy and fill the history IO arrays ! --------------------------------------------------------------------------------- - call this%flush_hvars(nc,upfreq_in=group_dyna_simple) - siteloop: do s = 1,nsites io_si = sites(s)%h_gid @@ -3277,7 +3275,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! Loop through the FATES scale hierarchy and fill the history IO arrays ! --------------------------------------------------------------------------------- - call this%flush_hvars(nc,upfreq_in=group_dyna_complx) siteloop: do s = 1,nsites @@ -4893,6 +4890,7 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_tveg => this%hvars(ih_tveg_si)%r81d) + ! Move this to the interface for consistency (rgk 0524) call this%flush_hvars(nc,upfreq_in=group_hifr_simple) dt_tstep_inv = 1.0_r8/dt_tstep @@ -5178,6 +5176,7 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_laisha_si_can => this%hvars(ih_laisha_si_can)%r82d ) + ! Move this to the interface for consistency (rgk 0524) call this%flush_hvars(nc,upfreq_in=group_hifr_complx) dt_tstep_inv = 1.0_r8/dt_tstep @@ -5609,6 +5608,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) if_hifrq0: if(hlm_hist_level_hifrq>0) then + ! Move this to the interface for consistency (rgk 0524) call this%flush_hvars(nc,upfreq_in=group_hydr_simple) associate( hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d, & @@ -5715,6 +5715,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) hio_rootuptake50_scpf => this%hvars(ih_rootuptake50_scpf)%r82d, & hio_rootuptake100_scpf => this%hvars(ih_rootuptake100_scpf)%r82d ) + ! Move this to the interface for consistency (rgk 0524) call this%flush_hvars(nc,upfreq_in=group_hydr_complx) do s = 1,nsites From b9a8f432f24185c59a8524cbff89b781e0c73a7a Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 28 May 2024 13:23:50 -0600 Subject: [PATCH 256/300] Added flush_all_hvars to be used by interface calls in cold-start and restart sequences --- main/FatesHistoryInterfaceMod.F90 | 36 ++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 8defbcb3dd..2ea35e2ce8 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -900,7 +900,7 @@ module FatesHistoryInterfaceMod procedure, public :: flush_hvars procedure, public :: zero_site_hvars - + procedure, public :: flush_all_hvars end type fates_history_interface_type @@ -1812,6 +1812,40 @@ subroutine zero_site_hvars(this, currentSite, upfreq_in) return end subroutine zero_site_hvars + + ! ====================================================================================== + + subroutine flush_all_hvars(this,nc) + + ! A wrapper to flush all active history + ! groups to their flush value + + class(fates_history_interface_type) :: this + integer,intent(in) :: nc + + if(hlm_hist_level_hifrq>0) then + call this%flush_hvars(nc,upfreq_in=group_hifr_simple) + if (hlm_use_planthydro.eq.itrue) call this%flush_hvars(nc,upfreq_in=group_hydr_simple) + end if + if(hlm_hist_level_hifrq>1) then + call this%flush_hvars(nc,upfreq_in=group_hifr_complx) + if (hlm_use_planthydro.eq.itrue) call this%flush_hvars(nc,upfreq_in=group_hydr_complx) + end if + end if + end if + + if(hlm_hist_level_dynam>0) then + call this%flush_hvars(nc,upfreq_in=group_dyna_simple) + call this%flush_hvars(nc,upfreq_in=group_nflx_simple) + if(hlm_hist_level_dynam>1) then + call this%flush_hvars(nc,upfreq_in=group_dyna_complx) + call this%flush_hvars(nc,upfreq_in=group_nflx_complx) + end if + end if + + return + end subroutine flush_all_hvars + ! ====================================================================================== subroutine flush_hvars(this,nc,upfreq_in) From 3d799f9e9f61f08959c7c2fcec2e0f800b542040 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 28 May 2024 17:53:59 -0600 Subject: [PATCH 257/300] bug fix for history refactors --- main/FatesHistoryInterfaceMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 2ea35e2ce8..fef7cc2cad 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1826,11 +1826,9 @@ subroutine flush_all_hvars(this,nc) if(hlm_hist_level_hifrq>0) then call this%flush_hvars(nc,upfreq_in=group_hifr_simple) if (hlm_use_planthydro.eq.itrue) call this%flush_hvars(nc,upfreq_in=group_hydr_simple) - end if if(hlm_hist_level_hifrq>1) then call this%flush_hvars(nc,upfreq_in=group_hifr_complx) if (hlm_use_planthydro.eq.itrue) call this%flush_hvars(nc,upfreq_in=group_hydr_complx) - end if end if end if From 9d8f4040a6f7d3f99942111cbbc81b138dc827c0 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 29 May 2024 08:30:37 -0600 Subject: [PATCH 258/300] updates to c13 disc --- main/FatesHistoryInterfaceMod.F90 | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index fef7cc2cad..4f345e24f9 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3069,8 +3069,9 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) integer :: iscagpft ! size-class x age x pft index integer :: icdpf, icdsc, icdam ! iterators for the crown damage level integer :: i_agefuel ! age x fuel size class index - real(r8) :: gpp_cached ! variable used to cache gpp value in previous time step; for C13 discrimination + real(r8) :: gpp_cached ! gpp from previous timestep, for c13 discrimination real(r8) :: crown_depth ! Depth of the crown [m] + real(r8) :: gpp_cached_scpf(numpft*nlevsclass) ! variable used to cache gpp value in previous time step; for C13 discrimination real(r8) :: storen_canopy_scpf(numpft*nlevsclass) real(r8) :: storen_understory_scpf(numpft*nlevsclass) real(r8) :: storep_canopy_scpf(numpft*nlevsclass) @@ -3312,6 +3313,11 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) io_si = sites(s)%h_gid + ! C13 will not get b4b restarts on the first day because + ! there is no mechanism to remember the previous day's values + ! through a restart. This should be added with the next refactor + gpp_cached_scpf(:) = hio_gpp_si_scpf(io_si,:) + call this%zero_site_hvars(sites(s),upfreq_in=group_dyna_complx) ! These are weighting factors @@ -3680,9 +3686,6 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) capf => ccohort%coage_by_pft_class, & cdam => ccohort%crowndamage) - gpp_cached = (hio_gpp_si_scpf(io_si,scpf)) * & - days_per_year * sec_per_day - ! [kgC/m2/s] hio_gpp_si_scpf(io_si,scpf) = hio_gpp_si_scpf(io_si,scpf) + & n_perm2*ccohort%gpp_acc_hold / days_per_year / sec_per_day @@ -3786,12 +3789,16 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) end if !C13 discrimination - if(gpp_cached + ccohort%gpp_acc_hold > 0.0_r8)then + if(abs(gpp_cached_scpf(scpf)-hlm_hio_ignore_val)>nearzero .and. & + (gpp_cached_scpf(scpf) + ccohort%gpp_acc_hold) > 0.0_r8) then + + gpp_cached = gpp_cached_scpf(scpf)*days_per_year*sec_per_day + hio_c13disc_si_scpf(io_si,scpf) = ((hio_c13disc_si_scpf(io_si,scpf) * gpp_cached) + & (ccohort%c13disc_acc * ccohort%gpp_acc_hold)) / (gpp_cached + ccohort%gpp_acc_hold) else hio_c13disc_si_scpf(io_si,scpf) = 0.0_r8 - endif + end if ! number density [/m2] hio_nplant_si_scpf(io_si,scpf) = hio_nplant_si_scpf(io_si,scpf) + ccohort%n / m2_per_ha From 7a3c437861dffbde2115bbfec2c9dfddb840e911 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 29 May 2024 10:15:47 -0600 Subject: [PATCH 259/300] update to cached gpp in c13 disc --- main/EDTypesMod.F90 | 21 +++++++++++++++-- main/FatesHistoryInterfaceMod.F90 | 38 +++++++++++++++++++------------ 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 9c92871f1f..b482370058 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -150,8 +150,13 @@ module EDTypesMod type, public :: site_fluxdiags_type ! ---------------------------------------------------------------------------------- - ! Diagnostics for fluxes into the litter pool from plants - ! these fluxes are the total from + ! Diagnostics of fluxes + ! These act as an intermediary to write fluxes to the history + ! 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 @@ -162,6 +167,13 @@ module EDTypesMod real(r8) :: cwd_bg_input(1:ncwd) real(r8),allocatable :: leaf_litter_input(:) real(r8),allocatable :: root_litter_input(:) + + ! 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(:) + contains @@ -464,6 +476,11 @@ subroutine ZeroFluxDiags(this) 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 + return end subroutine ZeroFluxDiags diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 4f345e24f9..cf46ac8130 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -3651,16 +3651,16 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) ! update pft-resolved NPP and GPP fluxes hio_gpp_si_pft(io_si, ft) = hio_gpp_si_pft(io_si, ft) + & - ccohort%gpp_acc_hold * n_perm2 / days_per_year / sec_per_day + ccohort%gpp_acc_hold * n_perm2 / (days_per_year* sec_per_day) hio_npp_si_pft(io_si, ft) = hio_npp_si_pft(io_si, ft) + & - ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + ccohort%npp_acc_hold * n_perm2 / (days_per_year*sec_per_day) if ( cpatch%land_use_label .eq. secondaryland ) then hio_gpp_sec_si_pft(io_si, ft) = hio_gpp_sec_si_pft(io_si, ft) + & - ccohort%gpp_acc_hold * n_perm2 / days_per_year / sec_per_day + ccohort%gpp_acc_hold * n_perm2 / (days_per_year*sec_per_day) hio_npp_sec_si_pft(io_si, ft) = hio_npp_sec_si_pft(io_si, ft) + & - ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + ccohort%npp_acc_hold * n_perm2 / (days_per_year*sec_per_day) end if ! Turnover pools [kgC/day] * [day/yr] = [kgC/yr] @@ -3686,32 +3686,40 @@ subroutine update_history_dyn2(this,nc,nsites,sites,bc_in) capf => ccohort%coage_by_pft_class, & cdam => ccohort%crowndamage) - ! [kgC/m2/s] + ! convert [kgC/plant/year] -> [kgC/m2/s] hio_gpp_si_scpf(io_si,scpf) = hio_gpp_si_scpf(io_si,scpf) + & - n_perm2*ccohort%gpp_acc_hold / days_per_year / sec_per_day + n_perm2*ccohort%gpp_acc_hold / (days_per_year*sec_per_day) + hio_npp_totl_si_scpf(io_si,scpf) = hio_npp_totl_si_scpf(io_si,scpf) + & - ccohort%npp_acc_hold * n_perm2 / days_per_year / sec_per_day + ccohort%npp_acc_hold * n_perm2 / (days_per_year*sec_per_day) hio_npp_leaf_si_scpf(io_si,scpf) = hio_npp_leaf_si_scpf(io_si,scpf) + & - leaf_m_net_alloc*n_perm2 / days_per_year / sec_per_day + leaf_m_net_alloc*n_perm2 / (days_per_year*sec_per_day) + hio_npp_fnrt_si_scpf(io_si,scpf) = hio_npp_fnrt_si_scpf(io_si,scpf) + & - fnrt_m_net_alloc*n_perm2 / days_per_year / sec_per_day + fnrt_m_net_alloc*n_perm2 / (days_per_year*sec_per_day) + hio_npp_bgsw_si_scpf(io_si,scpf) = hio_npp_bgsw_si_scpf(io_si,scpf) + & sapw_m_net_alloc*n_perm2*(1._r8-prt_params%allom_agb_frac(ccohort%pft)) / & - days_per_year / sec_per_day + (days_per_year*sec_per_day) + hio_npp_agsw_si_scpf(io_si,scpf) = hio_npp_agsw_si_scpf(io_si,scpf) + & sapw_m_net_alloc*n_perm2*prt_params%allom_agb_frac(ccohort%pft) / & - days_per_year / sec_per_day + (days_per_year*sec_per_day) + hio_npp_bgdw_si_scpf(io_si,scpf) = hio_npp_bgdw_si_scpf(io_si,scpf) + & struct_m_net_alloc*n_perm2*(1._r8-prt_params%allom_agb_frac(ccohort%pft)) / & - days_per_year / sec_per_day + (days_per_year*sec_per_day) + hio_npp_agdw_si_scpf(io_si,scpf) = hio_npp_agdw_si_scpf(io_si,scpf) + & struct_m_net_alloc*n_perm2*prt_params%allom_agb_frac(ccohort%pft) / & - days_per_year / sec_per_day + (days_per_year*sec_per_day) + hio_npp_seed_si_scpf(io_si,scpf) = hio_npp_seed_si_scpf(io_si,scpf) + & - repro_m_net_alloc*n_perm2 / days_per_year / sec_per_day + repro_m_net_alloc*n_perm2 / (days_per_year*sec_per_day) + hio_npp_stor_si_scpf(io_si,scpf) = hio_npp_stor_si_scpf(io_si,scpf) + & - store_m_net_alloc*n_perm2 / days_per_year / sec_per_day + store_m_net_alloc*n_perm2 / (days_per_year*sec_per_day) ! Woody State Variables (basal area growth increment) if ( prt_params%woody(ft) == itrue) then From d38bc5986bd8963642f656b6ed0d04935fcd53b0 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 29 May 2024 16:37:45 -0600 Subject: [PATCH 260/300] remove merge conflict artifacts --- main/EDTypesMod.F90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 2e5b98a0d1..d8a0eb5e73 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -464,11 +464,7 @@ module EDTypesMod procedure, public :: get_current_landuse_statevector procedure, public :: get_secondary_young_fraction -<<<<<<< HEAD - -======= ->>>>>>> 827ab3f1d63f710f8819d4329253d0a7d75a4bed end type ed_site_type ! Make public necessary subroutines and functions From 9d8628e1d7cb79d235dff93ace8ab4f0c79cf330 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 30 May 2024 12:24:28 -0600 Subject: [PATCH 261/300] shortened some restart var names --- main/FatesRestartInterfaceMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 57b0bd6ea9..3f7e8375fe 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1157,12 +1157,12 @@ subroutine define_restart_vars(this, initialize_variables) end if - call this%RegisterCohortVector(symbol_base='fates_woodproduct_harvest', vtype=cohort_r8, & + call this%RegisterCohortVector(symbol_base='fates_woodprod_harv', vtype=cohort_r8, & long_name_base='Current wood product flux from harvest', & units='kg/m2/day', veclength=num_elements, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_woodprod_harvest_mbal) - call this%RegisterCohortVector(symbol_base='fates_woodproduct_landusechange', vtype=cohort_r8, & + call this%RegisterCohortVector(symbol_base='fates_woodprod_luc', vtype=cohort_r8, & long_name_base='Current wood product flux from land use change', & units='kg/m2/day', veclength=num_elements, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_woodprod_landusechange_mbal) From 9c2444ffe393dbf49bebfbc301cef7e6269a63ff Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 4 Jun 2024 11:12:57 -0700 Subject: [PATCH 262/300] change nocomp_pft_area_vector check to first diff then sum for better precision --- biogeochem/EDPatchDynamicsMod.F90 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index a6e05617be..38a5c16793 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1472,7 +1472,7 @@ subroutine spawn_patches( currentSite, bc_in) buffer_patch_used_if: if ( buffer_patch_used ) then ! at this point, lets check that the total patch area remaining to be relabelled equals what we think that it is. - if (abs(sum(nocomp_pft_area_vector(:)) - sum(nocomp_pft_area_vector_filled(:)) - buffer_patch%area) .gt. rsnbl_math_prec) then + if (abs(sum(nocomp_pft_area_vector(:) - nocomp_pft_area_vector_filled(:)) - buffer_patch%area) .gt. rsnbl_math_prec) then write(fates_log(),*) 'midway through patch reallocation and things are already not adding up.', i_land_use_label write(fates_log(),*) currentSite%area_pft(:,i_land_use_label) write(fates_log(),*) '-----' @@ -1552,7 +1552,7 @@ subroutine spawn_patches( currentSite, bc_in) write(fates_log(),*) 'Buffer patch still has area and it wasnt put into the linked list' write(fates_log(),*) 'buffer_patch%area', buffer_patch%area write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)), sum(nocomp_pft_area_vector(:)) - write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:)) + write(fates_log(),*) sum(nocomp_pft_area_vector_filled(:) - nocomp_pft_area_vector(:)) call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1568,8 +1568,8 @@ subroutine spawn_patches( currentSite, bc_in) end if buffer_patch_used_if ! check that the area we have added is the same as the area we have taken away. if not, crash. - if ( abs(sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:))) .gt. rsnbl_math_prec) then - write(fates_log(),*) 'patch reallocation logic doesnt add up. difference is: ', sum(nocomp_pft_area_vector_filled(:)) - sum(nocomp_pft_area_vector(:)) + if ( abs(sum(nocomp_pft_area_vector_filled(:) - nocomp_pft_area_vector(:))) .gt. rsnbl_math_prec) then + write(fates_log(),*) 'patch reallocation logic doesnt add up. difference is: ', sum(nocomp_pft_area_vector_filled(:) - nocomp_pft_area_vector(:)) write(fates_log(),*) nocomp_pft_area_vector_filled write(fates_log(),*) nocomp_pft_area_vector write(fates_log(),*) i_land_use_label From 737e81d3015eaf3fb83b7c6823b26d9208940c9a Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 5 Jun 2024 22:47:26 -0600 Subject: [PATCH 263/300] change check for buffer split to use fraction to keep --- biogeochem/EDPatchDynamicsMod.F90 | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 38a5c16793..40ca2ba7e4 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1499,15 +1499,19 @@ subroutine spawn_patches( currentSite, bc_in) if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then ! newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) + ! only bother doing this if the new new patch area needed is greater than some tiny amount if ( newp_area .gt. rsnbl_math_prec * 0.01_r8) then - ! - if (buffer_patch%area - newp_area .gt. rsnbl_math_prec * 0.01_r8) then + + ! Compute fraction to keep in buffer + fraction_to_keep = (buffer_patch%area - newp_area) / buffer_patch%area + + if (fraction_to_keep .gt. rsnbl_math_prec) then ! split buffer patch in two, keeping the smaller buffer patch to put into new patches allocate(temp_patch) - call split_patch(currentSite, buffer_patch, temp_patch, (1._r8 - newp_area/buffer_patch%area)) + call split_patch(currentSite, buffer_patch, temp_patch, fraction_to_keep) ! give the new patch the intended nocomp PFT label temp_patch%nocomp_pft_label = i_pft From 4b018eade498d063b21dddf26f77c9658ff80261 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 6 Jun 2024 16:53:16 -0600 Subject: [PATCH 264/300] add check to avoid bareground patches This avoids an out-of-bounds indexing error when in landuse mode --- biogeochem/FatesSoilBGCFluxMod.F90 | 175 +++++++++++++++-------------- 1 file changed, 88 insertions(+), 87 deletions(-) diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index 9d813c32b3..2c5b7d9b18 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -69,6 +69,7 @@ module FatesSoilBGCFluxMod use FatesConstantsMod, only : sec_per_day use FatesConstantsMod, only : years_per_day use FatesConstantsMod, only : itrue + use FatesConstantsMod, only : nocomp_bareground use FatesLitterMod, only : litter_type use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy @@ -287,107 +288,107 @@ subroutine PrepCH4BCs(csite,bc_in,bc_out) fp = 0 cpatch => csite%oldest_patch do while (associated(cpatch)) - - ! Patch ordering when passing boundary conditions - ! always goes from oldest to youngest, following - ! the convention of EDPatchDynamics::set_patchno() - - fp = fp + 1 - - agnpp = 0._r8 - bgnpp = 0._r8 - woody_area = 0._r8 - plant_area = 0._r8 - - ccohort => cpatch%tallest - do while (associated(ccohort)) + if_notbare: if(cpatch%nocomp_pft_label .ne. nocomp_bareground)then + ! Patch ordering when passing boundary conditions + ! always goes from oldest to youngest, following + ! the convention of EDPatchDynamics::set_patchno() - ! For consistency, only apply calculations to non-new - ! cohorts. New cohorts will not have respiration rates - ! at this point in the call sequence. + fp = fp + 1 - if(.not.ccohort%isnew) then - - pft = ccohort%pft - - call set_root_fraction(csite%rootfrac_scr, pft, csite%zi_soil, & - bc_in%max_rooting_depth_index_col ) - - fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) - - ! [kgC/day] - sapw_net_alloc = ccohort%prt%GetNetAlloc(sapw_organ, carbon12_element) * days_per_sec - store_net_alloc = ccohort%prt%GetNetAlloc(store_organ, carbon12_element) * days_per_sec - leaf_net_alloc = ccohort%prt%GetNetAlloc(leaf_organ, carbon12_element) * days_per_sec - fnrt_net_alloc = ccohort%prt%GetNetAlloc(fnrt_organ, carbon12_element) * days_per_sec - struct_net_alloc = ccohort%prt%GetNetAlloc(struct_organ, carbon12_element) * days_per_sec - repro_net_alloc = ccohort%prt%GetNetAlloc(repro_organ, carbon12_element) * days_per_sec - - ! [kgC/plant/day] -> [gC/m2/s] - agnpp = agnpp + ccohort%n/cpatch%area * (leaf_net_alloc + repro_net_alloc + & - prt_params%allom_agb_frac(pft)*(sapw_net_alloc+store_net_alloc+struct_net_alloc)) * g_per_kg + agnpp = 0._r8 + bgnpp = 0._r8 + woody_area = 0._r8 + plant_area = 0._r8 + + ccohort => cpatch%tallest + do while (associated(ccohort)) - ! [kgC/plant/day] -> [gC/m2/s] - bgnpp = bgnpp + ccohort%n/cpatch%area * (fnrt_net_alloc + & - (1._r8-prt_params%allom_agb_frac(pft))*(sapw_net_alloc+store_net_alloc+struct_net_alloc)) * g_per_kg + ! For consistency, only apply calculations to non-new + ! cohorts. New cohorts will not have respiration rates + ! at this point in the call sequence. - if(hlm_use_ch4==itrue)then + if(.not.ccohort%isnew) then - ! Fine root fraction over depth - bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) = & - bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) + & - csite%rootfrac_scr(1:bc_in%nlevsoil) + pft = ccohort%pft + + call set_root_fraction(csite%rootfrac_scr, pft, csite%zi_soil, & + bc_in%max_rooting_depth_index_col ) + + fnrt_c = ccohort%prt%GetState(fnrt_organ, carbon12_element) + + ! [kgC/day] + sapw_net_alloc = ccohort%prt%GetNetAlloc(sapw_organ, carbon12_element) * days_per_sec + store_net_alloc = ccohort%prt%GetNetAlloc(store_organ, carbon12_element) * days_per_sec + leaf_net_alloc = ccohort%prt%GetNetAlloc(leaf_organ, carbon12_element) * days_per_sec + fnrt_net_alloc = ccohort%prt%GetNetAlloc(fnrt_organ, carbon12_element) * days_per_sec + struct_net_alloc = ccohort%prt%GetNetAlloc(struct_organ, carbon12_element) * days_per_sec + repro_net_alloc = ccohort%prt%GetNetAlloc(repro_organ, carbon12_element) * days_per_sec + + ! [kgC/plant/day] -> [gC/m2/s] + agnpp = agnpp + ccohort%n/cpatch%area * (leaf_net_alloc + repro_net_alloc + & + prt_params%allom_agb_frac(pft)*(sapw_net_alloc+store_net_alloc+struct_net_alloc)) * g_per_kg + + ! [kgC/plant/day] -> [gC/m2/s] + bgnpp = bgnpp + ccohort%n/cpatch%area * (fnrt_net_alloc + & + (1._r8-prt_params%allom_agb_frac(pft))*(sapw_net_alloc+store_net_alloc+struct_net_alloc)) * g_per_kg - ! Fine root carbon, convert [kg/plant] -> [g/m2] - bc_out%frootc_pa(fp) = & - bc_out%frootc_pa(fp) + & - fnrt_c*ccohort%n/cpatch%area * g_per_kg + if(hlm_use_ch4==itrue)then + + ! Fine root fraction over depth + bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) = & + bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) + & + csite%rootfrac_scr(1:bc_in%nlevsoil) + + ! Fine root carbon, convert [kg/plant] -> [g/m2] + bc_out%frootc_pa(fp) = & + bc_out%frootc_pa(fp) + & + fnrt_c*ccohort%n/cpatch%area * g_per_kg + + ! (gC/m2/s) root respiration (fine root MR + total root GR) + ! RGK: We do not save root respiration and average over the day. Until we do + ! this is a best (bad) guess at fine root MR + total root GR + ! (kgC/indiv/yr) -> gC/m2/s + bc_out%root_resp(1:bc_in%nlevsoil) = bc_out%root_resp(1:bc_in%nlevsoil) + & + ccohort%resp_acc_hold*years_per_day*g_per_kg*days_per_sec* & + ccohort%n*area_inv*(1._r8-prt_params%allom_agb_frac(pft)) * csite%rootfrac_scr(1:bc_in%nlevsoil) + + end if + + if( prt_params%woody(pft)==itrue ) then + woody_area = woody_area + ccohort%c_area + end if + plant_area = plant_area + ccohort%c_area - ! (gC/m2/s) root respiration (fine root MR + total root GR) - ! RGK: We do not save root respiration and average over the day. Until we do - ! this is a best (bad) guess at fine root MR + total root GR - ! (kgC/indiv/yr) -> gC/m2/s - bc_out%root_resp(1:bc_in%nlevsoil) = bc_out%root_resp(1:bc_in%nlevsoil) + & - ccohort%resp_acc_hold*years_per_day*g_per_kg*days_per_sec* & - ccohort%n*area_inv*(1._r8-prt_params%allom_agb_frac(pft)) * csite%rootfrac_scr(1:bc_in%nlevsoil) end if - if( prt_params%woody(pft)==itrue ) then - woody_area = woody_area + ccohort%c_area + ccohort => ccohort%shorter + end do + + if(hlm_use_ch4==itrue)then + if( sum(bc_out%rootfr_pa(fp,1:bc_in%nlevsoil)) > nearzero) then + bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) = & + bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) / & + sum(bc_out%rootfr_pa(fp,1:bc_in%nlevsoil)) end if - plant_area = plant_area + ccohort%c_area + ! RGK: These averages should switch to the new patch averaging methods + ! when available. Right now we are not doing any time averaging + ! because it would be mixing the memory of patches, which + ! would be arguably worse than just using the instantaneous value - end if - - ccohort => ccohort%shorter - end do - - if(hlm_use_ch4==itrue)then - if( sum(bc_out%rootfr_pa(fp,1:bc_in%nlevsoil)) > nearzero) then - bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) = & - bc_out%rootfr_pa(fp,1:bc_in%nlevsoil) / & - sum(bc_out%rootfr_pa(fp,1:bc_in%nlevsoil)) - end if - - ! RGK: These averages should switch to the new patch averaging methods - ! when available. Right now we are not doing any time averaging - ! because it would be mixing the memory of patches, which - ! would be arguably worse than just using the instantaneous value - - ! gC/m2/s - bc_out%annavg_agnpp_pa(fp) = agnpp - bc_out%annavg_bgnpp_pa(fp) = bgnpp - ! gc/m2/yr - bc_out%annsum_npp_pa(fp) = (bgnpp+agnpp)*days_per_year*sec_per_day - - if(plant_area>nearzero) then - bc_out%woody_frac_aere_pa(fp) = woody_area/plant_area - end if + ! gC/m2/s + bc_out%annavg_agnpp_pa(fp) = agnpp + bc_out%annavg_bgnpp_pa(fp) = bgnpp + ! gc/m2/yr + bc_out%annsum_npp_pa(fp) = (bgnpp+agnpp)*days_per_year*sec_per_day + + if(plant_area>nearzero) then + bc_out%woody_frac_aere_pa(fp) = woody_area/plant_area + end if - end if - + end if + end if if_notbare cpatch => cpatch%younger end do From e407b81d3c0a9c8a3dede0dcd48df9c6dd3ee4bb Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 10 Jun 2024 11:57:07 -0600 Subject: [PATCH 265/300] Updated some text --- main/FatesHistoryInterfaceMod.F90 | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index cf46ac8130..156da135c2 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -4937,7 +4937,8 @@ subroutine update_history_hifrq1(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_tveg => this%hvars(ih_tveg_si)%r81d) - ! Move this to the interface for consistency (rgk 0524) + ! THIS CAN BE REMOVED WHEN BOTH CTSM AND E3SM CALL FLUSH_ALL_HVARS + ! THIS IS NOT A LIABILITY, IT IS JUST REDUNDANT call this%flush_hvars(nc,upfreq_in=group_hifr_simple) dt_tstep_inv = 1.0_r8/dt_tstep @@ -5223,7 +5224,8 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) hio_laisha_si_can => this%hvars(ih_laisha_si_can)%r82d ) - ! Move this to the interface for consistency (rgk 0524) + ! THIS CAN BE REMOVED WHEN BOTH CTSM AND E3SM CALL FLUSH_ALL_HVARS + ! THIS IS NOT A LIABILITY, IT IS JUST REDUNDANT call this%flush_hvars(nc,upfreq_in=group_hifr_complx) dt_tstep_inv = 1.0_r8/dt_tstep @@ -5655,7 +5657,8 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) if_hifrq0: if(hlm_hist_level_hifrq>0) then - ! Move this to the interface for consistency (rgk 0524) + ! THIS CAN BE REMOVED WHEN BOTH CTSM AND E3SM CALL FLUSH_ALL_HVARS + ! THIS IS NOT A LIABILITY, IT IS JUST REDUNDANT call this%flush_hvars(nc,upfreq_in=group_hydr_simple) associate( hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d, & @@ -5762,7 +5765,8 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) hio_rootuptake50_scpf => this%hvars(ih_rootuptake50_scpf)%r82d, & hio_rootuptake100_scpf => this%hvars(ih_rootuptake100_scpf)%r82d ) - ! Move this to the interface for consistency (rgk 0524) + ! THIS CAN BE REMOVED WHEN BOTH CTSM AND E3SM CALL FLUSH_ALL_HVARS + ! THIS IS NOT A LIABILITY, IT IS JUST REDUNDANT call this%flush_hvars(nc,upfreq_in=group_hydr_complx) do s = 1,nsites From 8d028eb7ea6c2f1f0c67cb4adad988b2422ee955 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 10 Jun 2024 11:58:43 -0600 Subject: [PATCH 266/300] removed redundant zero flush in history --- main/FatesHistoryInterfaceMod.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 156da135c2..6c34f48292 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5253,8 +5253,6 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) patch_area_by_age(1:nlevage) = 0._r8 canopy_area_by_age(1:nlevage) = 0._r8 - call this%zero_site_hvars(sites(s), upfreq_in=group_hifr_complx) - cpatch => sites(s)%oldest_patch do while(associated(cpatch)) From 812c7cc718206bd596d0c0a67af5645711757f5c Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Thu, 13 Jun 2024 14:21:02 -0600 Subject: [PATCH 267/300] simplify carea allometry wrap function to avoid redundant code --- biogeochem/FatesAllometryMod.F90 | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index e908bfd86e..8b9fbebb39 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -536,7 +536,7 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) call carea_2pwr(dbh,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & crowndamage, c_area, do_inverse) capped_allom = .false. - case(3) + case(3,5) dbh_eff = min(dbh,dbh_maxh) call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & crowndamage, c_area, do_inverse) @@ -547,11 +547,6 @@ subroutine carea_allom(dbh,nplant,site_spread,ipft,crowndamage,c_area,inverse) call carea_3pwr(dbh_eff,height,ipft,dbh_maxh, site_spread,d2bl_p2, & d2bl_ediff, d2ca_min,d2ca_max,crowndamage, c_area, do_inverse) capped_allom = .true. - case(5) - dbh_eff = min(dbh,dbh_maxh) - call carea_2pwr(dbh_eff,site_spread,d2bl_p2,d2bl_ediff,d2ca_min,d2ca_max, & - crowndamage, c_area, do_inverse) - capped_allom = .true. case DEFAULT write(fates_log(),*) 'An undefined leaf allometry was specified: ', & allom_lmode From 9857e2fdc05267724181698fb38f4fce52303bed Mon Sep 17 00:00:00 2001 From: Xiulin Gao Date: Thu, 13 Jun 2024 18:17:50 -0600 Subject: [PATCH 268/300] simplify calculation of biomass derivatives using biomass --- biogeochem/FatesAllometryMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 8b9fbebb39..d0957ef190 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1732,7 +1732,7 @@ subroutine dh2blmax_3pwr_grass(d,h,dhdd,p1,p2,p3,dbh_maxh,c2b,blmax,dblmaxdd) if(d .ge. dbh_maxh)then dblmaxdd = 0._r8 else - dblmaxdd = p1 * (p2 * duse**(p2 - 1.0_r8) * h**p3 + p3 * h**(p3 - 1.0_r8) * dhdd * duse**p2) / c2b + dblmaxdd = blmax * (p2 / duse + p3 * dhdd / h) end if end if @@ -2177,7 +2177,7 @@ subroutine dh2bagw_3pwr_grass(d,h,dhdd,p1,p2,p3,c2b,bagw,dbagwdd) !----Compute the aboveground biomass derivative with basal diameter if needed if (present(dbagwdd)) then - dbagwdd = p1 * (p2 * d**(p2 - 1.0_r8) * h**p3 + p3 * h**(p3 - 1.0_r8) * dhdd * d**p2) / c2b + dbagwdd = p2 * bagw / d + p3 * bagw * dhdd / h end if return From b43cb3a2a96b7761641f59dc0838759819d9220d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Sun, 23 Jun 2024 23:48:16 -0600 Subject: [PATCH 269/300] update split_patches to take optional area input --- biogeochem/EDPatchDynamicsMod.F90 | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 40ca2ba7e4..ec077dbc9e 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1511,7 +1511,7 @@ subroutine spawn_patches( currentSite, bc_in) ! split buffer patch in two, keeping the smaller buffer patch to put into new patches allocate(temp_patch) - call split_patch(currentSite, buffer_patch, temp_patch, fraction_to_keep) + call split_patch(currentSite, buffer_patch, temp_patch, fraction_to_keep, newp_area) ! give the new patch the intended nocomp PFT label temp_patch%nocomp_pft_label = i_pft @@ -1621,16 +1621,17 @@ end subroutine spawn_patches ! ----------------------------------------------------------------------------------------- - subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) + subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep, new_area) ! ! !DESCRIPTION: ! Split a patch into two patches that are identical except in their areas ! ! !ARGUMENTS: type(ed_site_type),intent(inout) :: currentSite - type(fates_patch_type) , intent(inout), pointer :: currentPatch ! Donor Patch - type(fates_patch_type) , intent(inout), pointer :: new_patch ! New Patch - real(r8), intent(in) :: fraction_to_keep ! fraction of currentPatch to keep, the rest goes to newpatch + type(fates_patch_type) , intent(inout), pointer :: currentPatch ! Donor Patch + type(fates_patch_type) , intent(inout), pointer :: new_patch ! New Patch + real(r8), intent(in) :: fraction_to_keep ! fraction of currentPatch to keep, the rest goes to newpatch + real(r8), intent(in), optional :: area_to_remove ! area of currentPatch to remove, the rest goes to newpatch ! ! !LOCAL VARIABLES: integer :: el ! element loop index @@ -1641,11 +1642,19 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) integer :: tnull ! is there a tallest cohort? integer :: snull ! is there a shortest cohort? integer :: pft + real(r8) :: temp_area + + temp_area = 0._r8 + if (present(area_to_remove)) then + temp_area = area_to_remove + else + temp_area = currentPatch%area - (currentPatch%area * fraction_to_keep) + end if ! first we need to make the new patch - call new_patch%Create(0._r8, & - currentPatch%area * (1._r8 - fraction_to_keep), currentPatch%land_use_label, currentPatch%nocomp_pft_label, & - num_swb, numpft, currentSite%nlevsoil, hlm_current_tod, & + call new_patch%Create(0._r8, temp_area, & + currentPatch%land_use_label, currentPatch%nocomp_pft_label, & + num_swb, numpft, currentSite%nlevsoil, hlm_current_tod, & regeneration_model) ! Initialize the litter pools to zero, these @@ -1663,7 +1672,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) call CopyPatchMeansTimers(currentPatch, new_patch) - call TransLitterNewPatch( currentSite, currentPatch, new_patch, currentPatch%area * (1.-fraction_to_keep)) + call TransLitterNewPatch( currentSite, currentPatch, new_patch, temp_area) currentPatch%burnt_frac_litter(:) = 0._r8 @@ -1730,7 +1739,7 @@ subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep) call sort_cohorts(currentPatch) !update area of donor patch - currentPatch%area = currentPatch%area * fraction_to_keep + currentPatch%area = currentPatch%area - temp_area end subroutine split_patch From 29621bc5fb0589da94ea470cb40c4b35a483776c Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jun 2024 12:02:02 -0600 Subject: [PATCH 270/300] fix split patch optional argument name error --- biogeochem/EDPatchDynamicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index ec077dbc9e..e62ae68dc7 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1621,7 +1621,7 @@ end subroutine spawn_patches ! ----------------------------------------------------------------------------------------- - subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep, new_area) + subroutine split_patch(currentSite, currentPatch, new_patch, fraction_to_keep, area_to_remove) ! ! !DESCRIPTION: ! Split a patch into two patches that are identical except in their areas From 9b724ea40a1c0dd4728ed198e4bae8f0af321e99 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jun 2024 11:38:40 -0600 Subject: [PATCH 271/300] correct bad merge --- main/FatesHistoryInterfaceMod.F90 | 47 ++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 6219f34915..c5b48735f6 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -14,7 +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 FatesConstantsMo , only : nocomp_bareground_land + use FatesConstantsMod , only : nocomp_bareground_land use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun use EDParamsMod , only : nclmax, maxpft @@ -90,6 +90,51 @@ module FatesHistoryInterfaceMod use shr_log_mod , only : errMsg => shr_log_errMsg use shr_infnan_mod , only : isnan => shr_infnan_isnan + use FatesConstantsMod , only : g_per_kg + use FatesConstantsMod , only : kg_per_g + use FatesConstantsMod , only : ha_per_m2 + use FatesConstantsMod , only : days_per_sec + use FatesConstantsMod , only : sec_per_day + use FatesConstantsMod , only : days_per_sec + use FatesConstantsMod , only : days_per_year + use FatesConstantsMod , only : years_per_day + use FatesConstantsMod , only : m2_per_km2 + use FatesConstantsMod , only : J_per_kJ + use FatesConstantsMod , only : m2_per_ha + use FatesConstantsMod , only : ha_per_m2 + use FatesConstantsMod , only : m_per_cm + use FatesConstantsMod , only : m_per_mm + use FatesConstantsMod , only : sec_per_min + use FatesConstantsMod , only : umol_per_mol,mol_per_umol + use FatesConstantsMod , only : pa_per_mpa + use FatesConstantsMod , only : dens_fresh_liquid_water + use FatesConstantsMod , only : grav_earth + use FatesLitterMod , only : litter_type + use FatesConstantsMod , only : secondaryland + + use PRTGenericMod , only : leaf_organ, fnrt_organ, sapw_organ + use PRTGenericMod , only : struct_organ, store_organ, repro_organ + use PRTGenericMod , only : carbon12_element + use PRTGenericMod , only : nitrogen_element, phosphorus_element + use PRTGenericMod , only : prt_carbon_allom_hyp + use PRTAllometricCNPMod , only : stoich_max,stoich_growth_min + use FatesSizeAgeTypeIndicesMod, only : get_layersizetype_class_index + use FatesSizeAgeTypeIndicesMod, only : get_age_class_index + + use FatesLitterMod , only : nfsc + use FatesLitterMod , only : ncwd + use FatesConstantsMod , only : ican_upper + use FatesConstantsMod , only : ican_ustory + use FatesSizeAgeTypeIndicesMod, only : get_sizeage_class_index + use FatesSizeAgeTypeIndicesMod, only : get_sizeagepft_class_index + use FatesSizeAgeTypeIndicesMod, only : get_agepft_class_index + use FatesSizeAgeTypeIndicesMod, only : get_agefuel_class_index + use FatesSizeAgeTypeIndicesMod, only : get_height_index + use FatesSizeAgeTypeIndicesMod, only : sizetype_class_index + use FatesSizeAgeTypeIndicesMod, only : get_cdamagesize_class_index + use FatesSizeAgeTypeIndicesMod, only : get_cdamagesizepft_class_index + use FatesSizeAgeTypeIndicesMod, only : coagetype_class_index + implicit none private ! By default everything is private From 3c02ded0ac23c46fd0784217b6ad0096a7385a6d Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jun 2024 00:49:50 -0600 Subject: [PATCH 272/300] refactor checks to determine what is sent to buffer patch --- biogeochem/EDPatchDynamicsMod.F90 | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index e62ae68dc7..083f290fb9 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -559,7 +559,7 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: fraction_to_keep integer :: i_land_use_label integer :: i_pft - real(r8) :: newp_area + real(r8) :: newp_area, area_to_keep logical :: buffer_patch_in_linked_list integer :: n_pfts_by_landuse integer :: which_pft_allowed @@ -1424,11 +1424,15 @@ subroutine spawn_patches( currentSite, bc_in) do while(associated(currentPatch)) if (currentPatch%changed_landuse_this_ts .and. currentPatch%land_use_label .eq. i_land_use_label) then - fraction_to_keep = (currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * sum(nocomp_pft_area_vector(:)) & - - nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label)) / currentPatch%area + ! Calculate the areas to be given to potentially give to the buffer patch and those to keep in the current patch + area_to_keep = currentSite%area_pft(currentPatch%nocomp_pft_label,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - & + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + newp_area = currentPatch%area - area_to_keep + fraction_to_keep = area_to_keep / currentPatch%area - if (fraction_to_keep .le. nearzero) then + if (fraction_to_keep .le. nearzero .or. area_to_keep .lt. rsnbl_math_prec) then ! we don't want any patch area with this PFT identity at all anymore. Fuse it into the buffer patch. + currentPatch%nocomp_pft_label = 0 if (associated(currentPatch%older)) then previousPatch => currentPatch%older @@ -1441,13 +1445,13 @@ subroutine spawn_patches( currentSite, bc_in) buffer_patch_used = .true. - elseif ( (1._r8 - fraction_to_keep) .gt. rsnbl_math_prec) then + elseif ( area_to_keep .ge. rsnbl_math_prec .and. newp_area .ge. rsnbl_math_prec) then ! we have more patch are of this PFT than we want, but we do want to keep some of it. ! we want to split the patch into two here. leave one patch as-is, and put the rest into the buffer patch. allocate(temp_patch) - call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep) + call split_patch(currentSite, currentPatch, temp_patch, fraction_to_keep, newp_area) ! temp_patch%nocomp_pft_label = 0 @@ -1461,9 +1465,11 @@ subroutine spawn_patches( currentSite, bc_in) buffer_patch_used = .true. else ! we want to keep all of this patch (and possibly more) + nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) = & nocomp_pft_area_vector_filled(currentPatch%nocomp_pft_label) + currentPatch%area currentPatch%changed_landuse_this_ts = .false. + endif end if From 7add4a11547caaead9d4b9b06c401e3cb34294a7 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jun 2024 00:54:50 -0600 Subject: [PATCH 273/300] make sure to skip the buffer patch split loop if the buffer patch is already in the linked list --- biogeochem/EDPatchDynamicsMod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 083f290fb9..24909933da 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1499,8 +1499,10 @@ subroutine spawn_patches( currentSite, bc_in) ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list nocomp_pft_loop_2: do i_pft = 1, numpft - ! - if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero) then + + ! Check the area fraction to makes sure that this pft should have area. Also make sure that the buffer patch hasn't been + ! added to the linked list already + if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero .and. .not. buffer_patch_in_linked_list) then ! if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then ! From fe795df74216244b15e8db647eca6a61c7b1a235 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jun 2024 01:07:03 -0600 Subject: [PATCH 274/300] refactor newp_area calculation to avoid potential precision error --- biogeochem/EDPatchDynamicsMod.F90 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 24909933da..3f9464e822 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -556,6 +556,7 @@ subroutine spawn_patches( currentSite, bc_in) type (fates_patch_type) , pointer :: buffer_patch, temp_patch, copyPatch, previousPatch real(r8) :: nocomp_pft_area_vector(numpft) real(r8) :: nocomp_pft_area_vector_filled(numpft) + real(r8) :: nocomp_pft_area_vector_alt(numpft) real(r8) :: fraction_to_keep integer :: i_land_use_label integer :: i_pft @@ -1505,8 +1506,13 @@ subroutine spawn_patches( currentSite, bc_in) if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero .and. .not. buffer_patch_in_linked_list) then ! if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then - ! - newp_area = currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:)) - nocomp_pft_area_vector_filled(i_pft) + + ! Slightly complicated way of making sure that the same pfts are subtracted from each other which may help to avoid precision + ! errors due to differencing between very large and very small areas + nocomp_pft_area_vector_alt(:) = nocomp_pft_area_vector(:) + nocomp_pft_area_vector_alt(i_pft) = 0._r8 + newp_area = (currentSite%area_pft(i_pft,i_land_use_label) * nocomp_pft_area_vector(i_pft)) - nocomp_pft_area_vector_filled(i_pft) + newp_area = newp_area + sum(currentSite%area_pft(i_pft,i_land_use_label)*nocomp_pft_area_vector_alt(:)) ! only bother doing this if the new new patch area needed is greater than some tiny amount if ( newp_area .gt. rsnbl_math_prec * 0.01_r8) then From 28511d1eb59bb58d2bee5d75c8ca4d83735fde78 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jun 2024 01:10:31 -0600 Subject: [PATCH 275/300] move the fraction to keep calculation earlier --- biogeochem/EDPatchDynamicsMod.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 3f9464e822..4eca17362d 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1514,12 +1514,12 @@ subroutine spawn_patches( currentSite, bc_in) newp_area = (currentSite%area_pft(i_pft,i_land_use_label) * nocomp_pft_area_vector(i_pft)) - nocomp_pft_area_vector_filled(i_pft) newp_area = newp_area + sum(currentSite%area_pft(i_pft,i_land_use_label)*nocomp_pft_area_vector_alt(:)) + ! Compute fraction to keep in buffer + fraction_to_keep = (buffer_patch%area - newp_area) / buffer_patch%area + ! only bother doing this if the new new patch area needed is greater than some tiny amount if ( newp_area .gt. rsnbl_math_prec * 0.01_r8) then - ! Compute fraction to keep in buffer - fraction_to_keep = (buffer_patch%area - newp_area) / buffer_patch%area - if (fraction_to_keep .gt. rsnbl_math_prec) then ! split buffer patch in two, keeping the smaller buffer patch to put into new patches From e8238300cbda07adf93355b3935b1c49be8e4742 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 24 Jun 2024 01:22:43 -0600 Subject: [PATCH 276/300] check absolute value of buffer area to keep --- biogeochem/EDPatchDynamicsMod.F90 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 4eca17362d..a20ede746c 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1514,13 +1514,14 @@ subroutine spawn_patches( currentSite, bc_in) newp_area = (currentSite%area_pft(i_pft,i_land_use_label) * nocomp_pft_area_vector(i_pft)) - nocomp_pft_area_vector_filled(i_pft) newp_area = newp_area + sum(currentSite%area_pft(i_pft,i_land_use_label)*nocomp_pft_area_vector_alt(:)) - ! Compute fraction to keep in buffer - fraction_to_keep = (buffer_patch%area - newp_area) / buffer_patch%area + ! Compute area and fraction to keep in buffer + area_to_keep = buffer_patch%area - newp_area + fraction_to_keep = area_to_keep / buffer_patch%area ! only bother doing this if the new new patch area needed is greater than some tiny amount if ( newp_area .gt. rsnbl_math_prec * 0.01_r8) then - if (fraction_to_keep .gt. rsnbl_math_prec) then + if (area_to_keep .gt. rsnbl_math_prec) then ! split buffer patch in two, keeping the smaller buffer patch to put into new patches allocate(temp_patch) From 2ec67f9370298d4086a2ab88baff13b50fa93608 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 25 Jun 2024 12:19:17 -0600 Subject: [PATCH 277/300] remove this check as we are now checking the new and remaining areas are non-negative --- biogeochem/EDPatchDynamicsMod.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index a20ede746c..af333bfe84 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1504,8 +1504,6 @@ subroutine spawn_patches( currentSite, bc_in) ! Check the area fraction to makes sure that this pft should have area. Also make sure that the buffer patch hasn't been ! added to the linked list already if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero .and. .not. buffer_patch_in_linked_list) then - ! - if (nocomp_pft_area_vector_filled(i_pft) .lt. currentSite%area_pft(i_pft,i_land_use_label) * sum(nocomp_pft_area_vector(:))) then ! Slightly complicated way of making sure that the same pfts are subtracted from each other which may help to avoid precision ! errors due to differencing between very large and very small areas @@ -1551,7 +1549,6 @@ subroutine spawn_patches( currentSite, bc_in) end if end if - end if end if end do nocomp_pft_loop_2 From 69e8f6a8feafb88929194b986525cecdd6060ae2 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 25 Jun 2024 13:01:31 -0600 Subject: [PATCH 278/300] correct whitespace --- biogeochem/EDPatchDynamicsMod.F90 | 60 +++++++++++++++---------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index af333bfe84..a5ec0e40b1 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -1505,50 +1505,50 @@ subroutine spawn_patches( currentSite, bc_in) ! added to the linked list already if ( currentSite%area_pft(i_pft,i_land_use_label) .gt. nearzero .and. .not. buffer_patch_in_linked_list) then - ! Slightly complicated way of making sure that the same pfts are subtracted from each other which may help to avoid precision - ! errors due to differencing between very large and very small areas - nocomp_pft_area_vector_alt(:) = nocomp_pft_area_vector(:) - nocomp_pft_area_vector_alt(i_pft) = 0._r8 - newp_area = (currentSite%area_pft(i_pft,i_land_use_label) * nocomp_pft_area_vector(i_pft)) - nocomp_pft_area_vector_filled(i_pft) - newp_area = newp_area + sum(currentSite%area_pft(i_pft,i_land_use_label)*nocomp_pft_area_vector_alt(:)) + ! Slightly complicated way of making sure that the same pfts are subtracted from each other which may help to avoid precision + ! errors due to differencing between very large and very small areas + nocomp_pft_area_vector_alt(:) = nocomp_pft_area_vector(:) + nocomp_pft_area_vector_alt(i_pft) = 0._r8 + newp_area = (currentSite%area_pft(i_pft,i_land_use_label) * nocomp_pft_area_vector(i_pft)) - nocomp_pft_area_vector_filled(i_pft) + newp_area = newp_area + sum(currentSite%area_pft(i_pft,i_land_use_label)*nocomp_pft_area_vector_alt(:)) - ! Compute area and fraction to keep in buffer - area_to_keep = buffer_patch%area - newp_area - fraction_to_keep = area_to_keep / buffer_patch%area + ! Compute area and fraction to keep in buffer + area_to_keep = buffer_patch%area - newp_area + fraction_to_keep = area_to_keep / buffer_patch%area - ! only bother doing this if the new new patch area needed is greater than some tiny amount - if ( newp_area .gt. rsnbl_math_prec * 0.01_r8) then + ! only bother doing this if the new new patch area needed is greater than some tiny amount + if ( newp_area .gt. rsnbl_math_prec * 0.01_r8) then - if (area_to_keep .gt. rsnbl_math_prec) then + if (area_to_keep .gt. rsnbl_math_prec) then - ! split buffer patch in two, keeping the smaller buffer patch to put into new patches - allocate(temp_patch) + ! split buffer patch in two, keeping the smaller buffer patch to put into new patches + allocate(temp_patch) - call split_patch(currentSite, buffer_patch, temp_patch, fraction_to_keep, newp_area) + call split_patch(currentSite, buffer_patch, temp_patch, fraction_to_keep, newp_area) - ! give the new patch the intended nocomp PFT label - temp_patch%nocomp_pft_label = i_pft + ! give the new patch the intended nocomp PFT label + temp_patch%nocomp_pft_label = i_pft - ! track that we have added this patch area - nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + temp_patch%area + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + temp_patch%area - ! put the new patch into the linked list - call InsertPatch(currentSite, temp_patch) + ! put the new patch into the linked list + call InsertPatch(currentSite, temp_patch) - else - ! give the buffer patch the intended nocomp PFT label - buffer_patch%nocomp_pft_label = i_pft + else + ! give the buffer patch the intended nocomp PFT label + buffer_patch%nocomp_pft_label = i_pft - ! track that we have added this patch area - nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area - ! put the buffer patch directly into the linked list - call InsertPatch(currentSite, buffer_patch) + ! put the buffer patch directly into the linked list + call InsertPatch(currentSite, buffer_patch) - buffer_patch_in_linked_list = .true. + buffer_patch_in_linked_list = .true. - end if end if + end if end if end do nocomp_pft_loop_2 From 88ce982d51fbfea6434f46ad6a4e36cf8938bca5 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Wed, 26 Jun 2024 08:44:50 -0600 Subject: [PATCH 279/300] Add logic to check for cases in which buffer should be inserted straight into the list This handles cases in which only one pft needs to receive patch area from the buffer, but due to precision errors, following the splitting routine would result in a very small patch, technically above the reasonable math precision limit, being held in the buffer --- biogeochem/EDPatchDynamicsMod.F90 | 39 ++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index a5ec0e40b1..55f7ba1311 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -557,10 +557,12 @@ subroutine spawn_patches( currentSite, bc_in) real(r8) :: nocomp_pft_area_vector(numpft) real(r8) :: nocomp_pft_area_vector_filled(numpft) real(r8) :: nocomp_pft_area_vector_alt(numpft) - real(r8) :: fraction_to_keep + real(r8) :: newp_area_buffer_frac(numpft) + real(r8) :: newp_area_vector(numpft) + real(r8) :: max_val integer :: i_land_use_label integer :: i_pft - real(r8) :: newp_area, area_to_keep + real(r8) :: newp_area, area_to_keep, fraction_to_keep logical :: buffer_patch_in_linked_list integer :: n_pfts_by_landuse integer :: which_pft_allowed @@ -1498,7 +1500,38 @@ subroutine spawn_patches( currentSite, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list + ! It's possible that we only need to move all of the buffer into one patch, so first determine what the new patch areas look + ! like and compare to the buffer patch area + newp_area_vector(:)= (currentSite%area_pft(:,i_land_use_label) * sum(nocomp_pft_area_vector(:))) - nocomp_pft_area_vector_filled(:) + newp_area_buffer_frac(:) = newp_area_vector(:) / buffer_patch%area + + ! Find the maximum value of the vector + max_val = maxval(newp_area_buffer_frac) + + ! If the max value is the only value in the array then loop through the array to find the max value pft index and insert buffer + if (abs(sum(newp_area_buffer_frac(:)) - max_val) .le. nearzero) then + i_pft = 1 + do while(.not. buffer_patch_in_linked_list) + if (abs(newp_area_buffer_frac(i_pft) - max_val) .le. nearzero) then + + ! give the buffer patch the intended nocomp PFT label + buffer_patch%nocomp_pft_label = i_pft + + ! track that we have added this patch area + nocomp_pft_area_vector_filled(i_pft) = nocomp_pft_area_vector_filled(i_pft) + buffer_patch%area + + ! put the buffer patch directly into the linked list + call InsertPatch(currentSite, buffer_patch) + + ! Set flag to skip the next pft loop + buffer_patch_in_linked_list = .true. + end if + i_pft = i_pft + 1 + end do + end if + + ! Now we need to loop through the nocomp PFTs, and split the buffer patch into a set of patches to put back in the linked list + ! if not already done so above nocomp_pft_loop_2: do i_pft = 1, numpft ! Check the area fraction to makes sure that this pft should have area. Also make sure that the buffer patch hasn't been From c9e72712f2822665083d3d6f9a0c39e178f2de52 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Thu, 27 Jun 2024 17:02:21 -0600 Subject: [PATCH 280/300] add sp mode check to litter initialization for bareground patches --- main/EDInitMod.F90 | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 49099b7ddf..ce76ba9017 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -760,7 +760,7 @@ subroutine init_patches( nsites, sites, bc_in) if (newparea .gt. min_patch_area_forced) then allocate(newp) - + call newp%Create(age, newparea, nocomp_bareground_land, nocomp_bareground, & num_swb, numpft, sites(s)%nlevsoil, hlm_current_tod, & regeneration_model) @@ -776,14 +776,20 @@ subroutine init_patches( nsites, sites, bc_in) ! Initialize the litter pools to zero, these ! pools will be populated by looping over the existing patches ! and transfering in mass + if(hlm_use_sp.eq.itrue)then + litt_init = fates_unset_r8 + else + litt_init = 0._r8 + end if do el=1,num_elements - call newp%litter(el)%InitConditions(init_leaf_fines=0._r8, & - init_root_fines=0._r8, & - init_ag_cwd=0._r8, & - init_bg_cwd=0._r8, & - init_seed=0._r8, & - init_seed_germ=0._r8) + call newp%litter(el)%InitConditions(init_leaf_fines=litt_init, & + init_root_fines=litt_init, & + init_ag_cwd=litt_init, & + init_bg_cwd=litt_init, & + init_seed=litt_init, & + init_seed_germ=litt_init) end do + else area_error = area_error + newparea endif @@ -796,12 +802,9 @@ subroutine init_patches( nsites, sites, bc_in) endif - ! not_all_bareground_if: if ((1._r8 - sites(s)%area_bareground) .gt. nearzero) then - ! Next, create the non-bareground patches. We do this for either of two scenarios: ! If 1) we are not doing both nocomp & fixed-biogeo ! 2) we are, but there is some non-zero bare-ground area - not_all_bare_if: if( ((1._r8 - sites(s)%area_bareground) > nearzero) .or. & (.not.(hlm_use_nocomp.eq.itrue .and. hlm_use_fixed_biogeog.eq.itrue)) ) then From bb3d58e0878964490ddc998bfd5593c53dab8b97 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Fri, 28 Jun 2024 12:39:38 -0600 Subject: [PATCH 281/300] initialize current tag for event code logging --- biogeochem/EDLoggingMortalityMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 6d373e995a..addb821f9a 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -287,6 +287,7 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, ! 0=use fates logging parameters directly when logging_time == .true. ! this means harvest the whole cohort area harvest_rate = 1._r8 + cur_harvest_tag = 0 else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_area_fraction) then ! We are harvesting based on areal fraction, not carbon/biomass terms. From 4ae398b955b1f4faddbd2632d98e6a8a3d247c03 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Sun, 7 Jul 2024 22:40:25 -0600 Subject: [PATCH 282/300] Revert "initialize current tag for event code logging" This reverts commit bb3d58e0878964490ddc998bfd5593c53dab8b97. --- biogeochem/EDLoggingMortalityMod.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index addb821f9a..6d373e995a 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -287,7 +287,6 @@ subroutine LoggingMortality_frac( currentSite, bc_in, pft_i, dbh, canopy_layer, ! 0=use fates logging parameters directly when logging_time == .true. ! this means harvest the whole cohort area harvest_rate = 1._r8 - cur_harvest_tag = 0 else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_area_fraction) then ! We are harvesting based on areal fraction, not carbon/biomass terms. From a2b3eada362248de87116f93da31c7337c700ce7 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 9 Jul 2024 14:06:20 -0400 Subject: [PATCH 283/300] changed ncan to nleaf --- biogeochem/EDCanopyStructureMod.F90 | 16 ++++++++-------- biogeochem/FatesPatchMod.F90 | 8 ++++---- biogeophys/FatesPlantRespPhotosynthMod.F90 | 16 ++++++++-------- main/FatesHistoryInterfaceMod.F90 | 2 +- main/FatesInterfaceMod.F90 | 2 +- radiation/FatesRadiationDriveMod.F90 | 2 +- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index a101065cf6..7f2db09cd2 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1500,7 +1500,7 @@ subroutine leaf_area_profile( currentSite ) ! The following patch level diagnostics are updated here: ! ! currentPatch%canopy_layer_tlai(cl) ! total leaf area index of canopy layer - ! currentPatch%ncan(cl,ft) ! number of vegetation layers needed + ! currentPatch%nleaf(cl,ft) ! number of vegetation layers needed ! ! in this patch's pft/canopy-layer ! currentPatch%nrad(cl,ft) ! same as ncan, but does not include ! ! layers occluded by snow @@ -1558,8 +1558,8 @@ subroutine leaf_area_profile( currentSite ) cpatch => currentSite%oldest_patch do while(associated(cpatch)) - cpatch%ncan(:,:) = 0 - ! This routine updates the %ncan array + cpatch%nleaf(:,:) = 0 + ! This routine updates the %nleaf array call UpdatePatchLAI(cpatch) @@ -1589,7 +1589,7 @@ subroutine leaf_area_profile( currentSite ) ! UNDER THE SNOW, BUT WE DONT REALLY USE IT TO FILTER ! THEM OUT. CHECK THE CODE AND CONSIDER REMOVING NRAD ! ALTOGETHER (RGK 05-2024) - cpatch%nrad(:,:) = cpatch%ncan(:,:) + cpatch%nrad(:,:) = cpatch%nleaf(:,:) ! ------------------------------------------------------------------------------ ! It is remotely possible that in deserts we will not have any canopy @@ -1629,7 +1629,7 @@ subroutine leaf_area_profile( currentSite ) fleaf = 0._r8 endif - cpatch%nrad(cl,ft) = cpatch%ncan(cl,ft) + cpatch%nrad(cl,ft) = cpatch%nleaf(cl,ft) if (cpatch%nrad(cl,ft) > nlevleaf ) then write(fates_log(), *) 'Number of radiative leaf layers is larger' @@ -1789,7 +1789,7 @@ subroutine leaf_area_profile( currentSite ) ! -------------------------------------------------------------------------- do cl = 1,cpatch%NCL_p - do iv = 1,cpatch%ncan(cl,ft) + do iv = 1,cpatch%nleaf(cl,ft) if( debug .and. sum(cpatch%canopy_area_profile(cl,:,iv)) > 1.0001_r8 ) then @@ -1814,7 +1814,7 @@ subroutine leaf_area_profile( currentSite ) end do do ft = 1,numpft - do iv = 1,cpatch%ncan(cl,ft) + do iv = 1,cpatch%nleaf(cl,ft) if( cpatch%canopy_area_profile(cl,ft,iv) > nearzero ) then @@ -2235,7 +2235,7 @@ subroutine UpdatePatchLAI(currentPatch) currentPatch%total_canopy_area) ! Update the number of number of vegetation layers - currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV) + currentPatch%nleaf(cl,ft) = max(currentPatch%nleaf(cl,ft),currentCohort%NV) ! Update the patch canopy layer tlai (LAI per canopy area) currentPatch%canopy_layer_tlai(cl) = currentPatch%canopy_layer_tlai(cl) + & diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index a660c725cd..952f5a7a0d 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -117,8 +117,8 @@ module FatesPatchMod ! from all cohorts that donate to canopy_area integer :: canopy_mask(nclmax,maxpft) ! is there any of this pft in this canopy layer? - integer :: nrad(nclmax,maxpft) ! number of exposed leaf layers for each canopy layer and pft - integer :: ncan(nclmax,maxpft) ! number of total leaf layers for each canopy layer and pft + integer :: nrad(nclmax,maxpft) ! number of exposed vegetation layers for each canopy layer and pft + integer :: nleaf(nclmax,maxpft) ! number of total leaf layers for each canopy layer and pft real(r8) :: c_stomata ! mean stomatal conductance of all leaves in the patch [umol/m2/s] real(r8) :: c_lblayer ! mean boundary layer conductance of all leaves in the patch [umol/m2/s] @@ -307,7 +307,7 @@ subroutine ReAllocateDynamics(this) ! as defined in the allocation space ncan = this%ncl_p - nveg = maxval(this%ncan(:,:)) + nveg = maxval(this%nleaf(:,:)) ! Assume we will need to allocate, unless the ! arrays already are allocated and require the same size @@ -456,7 +456,7 @@ subroutine NanValues(this) this%canopy_mask(:,:) = fates_unset_int this%nrad(:,:) = fates_unset_int - this%ncan(:,:) = fates_unset_int + this%nleaf(:,:) = fates_unset_int this%c_stomata = nan this%c_lblayer = nan diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index 16f242a0f2..b338ab5b51 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -372,7 +372,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) ! Part III. Calculate the number of sublayers for each pft and layer. ! And then identify which layer/pft combinations have things in them. ! Output: - ! currentPatch%ncan(:,:) + ! currentPatch%nleaf(:,:) ! currentPatch%canopy_mask(:,:) call UpdateCanopyNCanNRadPresent(currentPatch) @@ -1978,16 +1978,16 @@ subroutine UpdateCanopyNCanNRadPresent(currentPatch) ! --------------------------------------------------------------------------------- ! This subroutine calculates two patch level quanities: - ! currentPatch%ncan and + ! currentPatch%nleaf and ! currentPatch%canopy_mask ! - ! currentPatch%ncan(:,:) is a two dimensional array that indicates + ! currentPatch%nleaf(:,:) is a two dimensional array that indicates ! the total number of leaf layers (including those that are not exposed to light) ! in each canopy layer and for each functional type. ! ! currentPatch%nrad(:,:) is a two dimensional array that indicates ! the total number of EXPOSED leaf layers, but for all intents and purposes - ! in the photosynthesis routine, this appears to be the same as %ncan... + ! in the photosynthesis routine, this appears to be the same as %nleaf... ! ! currentPatch%canopy_mask(:,:) has the same dimensions, is binary, and ! indicates whether or not leaf layers are present (by evaluating the canopy area @@ -2008,14 +2008,14 @@ subroutine UpdateCanopyNCanNRadPresent(currentPatch) ! of the layer/pft index it is in ! --------------------------------------------------------------------------------- - currentPatch%ncan(:,:) = 0 + currentPatch%nleaf(:,:) = 0 ! redo the canopy structure algorithm to get round a ! bug that is happening for site 125, FT13. currentCohort => currentPatch%tallest do while(associated(currentCohort)) - currentPatch%ncan(currentCohort%canopy_layer,currentCohort%pft) = & - max(currentPatch%ncan(currentCohort%canopy_layer,currentCohort%pft), & + currentPatch%nleaf(currentCohort%canopy_layer,currentCohort%pft) = & + max(currentPatch%nleaf(currentCohort%canopy_layer,currentCohort%pft), & currentCohort%NV) currentCohort => currentCohort%shorter @@ -2023,7 +2023,7 @@ subroutine UpdateCanopyNCanNRadPresent(currentPatch) enddo !cohort ! NRAD = NCAN ... - currentPatch%nrad = currentPatch%ncan + currentPatch%nrad = currentPatch%nleaf ! Now loop through and identify which layer and pft combo has scattering elements do cl = 1,currentPatch%ncl_p diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index c5b48735f6..fd3c09dfd5 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -5395,7 +5395,7 @@ subroutine update_history_hifrq2(this,nc,nsites,sites,bc_in,bc_out,dt_tstep) do_pft1: do ipft=1,numpft do_canlev1: do ican=1,cpatch%ncl_p - do_leaflev1: do ileaf=1,cpatch%ncan(ican,ipft) + do_leaflev1: do ileaf=1,cpatch%nleaf(ican,ipft) ! calculate where we are on multiplexed dimensions clllpf_indx = ileaf + (ican-1) * nlevleaf + (ipft-1) * nlevleaf * nclmax diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index eea65eaa0a..12eb83bcc0 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -2240,7 +2240,7 @@ subroutine SeedlingParPatch(cpatch, & cl_par = 0._r8 cl_area = 0._r8 do ipft = 1,numpft - iv = cpatch%ncan(cl,ipft) + iv = cpatch%nleaf(cl,ipft) ! Avoid calculating when there are no leaf layers for the given pft in the current canopy layer if (iv .ne. 0) then cl_par = cl_par + cpatch%canopy_area_profile(cl,ipft,1)* & diff --git a/radiation/FatesRadiationDriveMod.F90 b/radiation/FatesRadiationDriveMod.F90 index e8170a74a9..eee478446c 100644 --- a/radiation/FatesRadiationDriveMod.F90 +++ b/radiation/FatesRadiationDriveMod.F90 @@ -471,7 +471,7 @@ subroutine FatesSunShadeFracs(nsites, sites,bc_in,bc_out) end do do_icol do ft = 1,numpft - do_iv: do iv = 1, cpatch%ncan(cl,ft)! nlevleaf + do_iv: do iv = 1, cpatch%nleaf(cl,ft)! nlevleaf if(area_vlpfcl(iv,ft,cl) Date: Wed, 10 Jul 2024 15:07:30 -0600 Subject: [PATCH 284/300] fix on recruit l2fr --- biogeochem/EDPhysiologyMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index daeffc98ff..0f080127c9 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -3320,7 +3320,7 @@ subroutine UpdateRecruitL2FR(csite) end do ! Find the daily mean for each PFT weighted by number and add it to the running mean - do cl = 1,cpatch%ncl_p + do cl = 1,nclmax do ft = 1,numpft if(rec_n(ft,cl)>nearzero)then rec_l2fr0(ft,cl) = rec_l2fr0(ft,cl) / rec_n(ft,cl) From a2b71d0daa131b2b7da8b78eea3b0d1bfd46a723 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Mon, 15 Jul 2024 09:40:59 -0700 Subject: [PATCH 285/300] make sure to define state_vector if not in land use mode --- biogeochem/EDPatchDynamicsMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 55f7ba1311..586c3a1e3b 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -325,6 +325,8 @@ subroutine disturbance_rates( site_in, bc_in) call GetLUHStatedata(bc_in, state_vector) site_secondaryland_first_exceeding_min = (state_vector(secondaryland) .gt. site_in%min_allowed_landuse_fraction) & .and. (.not. site_in%landuse_vector_gt_min(secondaryland)) + else + state_vector = current_fates_landuse_state_vector end if currentPatch => site_in%oldest_patch From dfe771cf84a5cc447b8bfb97fa9c2857229e2d06 Mon Sep 17 00:00:00 2001 From: Gregory Lemieux Date: Tue, 23 Jul 2024 11:54:04 -0600 Subject: [PATCH 286/300] initialize the transitions matrix to zero --- main/EDInitMod.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index ce76ba9017..95da8cbfa8 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -276,6 +276,7 @@ subroutine zero_site( site_in ) ! Disturbance rates tracking site_in%primary_land_patchfusion_error = 0.0_r8 site_in%disturbance_rates(:,:,:) = 0.0_r8 + site_in%landuse_transition_matrix(:,:) = 0.0_r8 ! FIRE site_in%FDI = 0.0_r8 ! daily fire danger index (0-1) From d71c9f02ce2685a80812301c2c2785bffa16586c Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 23 Jul 2024 19:42:07 -0600 Subject: [PATCH 287/300] reverting nclmax to 3 for tests --- main/EDParamsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 2a57fe8ace..7defaa7f60 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -110,7 +110,7 @@ module EDParamsMod ! For large arrays at patch level we use dynamic allocation ! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code - integer, parameter, public :: nlevleaf = 60 ! number of leaf+stem layers in each canopy layer + integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in each canopy layer real(r8), public :: dinc_vai(nlevleaf) = fates_unset_r8 ! VAI bin widths array real(r8), public :: dlower_vai(nlevleaf) = fates_unset_r8 ! lower edges of VAI bins From cccfac6a8edbbc6644eb592984d890acf04e15b3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 25 Jul 2024 09:04:11 -0600 Subject: [PATCH 288/300] More zeroing of dynamic arrays --- biogeochem/FatesPatchMod.F90 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 952f5a7a0d..a1260517e7 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -535,6 +535,21 @@ subroutine ZeroDynamics(this) this%fabi_sha_z(:,:,:) = 0._r8 this%nrmlzd_parprof_pft_dir_z(:,:,:,:) = 0._r8 this%nrmlzd_parprof_pft_dif_z(:,:,:,:) = 0._r8 + + ! Added + this%elai_profile(:,:,:) = 0._r8 + this%esai_profile(:,:,:) = 0._r8 + this%tlai_profile(:,:,:) = 0._r8 + this%tsai_profile(:,:,:) = 0._r8 + this%canopy_area_profile(:,:,:) = 0._r8 + + this%ed_laisun_z(:,:,:) = 0._r8 + this%ed_laisha_z(:,:,:) = 0._r8 + this%ed_parsun_z(:,:,:) = 0._r8 + this%ed_parsha_z(:,:,:) = 0._r8 + + this%parprof_pft_dir_z(:,:,:) = 0._r8 + this%parprof_pft_dif_z(:,:,:) = 0._r8 end subroutine ZeroDynamics From 248595ca5e6ac0294928138645e7a2c010b95d06 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 26 Jul 2024 11:02:25 -0600 Subject: [PATCH 289/300] resetting nclmax to 2, since there is a bug that is preventing nclmax=3 in main --- main/EDParamsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 7defaa7f60..cc906fecef 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -104,7 +104,7 @@ module EDParamsMod real(r8), parameter, public :: soil_tfrz_thresh = -2.0_r8 ! Soil temperature threshold below which hydraulic failure mortality is off (non-hydro only) in degrees C - integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers (used only for scratch arrays) + integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers (used only for scratch arrays) ! We would make this even higher, but making this ! a little lower keeps the size down on some output arrays ! For large arrays at patch level we use dynamic allocation From 0897ba1cbcff1c9375b7126c5f2c0fa3e2ce6413 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 30 Jul 2024 10:59:48 -0600 Subject: [PATCH 290/300] attempts to get b4b, unsuccesfull so far --- biogeochem/EDCanopyStructureMod.F90 | 17 ++++++++++++----- biogeochem/FatesPatchMod.F90 | 12 ++++++------ radiation/FatesNormanRadMod.F90 | 2 +- radiation/FatesRadiationDriveMod.F90 | 2 +- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 7f2db09cd2..d88f6057fe 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1557,12 +1557,12 @@ subroutine leaf_area_profile( currentSite ) cpatch => currentSite%oldest_patch do while(associated(cpatch)) - + cpatch%nleaf(:,:) = 0 ! This routine updates the %nleaf array call UpdatePatchLAI(cpatch) - - + + ! This call assesses if the large, dynamically allocated ! patch arrays need to be allocated for the first time, ! or resized @@ -1589,14 +1589,21 @@ subroutine leaf_area_profile( currentSite ) ! UNDER THE SNOW, BUT WE DONT REALLY USE IT TO FILTER ! THEM OUT. CHECK THE CODE AND CONSIDER REMOVING NRAD ! ALTOGETHER (RGK 05-2024) - cpatch%nrad(:,:) = cpatch%nleaf(:,:) + !cpatch%nrad(:,:) = cpatch%nleaf(:,:) ! ------------------------------------------------------------------------------ ! It is remotely possible that in deserts we will not have any canopy ! area, ie not plants at all... ! ------------------------------------------------------------------------------ - if_any_canopy_area: if (cpatch%total_canopy_area > nearzero ) then + if_any_canopy_area: if (cpatch%total_canopy_area <= nearzero ) then + + cpatch%nleaf(:,:) = 0 + cpatch%nrad(:,:) = 0 + + else + + cpatch%nrad(:,:) = cpatch%nleaf(:,:) ! ----------------------------------------------------------------------------- ! Standard canopy layering model. diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index a1260517e7..0e3e8427f9 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -394,10 +394,11 @@ subroutine NanDynamics(this) this%elai_profile(:,:,:) = nan this%esai_profile(:,:,:) = nan this%tlai_profile(:,:,:) = nan - this%tsai_profile(:,:,:) = nan + this%tsai_profile(:,:,:) = nan this%canopy_area_profile(:,:,:) = nan this%nrmlzd_parprof_pft_dir_z(:,:,:,:) = nan this%nrmlzd_parprof_pft_dif_z(:,:,:,:) = nan + this%fabd_sun_z(:,:,:) = nan this%fabd_sha_z(:,:,:) = nan this%fabi_sun_z(:,:,:) = nan @@ -538,16 +539,15 @@ subroutine ZeroDynamics(this) ! Added this%elai_profile(:,:,:) = 0._r8 - this%esai_profile(:,:,:) = 0._r8 - this%tlai_profile(:,:,:) = 0._r8 - this%tsai_profile(:,:,:) = 0._r8 - this%canopy_area_profile(:,:,:) = 0._r8 + !this%esai_profile(:,:,:) = 0._r8 + !this%tlai_profile(:,:,:) = 0._r8 + !this%tsai_profile(:,:,:) = 0._r8 + !this%canopy_area_profile(:,:,:) = 0._r8 this%ed_laisun_z(:,:,:) = 0._r8 this%ed_laisha_z(:,:,:) = 0._r8 this%ed_parsun_z(:,:,:) = 0._r8 this%ed_parsha_z(:,:,:) = 0._r8 - this%parprof_pft_dir_z(:,:,:) = 0._r8 this%parprof_pft_dif_z(:,:,:) = 0._r8 diff --git a/radiation/FatesNormanRadMod.F90 b/radiation/FatesNormanRadMod.F90 index ae73748a42..2310f5ca54 100644 --- a/radiation/FatesNormanRadMod.F90 +++ b/radiation/FatesNormanRadMod.F90 @@ -189,7 +189,7 @@ subroutine PatchNormanRadiation (currentPatch, & tau_layer(:,:,:,:)=0.0_r8 f_abs(:,:,:,:)=0.0_r8 f_abs_leaf(:,:,:,:)=0._r8 - do L = 1,currentPatch%ncl_p + do L = 1,nclmax !currentPatch%ncl_p do ft = 1,numpft currentPatch%canopy_mask(L,ft) = 0 do iv = 1, currentPatch%nrad(L,ft) diff --git a/radiation/FatesRadiationDriveMod.F90 b/radiation/FatesRadiationDriveMod.F90 index eee478446c..8718cf43b7 100644 --- a/radiation/FatesRadiationDriveMod.F90 +++ b/radiation/FatesRadiationDriveMod.F90 @@ -471,7 +471,7 @@ subroutine FatesSunShadeFracs(nsites, sites,bc_in,bc_out) end do do_icol do ft = 1,numpft - do_iv: do iv = 1, cpatch%nleaf(cl,ft)! nlevleaf + do_iv: do iv = 1, nlevleaf !cpatch%nleaf(cl,ft) if(area_vlpfcl(iv,ft,cl) Date: Tue, 30 Jul 2024 12:00:18 -0600 Subject: [PATCH 291/300] zeroing psn_z --- biogeophys/FatesPlantRespPhotosynthMod.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index b338ab5b51..b37e3630a0 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -356,6 +356,8 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) bc_out(s)%rssun_pa(ifp) = 0._r8 bc_out(s)%rssha_pa(ifp) = 0._r8 + psn_z(:,:,:) = 0._r8 + g_sb_leaves = 0._r8 patch_la = 0._r8 From ed62e8203e9b3cd2d7a174d73ea97e75e9ad7427 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 30 Jul 2024 13:57:10 -0600 Subject: [PATCH 292/300] remove canopy closure clause --- biogeochem/EDCanopyStructureMod.F90 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index d88f6057fe..da8c33860a 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1596,12 +1596,12 @@ subroutine leaf_area_profile( currentSite ) ! area, ie not plants at all... ! ------------------------------------------------------------------------------ - if_any_canopy_area: if (cpatch%total_canopy_area <= nearzero ) then +! if_any_canopy_area: if (cpatch%total_canopy_area <= nearzero ) then - cpatch%nleaf(:,:) = 0 - cpatch%nrad(:,:) = 0 +! cpatch%nleaf(:,:) = 0 +! cpatch%nrad(:,:) = 0 - else +! else cpatch%nrad(:,:) = cpatch%nleaf(:,:) @@ -1873,7 +1873,7 @@ subroutine leaf_area_profile( currentSite ) end if - end if if_any_canopy_area + !end if if_any_canopy_area cpatch => cpatch%younger From 9b6b33611a1f88bb7e18040d195b7214e0f34127 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 31 Jul 2024 09:00:53 -0600 Subject: [PATCH 293/300] fixes to summed lai --- biogeochem/EDCanopyStructureMod.F90 | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index da8c33860a..42402ce566 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1559,6 +1559,7 @@ subroutine leaf_area_profile( currentSite ) do while(associated(cpatch)) cpatch%nleaf(:,:) = 0 + cpatch%canopy_layer_tlai(:) = 0._r8 ! This routine updates the %nleaf array call UpdatePatchLAI(cpatch) @@ -1577,7 +1578,6 @@ subroutine leaf_area_profile( currentSite ) ! calculate tree lai and sai. ! -------------------------------------------------------------------------------- - cpatch%canopy_layer_tlai(:) = 0._r8 cpatch%tlai_profile(:,:,:) = 0._r8 cpatch%tsai_profile(:,:,:) = 0._r8 cpatch%elai_profile(:,:,:) = 0._r8 @@ -1589,22 +1589,15 @@ subroutine leaf_area_profile( currentSite ) ! UNDER THE SNOW, BUT WE DONT REALLY USE IT TO FILTER ! THEM OUT. CHECK THE CODE AND CONSIDER REMOVING NRAD ! ALTOGETHER (RGK 05-2024) - !cpatch%nrad(:,:) = cpatch%nleaf(:,:) + cpatch%nrad(:,:) = cpatch%nleaf(:,:) ! ------------------------------------------------------------------------------ ! It is remotely possible that in deserts we will not have any canopy ! area, ie not plants at all... ! ------------------------------------------------------------------------------ -! if_any_canopy_area: if (cpatch%total_canopy_area <= nearzero ) then + if_any_canopy_area: if (cpatch%total_canopy_area > nearzero ) then -! cpatch%nleaf(:,:) = 0 -! cpatch%nrad(:,:) = 0 - -! else - - cpatch%nrad(:,:) = cpatch%nleaf(:,:) - ! ----------------------------------------------------------------------------- ! Standard canopy layering model. ! Go through all cohorts and add their leaf area @@ -1873,7 +1866,7 @@ subroutine leaf_area_profile( currentSite ) end if - !end if if_any_canopy_area + end if if_any_canopy_area cpatch => cpatch%younger From 8da0669aac08dbb84c1a7d8762ff81597e1fa5a8 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 31 Jul 2024 09:40:56 -0600 Subject: [PATCH 294/300] small additions to patch arrays --- biogeochem/EDCanopyStructureMod.F90 | 12 +----------- biogeochem/FatesPatchMod.F90 | 8 ++++---- radiation/FatesNormanRadMod.F90 | 2 +- radiation/FatesRadiationDriveMod.F90 | 2 +- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 42402ce566..e859a7339f 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -1573,17 +1573,7 @@ subroutine leaf_area_profile( currentSite ) call cpatch%NanDynamics() call cpatch%ZeroDynamics() - ! -------------------------------------------------------------------------------- - ! Calculate tree and canopy areas. - ! calculate tree lai and sai. - ! -------------------------------------------------------------------------------- - - cpatch%tlai_profile(:,:,:) = 0._r8 - cpatch%tsai_profile(:,:,:) = 0._r8 - cpatch%elai_profile(:,:,:) = 0._r8 - cpatch%esai_profile(:,:,:) = 0._r8 - cpatch%canopy_area_profile(:,:,:) = 0._r8 - cpatch%canopy_mask(:,:) = 0 + cpatch%canopy_mask(:,:) = 0 ! TO-DO: NRAD HYPOTHETICALLY WOULDNT INCLUDE LAYERS ! UNDER THE SNOW, BUT WE DONT REALLY USE IT TO FILTER diff --git a/biogeochem/FatesPatchMod.F90 b/biogeochem/FatesPatchMod.F90 index 0e3e8427f9..cc6c77ded1 100644 --- a/biogeochem/FatesPatchMod.F90 +++ b/biogeochem/FatesPatchMod.F90 @@ -539,10 +539,10 @@ subroutine ZeroDynamics(this) ! Added this%elai_profile(:,:,:) = 0._r8 - !this%esai_profile(:,:,:) = 0._r8 - !this%tlai_profile(:,:,:) = 0._r8 - !this%tsai_profile(:,:,:) = 0._r8 - !this%canopy_area_profile(:,:,:) = 0._r8 + this%esai_profile(:,:,:) = 0._r8 + this%tlai_profile(:,:,:) = 0._r8 + this%tsai_profile(:,:,:) = 0._r8 + this%canopy_area_profile(:,:,:) = 0._r8 this%ed_laisun_z(:,:,:) = 0._r8 this%ed_laisha_z(:,:,:) = 0._r8 diff --git a/radiation/FatesNormanRadMod.F90 b/radiation/FatesNormanRadMod.F90 index 2310f5ca54..ae73748a42 100644 --- a/radiation/FatesNormanRadMod.F90 +++ b/radiation/FatesNormanRadMod.F90 @@ -189,7 +189,7 @@ subroutine PatchNormanRadiation (currentPatch, & tau_layer(:,:,:,:)=0.0_r8 f_abs(:,:,:,:)=0.0_r8 f_abs_leaf(:,:,:,:)=0._r8 - do L = 1,nclmax !currentPatch%ncl_p + do L = 1,currentPatch%ncl_p do ft = 1,numpft currentPatch%canopy_mask(L,ft) = 0 do iv = 1, currentPatch%nrad(L,ft) diff --git a/radiation/FatesRadiationDriveMod.F90 b/radiation/FatesRadiationDriveMod.F90 index 8718cf43b7..b3e36c39b0 100644 --- a/radiation/FatesRadiationDriveMod.F90 +++ b/radiation/FatesRadiationDriveMod.F90 @@ -471,7 +471,7 @@ subroutine FatesSunShadeFracs(nsites, sites,bc_in,bc_out) end do do_icol do ft = 1,numpft - do_iv: do iv = 1, nlevleaf !cpatch%nleaf(cl,ft) + do_iv: do iv = 1,cpatch%nleaf(cl,ft) if(area_vlpfcl(iv,ft,cl) Date: Tue, 13 Aug 2024 11:02:34 -0400 Subject: [PATCH 295/300] Added parameter checking for sapwood allometry 2 and woody pft, removed crown damage code from grass sapwood allometry --- biogeochem/FatesAllometryMod.F90 | 20 +++++--------------- main/EDPftvarcon.F90 | 13 +++++++++++++ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index d0957ef190..2339df3b1a 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1050,21 +1050,11 @@ subroutine bsap_allom(d,ipft,crowndamage,canopy_trim,elongf_stem, sapw_area,bsap call bbgw_allom(d,ipft, elongf_stem,bbgw,dbbgwdd) bsap = bagw + bbgw - ! replicate the crown damage code - ! Do we really need this for grass? I would think this can be helpful for - ! grazing in the future. --XLG - if(crowndamage > 1)then - call GetCrownReduction(crowndamage, crown_reduction) - bsap = elongf_stem * (bsap - (bsap * agb_frac * branch_frac * crown_reduction)) - if(present(dbsapdd))then - dbsapdd = elongf_stem * & - (dbagwdd + dbbgwdd - ((dbagwdd + dbbgwdd) * agb_frac * branch_frac * crown_reduction)) - end if - else - bsap = elongf_stem * bsap - if (present(dbsapdd))then - dbsapdd = elongf_stem * (dbagwdd + dbbgwdd) - end if + ! This is a grass-only functionnal type, no need to run crown-damage effects + + bsap = elongf_stem * bsap + if (present(dbsapdd))then + dbsapdd = elongf_stem * (dbagwdd + dbbgwdd) end if if(present(dbsapdd))then diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 8e10ebdcf7..3d91f2f1b9 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -2183,6 +2183,19 @@ subroutine FatesCheckParams(is_master) end if + ! Check to make sure that if a grass sapwood allometry is used, it is not + ! a woody plant. + if ( ( prt_params%allom_smode(ipft)==2 ) .and. (prt_params%woody(ipft)==itrue) ) then + write(fates_log(),*) 'Allometry mode 2 is a mode that is only appropriate' + write(fates_log(),*) 'for a grass functional type. Sapwood allometry is set with' + write(fates_log(),*) 'fates_allom_smode in the parameter file. Woody versus non woody' + write(fates_log(),*) 'plants are set via fates_woody in the parameter file.' + write(fates_log(),*) 'Current settings for pft number: ',ipft + write(fates_log(),*) 'fates_woody: true' + write(fates_log(),*) 'fates_allom_smode: ',prt_params%allom_smode(ipft) + write(fates_log(),*) 'Please correct this discrepancy before re-running. Aborting.' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if ! Check if fraction of storage to reproduction is between 0-1 ! ---------------------------------------------------------------------------------- From d8f383f311facd3e2f46aafed0bfd07dad7f1fa4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Aug 2024 14:34:25 -0400 Subject: [PATCH 296/300] Adding api36.2 (or 36.1) parameter change xml file --- .../archive/api36.2.0_081324_patch_params.xml | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 parameter_files/archive/api36.2.0_081324_patch_params.xml diff --git a/parameter_files/archive/api36.2.0_081324_patch_params.xml b/parameter_files/archive/api36.2.0_081324_patch_params.xml new file mode 100644 index 0000000000..0337fae5aa --- /dev/null +++ b/parameter_files/archive/api36.2.0_081324_patch_params.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + archive/api36.0.0_params_default.cdl + fates_params_default.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, 0.0728698, 0.06896, 0.06896, 0.06896, 0.001, 0.001, 0.003 + + + 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, 0.572, 0.572, 0.572, 1.6592, 1.6592, 1.3456 + + + 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.248, 1.248, 1.869 + + + 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, -999.9, -999.9, -999.9 + + + 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 1, 1, 1 + + + 3, 3, 3, 3, 3, 3, 1, 1, 1, 5, 5, 5 + + + -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, 0, 0, -0.487, -0.487, -0.259 + + + 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, 0.0004, 0.0004, 0.0012 + + + 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, 1.3998939, 1.3, 1.3, 1.3, 1.7092, 1.7092, 1.5879 + + + 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.3417, 0.3417, 0.9948 + + + 0.2715891, 0.3693718, 1.0787259, 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.0408, 0.0408, 0.0862 + + + 0.2715891, 0.3693718, 1.0787259, 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.0408, 0.0408, 0.0862 + + + 78.4087704, 306.842667, 106.8745821, 104.3586841, 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.1812, 0.1812, 0.3353 + + + 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, 0.9734088, 0.37, 0.37, 0.37, 0.6384, 0.6384, 0.4235 + + + 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, 20, 20, 30 + + + 5, 5, 5, 5, 5, 5, 1, 1, 1, 3, 3, 3 + + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.67, 0.67, 1.41 + + + fates_allom_lmode + 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 5, 5 + + + fates_allom_smode + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2 + + + fates_leaf_slamax + 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.05, 0.05, 0.05 + + + fates_leaf_slatop + 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, 0.03, 0.05, 0.05, 0.05 + + + fates_recruit_height_min + 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 + + + fates_recruit_seed_alloc + 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0 + + + fates_recruit_seed_alloc_mature + 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.25, 0.25, 0.2 + + + fates_recruit_seed_dbh_repro_threshold + 90, 80, 80, 80, 90, 80, 3, 3, 2, 3, 3, 3 + + + fates_cnp_prescribed_nuptake + 0,0,0,0,0,0,0,0,0,0,0,0 + + + fates_cnp_prescribed_puptake + 0,0,0,0,0,0,0,0,0,0,0,0 + + + fates_turnover_leaf + + + fates_turnover_leaf_canopy + fates_leafage_class, fates_pft + yr + Leaf longevity (ie turnover timescale) of canopy plants. For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season. + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 + + + fates_turnover_leaf_ustory + fates_leafage_class, fates_pft + yr + Leaf longevity (ie turnover timescale) of understory plants. + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 + + + + + From 8fb5f4f7afaed33342b5bd2e3531c9c128e8d02b Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Aug 2024 18:23:36 -0400 Subject: [PATCH 297/300] debugged and applied first pass of the api36.1 parameters --- .../archive/api36.0.0_params_default.cdl | 1786 +++++++++++++++++ ....xml => api36.1.0_081324_patch_params.xml} | 31 +- parameter_files/fates_params_default.cdl | 83 +- tools/UpdateParamAPI.py | 10 +- 4 files changed, 1849 insertions(+), 61 deletions(-) create mode 100644 parameter_files/archive/api36.0.0_params_default.cdl rename parameter_files/archive/{api36.2.0_081324_patch_params.xml => api36.1.0_081324_patch_params.xml} (87%) diff --git a/parameter_files/archive/api36.0.0_params_default.cdl b/parameter_files/archive/api36.0.0_params_default.cdl new file mode 100644 index 0000000000..2eaeb875fe --- /dev/null +++ b/parameter_files/archive/api36.0.0_params_default.cdl @@ -0,0 +1,1786 @@ +netcdf tmp { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_coage_bins = 2 ; + fates_history_damage_bins = 2 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hlm_pftno = 14 ; + fates_hydr_organs = 4 ; + fates_landuseclass = 5 ; + fates_leafage_class = 1 ; + fates_litterclass = 6 ; + fates_pft = 12 ; + fates_plant_organs = 4 ; + fates_string_length = 60 ; +variables: + double fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; + fates_history_coageclass_bin_edges:units = "years" ; + fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; + double fates_history_height_bin_edges(fates_history_height_bins) ; + fates_history_height_bin_edges:units = "m" ; + fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; + double fates_history_damage_bin_edges(fates_history_damage_bins) ; + fates_history_damage_bin_edges:units = "% crown loss" ; + fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; + double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; + fates_history_sizeclass_bin_edges:units = "cm" ; + fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; + double fates_alloc_organ_id(fates_plant_organs) ; + fates_alloc_organ_id:units = "unitless" ; + fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; + double fates_hydro_htftype_node(fates_hydr_organs) ; + fates_hydro_htftype_node:units = "unitless" ; + fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; + fates_hydro_organ_name:units = "unitless - string" ; + fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; + fates_alloc_organ_name:units = "unitless - string" ; + fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; + char fates_landuseclass_name(fates_landuseclass, fates_string_length) ; + fates_landuseclass_name:units = "unitless - string" ; + fates_landuseclass_name:long_name = "Name of the land use classes, for variables associated with dimension fates_landuseclass" ; + char fates_litterclass_name(fates_litterclass, fates_string_length) ; + fates_litterclass_name:units = "unitless - string" ; + fates_litterclass_name:long_name = "Name of the litter classes, for variables associated with dimension fates_litterclass" ; + double fates_alloc_organ_priority(fates_plant_organs, fates_pft) ; + fates_alloc_organ_priority:units = "index" ; + fates_alloc_organ_priority:long_name = "Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance" ; + double fates_alloc_storage_cushion(fates_pft) ; + fates_alloc_storage_cushion:units = "fraction" ; + fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; + double fates_alloc_store_priority_frac(fates_pft) ; + fates_alloc_store_priority_frac:units = "unitless" ; + fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; + double fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + double fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + double fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + double fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + double fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + double fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index." ; + double fates_allom_blca_expnt_diff(fates_pft) ; + fates_allom_blca_expnt_diff:units = "unitless" ; + fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; + double fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; + double fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + double fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + double fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + double fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + double fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + double fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + double fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + double fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + double fates_allom_dmode(fates_pft) ; + fates_allom_dmode:units = "index" ; + fates_allom_dmode:long_name = "crown depth allometry function index" ; + double fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index." ; + double fates_allom_fnrt_prof_a(fates_pft) ; + fates_allom_fnrt_prof_a:units = "unitless" ; + fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; + double fates_allom_fnrt_prof_b(fates_pft) ; + fates_allom_fnrt_prof_b:units = "unitless" ; + fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; + double fates_allom_fnrt_prof_mode(fates_pft) ; + fates_allom_fnrt_prof_mode:units = "index" ; + fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; + double fates_allom_frbstor_repro(fates_pft) ; + fates_allom_frbstor_repro:units = "fraction" ; + fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; + double fates_allom_h2cd1(fates_pft) ; + fates_allom_h2cd1:units = "variable" ; + fates_allom_h2cd1:long_name = "Parameter 1 for h2cd allometry (exp(log-intercept) or scaling). If allom_dmode=1; this is the same as former crown_depth_frac parameter" ; + double fates_allom_h2cd2(fates_pft) ; + fates_allom_h2cd2:units = "variable" ; + fates_allom_h2cd2:long_name = "Parameter 2 for h2cd allometry (log-slope or exponent). If allom_dmode=1; this is not needed (as exponent is assumed 1)" ; + double fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index." ; + double fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + double fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + double fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + double fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index." ; + double fates_allom_sai_scaler(fates_pft) ; + fates_allom_sai_scaler:units = "m2/m2" ; + fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; + double fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index." ; + double fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; + double fates_allom_zroot_k(fates_pft) ; + fates_allom_zroot_k:units = "unitless" ; + fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; + double fates_allom_zroot_max_dbh(fates_pft) ; + fates_allom_zroot_max_dbh:units = "cm" ; + fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; + double fates_allom_zroot_max_z(fates_pft) ; + fates_allom_zroot_max_z:units = "m" ; + fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_allom_zroot_min_dbh(fates_pft) ; + fates_allom_zroot_min_dbh:units = "cm" ; + fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; + double fates_allom_zroot_min_z(fates_pft) ; + fates_allom_zroot_min_z:units = "m" ; + fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; + double fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + double fates_cnp_eca_alpha_ptase(fates_pft) ; + fates_cnp_eca_alpha_ptase:units = "g/m3" ; + fates_cnp_eca_alpha_ptase:long_name = "(INACTIVE, KEEP AT 0) fraction of P from ptase activity sent directly to plant (ECA)" ; + double fates_cnp_eca_decompmicc(fates_pft) ; + fates_cnp_eca_decompmicc:units = "gC/m3" ; + fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; + double fates_cnp_eca_km_nh4(fates_pft) ; + fates_cnp_eca_km_nh4:units = "gN/m3" ; + fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_km_no3(fates_pft) ; + fates_cnp_eca_km_no3:units = "gN/m3" ; + fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; + double fates_cnp_eca_km_p(fates_pft) ; + fates_cnp_eca_km_p:units = "gP/m3" ; + fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; + double fates_cnp_eca_km_ptase(fates_pft) ; + fates_cnp_eca_km_ptase:units = "gP/m3" ; + fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; + double fates_cnp_eca_lambda_ptase(fates_pft) ; + fates_cnp_eca_lambda_ptase:units = "g/m3" ; + fates_cnp_eca_lambda_ptase:long_name = "(INACTIVE, KEEP AT 0) critical value for biochemical production (ECA)" ; + double fates_cnp_eca_vmax_ptase(fates_pft) ; + fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; + fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "fraction" ; + fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; + double fates_cnp_nitr_store_ratio(fates_pft) ; + fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; + fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; + double fates_cnp_phos_store_ratio(fates_pft) ; + fates_cnp_phos_store_ratio:units = "(gP/gP)" ; + fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; + double fates_cnp_pid_kd(fates_pft) ; + fates_cnp_pid_kd:units = "unknown" ; + fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_ki(fates_pft) ; + fates_cnp_pid_ki:units = "unknown" ; + fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_pid_kp(fates_pft) ; + fates_cnp_pid_kp:units = "unknown" ; + fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; + double fates_cnp_prescribed_nuptake(fates_pft) ; + fates_cnp_prescribed_nuptake:units = "fraction" ; + fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; + double fates_cnp_prescribed_puptake(fates_pft) ; + fates_cnp_prescribed_puptake:units = "fraction" ; + fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; + double fates_cnp_store_ovrflw_frac(fates_pft) ; + fates_cnp_store_ovrflw_frac:units = "fraction" ; + fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; + double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_nitr_retrans:units = "fraction" ; + fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; + double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; + fates_cnp_turnover_phos_retrans:units = "fraction" ; + fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; + double fates_cnp_vmax_nh4(fates_pft) ; + fates_cnp_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; + double fates_cnp_vmax_no3(fates_pft) ; + fates_cnp_vmax_no3:units = "gN/gC/s" ; + fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; + double fates_cnp_vmax_p(fates_pft) ; + fates_cnp_vmax_p:units = "gP/gC/s" ; + fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; + double fates_damage_frac(fates_pft) ; + fates_damage_frac:units = "fraction" ; + fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; + double fates_damage_mort_p1(fates_pft) ; + fates_damage_mort_p1:units = "fraction" ; + fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; + double fates_damage_mort_p2(fates_pft) ; + fates_damage_mort_p2:units = "unitless" ; + fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; + double fates_damage_recovery_scalar(fates_pft) ; + fates_damage_recovery_scalar:units = "unitless" ; + fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; + double fates_dev_arbitrary_pft(fates_pft) ; + fates_dev_arbitrary_pft:units = "unknown" ; + fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + double fates_fire_bark_scaler(fates_pft) ; + fates_fire_bark_scaler:units = "fraction" ; + fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; + double fates_fire_crown_kill(fates_pft) ; + fates_fire_crown_kill:units = "NA" ; + fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; + double fates_frag_fnrt_fcel(fates_pft) ; + fates_frag_fnrt_fcel:units = "fraction" ; + fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; + double fates_frag_fnrt_flab(fates_pft) ; + fates_frag_fnrt_flab:units = "fraction" ; + fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; + double fates_frag_fnrt_flig(fates_pft) ; + fates_frag_fnrt_flig:units = "fraction" ; + fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; + double fates_frag_leaf_fcel(fates_pft) ; + fates_frag_leaf_fcel:units = "fraction" ; + fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; + double fates_frag_leaf_flab(fates_pft) ; + fates_frag_leaf_flab:units = "fraction" ; + fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; + double fates_frag_leaf_flig(fates_pft) ; + fates_frag_leaf_flig:units = "fraction" ; + fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; + double fates_frag_seed_decay_rate(fates_pft) ; + fates_frag_seed_decay_rate:units = "yr-1" ; + fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; + double fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + double fates_hydro_avuln_gs(fates_pft) ; + fates_hydro_avuln_gs:units = "unitless" ; + fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; + double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; + fates_hydro_avuln_node:units = "unitless" ; + fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; + double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydro_epsil_node:units = "MPa" ; + fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; + double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydro_fcap_node:units = "unitless" ; + fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; + double fates_hydro_k_lwp(fates_pft) ; + fates_hydro_k_lwp:units = "unitless" ; + fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; + double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydro_kmax_node:units = "kg/MPa/m/s" ; + fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + double fates_hydro_p50_gs(fates_pft) ; + fates_hydro_p50_gs:units = "MPa" ; + fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; + double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; + fates_hydro_p50_node:units = "MPa" ; + fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; + double fates_hydro_p_taper(fates_pft) ; + fates_hydro_p_taper:units = "unitless" ; + fates_hydro_p_taper:long_name = "xylem taper exponent" ; + double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pinot_node:units = "MPa" ; + fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; + double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydro_pitlp_node:units = "MPa" ; + fates_hydro_pitlp_node:long_name = "turgor loss point" ; + double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydro_resid_node:units = "cm3/cm3" ; + fates_hydro_resid_node:long_name = "residual water conent" ; + double fates_hydro_rfrac_stem(fates_pft) ; + fates_hydro_rfrac_stem:units = "fraction" ; + fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; + double fates_hydro_rs2(fates_pft) ; + fates_hydro_rs2:units = "m" ; + fates_hydro_rs2:long_name = "absorbing root radius" ; + double fates_hydro_srl(fates_pft) ; + fates_hydro_srl:units = "m g-1" ; + fates_hydro_srl:long_name = "specific root length" ; + double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; + fates_hydro_thetas_node:units = "cm3/cm3" ; + fates_hydro_thetas_node:long_name = "saturated water content" ; + double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_alpha_node:units = "MPa-1" ; + fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; + double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_m_node:units = "unitless" ; + fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; + double fates_hydro_vg_n_node(fates_hydr_organs, fates_pft) ; + fates_hydro_vg_n_node:units = "unitless" ; + fates_hydro_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + double fates_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + double fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_slamax(fates_pft) ; + fates_leaf_slamax:units = "m^2/gC" ; + fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; + double fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + double fates_leaf_stomatal_intercept(fates_pft) ; + fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; + fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; + double fates_leaf_stomatal_slope_ballberry(fates_pft) ; + fates_leaf_stomatal_slope_ballberry:units = "unitless" ; + fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; + double fates_leaf_stomatal_slope_medlyn(fates_pft) ; + fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; + fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; + double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; + fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; + fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; + double fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; + double fates_leafn_vert_scaler_coeff1(fates_pft) ; + fates_leafn_vert_scaler_coeff1:units = "unitless" ; + fates_leafn_vert_scaler_coeff1:long_name = "Coefficient one for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010." ; + double fates_leafn_vert_scaler_coeff2(fates_pft) ; + fates_leafn_vert_scaler_coeff2:units = "unitless" ; + fates_leafn_vert_scaler_coeff2:long_name = "Coefficient two for decrease in leaf nitrogen through the canopy, from Lloyd et al. 2010." ; + double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; + fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; + fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; + double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; + fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; + fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; + double fates_maintresp_leaf_vert_scaler_coeff1(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff1:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff1:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff1." ; + double fates_maintresp_leaf_vert_scaler_coeff2(fates_pft) ; + fates_maintresp_leaf_vert_scaler_coeff2:units = "unitless" ; + fates_maintresp_leaf_vert_scaler_coeff2:long_name = "Leaf maintenance respiration decrease through the canopy. Only applies to Atkin et al. 2017. For proportionality between photosynthesis and respiration through the canopy, match with fates_leafn_vert_scaler_coeff2." ; + double fates_maintresp_reduction_curvature(fates_pft) ; + fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; + fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; + double fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + double fates_maintresp_reduction_upthresh(fates_pft) ; + fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; + fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; + double fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + double fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "degrees C" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance" ; + double fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; + double fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + double fates_mort_ip_age_senescence(fates_pft) ; + fates_mort_ip_age_senescence:units = "years" ; + fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; + double fates_mort_ip_size_senescence(fates_pft) ; + fates_mort_ip_size_senescence:units = "dbh cm" ; + fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; + double fates_mort_prescribed_canopy(fates_pft) ; + fates_mort_prescribed_canopy:units = "1/yr" ; + fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; + double fates_mort_prescribed_understory(fates_pft) ; + fates_mort_prescribed_understory:units = "1/yr" ; + fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; + double fates_mort_r_age_senescence(fates_pft) ; + fates_mort_r_age_senescence:units = "mortality rate year^-1" ; + fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; + double fates_mort_r_size_senescence(fates_pft) ; + fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; + fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; + double fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + double fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + double fates_mort_scalar_hydrfailure(fates_pft) ; + fates_mort_scalar_hydrfailure:units = "1/yr" ; + fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; + double fates_mort_upthresh_cstarvation(fates_pft) ; + fates_mort_upthresh_cstarvation:units = "unitless" ; + fates_mort_upthresh_cstarvation:long_name = "threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero" ; + double fates_nonhydro_smpsc(fates_pft) ; + fates_nonhydro_smpsc:units = "mm" ; + fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; + double fates_nonhydro_smpso(fates_pft) ; + fates_nonhydro_smpso:units = "mm" ; + fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; + double fates_phen_cold_size_threshold(fates_pft) ; + fates_phen_cold_size_threshold:units = "cm" ; + fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; + double fates_phen_drought_threshold(fates_pft) ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + double fates_phen_flush_fraction(fates_pft) ; + fates_phen_flush_fraction:units = "fraction" ; + fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; + double fates_phen_fnrt_drop_fraction(fates_pft) ; + fates_phen_fnrt_drop_fraction:units = "fraction" ; + fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; + double fates_phen_mindaysoff(fates_pft) ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; + double fates_phen_moist_threshold(fates_pft) ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; + double fates_phen_season_decid(fates_pft) ; + fates_phen_season_decid:units = "logical flag" ; + fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; + double fates_phen_stem_drop_fraction(fates_pft) ; + fates_phen_stem_drop_fraction:units = "fraction" ; + fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; + double fates_phen_stress_decid(fates_pft) ; + fates_phen_stress_decid:units = "logical flag" ; + fates_phen_stress_decid:long_name = "Flag for stress/drought-deciduous leaf habit. 0 - not stress deciduous; 1 - default drought deciduous (two target states only, fully flushed or fully abscised); 2 - semi-deciduous" ; + double fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + double fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + double fates_rad_leaf_clumping_index(fates_pft) ; + fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; + fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; + double fates_rad_leaf_rhonir(fates_pft) ; + fates_rad_leaf_rhonir:units = "fraction" ; + fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; + double fates_rad_leaf_rhovis(fates_pft) ; + fates_rad_leaf_rhovis:units = "fraction" ; + fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; + double fates_rad_leaf_taunir(fates_pft) ; + fates_rad_leaf_taunir:units = "fraction" ; + fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; + double fates_rad_leaf_tauvis(fates_pft) ; + fates_rad_leaf_tauvis:units = "fraction" ; + fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; + double fates_rad_leaf_xl(fates_pft) ; + fates_rad_leaf_xl:units = "unitless" ; + fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; + double fates_rad_stem_rhonir(fates_pft) ; + fates_rad_stem_rhonir:units = "fraction" ; + fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; + double fates_rad_stem_rhovis(fates_pft) ; + fates_rad_stem_rhovis:units = "fraction" ; + fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; + double fates_rad_stem_taunir(fates_pft) ; + fates_rad_stem_taunir:units = "fraction" ; + fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; + double fates_rad_stem_tauvis(fates_pft) ; + fates_rad_stem_tauvis:units = "fraction" ; + fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; + double fates_recruit_height_min(fates_pft) ; + fates_recruit_height_min:units = "m" ; + fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; + double fates_recruit_init_density(fates_pft) ; + fates_recruit_init_density:units = "stems/m2" ; + fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; + double fates_recruit_prescribed_rate(fates_pft) ; + fates_recruit_prescribed_rate:units = "n/yr" ; + fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; + double fates_recruit_seed_alloc(fates_pft) ; + fates_recruit_seed_alloc:units = "fraction" ; + fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + double fates_recruit_seed_alloc_mature(fates_pft) ; + fates_recruit_seed_alloc_mature:units = "fraction" ; + fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; + double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; + fates_recruit_seed_dbh_repro_threshold:units = "cm" ; + fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; + double fates_recruit_seed_germination_rate(fates_pft) ; + fates_recruit_seed_germination_rate:units = "yr-1" ; + fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; + double fates_recruit_seed_supplement(fates_pft) ; + fates_recruit_seed_supplement:units = "KgC/m2/yr" ; + fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; + double fates_seed_dispersal_fraction(fates_pft) ; + fates_seed_dispersal_fraction:units = "fraction" ; + fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; + double fates_seed_dispersal_max_dist(fates_pft) ; + fates_seed_dispersal_max_dist:units = "m" ; + fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; + double fates_seed_dispersal_pdf_scale(fates_pft) ; + fates_seed_dispersal_pdf_scale:units = "unitless" ; + fates_seed_dispersal_pdf_scale:long_name = "seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016" ; + double fates_seed_dispersal_pdf_shape(fates_pft) ; + fates_seed_dispersal_pdf_shape:units = "unitless" ; + fates_seed_dispersal_pdf_shape:long_name = "seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016" ; + double fates_stoich_nitr(fates_plant_organs, fates_pft) ; + fates_stoich_nitr:units = "gN/gC" ; + fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; + double fates_stoich_phos(fates_plant_organs, fates_pft) ; + fates_stoich_phos:units = "gP/gC" ; + fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; + double fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + double fates_trim_limit(fates_pft) ; + fates_trim_limit:units = "m2/m2" ; + fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; + double fates_trs_repro_alloc_a(fates_pft) ; + fates_trs_repro_alloc_a:units = "fraction" ; + fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_alloc_b(fates_pft) ; + fates_trs_repro_alloc_b:units = "fraction" ; + fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; + double fates_trs_repro_frac_seed(fates_pft) ; + fates_trs_repro_frac_seed:units = "fraction" ; + fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; + double fates_trs_seedling_a_emerg(fates_pft) ; + fates_trs_seedling_a_emerg:units = "day -1" ; + fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; + double fates_trs_seedling_b_emerg(fates_pft) ; + fates_trs_seedling_b_emerg:units = "day -1" ; + fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; + double fates_trs_seedling_background_mort(fates_pft) ; + fates_trs_seedling_background_mort:units = "yr-1" ; + fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; + double fates_trs_seedling_h2o_mort_a(fates_pft) ; + fates_trs_seedling_h2o_mort_a:units = "-" ; + fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_b(fates_pft) ; + fates_trs_seedling_h2o_mort_b:units = "-" ; + fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_h2o_mort_c(fates_pft) ; + fates_trs_seedling_h2o_mort_c:units = "-" ; + fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; + double fates_trs_seedling_light_mort_a(fates_pft) ; + fates_trs_seedling_light_mort_a:units = "-" ; + fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_mort_b(fates_pft) ; + fates_trs_seedling_light_mort_b:units = "-" ; + fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; + double fates_trs_seedling_light_rec_a(fates_pft) ; + fates_trs_seedling_light_rec_a:units = "-" ; + fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_light_rec_b(fates_pft) ; + fates_trs_seedling_light_rec_b:units = "-" ; + fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; + double fates_trs_seedling_mdd_crit(fates_pft) ; + fates_trs_seedling_mdd_crit:units = "mm H2O day" ; + fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; + double fates_trs_seedling_par_crit_germ(fates_pft) ; + fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; + fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; + double fates_trs_seedling_psi_crit(fates_pft) ; + fates_trs_seedling_psi_crit:units = "mm H2O" ; + fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; + double fates_trs_seedling_psi_emerg(fates_pft) ; + fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; + fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; + double fates_trs_seedling_root_depth(fates_pft) ; + fates_trs_seedling_root_depth:units = "m" ; + fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; + double fates_turb_displar(fates_pft) ; + fates_turb_displar:units = "unitless" ; + fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; + double fates_turb_leaf_diameter(fates_pft) ; + fates_turb_leaf_diameter:units = "m" ; + fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; + double fates_turb_z0mr(fates_pft) ; + fates_turb_z0mr:units = "unitless" ; + fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + double fates_turnover_branch(fates_pft) ; + fates_turnover_branch:units = "yr" ; + fates_turnover_branch:long_name = "turnover time of branches" ; + double fates_turnover_fnrt(fates_pft) ; + fates_turnover_fnrt:units = "yr" ; + fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; + double fates_turnover_senleaf_fdrought(fates_pft) ; + fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; + fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; + double fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + double fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; + fates_hlm_pft_map:units = "area fraction" ; + fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; + double fates_fire_FBD(fates_litterclass) ; + fates_fire_FBD:units = "kg Biomass/m3" ; + fates_fire_FBD:long_name = "fuel bulk density" ; + double fates_fire_low_moisture_Coeff(fates_litterclass) ; + fates_fire_low_moisture_Coeff:units = "NA" ; + fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_low_moisture_Slope(fates_litterclass) ; + fates_fire_low_moisture_Slope:units = "NA" ; + fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture(fates_litterclass) ; + fates_fire_mid_moisture:units = "NA" ; + fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + double fates_fire_mid_moisture_Coeff(fates_litterclass) ; + fates_fire_mid_moisture_Coeff:units = "NA" ; + fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_mid_moisture_Slope(fates_litterclass) ; + fates_fire_mid_moisture_Slope:units = "NA" ; + fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + double fates_fire_min_moisture(fates_litterclass) ; + fates_fire_min_moisture:units = "NA" ; + fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + double fates_fire_SAV(fates_litterclass) ; + fates_fire_SAV:units = "cm-1" ; + fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; + double fates_frag_maxdecomp(fates_litterclass) ; + fates_frag_maxdecomp:units = "yr-1" ; + fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + double fates_frag_cwd_frac(fates_NCWD) ; + fates_frag_cwd_frac:units = "fraction" ; + fates_frag_cwd_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + double fates_maxpatches_by_landuse(fates_landuseclass) ; + fates_maxpatches_by_landuse:units = "count" ; + fates_maxpatches_by_landuse:long_name = "maximum number of patches per site on each land use type" ; + double fates_canopy_closure_thresh ; + fates_canopy_closure_thresh:units = "unitless" ; + fates_canopy_closure_thresh:long_name = "tree canopy coverage at which crown area allometry changes from savanna to forest value" ; + double fates_cnp_eca_plant_escalar ; + fates_cnp_eca_plant_escalar:units = "" ; + fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; + double fates_cohort_age_fusion_tol ; + fates_cohort_age_fusion_tol:units = "unitless" ; + fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; + double fates_cohort_size_fusion_tol ; + fates_cohort_size_fusion_tol:units = "unitless" ; + fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + double fates_comp_excln ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; + double fates_damage_canopy_layer_code ; + fates_damage_canopy_layer_code:units = "unitless" ; + fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; + double fates_damage_event_code ; + fates_damage_event_code:units = "unitless" ; + fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; + double fates_daylength_factor_switch ; + fates_daylength_factor_switch:units = "unitless" ; + fates_daylength_factor_switch:long_name = "user switch for turning on (1) or off (0) the day length factor scaling for photosynthetic parameters (ie scale vcmax and jmax)" ; + double fates_dev_arbitrary ; + fates_dev_arbitrary:units = "unknown" ; + fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; + double fates_fire_active_crown_fire ; + fates_fire_active_crown_fire:units = "0 or 1" ; + fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; + double fates_fire_cg_strikes ; + fates_fire_cg_strikes:units = "fraction (0-1)" ; + fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; + double fates_fire_drying_ratio ; + fates_fire_drying_ratio:units = "NA" ; + fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; + double fates_fire_durat_slope ; + fates_fire_durat_slope:units = "NA" ; + fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + double fates_fire_fdi_a ; + fates_fire_fdi_a:units = "NA" ; + fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; + double fates_fire_fdi_alpha ; + fates_fire_fdi_alpha:units = "NA" ; + fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + double fates_fire_fdi_b ; + fates_fire_fdi_b:units = "NA" ; + fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; + double fates_fire_fuel_energy ; + fates_fire_fuel_energy:units = "kJ/kg" ; + fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; + double fates_fire_max_durat ; + fates_fire_max_durat:units = "minutes" ; + fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + double fates_fire_miner_damp ; + fates_fire_miner_damp:units = "NA" ; + fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + double fates_fire_miner_total ; + fates_fire_miner_total:units = "fraction" ; + fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + double fates_fire_nignitions ; + fates_fire_nignitions:units = "ignitions per year per km2" ; + fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; + double fates_fire_part_dens ; + fates_fire_part_dens:units = "kg/m2" ; + fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + double fates_fire_threshold ; + fates_fire_threshold:units = "kW/m" ; + fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; + double fates_frag_cwd_fcel ; + fates_frag_cwd_fcel:units = "unitless" ; + fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + double fates_frag_cwd_flig ; + fates_frag_cwd_flig:units = "unitless" ; + fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + double fates_hydro_kmax_rsurf1 ; + fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; + double fates_hydro_kmax_rsurf2 ; + fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; + fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; + double fates_hydro_psi0 ; + fates_hydro_psi0:units = "MPa" ; + fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; + double fates_hydro_psicap ; + fates_hydro_psicap:units = "MPa" ; + fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + double fates_hydro_solver ; + fates_hydro_solver:units = "unitless" ; + fates_hydro_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard, 3 = 2D Newton (deprecated)" ; + double fates_landuse_logging_coll_under_frac ; + fates_landuse_logging_coll_under_frac:units = "fraction" ; + fates_landuse_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; + double fates_landuse_logging_collateral_frac ; + fates_landuse_logging_collateral_frac:units = "fraction" ; + fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + double fates_landuse_logging_dbhmax ; + fates_landuse_logging_dbhmax:units = "cm" ; + fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; + double fates_landuse_logging_dbhmax_infra ; + fates_landuse_logging_dbhmax_infra:units = "cm" ; + fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; + double fates_landuse_logging_dbhmin ; + fates_landuse_logging_dbhmin:units = "cm" ; + fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + double fates_landuse_logging_direct_frac ; + fates_landuse_logging_direct_frac:units = "fraction" ; + fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + double fates_landuse_logging_event_code ; + fates_landuse_logging_event_code:units = "unitless" ; + fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + double fates_landuse_logging_export_frac ; + fates_landuse_logging_export_frac:units = "fraction" ; + fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; + double fates_landuse_logging_mechanical_frac ; + fates_landuse_logging_mechanical_frac:units = "fraction" ; + fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + double fates_landuse_pprodharv10_forest_mean ; + fates_landuse_pprodharv10_forest_mean:units = "fraction" ; + fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; + double fates_leaf_photo_temp_acclim_thome_time ; + fates_leaf_photo_temp_acclim_thome_time:units = "years" ; + fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_temp_acclim_timescale ; + fates_leaf_photo_temp_acclim_timescale:units = "days" ; + fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; + double fates_leaf_photo_tempsens_model ; + fates_leaf_photo_tempsens_model:units = "unitless" ; + fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; + double fates_leaf_stomatal_assim_model ; + fates_leaf_stomatal_assim_model:units = "unitless" ; + fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; + double fates_leaf_stomatal_model ; + fates_leaf_stomatal_model:units = "unitless" ; + fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; + double fates_leaf_theta_cj_c3 ; + fates_leaf_theta_cj_c3:units = "unitless" ; + fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; + double fates_leaf_theta_cj_c4 ; + fates_leaf_theta_cj_c4:units = "unitless" ; + fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; + double fates_maintresp_leaf_model ; + fates_maintresp_leaf_model:units = "unitless" ; + fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; + double fates_maintresp_nonleaf_baserate ; + fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; + fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + double fates_maxcohort ; + fates_maxcohort:units = "count" ; + fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; + double fates_mort_cstarvation_model ; + fates_mort_cstarvation_model:units = "unitless" ; + fates_mort_cstarvation_model:long_name = "switch defining the carbon starvation model ( 1) Linear or 2) Exponential) in the mortality_rates function." ; + double fates_mort_disturb_frac ; + fates_mort_disturb_frac:units = "fraction" ; + fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; + double fates_mort_understorey_death ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + double fates_patch_fusion_tol ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + double fates_phen_chilltemp ; + fates_phen_chilltemp:units = "degrees C" ; + fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; + double fates_phen_coldtemp ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; + double fates_phen_gddthresh_a ; + fates_phen_gddthresh_a:units = "none" ; + fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_b ; + fates_phen_gddthresh_b:units = "none" ; + fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_gddthresh_c ; + fates_phen_gddthresh_c:units = "none" ; + fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + double fates_phen_mindayson ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + double fates_phen_ncolddayslim ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + double fates_q10_froz ; + fates_q10_froz:units = "unitless" ; + fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; + double fates_q10_mr ; + fates_q10_mr:units = "unitless" ; + fates_q10_mr:long_name = "Q10 for maintenance respiration" ; + double fates_rad_model ; + fates_rad_model:units = "unitless" ; + fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; + double fates_regeneration_model ; + fates_regeneration_model:units = "-" ; + fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; + double fates_soil_salinity ; + fates_soil_salinity:units = "ppt" ; + fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; + double fates_trs_seedling2sap_par_timescale ; + fates_trs_seedling2sap_par_timescale:units = "days" ; + fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; + double fates_trs_seedling_emerg_h2o_timescale ; + fates_trs_seedling_emerg_h2o_timescale:units = "days" ; + fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; + double fates_trs_seedling_mdd_timescale ; + fates_trs_seedling_mdd_timescale:units = "days" ; + fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; + double fates_trs_seedling_mort_par_timescale ; + fates_trs_seedling_mort_par_timescale:units = "days" ; + fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; + double fates_vai_top_bin_width ; + fates_vai_top_bin_width:units = "m2/m2" ; + fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; + double fates_vai_width_increase_factor ; + fates_vai_width_increase_factor:units = "unitless" ; + fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; + +// global attributes: + :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; +data: + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_history_coageclass_bin_edges = 0, 5 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_history_damage_bin_edges = 0, 80 ; + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_alloc_organ_id = 1, 2, 3, 6 ; + + fates_hydro_htftype_node = 1, 1, 1, 1 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "needleleaf_evergreen_extratrop_tree ", + "needleleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_tree ", + "broadleaf_hydrodecid_tropical_tree ", + "broadleaf_colddecid_extratrop_tree ", + "broadleaf_evergreen_extratrop_shrub ", + "broadleaf_hydrodecid_extratrop_shrub ", + "broadleaf_colddecid_extratrop_shrub ", + "arctic_c3_grass ", + "cool_c3_grass ", + "c4_grass " ; + + fates_hydro_organ_name = + "leaf ", + "stem ", + "transporting root ", + "absorbing root " ; + + fates_alloc_organ_name = + "leaf", + "fine root", + "sapwood", + "structure" ; + + fates_landuseclass_name = + "primaryland", + "secondaryland", + "rangeland", + "pastureland", + "cropland" ; + + fates_litterclass_name = + "twig ", + "small branch ", + "large branch ", + "trunk ", + "dead leaves ", + "live grass " ; + + fates_alloc_organ_priority = + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; + + fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, + 1.2, 1.2, 1.2 ; + + fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8, 0.8 ; + + fates_allom_agb1 = 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, + 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + + fates_allom_agb2 = 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, + 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, + 1.94, 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, + 0.931, 0.931, 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; + + fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; + + fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, + 0, 0, 0, 0, 0 ; + + fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, + 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, + 0.55, 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.2715891, 0.3693718, 1.0787259, + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, + 0.6568464, 0.6568464, 0.6568464 ; + + fates_allom_d2h1 = 78.4087704, 306.842667, 106.8745821, 104.3586841, + 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; + + fates_allom_d2h2 = 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, + 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; + + fates_allom_d2h3 = 47.6666164, 196.6865691, 93.9790461, 160.6835089, + 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + + fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + + fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_h2cd1 = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, 0.95, 1, 1, 1 ; + + fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; + + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, + 0.8, 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 ; + + fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; + + fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; + + fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_cnp_eca_alpha_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 280, 280 ; + + fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 0.14, 0.14, 0.14 ; + + fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 0.27, 0.27, 0.27 ; + + fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1 ; + + fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_eca_lambda_ptase = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; + + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, + 1.5, 1.5, 1.5 ; + + fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; + + fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; + + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_cnp_turnover_nitr_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_turnover_phos_retrans = + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, + 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; + + fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, + 5e-10, 5e-10, 5e-10, 5e-10 ; + + fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01 ; + + fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; + + fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, + 5.5, 5.5 ; + + fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, + 0.07, 0.07, 0.07, 0.07 ; + + fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 0.775, 0.775, 0.775, 0.775, 0.775 ; + + fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5 ; + + fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, + 0.25, 0.25, 0.25 ; + + fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, + 0.51, 0.51, 0.51, 0.51 ; + + fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, + 0.11, 0.11 ; + + fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, + 2.5, 2.5 ; + + fates_hydro_avuln_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_hydro_epsil_node = + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_hydro_fcap_node = + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_hydro_kmax_node = + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, + -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; + + fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + -1.5, -1.5, -1.5 ; + + fates_hydro_p50_node = + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, + 0.333, 0.333, 0.333, 0.333, 0.333 ; + + fates_hydro_pinot_node = + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, + -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; + + fates_hydro_pitlp_node = + -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + -1.67, -1.67, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, + -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; + + fates_hydro_resid_node = + 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; + + fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 0.625, 0.625, 0.625, 0.625, 0.625 ; + + fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; + + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + + fates_hydro_thetas_node = + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, + 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; + + fates_hydro_vg_alpha_node = + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005, + 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 0.005, 0.005 ; + + fates_hydro_vg_m_node = + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_hydro_vg_n_node = + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; + + fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; + + fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + 43540, 43540, 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, + 152040, 152040, 152040, 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, + 495 ; + + fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 0.03, 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, + 0.03, 0.03, 0.03, 0.03 ; + + fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, + 10000, 10000, 10000, 10000, 10000, 40000 ; + + fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; + + fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, + 4.7, 2.2, 5.3, 1.6 ; + + fates_leaf_vcmax25top = + 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; + + fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 65330, 65330, 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, + 149250, 149250, 149250, 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, + 485 ; + + fates_leafn_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963 ; + + fates_leafn_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43 ; + + fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, + 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; + + fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, + 2.525e-06, 2.525e-06, 2.525e-06 ; + + fates_maintresp_leaf_vert_scaler_coeff1 = 0.00963, 0.00963, 0.00963, + 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, 0.00963, + 0.00963 ; + + fates_maintresp_leaf_vert_scaler_coeff2 = 2.43, 2.43, 2.43, 2.43, 2.43, + 2.43, 2.43, 2.43, 2.43, 2.43, 2.43, 2.43 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 0.014, 0.014, 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, + -20, 2.5 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, + 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; + + fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, + 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; + + fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, + 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; + + fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6, 0.6 ; + + fates_mort_upthresh_cstarvation = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; + + fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, + -66000, -66000, -66000, -66000, -66000, -66000 ; + + fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, + -152957.4, -152957.4 ; + + fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; + + fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, + 0.5 ; + + fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100 ; + + fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, + -122365.9, -122365.9 ; + + fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; + + fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; + + fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 0.4, 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, + 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; + + fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, + 0.9, 0.75, 0.75, 0.75 ; + + fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, + 0.41, 0.28, 0.28, 0.28 ; + + fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, + 0.08, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, + 0.43, 0.4, 0.4, 0.4 ; + + fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.05, 0.05, 0.05 ; + + fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, + -0.23, -0.23, -0.23 ; + + fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, + 0.49, 0.53, 0.53, 0.53 ; + + fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, + 0.21, 0.31, 0.31, 0.31 ; + + fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.25, 0.25, 0.25 ; + + fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, + 0.001, 0.001, 0.12, 0.12, 0.12 ; + + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, + 0.125, 0.125, 0.125 ; + + fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2, 0.2 ; + + fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, + 0.02, 0.02, 0.02, 0.02, 0.02 ; + + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; + + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; + + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, + 0.35, 0.35, 0.35 ; + + fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5 ; + + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + + fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_scale = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_seed_dispersal_pdf_shape = _, _, _, _, _, _, _, _, _, _, _, _ ; + + fates_stoich_nitr = + 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, + 0.024, 0.024, + 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, + 1e-08, 1e-08, + 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, + 0.0047, 0.0047, 0.0047 ; + + fates_stoich_phos = + 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, + 0.004, 0.004, + 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, + 0.0024, 0.0024, 0.0024, + 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, + 1e-09, 1e-09, + 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, + 0.00047, 0.00047, 0.00047, 0.00047 ; + + fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, + 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; + + fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, + 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; + + fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, + -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; + + fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, + 0.24, 0.24, 0.24, 0.24 ; + + fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, + 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; + + fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, + 1.2, 1.2, 1.2 ; + + fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, + 0.1085371, 0.1085371, 0.1085371 ; + + fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, + 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; + + fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, + -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; + + fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, + 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; + + fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, + -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; + + fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, + -7.154063, -7.154063, -7.154063 ; + + fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, + 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; + + fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, + 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; + + fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, + 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; + + fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, + 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; + + fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, + -251995.7, -251995.7 ; + + fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, + -15744.65, -15744.65 ; + + fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, + 0.06, 0.06, 0.06, 0.06, 0.06 ; + + fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, + 0.67, 0.67, 0.67 ; + + fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, + 0.04, 0.04, 0.04, 0.04 ; + + fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, + 0.055, 0.055, 0.055, 0.055 ; + + fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; + + fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + + fates_wood_density = 0.548327, 0.44235, 0.454845, 0.754336, 0.548327, + 0.566452, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7 ; + + fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; + + fates_hlm_pft_map = + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; + + fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; + + fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; + + fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; + + fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; + + fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; + + fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; + + fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; + + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_maxpatches_by_landuse = 9, 4, 1, 1, 1 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cnp_eca_plant_escalar = 1.25e-05 ; + + fates_cohort_age_fusion_tol = 0.08 ; + + fates_cohort_size_fusion_tol = 0.08 ; + + fates_comp_excln = 3 ; + + fates_damage_canopy_layer_code = 1 ; + + fates_damage_event_code = 1 ; + + fates_daylength_factor_switch = 1 ; + + fates_dev_arbitrary = _ ; + + fates_fire_active_crown_fire = 0 ; + + fates_fire_cg_strikes = 0.2 ; + + fates_fire_drying_ratio = 66000 ; + + fates_fire_durat_slope = -11.06 ; + + fates_fire_fdi_a = 17.62 ; + + fates_fire_fdi_alpha = 0.00037 ; + + fates_fire_fdi_b = 243.12 ; + + fates_fire_fuel_energy = 18000 ; + + fates_fire_max_durat = 240 ; + + fates_fire_miner_damp = 0.41739 ; + + fates_fire_miner_total = 0.055 ; + + fates_fire_nignitions = 15 ; + + fates_fire_part_dens = 513 ; + + fates_fire_threshold = 50 ; + + fates_frag_cwd_fcel = 0.76 ; + + fates_frag_cwd_flig = 0.24 ; + + fates_hydro_kmax_rsurf1 = 20 ; + + fates_hydro_kmax_rsurf2 = 0.0001 ; + + fates_hydro_psi0 = 0 ; + + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; + + fates_landuse_logging_coll_under_frac = 0.55983 ; + + fates_landuse_logging_collateral_frac = 0.05 ; + + fates_landuse_logging_dbhmax = _ ; + + fates_landuse_logging_dbhmax_infra = 35 ; + + fates_landuse_logging_dbhmin = 50 ; + + fates_landuse_logging_direct_frac = 0.15 ; + + fates_landuse_logging_event_code = -30 ; + + fates_landuse_logging_export_frac = 0.8 ; + + fates_landuse_logging_mechanical_frac = 0.05 ; + + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + fates_leaf_photo_temp_acclim_thome_time = 30 ; + + fates_leaf_photo_temp_acclim_timescale = 30 ; + + fates_leaf_photo_tempsens_model = 1 ; + + fates_leaf_stomatal_assim_model = 1 ; + + fates_leaf_stomatal_model = 1 ; + + fates_leaf_theta_cj_c3 = 0.999 ; + + fates_leaf_theta_cj_c4 = 0.999 ; + + fates_maintresp_leaf_model = 1 ; + + fates_maintresp_nonleaf_baserate = 2.525e-06 ; + + fates_maxcohort = 100 ; + + fates_mort_cstarvation_model = 1 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_chilltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_gddthresh_a = -68 ; + + fates_phen_gddthresh_b = 638 ; + + fates_phen_gddthresh_c = -0.01 ; + + fates_phen_mindayson = 90 ; + + fates_phen_ncolddayslim = 5 ; + + fates_q10_froz = 1.5 ; + + fates_q10_mr = 1.5 ; + + fates_rad_model = 1 ; + + fates_regeneration_model = 1 ; + + fates_soil_salinity = 0.4 ; + + fates_trs_seedling2sap_par_timescale = 32 ; + + fates_trs_seedling_emerg_h2o_timescale = 7 ; + + fates_trs_seedling_mdd_timescale = 126 ; + + fates_trs_seedling_mort_par_timescale = 32 ; + + fates_vai_top_bin_width = 1 ; + + fates_vai_width_increase_factor = 1 ; +} diff --git a/parameter_files/archive/api36.2.0_081324_patch_params.xml b/parameter_files/archive/api36.1.0_081324_patch_params.xml similarity index 87% rename from parameter_files/archive/api36.2.0_081324_patch_params.xml rename to parameter_files/archive/api36.1.0_081324_patch_params.xml index 0337fae5aa..df0b5cb7e3 100644 --- a/parameter_files/archive/api36.2.0_081324_patch_params.xml +++ b/parameter_files/archive/api36.1.0_081324_patch_params.xml @@ -75,44 +75,34 @@ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.67, 0.67, 1.41 - - fates_allom_lmode + 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 5, 5 - - fates_allom_smode + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2 - - fates_leaf_slamax + 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, 0.03, 0.03, 0.05, 0.05, 0.05 - - fates_leaf_slatop + 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, 0.03, 0.05, 0.05, 0.05 - - fates_recruit_height_min + 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 - - fates_recruit_seed_alloc + 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, 0, 0 - - fates_recruit_seed_alloc_mature + 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.25, 0.25, 0.2 - - fates_recruit_seed_dbh_repro_threshold + 90, 80, 80, 80, 90, 80, 3, 3, 2, 3, 3, 3 - - fates_cnp_prescribed_nuptake + 0,0,0,0,0,0,0,0,0,0,0,0 - - fates_cnp_prescribed_puptake + 0,0,0,0,0,0,0,0,0,0,0,0 @@ -132,6 +122,7 @@ Leaf longevity (ie turnover timescale) of understory plants. 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 2eaeb875fe..f018428408 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -645,9 +645,12 @@ variables: double fates_turnover_fnrt(fates_pft) ; fates_turnover_fnrt:units = "yr" ; fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; + double fates_turnover_leaf_canopy(fates_leafage_class, fates_pft) ; + fates_turnover_leaf_canopy:units = "yr" ; + fates_turnover_leaf_canopy:long_name = "Leaf longevity (ie turnover timescale) of canopy plants. For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; + double fates_turnover_leaf_ustory(fates_leafage_class, fates_pft) ; + fates_turnover_leaf_ustory:units = "yr" ; + fates_turnover_leaf_ustory:long_name = "Leaf longevity (ie turnover timescale) of understory plants." ; double fates_turnover_senleaf_fdrought(fates_pft) ; fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; @@ -983,55 +986,54 @@ data: 0.8, 0.8, 0.8, 0.8 ; fates_allom_agb1 = 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, - 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; + 0.0728698, 0.06896, 0.06896, 0.06896, 0.001, 0.001, 0.003 ; fates_allom_agb2 = 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, - 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; + 0.572, 0.572, 0.572, 1.6592, 1.6592, 1.3456 ; fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; + 1.248, 1.248, 1.869 ; fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; + 0.931, -999.9, -999.9, -999.9 ; - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 1, 1, 1 ; - fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; + fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 5, 5, 5 ; fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, - 0, 0, 0, 0, 0 ; + 0, 0, -0.487, -0.487, -0.259 ; fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; + 0.0004, 0.0004, 0.0012 ; fates_allom_d2bl2 = 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, - 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; + 1.3998939, 1.3, 1.3, 1.3, 1.7092, 1.7092, 1.5879 ; fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; + 0.3417, 0.3417, 0.9948 ; fates_allom_d2ca_coefficient_max = 0.2715891, 0.3693718, 1.0787259, - 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.0408, + 0.0408, 0.0862 ; fates_allom_d2ca_coefficient_min = 0.2715891, 0.3693718, 1.0787259, - 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; + 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, 0.0408, + 0.0408, 0.0862 ; fates_allom_d2h1 = 78.4087704, 306.842667, 106.8745821, 104.3586841, - 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; + 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.1812, 0.1812, 0.3353 ; fates_allom_d2h2 = 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, - 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; + 0.9734088, 0.37, 0.37, 0.37, 0.6384, 0.6384, 0.4235 ; fates_allom_d2h3 = 47.6666164, 196.6865691, 93.9790461, 160.6835089, 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; - fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, - 0.35, 0.35, 0.35 ; + fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, 20, + 20, 30 ; fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1049,21 +1051,21 @@ data: fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 3, 3, 3 ; - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.67, 0.67, 1.41 ; fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 ; + fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 5, 5 ; fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2 ; fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1118,9 +1120,9 @@ data: fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_prescribed_nuptake = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_prescribed_puptake = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1306,10 +1308,10 @@ data: 495 ; fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; + 0.03, 0.03, 0.05, 0.05, 0.05 ; fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; + 0.03, 0.05, 0.05, 0.05 ; fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 40000 ; @@ -1462,8 +1464,8 @@ data: fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.12, 0.12, 0.12 ; - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, - 0.125, 0.125, 0.125 ; + fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, 0.2, + 0.2, 0.2 ; fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; @@ -1471,14 +1473,14 @@ data: fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 ; - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, + 0, 0 ; - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, - 0.9 ; + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.25, + 0.25, 0.2 ; - fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, - 0.35, 0.35, 0.35 ; + fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, 3, + 3, 3 ; fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; @@ -1592,7 +1594,10 @@ data: fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_leaf = + fates_turnover_leaf_canopy = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + + fates_turnover_leaf_ustory = 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; diff --git a/tools/UpdateParamAPI.py b/tools/UpdateParamAPI.py index cc9ffa1faa..b158e2961e 100755 --- a/tools/UpdateParamAPI.py +++ b/tools/UpdateParamAPI.py @@ -293,7 +293,7 @@ def main(): print("dimension: {}, removed".format(dimname)) elif(mod.attrib['type'].strip() == 'variable_add'): - + print("Adding Parameter") try: paramname = mod.find('na').text.strip() except: @@ -365,6 +365,7 @@ def main(): elif(mod.attrib['type'] == 'variable_del'): + print("Deleting Parameter") try: paramname = mod.find('na').text.strip() except: @@ -376,6 +377,8 @@ def main(): elif(mod.attrib['type'] == 'variable_change'): + print("Changing Parameter") + try: paramname_o = mod.attrib['name'].strip() except: @@ -404,6 +407,8 @@ def main(): # Change the parameter's name and/or the dimensionality if(not isinstance(newparamname,type(None)) or not isinstance(dimnames,type(None))): + print("Changing Name") + # Initialize the parameter name to pass to the create variable function # If this is None, a dimension update is happening and this will be updated # below @@ -448,7 +453,8 @@ def main(): else: ncvar = ncvar_o - + dims_o = ncvar_o.dimensions + # Change the metadata: try: units = mod.find('un').text.strip() From f73999b554ef05517ca7a83569d710998948753d Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Aug 2024 18:30:00 -0400 Subject: [PATCH 298/300] Reverting changes to the parameter file. Those changes will be added to a later PR --- parameter_files/fates_params_default.cdl | 56 ++++++++++++------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 036a43cb4f..b66336bbf2 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -992,55 +992,55 @@ data: 0.8, 0.8, 0.8, 0.8 ; fates_allom_agb1 = 0.0673, 0.1364012, 0.0393057, 0.2653695, 0.0673, - 0.0728698, 0.06896, 0.06896, 0.06896, 0.001, 0.001, 0.003 ; + 0.0728698, 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; fates_allom_agb2 = 0.976, 0.9449041, 1.087335, 0.8321321, 0.976, 1.0373211, - 0.572, 0.572, 0.572, 1.6592, 1.6592, 1.3456 ; + 0.572, 0.572, 0.572, 0.572, 0.572, 0.572 ; fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.248, 1.248, 1.869 ; + 1.94, 1.94, 1.94 ; fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, -999.9, -999.9, -999.9 ; + 0.931, 0.931, 0.931, 0.931 ; - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 1, - 1, 1 ; + fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, + 0.6, 0.6 ; - fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 5, 5, 5 ; + fates_allom_amode = 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 ; fates_allom_blca_expnt_diff = -0.12, -0.34, -0.32, -0.22, -0.12, -0.35, 0, - 0, 0, -0.487, -0.487, -0.259 ; + 0, 0, 0, 0, 0 ; fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_d2bl1 = 0.04, 0.07, 0.07, 0.01, 0.04, 0.07, 0.07, 0.07, 0.07, - 0.0004, 0.0004, 0.0012 ; + 0.07, 0.07, 0.07 ; fates_allom_d2bl2 = 1.6019679, 1.5234373, 1.3051237, 1.9621397, 1.6019679, - 1.3998939, 1.3, 1.3, 1.3, 1.7092, 1.7092, 1.5879 ; + 1.3998939, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3 ; fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.3417, 0.3417, 0.9948 ; + 0.55, 0.55, 0.55 ; fates_allom_d2ca_coefficient_max = 0.2715891, 0.3693718, 1.0787259, 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, - 0.0408, 0.0408, 0.0862 ; + 0.6568464, 0.6568464, 0.6568464 ; fates_allom_d2ca_coefficient_min = 0.2715891, 0.3693718, 1.0787259, 0.0579297, 0.2715891, 1.1553612, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.0408, 0.0862 ; + 0.6568464, 0.6568464, 0.6568464 ; fates_allom_d2h1 = 78.4087704, 306.842667, 106.8745821, 104.3586841, - 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.1812, 0.1812, 0.3353 ; + 78.4087704, 31.4557047, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64 ; fates_allom_d2h2 = 0.8124383, 0.752377, 0.9471302, 1.1146973, 0.8124383, - 0.9734088, 0.37, 0.37, 0.37, 0.6384, 0.6384, 0.4235 ; + 0.9734088, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37 ; fates_allom_d2h3 = 47.6666164, 196.6865691, 93.9790461, 160.6835089, 47.6666164, 16.5928174, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9 ; fates_allom_dbh_maxheight = 1000, 1000, 1000, 1000, 1000, 1000, 3, 3, 2, - 20, 20, 30 ; + 0.35, 0.35, 0.35 ; fates_allom_dmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1058,21 +1058,21 @@ data: fates_allom_h2cd2 = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 3, 3, 3 ; + fates_allom_hmode = 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1 ; - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.67, 0.67, 1.41 ; + fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8 ; fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 5, 5, 5 ; + fates_allom_lmode = 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1 ; fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2 ; + fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; @@ -1325,10 +1325,10 @@ data: 495 ; fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.05, 0.05, 0.05 ; + 0.03, 0.03, 0.03, 0.03, 0.03 ; fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.05, 0.05, 0.05 ; + 0.03, 0.03, 0.03, 0.03 ; fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 10000, 40000 ; @@ -1482,7 +1482,7 @@ data: 0.001, 0.001, 0.12, 0.12, 0.12 ; fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2 ; + 0.125, 0.125, 0.125 ; fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 ; @@ -1490,14 +1490,14 @@ data: fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 ; - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0, - 0, 0 ; + fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, + 0.1, 0.1 ; - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.25, 0.25, - 0.2 ; + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, - 3, 3, 3 ; + 0.35, 0.35, 0.35 ; fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; From 3cab77640d6c45f62a0cfd50f4d878f85dbadd48 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 14 Aug 2024 13:52:40 -0600 Subject: [PATCH 299/300] reverting parameter file default --- parameter_files/fates_params_default.cdl | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 445fbb35e5..b66336bbf2 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -657,12 +657,9 @@ variables: double fates_turnover_fnrt(fates_pft) ; fates_turnover_fnrt:units = "yr" ; fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf_canopy(fates_leafage_class, fates_pft) ; - fates_turnover_leaf_canopy:units = "yr" ; - fates_turnover_leaf_cannopy:long_name = "Leaf longevity (ie turnover timescale) of canopy plants. For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; - double fates_turnover_leaf_ustory(fates_leafage_class, fates_pft) ; - fates_turnover_leaf_ustory:units = "yr" ; - fates_turnover_leaf_ustory:long_name = "Leaf longevity (ie turnover timescale) of understory plants." ; + double fates_turnover_leaf(fates_leafage_class, fates_pft) ; + fates_turnover_leaf:units = "yr" ; + fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; double fates_turnover_senleaf_fdrought(fates_pft) ; fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; @@ -1614,10 +1611,7 @@ data: fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_leaf_canopy = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_leaf_ustory = + fates_turnover_leaf = 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; From a60b10873c0b9a2de2f01e0eceadc64d27b16175 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 14 Aug 2024 14:03:15 -0600 Subject: [PATCH 300/300] updated naming convention of parameter changing files --- .../archive/api33.0_fates_params_deafult.cdl | 1741 ----------------- parameter_files/archive/api33_pr1136.xml | 42 - ...fault.cdl => api36.1.0_params_default.cdl} | 0 ..._params.xml => api36.1.0_patch_params.xml} | 2 +- 4 files changed, 1 insertion(+), 1784 deletions(-) delete mode 100644 parameter_files/archive/api33.0_fates_params_deafult.cdl delete mode 100644 parameter_files/archive/api33_pr1136.xml rename parameter_files/archive/{api36.0.0_params_default.cdl => api36.1.0_params_default.cdl} (100%) rename parameter_files/archive/{api36.1.0_081324_patch_params.xml => api36.1.0_patch_params.xml} (99%) diff --git a/parameter_files/archive/api33.0_fates_params_deafult.cdl b/parameter_files/archive/api33.0_fates_params_deafult.cdl deleted file mode 100644 index 4531d54041..0000000000 --- a/parameter_files/archive/api33.0_fates_params_deafult.cdl +++ /dev/null @@ -1,1741 +0,0 @@ -netcdf fates_params_default { -dimensions: - fates_NCWD = 4 ; - fates_history_age_bins = 7 ; - fates_history_coage_bins = 2 ; - fates_history_damage_bins = 2 ; - fates_history_height_bins = 6 ; - fates_history_size_bins = 13 ; - fates_hlm_pftno = 14 ; - fates_hydr_organs = 4 ; - fates_leafage_class = 1 ; - fates_litterclass = 6 ; - fates_pft = 12 ; - fates_plant_organs = 4 ; - fates_string_length = 60 ; -variables: - double fates_history_ageclass_bin_edges(fates_history_age_bins) ; - fates_history_ageclass_bin_edges:units = "yr" ; - fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; - double fates_history_coageclass_bin_edges(fates_history_coage_bins) ; - fates_history_coageclass_bin_edges:units = "years" ; - fates_history_coageclass_bin_edges:long_name = "Lower edges for cohort age class bins used in cohort age resolved history output" ; - double fates_history_height_bin_edges(fates_history_height_bins) ; - fates_history_height_bin_edges:units = "m" ; - fates_history_height_bin_edges:long_name = "Lower edges for height bins used in height-resolved history output" ; - double fates_history_damage_bin_edges(fates_history_damage_bins) ; - fates_history_damage_bin_edges:units = "% crown loss" ; - fates_history_damage_bin_edges:long_name = "Lower edges for damage class bins used in cohort history output" ; - double fates_history_sizeclass_bin_edges(fates_history_size_bins) ; - fates_history_sizeclass_bin_edges:units = "cm" ; - fates_history_sizeclass_bin_edges:long_name = "Lower edges for DBH size class bins used in size-resolved cohort history output" ; - double fates_alloc_organ_id(fates_plant_organs) ; - fates_alloc_organ_id:units = "unitless" ; - fates_alloc_organ_id:long_name = "This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90" ; - double fates_hydro_htftype_node(fates_hydr_organs) ; - fates_hydro_htftype_node:units = "unitless" ; - fates_hydro_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - char fates_pftname(fates_pft, fates_string_length) ; - fates_pftname:units = "unitless - string" ; - fates_pftname:long_name = "Description of plant type" ; - char fates_hydro_organ_name(fates_hydr_organs, fates_string_length) ; - fates_hydro_organ_name:units = "unitless - string" ; - fates_hydro_organ_name:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; - char fates_alloc_organ_name(fates_plant_organs, fates_string_length) ; - fates_alloc_organ_name:units = "unitless - string" ; - fates_alloc_organ_name:long_name = "Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90)" ; - char fates_litterclass_name(fates_litterclass, fates_string_length) ; - fates_litterclass_name:units = "unitless - string" ; - fates_litterclass_name:long_name = "Name of the litter classes, for variables associated with dimension fates_litterclass" ; - double fates_alloc_organ_priority(fates_plant_organs, fates_pft) ; - fates_alloc_organ_priority:units = "index" ; - fates_alloc_organ_priority:long_name = "Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance" ; - double fates_alloc_storage_cushion(fates_pft) ; - fates_alloc_storage_cushion:units = "fraction" ; - fates_alloc_storage_cushion:long_name = "maximum size of storage C pool, relative to maximum size of leaf C pool" ; - double fates_alloc_store_priority_frac(fates_pft) ; - fates_alloc_store_priority_frac:units = "unitless" ; - fates_alloc_store_priority_frac:long_name = "for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage" ; - double fates_allom_agb1(fates_pft) ; - fates_allom_agb1:units = "variable" ; - fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; - double fates_allom_agb2(fates_pft) ; - fates_allom_agb2:units = "variable" ; - fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; - double fates_allom_agb3(fates_pft) ; - fates_allom_agb3:units = "variable" ; - fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; - double fates_allom_agb4(fates_pft) ; - fates_allom_agb4:units = "variable" ; - fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; - double fates_allom_agb_frac(fates_pft) ; - fates_allom_agb_frac:units = "fraction" ; - fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; - double fates_allom_amode(fates_pft) ; - fates_allom_amode:units = "index" ; - fates_allom_amode:long_name = "AGB allometry function index." ; - double fates_allom_blca_expnt_diff(fates_pft) ; - fates_allom_blca_expnt_diff:units = "unitless" ; - fates_allom_blca_expnt_diff:long_name = "difference between allometric DBH:bleaf and DBH:crown area exponents" ; - double fates_allom_cmode(fates_pft) ; - fates_allom_cmode:units = "index" ; - fates_allom_cmode:long_name = "coarse root biomass allometry function index." ; - double fates_allom_crown_depth_frac(fates_pft) ; - fates_allom_crown_depth_frac:units = "fraction" ; - fates_allom_crown_depth_frac:long_name = "the depth of a cohort crown as a fraction of its height" ; - double fates_allom_d2bl1(fates_pft) ; - fates_allom_d2bl1:units = "variable" ; - fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; - double fates_allom_d2bl2(fates_pft) ; - fates_allom_d2bl2:units = "variable" ; - fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; - double fates_allom_d2bl3(fates_pft) ; - fates_allom_d2bl3:units = "unitless" ; - fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; - double fates_allom_d2ca_coefficient_max(fates_pft) ; - fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2ca_coefficient_min(fates_pft) ; - fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; - fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; - double fates_allom_d2h1(fates_pft) ; - fates_allom_d2h1:units = "variable" ; - fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; - double fates_allom_d2h2(fates_pft) ; - fates_allom_d2h2:units = "variable" ; - fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; - double fates_allom_d2h3(fates_pft) ; - fates_allom_d2h3:units = "variable" ; - fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; - double fates_allom_dbh_maxheight(fates_pft) ; - fates_allom_dbh_maxheight:units = "cm" ; - fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; - double fates_allom_fmode(fates_pft) ; - fates_allom_fmode:units = "index" ; - fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - double fates_allom_fnrt_prof_a(fates_pft) ; - fates_allom_fnrt_prof_a:units = "unitless" ; - fates_allom_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_allom_fnrt_prof_b(fates_pft) ; - fates_allom_fnrt_prof_b:units = "unitless" ; - fates_allom_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_allom_fnrt_prof_mode(fates_pft) ; - fates_allom_fnrt_prof_mode:units = "index" ; - fates_allom_fnrt_prof_mode:long_name = "Index to select fine root profile function: 1) Jackson Beta, 2) 1-param exponential 3) 2-param exponential" ; - double fates_allom_frbstor_repro(fates_pft) ; - fates_allom_frbstor_repro:units = "fraction" ; - fates_allom_frbstor_repro:long_name = "fraction of bstore goes to reproduction after plant dies" ; - double fates_allom_hmode(fates_pft) ; - fates_allom_hmode:units = "index" ; - fates_allom_hmode:long_name = "height allometry function index." ; - double fates_allom_l2fr(fates_pft) ; - fates_allom_l2fr:units = "gC/gC" ; - fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; - double fates_allom_la_per_sa_int(fates_pft) ; - fates_allom_la_per_sa_int:units = "m2/cm2" ; - fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; - double fates_allom_la_per_sa_slp(fates_pft) ; - fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; - fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; - double fates_allom_lmode(fates_pft) ; - fates_allom_lmode:units = "index" ; - fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - double fates_allom_sai_scaler(fates_pft) ; - fates_allom_sai_scaler:units = "m2/m2" ; - fates_allom_sai_scaler:long_name = "allometric ratio of SAI per LAI" ; - double fates_allom_smode(fates_pft) ; - fates_allom_smode:units = "index" ; - fates_allom_smode:long_name = "sapwood allometry function index." ; - double fates_allom_stmode(fates_pft) ; - fates_allom_stmode:units = "index" ; - fates_allom_stmode:long_name = "storage allometry function index: 1) Storage proportional to leaf biomass (with trimming), 2) Storage proportional to maximum leaf biomass (not trimmed)" ; - double fates_allom_zroot_k(fates_pft) ; - fates_allom_zroot_k:units = "unitless" ; - fates_allom_zroot_k:long_name = "scale coefficient of logistic rooting depth model" ; - double fates_allom_zroot_max_dbh(fates_pft) ; - fates_allom_zroot_max_dbh:units = "cm" ; - fates_allom_zroot_max_dbh:long_name = "dbh at which a plant reaches the maximum value for its maximum rooting depth" ; - double fates_allom_zroot_max_z(fates_pft) ; - fates_allom_zroot_max_z:units = "m" ; - fates_allom_zroot_max_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_max_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_allom_zroot_min_dbh(fates_pft) ; - fates_allom_zroot_min_dbh:units = "cm" ; - fates_allom_zroot_min_dbh:long_name = "dbh at which the maximum rooting depth for a recruit is defined" ; - double fates_allom_zroot_min_z(fates_pft) ; - fates_allom_zroot_min_z:units = "m" ; - fates_allom_zroot_min_z:long_name = "the maximum rooting depth defined at dbh = fates_allom_zroot_min_dbh. note: max_z=min_z=large, sets rooting depth to soil depth" ; - double fates_c2b(fates_pft) ; - fates_c2b:units = "ratio" ; - fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; - double fates_cnp_eca_alpha_ptase(fates_pft) ; - fates_cnp_eca_alpha_ptase:units = "g/m3" ; - fates_cnp_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_cnp_eca_decompmicc(fates_pft) ; - fates_cnp_eca_decompmicc:units = "gC/m3" ; - fates_cnp_eca_decompmicc:long_name = "maximum soil microbial decomposer biomass found over depth (will be applied at a reference depth w/ exponential attenuation) (ECA)" ; - double fates_cnp_eca_km_nh4(fates_pft) ; - fates_cnp_eca_km_nh4:units = "gN/m3" ; - fates_cnp_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_cnp_eca_km_no3(fates_pft) ; - fates_cnp_eca_km_no3:units = "gN/m3" ; - fates_cnp_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_cnp_eca_km_p(fates_pft) ; - fates_cnp_eca_km_p:units = "gP/m3" ; - fates_cnp_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_cnp_eca_km_ptase(fates_pft) ; - fates_cnp_eca_km_ptase:units = "gP/m3" ; - fates_cnp_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_cnp_eca_lambda_ptase(fates_pft) ; - fates_cnp_eca_lambda_ptase:units = "g/m3" ; - fates_cnp_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_cnp_eca_vmax_ptase(fates_pft) ; - fates_cnp_eca_vmax_ptase:units = "gP/m2/s" ; - fates_cnp_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; - double fates_cnp_nfix1(fates_pft) ; - fates_cnp_nfix1:units = "fraction" ; - fates_cnp_nfix1:long_name = "fractional surcharge added to maintenance respiration that drives symbiotic fixation" ; - double fates_cnp_nitr_store_ratio(fates_pft) ; - fates_cnp_nitr_store_ratio:units = "(gN/gN)" ; - fates_cnp_nitr_store_ratio:long_name = "storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code)" ; - double fates_cnp_phos_store_ratio(fates_pft) ; - fates_cnp_phos_store_ratio:units = "(gP/gP)" ; - fates_cnp_phos_store_ratio:long_name = "storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code)" ; - double fates_cnp_pid_kd(fates_pft) ; - fates_cnp_pid_kd:units = "unknown" ; - fates_cnp_pid_kd:long_name = "derivative constant of the PID controller on adaptive fine-root biomass" ; - double fates_cnp_pid_ki(fates_pft) ; - fates_cnp_pid_ki:units = "unknown" ; - fates_cnp_pid_ki:long_name = "integral constant of the PID controller on adaptive fine-root biomass" ; - double fates_cnp_pid_kp(fates_pft) ; - fates_cnp_pid_kp:units = "unknown" ; - fates_cnp_pid_kp:long_name = "proportional constant of the PID controller on adaptive fine-root biomass" ; - double fates_cnp_prescribed_nuptake(fates_pft) ; - fates_cnp_prescribed_nuptake:units = "fraction" ; - fates_cnp_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_cnp_prescribed_puptake(fates_pft) ; - fates_cnp_prescribed_puptake:units = "fraction" ; - fates_cnp_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_cnp_store_ovrflw_frac(fates_pft) ; - fates_cnp_store_ovrflw_frac:units = "fraction" ; - fates_cnp_store_ovrflw_frac:long_name = "size of overflow storage (for excess C,N or P) as a fraction of storage target" ; - double fates_cnp_turnover_nitr_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_nitr_retrans:units = "fraction" ; - fates_cnp_turnover_nitr_retrans:long_name = "retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues" ; - double fates_cnp_turnover_phos_retrans(fates_plant_organs, fates_pft) ; - fates_cnp_turnover_phos_retrans:units = "fraction" ; - fates_cnp_turnover_phos_retrans:long_name = "retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues" ; - double fates_cnp_vmax_nh4(fates_pft) ; - fates_cnp_vmax_nh4:units = "gN/gC/s" ; - fates_cnp_vmax_nh4:long_name = "maximum (potential) uptake rate of NH4 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_nh4 for usage)" ; - double fates_cnp_vmax_no3(fates_pft) ; - fates_cnp_vmax_no3:units = "gN/gC/s" ; - fates_cnp_vmax_no3:long_name = "maximum (potential) uptake rate of NO3 per gC of fineroot biomass (see main/EDPftvarcon.F90 vmax_no3 for usage)" ; - double fates_cnp_vmax_p(fates_pft) ; - fates_cnp_vmax_p:units = "gP/gC/s" ; - fates_cnp_vmax_p:long_name = "maximum production rate for phosphorus (ECA and RD)" ; - double fates_damage_frac(fates_pft) ; - fates_damage_frac:units = "fraction" ; - fates_damage_frac:long_name = "fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine)" ; - double fates_damage_mort_p1(fates_pft) ; - fates_damage_mort_p1:units = "fraction" ; - fates_damage_mort_p1:long_name = "inflection point of damage mortality function, a value of 0.8 means 50% mortality with 80% loss of crown, turn off with a large number" ; - double fates_damage_mort_p2(fates_pft) ; - fates_damage_mort_p2:units = "unitless" ; - fates_damage_mort_p2:long_name = "rate of mortality increase with damage" ; - double fates_damage_recovery_scalar(fates_pft) ; - fates_damage_recovery_scalar:units = "unitless" ; - fates_damage_recovery_scalar:long_name = "fraction of the cohort that recovers from damage" ; - double fates_dev_arbitrary_pft(fates_pft) ; - fates_dev_arbitrary_pft:units = "unknown" ; - fates_dev_arbitrary_pft:long_name = "Unassociated pft dimensioned free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_fire_alpha_SH(fates_pft) ; - fates_fire_alpha_SH:units = "m / (kw/m)**(2/3)" ; - fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; - double fates_fire_bark_scaler(fates_pft) ; - fates_fire_bark_scaler:units = "fraction" ; - fates_fire_bark_scaler:long_name = "the thickness of a cohorts bark as a fraction of its dbh" ; - double fates_fire_crown_kill(fates_pft) ; - fates_fire_crown_kill:units = "NA" ; - fates_fire_crown_kill:long_name = "fire parameter, see equation 22 in Thonicke et al 2010" ; - double fates_frag_fnrt_fcel(fates_pft) ; - fates_frag_fnrt_fcel:units = "fraction" ; - fates_frag_fnrt_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_frag_fnrt_flab(fates_pft) ; - fates_frag_fnrt_flab:units = "fraction" ; - fates_frag_fnrt_flab:long_name = "Fine root litter labile fraction" ; - double fates_frag_fnrt_flig(fates_pft) ; - fates_frag_fnrt_flig:units = "fraction" ; - fates_frag_fnrt_flig:long_name = "Fine root litter lignin fraction" ; - double fates_frag_leaf_fcel(fates_pft) ; - fates_frag_leaf_fcel:units = "fraction" ; - fates_frag_leaf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_frag_leaf_flab(fates_pft) ; - fates_frag_leaf_flab:units = "fraction" ; - fates_frag_leaf_flab:long_name = "Leaf litter labile fraction" ; - double fates_frag_leaf_flig(fates_pft) ; - fates_frag_leaf_flig:units = "fraction" ; - fates_frag_leaf_flig:long_name = "Leaf litter lignin fraction" ; - double fates_frag_seed_decay_rate(fates_pft) ; - fates_frag_seed_decay_rate:units = "yr-1" ; - fates_frag_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_grperc(fates_pft) ; - fates_grperc:units = "unitless" ; - fates_grperc:long_name = "Growth respiration factor" ; - double fates_hydro_avuln_gs(fates_pft) ; - fates_hydro_avuln_gs:units = "unitless" ; - fates_hydro_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydro_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydro_avuln_node:units = "unitless" ; - fates_hydro_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydro_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydro_epsil_node:units = "MPa" ; - fates_hydro_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydro_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydro_fcap_node:units = "unitless" ; - fates_hydro_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydro_k_lwp(fates_pft) ; - fates_hydro_k_lwp:units = "unitless" ; - fates_hydro_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - double fates_hydro_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydro_kmax_node:units = "kg/MPa/m/s" ; - fates_hydro_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydro_p50_gs(fates_pft) ; - fates_hydro_p50_gs:units = "MPa" ; - fates_hydro_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydro_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydro_p50_node:units = "MPa" ; - fates_hydro_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydro_p_taper(fates_pft) ; - fates_hydro_p_taper:units = "unitless" ; - fates_hydro_p_taper:long_name = "xylem taper exponent" ; - double fates_hydro_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pinot_node:units = "MPa" ; - fates_hydro_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydro_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydro_pitlp_node:units = "MPa" ; - fates_hydro_pitlp_node:long_name = "turgor loss point" ; - double fates_hydro_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydro_resid_node:units = "cm3/cm3" ; - fates_hydro_resid_node:long_name = "residual water conent" ; - double fates_hydro_rfrac_stem(fates_pft) ; - fates_hydro_rfrac_stem:units = "fraction" ; - fates_hydro_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydro_rs2(fates_pft) ; - fates_hydro_rs2:units = "m" ; - fates_hydro_rs2:long_name = "absorbing root radius" ; - double fates_hydro_srl(fates_pft) ; - fates_hydro_srl:units = "m g-1" ; - fates_hydro_srl:long_name = "specific root length" ; - double fates_hydro_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydro_thetas_node:units = "cm3/cm3" ; - fates_hydro_thetas_node:long_name = "saturated water content" ; - double fates_hydro_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_alpha_node:units = "MPa-1" ; - fates_hydro_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydro_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_m_node:units = "unitless" ; - fates_hydro_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - double fates_hydro_vg_n_node(fates_hydr_organs, fates_pft) ; - fates_hydro_vg_n_node:units = "unitless" ; - fates_hydro_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; - double fates_leaf_c3psn(fates_pft) ; - fates_leaf_c3psn:units = "flag" ; - fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; - double fates_leaf_jmaxha(fates_pft) ; - fates_leaf_jmaxha:units = "J/mol" ; - fates_leaf_jmaxha:long_name = "activation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_jmaxhd(fates_pft) ; - fates_leaf_jmaxhd:units = "J/mol" ; - fates_leaf_jmaxhd:long_name = "deactivation energy for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_jmaxse(fates_pft) ; - fates_leaf_jmaxse:units = "J/mol/K" ; - fates_leaf_jmaxse:long_name = "entropy term for jmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_slamax(fates_pft) ; - fates_leaf_slamax:units = "m^2/gC" ; - fates_leaf_slamax:long_name = "Maximum Specific Leaf Area (SLA), even if under a dense canopy" ; - double fates_leaf_slatop(fates_pft) ; - fates_leaf_slatop:units = "m^2/gC" ; - fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; - double fates_leaf_stomatal_intercept(fates_pft) ; - fates_leaf_stomatal_intercept:units = "umol H2O/m**2/s" ; - fates_leaf_stomatal_intercept:long_name = "Minimum unstressed stomatal conductance for Ball-Berry model and Medlyn model" ; - double fates_leaf_stomatal_slope_ballberry(fates_pft) ; - fates_leaf_stomatal_slope_ballberry:units = "unitless" ; - fates_leaf_stomatal_slope_ballberry:long_name = "stomatal slope parameter, as per Ball-Berry" ; - double fates_leaf_stomatal_slope_medlyn(fates_pft) ; - fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; - fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_vcmax25top(fates_leafage_class, fates_pft) ; - fates_leaf_vcmax25top:units = "umol CO2/m^2/s" ; - fates_leaf_vcmax25top:long_name = "maximum carboxylation rate of Rub. at 25C, canopy top" ; - double fates_leaf_vcmaxha(fates_pft) ; - fates_leaf_vcmaxha:units = "J/mol" ; - fates_leaf_vcmaxha:long_name = "activation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_vcmaxhd(fates_pft) ; - fates_leaf_vcmaxhd:units = "J/mol" ; - fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_leaf_vcmaxse(fates_pft) ; - fates_leaf_vcmaxse:units = "J/mol/K" ; - fates_leaf_vcmaxse:long_name = "entropy term for vcmax. NOTE: if fates_leaf_photo_tempsens_model=2 then these values are NOT USED" ; - double fates_maintresp_leaf_atkin2017_baserate(fates_pft) ; - fates_maintresp_leaf_atkin2017_baserate:units = "umol CO2/m^2/s" ; - fates_maintresp_leaf_atkin2017_baserate:long_name = "Leaf maintenance respiration base rate parameter (r0) per Atkin et al 2017" ; - double fates_maintresp_leaf_ryan1991_baserate(fates_pft) ; - fates_maintresp_leaf_ryan1991_baserate:units = "gC/gN/s" ; - fates_maintresp_leaf_ryan1991_baserate:long_name = "Leaf maintenance respiration base rate per Ryan et al 1991" ; - double fates_maintresp_reduction_curvature(fates_pft) ; - fates_maintresp_reduction_curvature:units = "unitless (0-1)" ; - fates_maintresp_reduction_curvature:long_name = "curvature of MR reduction as f(carbon storage), 1=linear, 0=very curved" ; - double fates_maintresp_reduction_intercept(fates_pft) ; - fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; - fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; - double fates_maintresp_reduction_upthresh(fates_pft) ; - fates_maintresp_reduction_upthresh:units = "unitless (0-1)" ; - fates_maintresp_reduction_upthresh:long_name = "upper threshold for storage biomass (relative to leaf biomass) above which MR is not reduced" ; - double fates_mort_bmort(fates_pft) ; - fates_mort_bmort:units = "1/yr" ; - fates_mort_bmort:long_name = "background mortality rate" ; - double fates_mort_freezetol(fates_pft) ; - fates_mort_freezetol:units = "degrees C" ; - fates_mort_freezetol:long_name = "minimum temperature tolerance" ; - double fates_mort_hf_flc_threshold(fates_pft) ; - fates_mort_hf_flc_threshold:units = "fraction" ; - fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; - double fates_mort_hf_sm_threshold(fates_pft) ; - fates_mort_hf_sm_threshold:units = "unitless" ; - fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; - double fates_mort_ip_age_senescence(fates_pft) ; - fates_mort_ip_age_senescence:units = "years" ; - fates_mort_ip_age_senescence:long_name = "Mortality cohort age senescence inflection point. If _ this mortality term is off. Setting this value turns on age dependent mortality. " ; - double fates_mort_ip_size_senescence(fates_pft) ; - fates_mort_ip_size_senescence:units = "dbh cm" ; - fates_mort_ip_size_senescence:long_name = "Mortality dbh senescence inflection point. If _ this mortality term is off. Setting this value turns on size dependent mortality" ; - double fates_mort_prescribed_canopy(fates_pft) ; - fates_mort_prescribed_canopy:units = "1/yr" ; - fates_mort_prescribed_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_mort_prescribed_understory(fates_pft) ; - fates_mort_prescribed_understory:units = "1/yr" ; - fates_mort_prescribed_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; - double fates_mort_r_age_senescence(fates_pft) ; - fates_mort_r_age_senescence:units = "mortality rate year^-1" ; - fates_mort_r_age_senescence:long_name = "Mortality age senescence rate of change. Sensible range is around 0.03-0.06. Larger values givesteeper mortality curves." ; - double fates_mort_r_size_senescence(fates_pft) ; - fates_mort_r_size_senescence:units = "mortality rate dbh^-1" ; - fates_mort_r_size_senescence:long_name = "Mortality dbh senescence rate of change. Sensible range is around 0.03-0.06. Larger values give steeper mortality curves." ; - double fates_mort_scalar_coldstress(fates_pft) ; - fates_mort_scalar_coldstress:units = "1/yr" ; - fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; - double fates_mort_scalar_cstarvation(fates_pft) ; - fates_mort_scalar_cstarvation:units = "1/yr" ; - fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; - double fates_mort_scalar_hydrfailure(fates_pft) ; - fates_mort_scalar_hydrfailure:units = "1/yr" ; - fates_mort_scalar_hydrfailure:long_name = "maximum mortality rate from hydraulic failure" ; - double fates_mort_upthresh_cstarvation(fates_pft) ; - fates_mort_upthresh_cstarvation:units = "unitless" ; - fates_mort_upthresh_cstarvation:long_name = "threshold for storage biomass (relative to target leaf biomass) above which carbon starvation is zero" ; - double fates_nonhydro_smpsc(fates_pft) ; - fates_nonhydro_smpsc:units = "mm" ; - fates_nonhydro_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_nonhydro_smpso(fates_pft) ; - fates_nonhydro_smpso:units = "mm" ; - fates_nonhydro_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_phen_cold_size_threshold(fates_pft) ; - fates_phen_cold_size_threshold:units = "cm" ; - fates_phen_cold_size_threshold:long_name = "the dbh size above which will lead to phenology-related stem and leaf drop" ; - double fates_phen_drought_threshold(fates_pft) ; - fates_phen_drought_threshold:units = "m3/m3 or mm" ; - fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold for semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_evergreen(fates_pft) ; - fates_phen_evergreen:units = "logical flag" ; - fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; - double fates_phen_flush_fraction(fates_pft) ; - fates_phen_flush_fraction:units = "fraction" ; - fates_phen_flush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phen_fnrt_drop_fraction(fates_pft) ; - fates_phen_fnrt_drop_fraction:units = "fraction" ; - fates_phen_fnrt_drop_fraction:long_name = "fraction of fine roots to drop during drought/cold" ; - double fates_phen_mindaysoff(fates_pft) ; - fates_phen_mindaysoff:units = "days" ; - fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves abscised (shed)" ; - double fates_phen_moist_threshold(fates_pft) ; - fates_phen_moist_threshold:units = "m3/m3 or mm" ; - fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for drought semi-deciduous PFTs); the quantity depends on the sign: if positive, the threshold is volumetric soil moisture (m3/m3). If negative, the threshold is soil matric potentical (mm)" ; - double fates_phen_season_decid(fates_pft) ; - fates_phen_season_decid:units = "logical flag" ; - fates_phen_season_decid:long_name = "Binary flag for seasonal-deciduous leaf habit" ; - double fates_phen_stem_drop_fraction(fates_pft) ; - fates_phen_stem_drop_fraction:units = "fraction" ; - fates_phen_stem_drop_fraction:long_name = "fraction of stems to drop for non-woody species during drought/cold" ; - double fates_phen_stress_decid(fates_pft) ; - fates_phen_stress_decid:units = "logical flag" ; - fates_phen_stress_decid:long_name = "Binary flag for stress-deciduous leaf habit" ; - double fates_prescribed_npp_canopy(fates_pft) ; - fates_prescribed_npp_canopy:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; - double fates_prescribed_npp_understory(fates_pft) ; - fates_prescribed_npp_understory:units = "kgC / m^2 / yr" ; - fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; - double fates_rad_leaf_clumping_index(fates_pft) ; - fates_rad_leaf_clumping_index:units = "fraction (0-1)" ; - fates_rad_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_rad_leaf_rhonir(fates_pft) ; - fates_rad_leaf_rhonir:units = "fraction" ; - fates_rad_leaf_rhonir:long_name = "Leaf reflectance: near-IR" ; - double fates_rad_leaf_rhovis(fates_pft) ; - fates_rad_leaf_rhovis:units = "fraction" ; - fates_rad_leaf_rhovis:long_name = "Leaf reflectance: visible" ; - double fates_rad_leaf_taunir(fates_pft) ; - fates_rad_leaf_taunir:units = "fraction" ; - fates_rad_leaf_taunir:long_name = "Leaf transmittance: near-IR" ; - double fates_rad_leaf_tauvis(fates_pft) ; - fates_rad_leaf_tauvis:units = "fraction" ; - fates_rad_leaf_tauvis:long_name = "Leaf transmittance: visible" ; - double fates_rad_leaf_xl(fates_pft) ; - fates_rad_leaf_xl:units = "unitless" ; - fates_rad_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_rad_stem_rhonir(fates_pft) ; - fates_rad_stem_rhonir:units = "fraction" ; - fates_rad_stem_rhonir:long_name = "Stem reflectance: near-IR" ; - double fates_rad_stem_rhovis(fates_pft) ; - fates_rad_stem_rhovis:units = "fraction" ; - fates_rad_stem_rhovis:long_name = "Stem reflectance: visible" ; - double fates_rad_stem_taunir(fates_pft) ; - fates_rad_stem_taunir:units = "fraction" ; - fates_rad_stem_taunir:long_name = "Stem transmittance: near-IR" ; - double fates_rad_stem_tauvis(fates_pft) ; - fates_rad_stem_tauvis:units = "fraction" ; - fates_rad_stem_tauvis:long_name = "Stem transmittance: visible" ; - double fates_recruit_height_min(fates_pft) ; - fates_recruit_height_min:units = "m" ; - fates_recruit_height_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_init_density(fates_pft) ; - fates_recruit_init_density:units = "stems/m2" ; - fates_recruit_init_density:long_name = "initial seedling density for a cold-start near-bare-ground simulation. If negative sets initial tree dbh - only to be used in nocomp mode" ; - double fates_recruit_prescribed_rate(fates_pft) ; - fates_recruit_prescribed_rate:units = "n/yr" ; - fates_recruit_prescribed_rate:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_recruit_seed_alloc(fates_pft) ; - fates_recruit_seed_alloc:units = "fraction" ; - fates_recruit_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_recruit_seed_alloc_mature(fates_pft) ; - fates_recruit_seed_alloc_mature:units = "fraction" ; - fates_recruit_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_recruit_seed_dbh_repro_threshold(fates_pft) ; - fates_recruit_seed_dbh_repro_threshold:units = "cm" ; - fates_recruit_seed_dbh_repro_threshold:long_name = "the diameter where the plant will increase allocation to the seed pool by fraction: fates_recruit_seed_alloc_mature" ; - double fates_recruit_seed_germination_rate(fates_pft) ; - fates_recruit_seed_germination_rate:units = "yr-1" ; - fates_recruit_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_recruit_seed_supplement(fates_pft) ; - fates_recruit_seed_supplement:units = "KgC/m2/yr" ; - fates_recruit_seed_supplement:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_seed_dispersal_fraction(fates_pft) ; - fates_seed_dispersal_fraction:units = "fraction" ; - fates_seed_dispersal_fraction:long_name = "fraction of seed rain to be dispersed to other grid cells" ; - double fates_seed_dispersal_max_dist(fates_pft) ; - fates_seed_dispersal_max_dist:units = "m" ; - fates_seed_dispersal_max_dist:long_name = "maximum seed dispersal distance for a given pft" ; - double fates_seed_dispersal_pdf_scale(fates_pft) ; - fates_seed_dispersal_pdf_scale:units = "unitless" ; - fates_seed_dispersal_pdf_scale:long_name = "seed dispersal probability density function scale parameter, A, Table 1 Bullock et al 2016" ; - double fates_seed_dispersal_pdf_shape(fates_pft) ; - fates_seed_dispersal_pdf_shape:units = "unitless" ; - fates_seed_dispersal_pdf_shape:long_name = "seed dispersal probability density function shape parameter, B, Table 1 Bullock et al 2016" ; - double fates_stoich_nitr(fates_plant_organs, fates_pft) ; - fates_stoich_nitr:units = "gN/gC" ; - fates_stoich_nitr:long_name = "target nitrogen concentration (ratio with carbon) of organs" ; - double fates_stoich_phos(fates_plant_organs, fates_pft) ; - fates_stoich_phos:units = "gP/gC" ; - fates_stoich_phos:long_name = "target phosphorus concentration (ratio with carbon) of organs" ; - double fates_trim_inc(fates_pft) ; - fates_trim_inc:units = "m2/m2" ; - fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; - double fates_trim_limit(fates_pft) ; - fates_trim_limit:units = "m2/m2" ; - fates_trim_limit:long_name = "Arbitrary limit to reductions in leaf area with stress" ; - double fates_trs_repro_alloc_a(fates_pft) ; - fates_trs_repro_alloc_a:units = "fraction" ; - fates_trs_repro_alloc_a:long_name = "shape parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_trs_repro_alloc_b(fates_pft) ; - fates_trs_repro_alloc_b:units = "fraction" ; - fates_trs_repro_alloc_b:long_name = "intercept parameter for sigmoidal function relating dbh to reproductive allocation" ; - double fates_trs_repro_frac_seed(fates_pft) ; - fates_trs_repro_frac_seed:units = "fraction" ; - fates_trs_repro_frac_seed:long_name = "fraction of reproductive mass that is seed" ; - double fates_trs_seedling_a_emerg(fates_pft) ; - fates_trs_seedling_a_emerg:units = "day -1" ; - fates_trs_seedling_a_emerg:long_name = "mean fraction of seed bank emerging" ; - double fates_trs_seedling_b_emerg(fates_pft) ; - fates_trs_seedling_b_emerg:units = "day -1" ; - fates_trs_seedling_b_emerg:long_name = "seedling emergence sensitivity to soil moisture" ; - double fates_trs_seedling_background_mort(fates_pft) ; - fates_trs_seedling_background_mort:units = "yr-1" ; - fates_trs_seedling_background_mort:long_name = "background seedling mortality rate" ; - double fates_trs_seedling_h2o_mort_a(fates_pft) ; - fates_trs_seedling_h2o_mort_a:units = "-" ; - fates_trs_seedling_h2o_mort_a:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_h2o_mort_b(fates_pft) ; - fates_trs_seedling_h2o_mort_b:units = "-" ; - fates_trs_seedling_h2o_mort_b:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_h2o_mort_c(fates_pft) ; - fates_trs_seedling_h2o_mort_c:units = "-" ; - fates_trs_seedling_h2o_mort_c:long_name = "coefficient in moisture-based seedling mortality" ; - double fates_trs_seedling_light_mort_a(fates_pft) ; - fates_trs_seedling_light_mort_a:units = "-" ; - fates_trs_seedling_light_mort_a:long_name = "light-based seedling mortality coefficient" ; - double fates_trs_seedling_light_mort_b(fates_pft) ; - fates_trs_seedling_light_mort_b:units = "-" ; - fates_trs_seedling_light_mort_b:long_name = "light-based seedling mortality coefficient" ; - double fates_trs_seedling_light_rec_a(fates_pft) ; - fates_trs_seedling_light_rec_a:units = "-" ; - fates_trs_seedling_light_rec_a:long_name = "coefficient in light-based seedling to sapling transition" ; - double fates_trs_seedling_light_rec_b(fates_pft) ; - fates_trs_seedling_light_rec_b:units = "-" ; - fates_trs_seedling_light_rec_b:long_name = "coefficient in light-based seedling to sapling transition" ; - double fates_trs_seedling_mdd_crit(fates_pft) ; - fates_trs_seedling_mdd_crit:units = "mm H2O day" ; - fates_trs_seedling_mdd_crit:long_name = "critical moisture deficit (suction) day accumulation for seedling moisture-based seedling mortality to begin" ; - double fates_trs_seedling_par_crit_germ(fates_pft) ; - fates_trs_seedling_par_crit_germ:units = "MJ m-2 day-1" ; - fates_trs_seedling_par_crit_germ:long_name = "critical light level for germination" ; - double fates_trs_seedling_psi_crit(fates_pft) ; - fates_trs_seedling_psi_crit:units = "mm H2O" ; - fates_trs_seedling_psi_crit:long_name = "critical soil moisture (suction) for seedling stress" ; - double fates_trs_seedling_psi_emerg(fates_pft) ; - fates_trs_seedling_psi_emerg:units = "mm h20 suction" ; - fates_trs_seedling_psi_emerg:long_name = "critical soil moisture for seedling emergence" ; - double fates_trs_seedling_root_depth(fates_pft) ; - fates_trs_seedling_root_depth:units = "m" ; - fates_trs_seedling_root_depth:long_name = "rooting depth of seedlings" ; - double fates_turb_displar(fates_pft) ; - fates_turb_displar:units = "unitless" ; - fates_turb_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_turb_leaf_diameter(fates_pft) ; - fates_turb_leaf_diameter:units = "m" ; - fates_turb_leaf_diameter:long_name = "Characteristic leaf dimension" ; - double fates_turb_z0mr(fates_pft) ; - fates_turb_z0mr:units = "unitless" ; - fates_turb_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - double fates_turnover_branch(fates_pft) ; - fates_turnover_branch:units = "yr" ; - fates_turnover_branch:long_name = "turnover time of branches" ; - double fates_turnover_fnrt(fates_pft) ; - fates_turnover_fnrt:units = "yr" ; - fates_turnover_fnrt:long_name = "root longevity (alternatively, turnover time)" ; - double fates_turnover_leaf(fates_leafage_class, fates_pft) ; - fates_turnover_leaf:units = "yr" ; - fates_turnover_leaf:long_name = "Leaf longevity (ie turnover timescale). For drought-deciduous PFTs, this also indicates the maximum length of the growing (i.e., leaves on) season." ; - double fates_turnover_leaf_ustory(fates_leafage_class, fates_pft) ; - fates_turnover_leaf_ustory:units = "yr" ; - fates_turnover_leaf_ustory:long_name = "Leaf longevity (ie turnover timescale) of understory plants." ; - double fates_turnover_senleaf_fdrought(fates_pft) ; - fates_turnover_senleaf_fdrought:units = "unitless[0-1]" ; - fates_turnover_senleaf_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_wood_density(fates_pft) ; - fates_wood_density:units = "g/cm3" ; - fates_wood_density:long_name = "mean density of woody tissue in plant" ; - double fates_woody(fates_pft) ; - fates_woody:units = "logical flag" ; - fates_woody:long_name = "Binary woody lifeform flag" ; - double fates_hlm_pft_map(fates_hlm_pftno, fates_pft) ; - fates_hlm_pft_map:units = "area fraction" ; - fates_hlm_pft_map:long_name = "In fixed biogeog mode, fraction of HLM area associated with each FATES PFT" ; - double fates_fire_FBD(fates_litterclass) ; - fates_fire_FBD:units = "kg Biomass/m3" ; - fates_fire_FBD:long_name = "fuel bulk density" ; - double fates_fire_low_moisture_Coeff(fates_litterclass) ; - fates_fire_low_moisture_Coeff:units = "NA" ; - fates_fire_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_low_moisture_Slope(fates_litterclass) ; - fates_fire_low_moisture_Slope:units = "NA" ; - fates_fire_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture(fates_litterclass) ; - fates_fire_mid_moisture:units = "NA" ; - fates_fire_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; - double fates_fire_mid_moisture_Coeff(fates_litterclass) ; - fates_fire_mid_moisture_Coeff:units = "NA" ; - fates_fire_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_mid_moisture_Slope(fates_litterclass) ; - fates_fire_mid_moisture_Slope:units = "NA" ; - fates_fire_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; - double fates_fire_min_moisture(fates_litterclass) ; - fates_fire_min_moisture:units = "NA" ; - fates_fire_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; - double fates_fire_SAV(fates_litterclass) ; - fates_fire_SAV:units = "cm-1" ; - fates_fire_SAV:long_name = "fuel surface area to volume ratio" ; - double fates_frag_maxdecomp(fates_litterclass) ; - fates_frag_maxdecomp:units = "yr-1" ; - fates_frag_maxdecomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - double fates_frag_cwd_frac(fates_NCWD) ; - fates_frag_cwd_frac:units = "fraction" ; - fates_frag_cwd_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; - double fates_canopy_closure_thresh ; - fates_canopy_closure_thresh:units = "unitless" ; - fates_canopy_closure_thresh:long_name = "tree canopy coverage at which crown area allometry changes from savanna to forest value" ; - double fates_cnp_eca_plant_escalar ; - fates_cnp_eca_plant_escalar:units = "" ; - fates_cnp_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; - double fates_cohort_age_fusion_tol ; - fates_cohort_age_fusion_tol:units = "unitless" ; - fates_cohort_age_fusion_tol:long_name = "minimum fraction in differece in cohort age between cohorts." ; - double fates_cohort_size_fusion_tol ; - fates_cohort_size_fusion_tol:units = "unitless" ; - fates_cohort_size_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; - double fates_comp_excln ; - fates_comp_excln:units = "none" ; - fates_comp_excln:long_name = "IF POSITIVE: weighting factor (exponent on dbh) for canopy layer exclusion and promotion, IF NEGATIVE: switch to use deterministic height sorting" ; - double fates_damage_canopy_layer_code ; - fates_damage_canopy_layer_code:units = "unitless" ; - fates_damage_canopy_layer_code:long_name = "Integer code that decides whether damage affects canopy trees (1), understory trees (2)" ; - double fates_damage_event_code ; - fates_damage_event_code:units = "unitless" ; - fates_damage_event_code:long_name = "Integer code that options how damage events are structured" ; - double fates_dev_arbitrary ; - fates_dev_arbitrary:units = "unknown" ; - fates_dev_arbitrary:long_name = "Unassociated free parameter that developers can use for testing arbitrary new hypotheses" ; - double fates_fire_active_crown_fire ; - fates_fire_active_crown_fire:units = "0 or 1" ; - fates_fire_active_crown_fire:long_name = "flag, 1=active crown fire 0=no active crown fire" ; - double fates_fire_cg_strikes ; - fates_fire_cg_strikes:units = "fraction (0-1)" ; - fates_fire_cg_strikes:long_name = "fraction of cloud to ground lightning strikes" ; - double fates_fire_drying_ratio ; - fates_fire_drying_ratio:units = "NA" ; - fates_fire_drying_ratio:long_name = "spitfire parameter, fire drying ratio for fuel moisture, alpha_FMC EQ 6 Thonicke et al 2010" ; - double fates_fire_durat_slope ; - fates_fire_durat_slope:units = "NA" ; - fates_fire_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; - double fates_fire_fdi_a ; - fates_fire_fdi_a:units = "NA" ; - fates_fire_fdi_a:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010" ; - double fates_fire_fdi_alpha ; - fates_fire_fdi_alpha:units = "NA" ; - fates_fire_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; - double fates_fire_fdi_b ; - fates_fire_fdi_b:units = "NA" ; - fates_fire_fdi_b:long_name = "spitfire parameter, fire danger index, EQ 5 Thonicke et al 2010 " ; - double fates_fire_fuel_energy ; - fates_fire_fuel_energy:units = "kJ/kg" ; - fates_fire_fuel_energy:long_name = "spitfire parameter, heat content of fuel" ; - double fates_fire_max_durat ; - fates_fire_max_durat:units = "minutes" ; - fates_fire_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; - double fates_fire_miner_damp ; - fates_fire_miner_damp:units = "NA" ; - fates_fire_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; - double fates_fire_miner_total ; - fates_fire_miner_total:units = "fraction" ; - fates_fire_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; - double fates_fire_nignitions ; - fates_fire_nignitions:units = "ignitions per year per km2" ; - fates_fire_nignitions:long_name = "number of annual ignitions per square km" ; - double fates_fire_part_dens ; - fates_fire_part_dens:units = "kg/m2" ; - fates_fire_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; - double fates_fire_threshold ; - fates_fire_threshold:units = "kW/m" ; - fates_fire_threshold:long_name = "spitfire parameter, fire intensity threshold for tracking fires that spread" ; - double fates_frag_cwd_fcel ; - fates_frag_cwd_fcel:units = "unitless" ; - fates_frag_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_frag_cwd_flig ; - fates_frag_cwd_flig:units = "unitless" ; - fates_frag_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; - double fates_hydro_kmax_rsurf1 ; - fates_hydro_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydro_kmax_rsurf2 ; - fates_hydro_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydro_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydro_psi0 ; - fates_hydro_psi0:units = "MPa" ; - fates_hydro_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydro_psicap ; - fates_hydro_psicap:units = "MPa" ; - fates_hydro_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - double fates_hydro_solver ; - fates_hydro_solver:units = "unitless" ; - fates_hydro_solver:long_name = "switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard, 3 = 2D Newton (deprecated)" ; - double fates_landuse_logging_coll_under_frac ; - fates_landuse_logging_coll_under_frac:units = "fraction" ; - fates_landuse_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; - double fates_landuse_logging_collateral_frac ; - fates_landuse_logging_collateral_frac:units = "fraction" ; - fates_landuse_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_landuse_logging_dbhmax ; - fates_landuse_logging_dbhmax:units = "cm" ; - fates_landuse_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_landuse_logging_dbhmax_infra ; - fates_landuse_logging_dbhmax_infra:units = "cm" ; - fates_landuse_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_landuse_logging_dbhmin ; - fates_landuse_logging_dbhmin:units = "cm" ; - fates_landuse_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_landuse_logging_direct_frac ; - fates_landuse_logging_direct_frac:units = "fraction" ; - fates_landuse_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_landuse_logging_event_code ; - fates_landuse_logging_event_code:units = "unitless" ; - fates_landuse_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_landuse_logging_export_frac ; - fates_landuse_logging_export_frac:units = "fraction" ; - fates_landuse_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_landuse_logging_mechanical_frac ; - fates_landuse_logging_mechanical_frac:units = "fraction" ; - fates_landuse_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_landuse_pprodharv10_forest_mean ; - fates_landuse_pprodharv10_forest_mean:units = "fraction" ; - fates_landuse_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types" ; - double fates_leaf_photo_temp_acclim_thome_time ; - fates_leaf_photo_temp_acclim_thome_time:units = "years" ; - fates_leaf_photo_temp_acclim_thome_time:long_name = "Length of the window for the long-term (i.e. T_home in Kumarathunge et al 2019) exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_leaf_photo_tempsens_model = 2)" ; - double fates_leaf_photo_temp_acclim_timescale ; - fates_leaf_photo_temp_acclim_timescale:units = "days" ; - fates_leaf_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (used if fates_maintresp_leaf_model=2 or fates_leaf_photo_tempsens_model = 2)" ; - double fates_leaf_photo_tempsens_model ; - fates_leaf_photo_tempsens_model:units = "unitless" ; - fates_leaf_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating; 2=Kumarathunge et al 2019" ; - double fates_leaf_stomatal_assim_model ; - fates_leaf_stomatal_assim_model:units = "unitless" ; - fates_leaf_stomatal_assim_model:long_name = "a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model" ; - double fates_leaf_stomatal_model ; - fates_leaf_stomatal_model:units = "unitless" ; - fates_leaf_stomatal_model:long_name = "switch for choosing between Ball-Berry (1) stomatal conductance model and Medlyn (2) model" ; - double fates_leaf_theta_cj_c3 ; - fates_leaf_theta_cj_c3:units = "unitless" ; - fates_leaf_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_leaf_theta_cj_c4 ; - fates_leaf_theta_cj_c4:units = "unitless" ; - fates_leaf_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; - double fates_maintresp_leaf_model ; - fates_maintresp_leaf_model:units = "unitless" ; - fates_maintresp_leaf_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991), 2=Atkin et al., (2017)" ; - double fates_maintresp_nonleaf_baserate ; - fates_maintresp_nonleaf_baserate:units = "gC/gN/s" ; - fates_maintresp_nonleaf_baserate:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; - double fates_maxcohort ; - fates_maxcohort:units = "count" ; - fates_maxcohort:long_name = "maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances" ; - double fates_maxpatch_primary ; - fates_maxpatch_primary:units = "count" ; - fates_maxpatch_primary:long_name = "maximum number of primary vegetation patches per site" ; - double fates_maxpatch_secondary ; - fates_maxpatch_secondary:units = "count" ; - fates_maxpatch_secondary:long_name = "maximum number of secondary vegetation patches per site" ; - double fates_mort_disturb_frac ; - fates_mort_disturb_frac:units = "fraction" ; - fates_mort_disturb_frac:long_name = "fraction of canopy mortality that results in disturbance (i.e. transfer of area from new to old patch)" ; - double fates_mort_understorey_death ; - fates_mort_understorey_death:units = "fraction" ; - fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; - double fates_patch_fusion_tol ; - fates_patch_fusion_tol:units = "unitless" ; - fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; - double fates_phen_chilltemp ; - fates_phen_chilltemp:units = "degrees C" ; - fates_phen_chilltemp:long_name = "chilling day counting threshold for vegetation" ; - double fates_phen_coldtemp ; - fates_phen_coldtemp:units = "degrees C" ; - fates_phen_coldtemp:long_name = "vegetation temperature exceedance that flags a cold-day for leaf-drop" ; - double fates_phen_gddthresh_a ; - fates_phen_gddthresh_a:units = "none" ; - fates_phen_gddthresh_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_b ; - fates_phen_gddthresh_b:units = "none" ; - fates_phen_gddthresh_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_gddthresh_c ; - fates_phen_gddthresh_c:units = "none" ; - fates_phen_gddthresh_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_mindayson ; - fates_phen_mindayson:units = "days" ; - fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; - double fates_phen_ncolddayslim ; - fates_phen_ncolddayslim:units = "days" ; - fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_q10_froz ; - fates_q10_froz:units = "unitless" ; - fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; - double fates_q10_mr ; - fates_q10_mr:units = "unitless" ; - fates_q10_mr:long_name = "Q10 for maintenance respiration" ; - double fates_rad_model ; - fates_rad_model:units = "unitless" ; - fates_rad_model:long_name = "switch designating the model for canopy radiation, 1 = Norman, 2 = Two-stream (experimental)" ; - double fates_regeneration_model ; - fates_regeneration_model:units = "-" ; - fates_regeneration_model:long_name = "switch for choosing between FATES\'s: 1) default regeneration scheme , 2) the Tree Recruitment Scheme (Hanbury-Brown et al., 2022), or (3) the Tree Recruitment Scheme without seedling dynamics" ; - double fates_soil_salinity ; - fates_soil_salinity:units = "ppt" ; - fates_soil_salinity:long_name = "soil salinity used for model when not coupled to dynamic soil salinity" ; - double fates_trs_seedling2sap_par_timescale ; - fates_trs_seedling2sap_par_timescale:units = "days" ; - fates_trs_seedling2sap_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling to sapling transition rates" ; - double fates_trs_seedling_emerg_h2o_timescale ; - fates_trs_seedling_emerg_h2o_timescale:units = "days" ; - fates_trs_seedling_emerg_h2o_timescale:long_name = "Length of the window for the exponential moving average of smp used to calculate seedling emergence" ; - double fates_trs_seedling_mdd_timescale ; - fates_trs_seedling_mdd_timescale:units = "days" ; - fates_trs_seedling_mdd_timescale:long_name = "Length of the window for the exponential moving average of moisture deficit days used to calculate seedling mortality" ; - double fates_trs_seedling_mort_par_timescale ; - fates_trs_seedling_mort_par_timescale:units = "days" ; - fates_trs_seedling_mort_par_timescale:long_name = "Length of the window for the exponential moving average of par at the seedling layer used to calculate seedling mortality" ; - double fates_vai_top_bin_width ; - fates_vai_top_bin_width:units = "m2/m2" ; - fates_vai_top_bin_width:long_name = "width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer" ; - double fates_vai_width_increase_factor ; - fates_vai_width_increase_factor:units = "unitless" ; - fates_vai_width_increase_factor:long_name = "factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing)" ; - -// global attributes: - :history = "This file was generated by BatchPatchParams.py:\nCDL Base File = archive/api24.1.0_101722_fates_params_default.cdl\nXML patch file = archive/api24.1.0_101722_patch_params.xml" ; -data: - - fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; - - fates_history_coageclass_bin_edges = 0, 5 ; - - fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - - fates_history_damage_bin_edges = 0, 80 ; - - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, - 80, 90, 100 ; - - fates_alloc_organ_id = 1, 2, 3, 6 ; - - fates_hydro_htftype_node = 1, 1, 1, 1 ; - - fates_pftname = - "broadleaf_evergreen_tropical_tree ", - "needleleaf_evergreen_extratrop_tree ", - "needleleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_tree ", - "broadleaf_hydrodecid_tropical_tree ", - "broadleaf_colddecid_extratrop_tree ", - "broadleaf_evergreen_extratrop_shrub ", - "broadleaf_hydrodecid_extratrop_shrub ", - "broadleaf_colddecid_extratrop_shrub ", - "arctic_c3_grass ", - "cool_c3_grass ", - "c4_grass " ; - - fates_hydro_organ_name = - "leaf ", - "stem ", - "transporting root ", - "absorbing root " ; - - fates_alloc_organ_name = - "leaf", - "fine root", - "sapwood", - "structure" ; - - fates_litterclass_name = - "twig ", - "small branch ", - "large branch ", - "trunk ", - "dead leaves ", - "live grass " ; - - fates_alloc_organ_priority = - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ; - - fates_alloc_storage_cushion = 1.2, 1.2, 1.2, 1.2, 2.4, 1.2, 1.2, 2.4, 1.2, - 1.2, 1.2, 1.2 ; - - fates_alloc_store_priority_frac = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8, 0.8 ; - - fates_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, - 0.06896, 0.06896, 0.06896, 0.01, 0.01, 0.01 ; - - fates_allom_agb2 = 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, 0.572, - 0.572, 0.572, 0.572, 0.572 ; - - fates_allom_agb3 = 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, 1.94, - 1.94, 1.94, 1.94 ; - - fates_allom_agb4 = 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, 0.931, - 0.931, 0.931, 0.931, 0.931 ; - - fates_allom_agb_frac = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6 ; - - fates_allom_amode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_blca_expnt_diff = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_cmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_crown_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_allom_d2bl1 = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07 ; - - fates_allom_d2bl2 = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, - 1.3 ; - - fates_allom_d2bl3 = 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, 0.55, - 0.55, 0.55, 0.55 ; - - fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, 0.6568464, - 0.6568464, 0.6568464, 0.6568464 ; - - fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, 0.3381119, - 0.3381119, 0.3381119, 0.3381119 ; - - fates_allom_d2h1 = 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, 0.64, - 0.64, 0.64, 0.64 ; - - fates_allom_d2h2 = 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, 0.37, - 0.37, 0.37, 0.37 ; - - fates_allom_d2h3 = -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, -999.9, - -999.9, -999.9, -999.9, -999.9, -999.9 ; - - fates_allom_dbh_maxheight = 90, 80, 80, 80, 90, 80, 3, 3, 2, 0.35, 0.35, 0.35 ; - - fates_allom_fmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; - - fates_allom_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; - - fates_allom_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_allom_frbstor_repro = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_hmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_l2fr = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_la_per_sa_int = 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, - 0.8, 0.8, 0.8 ; - - fates_allom_la_per_sa_slp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_allom_lmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_sai_scaler = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_allom_smode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_stmode = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_allom_zroot_k = 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ; - - fates_allom_zroot_max_dbh = 100, 100, 100, 100, 100, 100, 2, 2, 2, 2, 2, 2 ; - - fates_allom_zroot_max_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_allom_zroot_min_dbh = 1, 1, 1, 2.5, 2.5, 2.5, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_cnp_eca_alpha_ptase = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, - 280, 280 ; - - fates_cnp_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, - 0.14, 0.14, 0.14 ; - - fates_cnp_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, - 0.27, 0.27, 0.27 ; - - fates_cnp_eca_km_p = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1 ; - - fates_cnp_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, - 5e-09, 5e-09, 5e-09, 5e-09, 5e-09 ; - - fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_nitr_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_phos_store_ratio = 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, - 1.5, 1.5, 1.5 ; - - fates_cnp_pid_kd = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 ; - - fates_cnp_pid_ki = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_pid_kp = 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005 ; - - fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_store_ovrflw_frac = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_cnp_turnover_nitr_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_turnover_phos_retrans = - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_cnp_vmax_nh4 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, - 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; - - fates_cnp_vmax_no3 = 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, - 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09, 2.5e-09 ; - - fates_cnp_vmax_p = 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, 5e-10, - 5e-10, 5e-10, 5e-10, 5e-10 ; - - fates_damage_frac = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01 ; - - fates_damage_mort_p1 = 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 ; - - fates_damage_mort_p2 = 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, - 5.5, 5.5 ; - - fates_damage_recovery_scalar = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_fire_alpha_SH = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2 ; - - fates_fire_bark_scaler = 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, 0.07, - 0.07, 0.07, 0.07, 0.07 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, - 0.775, 0.775, 0.775, 0.775, 0.775 ; - - fates_frag_fnrt_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_fnrt_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_fnrt_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_fcel = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5 ; - - fates_frag_leaf_flab = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_leaf_flig = 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - 0.25, 0.25, 0.25 ; - - fates_frag_seed_decay_rate = 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, 0.51, - 0.51, 0.51, 0.51, 0.51 ; - - fates_grperc = 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, - 0.11, 0.11 ; - - fates_hydro_avuln_gs = 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, - 2.5, 2.5 ; - - fates_hydro_avuln_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_hydro_epsil_node = - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_hydro_fcap_node = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, 0.08, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_k_lwp = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_hydro_kmax_node = - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, - -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999, -999 ; - - fates_hydro_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, - -1.5, -1.5, -1.5 ; - - fates_hydro_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25, - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, - -2.25, -2.25 ; - - fates_hydro_p_taper = 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, 0.333, - 0.333, 0.333, 0.333, 0.333, 0.333 ; - - fates_hydro_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.22807, -1.22807, -1.22807, -1.22807, -1.22807, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, - -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - - fates_hydro_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, - -1.67, -1.67, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, -1.4, - -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2, -1.2 ; - - fates_hydro_resid_node = - 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, 0.16, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11 ; - - fates_hydro_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, - 0.625, 0.625, 0.625, 0.625, 0.625 ; - - fates_hydro_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, - 0.0001, 0.0001, 0.0001, 0.0001, 0.0001 ; - - fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - - fates_hydro_thetas_node = - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, 0.65, - 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75, 0.75 ; - - fates_hydro_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005, - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, - 0.005, 0.005 ; - - fates_hydro_vg_m_node = - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_hydro_vg_n_node = - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - - fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - - fates_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, - 43540, 43540, 43540, 43540 ; - - fates_leaf_jmaxhd = 152040, 152040, 152040, 152040, 152040, 152040, 152040, - 152040, 152040, 152040, 152040, 152040 ; - - fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, - 495 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, - 0.03, 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_slatop = 0.012, 0.005, 0.024, 0.009, 0.03, 0.03, 0.012, 0.03, - 0.03, 0.03, 0.03, 0.03 ; - - fates_leaf_stomatal_intercept = 10000, 10000, 10000, 10000, 10000, 10000, - 10000, 10000, 10000, 10000, 10000, 40000 ; - - fates_leaf_stomatal_slope_ballberry = 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ; - - fates_leaf_stomatal_slope_medlyn = 4.1, 2.3, 2.3, 4.1, 4.4, 4.4, 4.7, 4.7, - 4.7, 2.2, 5.3, 1.6 ; - - fates_leaf_vcmax25top = - 50, 62, 39, 61, 58, 58, 62, 54, 54, 78, 78, 78 ; - - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, - 65330, 65330, 65330, 65330 ; - - fates_leaf_vcmaxhd = 149250, 149250, 149250, 149250, 149250, 149250, 149250, - 149250, 149250, 149250, 149250, 149250 ; - - fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, - 485 ; - - fates_maintresp_leaf_atkin2017_baserate = 1.756, 1.4995, 1.4995, 1.756, - 1.756, 1.756, 2.0749, 2.0749, 2.0749, 2.1956, 2.1956, 2.1956 ; - - fates_maintresp_leaf_ryan1991_baserate = 2.525e-06, 2.525e-06, 2.525e-06, - 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, 2.525e-06, - 2.525e-06, 2.525e-06, 2.525e-06 ; - - fates_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, - 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ; - - fates_maintresp_reduction_intercept = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_maintresp_reduction_upthresh = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, - 0.014, 0.014, 0.014, 0.014 ; - - fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -80, -60, -10, -80, -80, - -20, 2.5 ; - - fates_mort_hf_flc_threshold = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5 ; - - fates_mort_hf_sm_threshold = 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, - 1e-06, 1e-06, 1e-06, 1e-06, 1e-06, 1e-06 ; - - fates_mort_ip_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_ip_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_prescribed_canopy = 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, - 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194, 0.0194 ; - - fates_mort_prescribed_understory = 0.025, 0.025, 0.025, 0.025, 0.025, 0.025, - 0.025, 0.025, 0.025, 0.025, 0.025, 0.025 ; - - fates_mort_r_age_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_r_size_senescence = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_mort_scalar_coldstress = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; - - fates_mort_scalar_cstarvation = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_scalar_hydrfailure = 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, - 0.6, 0.6, 0.6 ; - - fates_mort_upthresh_cstarvation = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000, -255000 ; - - fates_nonhydro_smpso = -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000, -66000 ; - - fates_phen_cold_size_threshold = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_drought_threshold = -152957.4, -152957.4, -152957.4, -152957.4, - -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, -152957.4, - -152957.4, -152957.4 ; - - fates_phen_evergreen = 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 ; - - fates_phen_flush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, - 0.5 ; - - fates_phen_fnrt_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_mindaysoff = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100 ; - - fates_phen_moist_threshold = -122365.9, -122365.9, -122365.9, -122365.9, - -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, -122365.9, - -122365.9, -122365.9 ; - - fates_phen_season_decid = 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0 ; - - fates_phen_stem_drop_fraction = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_phen_stress_decid = 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 ; - - fates_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, - 0.4, 0.4, 0.4 ; - - fates_prescribed_npp_understory = 0.03125, 0.03125, 0.03125, 0.03125, - 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125, 0.03125 ; - - fates_rad_leaf_clumping_index = 0.85, 0.85, 0.8, 0.85, 0.85, 0.9, 0.85, 0.9, - 0.9, 0.75, 0.75, 0.75 ; - - fates_rad_leaf_rhonir = 0.46, 0.41, 0.39, 0.46, 0.41, 0.41, 0.46, 0.41, - 0.41, 0.28, 0.28, 0.28 ; - - fates_rad_leaf_rhovis = 0.11, 0.09, 0.08, 0.11, 0.08, 0.08, 0.11, 0.08, - 0.08, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_taunir = 0.33, 0.32, 0.42, 0.33, 0.43, 0.43, 0.33, 0.43, - 0.43, 0.4, 0.4, 0.4 ; - - fates_rad_leaf_tauvis = 0.06, 0.04, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.05, 0.05, 0.05 ; - - fates_rad_leaf_xl = 0.32, 0.01, 0.01, 0.32, 0.2, 0.59, 0.32, 0.59, 0.59, - -0.23, -0.23, -0.23 ; - - fates_rad_stem_rhonir = 0.49, 0.36, 0.36, 0.49, 0.49, 0.49, 0.49, 0.49, - 0.49, 0.53, 0.53, 0.53 ; - - fates_rad_stem_rhovis = 0.21, 0.12, 0.12, 0.21, 0.21, 0.21, 0.21, 0.21, - 0.21, 0.31, 0.31, 0.31 ; - - fates_rad_stem_taunir = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.25, 0.25, 0.25 ; - - fates_rad_stem_tauvis = 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, - 0.001, 0.001, 0.12, 0.12, 0.12 ; - - fates_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.2, 0.2, 0.2, - 0.125, 0.125, 0.125 ; - - fates_recruit_init_density = 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, - 0.2, 0.2, 0.2 ; - - fates_recruit_prescribed_rate = 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, - 0.02, 0.02, 0.02, 0.02, 0.02 ; - - fates_recruit_seed_alloc = 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, - 0.1, 0.1 ; - - fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, - 0.9 ; - - fates_recruit_seed_dbh_repro_threshold = 90, 80, 80, 80, 90, 80, 3, 3, 2, - 0.35, 0.35, 0.35 ; - - fates_recruit_seed_germination_rate = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - - fates_seed_dispersal_fraction = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_max_dist = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_pdf_scale = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_seed_dispersal_pdf_shape = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_stoich_nitr = - 0.033, 0.029, 0.04, 0.033, 0.04, 0.04, 0.033, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, 0.024, - 0.024, 0.024, - 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, 1e-08, - 1e-08, 1e-08, - 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, 0.0047, - 0.0047, 0.0047, 0.0047 ; - - fates_stoich_phos = - 0.0033, 0.0029, 0.004, 0.0033, 0.004, 0.004, 0.0033, 0.004, 0.004, 0.004, - 0.004, 0.004, - 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, 0.0024, - 0.0024, 0.0024, 0.0024, - 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, 1e-09, - 1e-09, 1e-09, - 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, 0.00047, - 0.00047, 0.00047, 0.00047, 0.00047 ; - - fates_trim_inc = 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, - 0.03, 0.03 ; - - fates_trim_limit = 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3, 0.3 ; - - fates_trs_repro_alloc_a = 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, - 0.0049, 0.0049, 0.0049, 0.0049, 0.0049, 0.0049 ; - - fates_trs_repro_alloc_b = -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, - -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171, -2.6171 ; - - fates_trs_repro_frac_seed = 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, 0.24, - 0.24, 0.24, 0.24, 0.24 ; - - fates_trs_seedling_a_emerg = 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, - 0.0003, 0.0003, 0.0003, 0.0003, 0.0003, 0.0003 ; - - fates_trs_seedling_b_emerg = 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, 1.2, - 1.2, 1.2, 1.2 ; - - fates_trs_seedling_background_mort = 0.1085371, 0.1085371, 0.1085371, - 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, 0.1085371, - 0.1085371, 0.1085371, 0.1085371 ; - - fates_trs_seedling_h2o_mort_a = 4.070565e-17, 4.070565e-17, 4.070565e-17, - 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17, - 4.070565e-17, 4.070565e-17, 4.070565e-17, 4.070565e-17 ; - - fates_trs_seedling_h2o_mort_b = -6.390757e-11, -6.390757e-11, -6.390757e-11, - -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, - -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11, -6.390757e-11 ; - - fates_trs_seedling_h2o_mort_c = 1.268992e-05, 1.268992e-05, 1.268992e-05, - 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05, - 1.268992e-05, 1.268992e-05, 1.268992e-05, 1.268992e-05 ; - - fates_trs_seedling_light_mort_a = -0.009897694, -0.009897694, -0.009897694, - -0.009897694, -0.009897694, -0.009897694, -0.009897694, -0.009897694, - -0.009897694, -0.009897694, -0.009897694, -0.009897694 ; - - fates_trs_seedling_light_mort_b = -7.154063, -7.154063, -7.154063, - -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, -7.154063, - -7.154063, -7.154063, -7.154063 ; - - fates_trs_seedling_light_rec_a = 0.007, 0.007, 0.007, 0.007, 0.007, 0.007, - 0.007, 0.007, 0.007, 0.007, 0.007, 0.007 ; - - fates_trs_seedling_light_rec_b = 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, - 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615, 0.8615 ; - - fates_trs_seedling_mdd_crit = 1400000, 1400000, 1400000, 1400000, 1400000, - 1400000, 1400000, 1400000, 1400000, 1400000, 1400000, 1400000 ; - - fates_trs_seedling_par_crit_germ = 0.656, 0.656, 0.656, 0.656, 0.656, 0.656, - 0.656, 0.656, 0.656, 0.656, 0.656, 0.656 ; - - fates_trs_seedling_psi_crit = -251995.7, -251995.7, -251995.7, -251995.7, - -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, -251995.7, - -251995.7, -251995.7 ; - - fates_trs_seedling_psi_emerg = -15744.65, -15744.65, -15744.65, -15744.65, - -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, -15744.65, - -15744.65, -15744.65 ; - - fates_trs_seedling_root_depth = 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, - 0.06, 0.06, 0.06, 0.06, 0.06 ; - - fates_turb_displar = 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, 0.67, - 0.67, 0.67, 0.67 ; - - fates_turb_leaf_diameter = 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, - 0.04, 0.04, 0.04, 0.04 ; - - fates_turb_z0mr = 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, 0.055, - 0.055, 0.055, 0.055, 0.055 ; - - fates_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - - fates_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_leaf = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_turnover_leaf_ustory = - 5, 8, 1, 3, 1, 1, 3, 1, 1, 1, 1, 1 ; - - fates_turnover_senleaf_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_wood_density = 0.7, 0.4, 0.7, 0.53, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, - 0.7 ; - - fates_woody = 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 ; - - fates_hlm_pft_map = - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 ; - - fates_fire_FBD = 15.4, 16.8, 19.6, 999, 4, 4 ; - - fates_fire_low_moisture_Coeff = 1.12, 1.09, 0.98, 0.8, 1.15, 1.15 ; - - fates_fire_low_moisture_Slope = 0.62, 0.72, 0.85, 0.8, 0.62, 0.62 ; - - fates_fire_mid_moisture = 0.72, 0.51, 0.38, 1, 0.8, 0.8 ; - - fates_fire_mid_moisture_Coeff = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_mid_moisture_Slope = 2.35, 1.47, 1.06, 0.8, 3.2, 3.2 ; - - fates_fire_min_moisture = 0.18, 0.12, 0, 0, 0.24, 0.24 ; - - fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - - fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - - fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; - - fates_canopy_closure_thresh = 0.8 ; - - fates_cnp_eca_plant_escalar = 1.25e-05 ; - - fates_cohort_age_fusion_tol = 0.08 ; - - fates_cohort_size_fusion_tol = 0.08 ; - - fates_comp_excln = 3 ; - - fates_damage_canopy_layer_code = 1 ; - - fates_damage_event_code = 1 ; - - fates_dev_arbitrary = _ ; - - fates_fire_active_crown_fire = 0 ; - - fates_fire_cg_strikes = 0.2 ; - - fates_fire_drying_ratio = 66000 ; - - fates_fire_durat_slope = -11.06 ; - - fates_fire_fdi_a = 17.62 ; - - fates_fire_fdi_alpha = 0.00037 ; - - fates_fire_fdi_b = 243.12 ; - - fates_fire_fuel_energy = 18000 ; - - fates_fire_max_durat = 240 ; - - fates_fire_miner_damp = 0.41739 ; - - fates_fire_miner_total = 0.055 ; - - fates_fire_nignitions = 15 ; - - fates_fire_part_dens = 513 ; - - fates_fire_threshold = 50 ; - - fates_frag_cwd_fcel = 0.76 ; - - fates_frag_cwd_flig = 0.24 ; - - fates_hydro_kmax_rsurf1 = 20 ; - - fates_hydro_kmax_rsurf2 = 0.0001 ; - - fates_hydro_psi0 = 0 ; - - fates_hydro_psicap = -0.6 ; - - fates_hydro_solver = 1 ; - - fates_landuse_logging_coll_under_frac = 0.55983 ; - - fates_landuse_logging_collateral_frac = 0.05 ; - - fates_landuse_logging_dbhmax = _ ; - - fates_landuse_logging_dbhmax_infra = 35 ; - - fates_landuse_logging_dbhmin = 50 ; - - fates_landuse_logging_direct_frac = 0.15 ; - - fates_landuse_logging_event_code = -30 ; - - fates_landuse_logging_export_frac = 0.8 ; - - fates_landuse_logging_mechanical_frac = 0.05 ; - - fates_landuse_pprodharv10_forest_mean = 0.8125 ; - - fates_leaf_photo_temp_acclim_thome_time = 30 ; - - fates_leaf_photo_temp_acclim_timescale = 30 ; - - fates_leaf_photo_tempsens_model = 1 ; - - fates_leaf_stomatal_assim_model = 1 ; - - fates_leaf_stomatal_model = 1 ; - - fates_leaf_theta_cj_c3 = 0.999 ; - - fates_leaf_theta_cj_c4 = 0.999 ; - - fates_maintresp_leaf_model = 1 ; - - fates_maintresp_nonleaf_baserate = 2.525e-06 ; - - fates_maxcohort = 100 ; - - fates_maxpatch_primary = 10 ; - - fates_maxpatch_secondary = 4 ; - - fates_mort_disturb_frac = 1 ; - - fates_mort_understorey_death = 0.55983 ; - - fates_patch_fusion_tol = 0.05 ; - - fates_phen_chilltemp = 5 ; - - fates_phen_coldtemp = 7.5 ; - - fates_phen_gddthresh_a = -68 ; - - fates_phen_gddthresh_b = 638 ; - - fates_phen_gddthresh_c = -0.01 ; - - fates_phen_mindayson = 90 ; - - fates_phen_ncolddayslim = 5 ; - - fates_q10_froz = 1.5 ; - - fates_q10_mr = 1.5 ; - - fates_rad_model = 1 ; - - fates_regeneration_model = 1 ; - - fates_soil_salinity = 0.4 ; - - fates_trs_seedling2sap_par_timescale = 32 ; - - fates_trs_seedling_emerg_h2o_timescale = 7 ; - - fates_trs_seedling_mdd_timescale = 126 ; - - fates_trs_seedling_mort_par_timescale = 32 ; - - fates_vai_top_bin_width = 1 ; - - fates_vai_width_increase_factor = 1 ; -} diff --git a/parameter_files/archive/api33_pr1136.xml b/parameter_files/archive/api33_pr1136.xml deleted file mode 100644 index e2df29e62a..0000000000 --- a/parameter_files/archive/api33_pr1136.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - archive/api33.0_fates_params_default.cdl - fates_params_default.cdl - 1,2,3,4,5,6,7,8,9,10,11,12 - - - - fates_turnover_leaf_ustory - fates_pft - years - understory leaf lifespan in years - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 - - - - fates_turnover_leaf_canopy - - - - diff --git a/parameter_files/archive/api36.0.0_params_default.cdl b/parameter_files/archive/api36.1.0_params_default.cdl similarity index 100% rename from parameter_files/archive/api36.0.0_params_default.cdl rename to parameter_files/archive/api36.1.0_params_default.cdl diff --git a/parameter_files/archive/api36.1.0_081324_patch_params.xml b/parameter_files/archive/api36.1.0_patch_params.xml similarity index 99% rename from parameter_files/archive/api36.1.0_081324_patch_params.xml rename to parameter_files/archive/api36.1.0_patch_params.xml index df0b5cb7e3..8d3e2c5ed0 100644 --- a/parameter_files/archive/api36.1.0_081324_patch_params.xml +++ b/parameter_files/archive/api36.1.0_patch_params.xml @@ -20,7 +20,7 @@ the variables --> - archive/api36.0.0_params_default.cdl + archive/api36.1.0_params_default.cdl fates_params_default.cdl 1,2,3,4,5,6,7,8,9,10,11,12