diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 9f0061f860..f195f59f0a 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -32,7 +32,6 @@ module EDCanopyStructureMod use FatesInterfaceTypesMod , only : numpft use FatesInterfaceTypesMod, only : bc_in_type use FatesPlantHydraulicsMod, only : UpdateH2OVeg,InitHydrCohort, RecruitWaterStorage - use EDTypesMod , only : maxCohortsPerPatch use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : leaf_organ @@ -56,6 +55,8 @@ module EDCanopyStructureMod public :: canopy_summarization public :: update_hlm_dynamics public :: UpdateFatesAvgSnowDepth + public :: UpdatePatchLAI + public :: UpdateCohortLAI logical, parameter :: debug=.false. @@ -1236,7 +1237,7 @@ subroutine canopy_spread( currentSite ) do while (associated(currentCohort)) call carea_allom(currentCohort%dbh,currentCohort%n, & currentSite%spread,currentCohort%pft,currentCohort%c_area) - if( ( int(prt_params%woody(currentCohort%pft)) .eq. itrue ) .and. & + if( ( prt_params%woody(currentCohort%pft) .eq. itrue ) .and. & (currentCohort%canopy_layer .eq. 1 ) ) then sitelevel_canopyarea = sitelevel_canopyarea + currentCohort%c_area endif @@ -1347,7 +1348,7 @@ subroutine canopy_summarization( nsites, sites, bc_in ) if(currentCohort%canopy_layer==1)then currentPatch%total_canopy_area = currentPatch%total_canopy_area + currentCohort%c_area - if( int(prt_params%woody(ft))==itrue)then + if( prt_params%woody(ft) == itrue)then currentPatch%total_tree_area = currentPatch%total_tree_area + currentCohort%c_area endif endif @@ -1503,7 +1504,6 @@ subroutine leaf_area_profile( currentSite ) real(r8) :: min_chite ! bottom of cohort canopy (m) real(r8) :: max_chite ! top of cohort canopy (m) real(r8) :: lai ! summed lai for checking m2 m-2 - real(r8) :: leaf_c ! leaf carbon [kg] !---------------------------------------------------------------------- @@ -1541,45 +1541,7 @@ subroutine leaf_area_profile( currentSite ) if (currentPatch%total_canopy_area > nearzero ) then - - currentCohort => currentPatch%tallest - do while(associated(currentCohort)) - - ft = currentCohort%pft - cl = currentCohort%canopy_layer - - ! Calculate LAI of layers above - ! Note that the canopy_layer_lai is also calculated in this loop - ! but since we go top down in terms of plant size, we should be okay - - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) - - currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & - currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - - if (hlm_use_sp .eq. ifalse) then - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai , & - currentCohort%vcmax25top,4) - end if - - currentCohort%lai = currentCohort%treelai *currentCohort%c_area/currentPatch%total_canopy_area - currentCohort%sai = currentCohort%treesai *currentCohort%c_area/currentPatch%total_canopy_area - - ! Number of actual vegetation layers in this cohort's crown - currentCohort%nv = count((currentCohort%treelai+currentCohort%treesai) .gt. dlower_vai(:)) + 1 - - currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV) - - patch_lai = patch_lai + currentCohort%lai - - currentPatch%canopy_layer_tlai(cl) = currentPatch%canopy_layer_tlai(cl) + currentCohort%lai - - currentCohort => currentCohort%shorter - - enddo !currentCohort + call UpdatePatchLAI(currentPatch, patch_lai) if(smooth_leaf_distribution == 1)then @@ -1604,19 +1566,19 @@ subroutine leaf_area_profile( currentSite ) currentCohort => currentPatch%shortest do while(associated(currentCohort)) ft = currentCohort%pft - min_chite = currentCohort%hite - currentCohort%hite * prt_params%crown(ft) + min_chite = currentCohort%hite - currentCohort%hite * prt_params%crown_depth_frac(ft) max_chite = currentCohort%hite do iv = 1,N_HITE_BINS frac_canopy(iv) = 0.0_r8 ! this layer is in the middle of the canopy if(max_chite > maxh(iv).and.min_chite < minh(iv))then - frac_canopy(iv)= min(1.0_r8,dh / (currentCohort%hite*prt_params%crown(ft))) + frac_canopy(iv)= min(1.0_r8,dh / (currentCohort%hite*prt_params%crown_depth_frac(ft) )) ! this is the layer with the bottom of the canopy in it. elseif(min_chite < maxh(iv).and.min_chite > minh(iv).and.max_chite > maxh(iv))then - frac_canopy(iv) = (maxh(iv) -min_chite ) / (currentCohort%hite*prt_params%crown(ft)) + frac_canopy(iv) = (maxh(iv) -min_chite ) / (currentCohort%hite*prt_params%crown_depth_frac(ft) ) ! this is the layer with the top of the canopy in it. elseif(max_chite > minh(iv).and.max_chite < maxh(iv).and.min_chite < minh(iv))then - frac_canopy(iv) = (max_chite - minh(iv)) / (currentCohort%hite*prt_params%crown(ft)) + frac_canopy(iv) = (max_chite - minh(iv)) / (currentCohort%hite*prt_params%crown_depth_frac(ft)) elseif(max_chite < maxh(iv).and.min_chite > minh(iv))then !the whole cohort is within this layer. frac_canopy(iv) = 1.0_r8 endif @@ -1712,11 +1674,11 @@ subroutine leaf_area_profile( currentSite ) layer_top_hite = currentCohort%hite - & ( real(iv-1,r8)/currentCohort%NV * currentCohort%hite * & - prt_params%crown(currentCohort%pft) ) + prt_params%crown_depth_frac(currentCohort%pft) ) layer_bottom_hite = currentCohort%hite - & ( real(iv,r8)/currentCohort%NV * currentCohort%hite * & - prt_params%crown(currentCohort%pft) ) + prt_params%crown_depth_frac(currentCohort%pft) ) fraction_exposed = 1.0_r8 if(currentSite%snow_depth > layer_top_hite)then @@ -1892,7 +1854,7 @@ end subroutine leaf_area_profile ! ====================================================================================== - subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_in,bc_out) + subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) ! ---------------------------------------------------------------------------------- ! The purpose of this routine is to package output boundary conditions related @@ -1901,14 +1863,13 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_in,bc_out) use EDTypesMod , only : ed_patch_type, ed_cohort_type, & ed_site_type, AREA - use FatesInterfaceTypesMod , only : bc_in_type, bc_out_type + use FatesInterfaceTypesMod , only : bc_out_type ! ! !ARGUMENTS integer, intent(in) :: nsites type(ed_site_type), intent(inout), target :: sites(nsites) integer, intent(in) :: fcolumn(nsites) - type(bc_in_type), intent(in) :: bc_in(nsites) type(bc_out_type), intent(inout) :: bc_out(nsites) ! Locals @@ -1940,7 +1901,10 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_in,bc_out) ifp = ifp+1 if ( currentPatch%total_canopy_area-currentPatch%area > 0.000001_r8 ) then - write(fates_log(),*) 'ED: canopy area bigger than area',currentPatch%total_canopy_area ,currentPatch%area + if(debug)then + write(fates_log(),*) 'ED: canopy area bigger than area', & + currentPatch%total_canopy_area ,currentPatch%area + end if currentPatch%total_canopy_area = currentPatch%area endif @@ -1977,21 +1941,6 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_in,bc_out) currentCohort => currentPatch%shortest do while(associated(currentCohort)) - if (hlm_use_sp.eq.ifalse) then - ! make sure that allometries are correct - call carea_allom(currentCohort%dbh,currentCohort%n,sites(s)%spread,& - currentCohort%pft,currentCohort%c_area) - - currentCohort%treelai = tree_lai(currentCohort%prt%GetState(leaf_organ, all_carbon_elements), & - currentCohort%pft, currentCohort%c_area, currentCohort%n, & - currentCohort%canopy_layer, currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) - - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai , & - currentCohort%vcmax25top,4) - endif - total_patch_leaf_stem_area = total_patch_leaf_stem_area + & (currentCohort%treelai + currentCohort%treesai) * currentCohort%c_area currentCohort => currentCohort%taller @@ -2214,8 +2163,8 @@ subroutine CanopyLayerArea(currentPatch,site_spread,layer_index,layer_area) real(r8),intent(inout) :: layer_area type(ed_cohort_type), pointer :: currentCohort - - + + layer_area = 0.0_r8 currentCohort => currentPatch%tallest do while (associated(currentCohort)) @@ -2227,8 +2176,102 @@ subroutine CanopyLayerArea(currentPatch,site_spread,layer_index,layer_area) currentCohort => currentCohort%shorter enddo return - end subroutine CanopyLayerArea + end subroutine CanopyLayerArea + + ! =============================================================================================== + subroutine UpdatePatchLAI(currentPatch, patch_lai) + + ! -------------------------------------------------------------------------------------------- + ! This subroutine works through the current patch cohorts and updates the canopy_layer_tlai + ! and related variables + ! --------------------------------------------------------------------------------------------- + + ! Uses + use EDtypesMod, only : dlower_vai + + ! Arguments + type(ed_patch_type),intent(inout), target :: currentPatch + real(r8), intent(inout) :: patch_lai + + ! Local Variables + type(ed_cohort_type), pointer :: currentCohort + integer :: cl ! Canopy layer index + integer :: ft ! Plant functional type index + + ! 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. + + 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 + + ! Update the cohort level lai and related variables + call UpdateCohortLAI(currentCohort,currentPatch%canopy_layer_tlai,currentPatch%total_canopy_area) + + ! Update the number of number of vegetation layers + currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV) + + ! Update the patch canopy layer tlai + currentPatch%canopy_layer_tlai(cl) = currentPatch%canopy_layer_tlai(cl) + currentCohort%lai + + ! Calculate the total patch lai + patch_lai = patch_lai + currentCohort%lai + end if + currentCohort => currentCohort%shorter + + end do cohortloop + end do canopyloop + + end subroutine UpdatePatchLAI + ! =============================================================================================== + + subroutine UpdateCohortLAI(currentCohort, canopy_layer_tlai, patcharea) + + ! Update LAI and related variables for a given cohort + + ! Uses + use EDtypesMod, only : dlower_vai + + ! Arguments + type(ed_cohort_type),intent(inout), target :: currentCohort + real(r8), intent(in) :: canopy_layer_tlai(nclmax) ! total leaf area index of each canopy layer + real(r8), intent(in) :: patcharea ! either patch%total_canopy_area or patch%area + + ! Local variables + real(r8) :: leaf_c ! leaf carbon [kg] + + ! Obtain the leaf carbon + leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) + + ! Note that tree_lai has an internal check on the canopy locatoin + currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, & + currentCohort%n, currentCohort%canopy_layer, & + canopy_layer_tlai,currentCohort%vcmax25top ) + + if (hlm_use_sp .eq. ifalse) then + currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & + currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & + canopy_layer_tlai, currentCohort%treelai , & + currentCohort%vcmax25top,4) + end if + + ! Update the cohort lai and sai + currentCohort%lai = currentCohort%treelai *currentCohort%c_area/patcharea + currentCohort%sai = currentCohort%treesai *currentCohort%c_area/patcharea + + ! Number of actual vegetation layers in this cohort's crown + currentCohort%nv = count((currentCohort%treelai+currentCohort%treesai) .gt. dlower_vai(:)) + 1 + + end subroutine UpdateCohortLAI + ! =============================================================================================== function NumPotentialCanopyLayers(currentPatch,site_spread,include_substory) result(z) @@ -2275,7 +2318,9 @@ function NumPotentialCanopyLayers(currentPatch,site_spread,include_substory) res if(arealayer > currentPatch%area)then z = z + 1 if(hlm_use_sp.eq.itrue)then - write(fates_log(),*) 'SPmode, canopy_layer full:',arealayer,currentPatch%area + if(debug)then + write(fates_log(),*) 'SPmode, canopy_layer full:',arealayer,currentPatch%area + end if end if endif diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 4318ee469f..ab06f828e7 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -32,7 +32,7 @@ module EDCohortDynamicsMod use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use FatesLitterMod , only : litter_type - use EDTypesMod , only : maxCohortsPerPatch + use EDParamsMod , only : max_cohort_per_patch use EDTypesMod , only : AREA use EDTypesMod , only : min_npm2, min_nppatch use EDTypesMod , only : min_n_safemath @@ -147,7 +147,7 @@ module EDCohortDynamicsMod subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & - prt, laimemory, sapwmemory, structmemory, & + prt, leafmemory, sapwmemory, structmemory, & status, recruitstatus,ctrim, carea, clayer, spread, bc_in) ! ! !DESCRIPTION: @@ -181,7 +181,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & real(r8), intent(in) :: dbh ! dbh: cm class(prt_vartypes),target :: prt ! The allocated PARTEH ! object - real(r8), intent(in) :: laimemory ! target leaf biomass- set from + real(r8), intent(in) :: leafmemory ! target leaf biomass- set from ! previous year: kGC per indiv real(r8), intent(in) :: sapwmemory ! target sapwood biomass- set from ! previous year: kGC per indiv @@ -237,7 +237,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, coage, dbh, & new_cohort%canopy_trim = ctrim new_cohort%canopy_layer = clayer new_cohort%canopy_layer_yesterday = real(clayer, r8) - new_cohort%laimemory = laimemory + new_cohort%leafmemory = leafmemory new_cohort%sapwmemory = sapwmemory new_cohort%structmemory = structmemory @@ -541,7 +541,7 @@ subroutine nan_cohort(cc_p) currentCohort%dbh = nan ! 'diameter at breast height' in cm currentCohort%coage = nan ! age of the cohort in years currentCohort%hite = nan ! height: meters - currentCohort%laimemory = nan ! target leaf biomass- set from previous year: kGC per indiv + currentCohort%leafmemory = nan ! target leaf biomass- set from previous year: kGC per indiv currentCohort%sapwmemory = nan ! target sapwood biomass- set from previous year: kGC per indiv currentCohort%structmemory = nan ! target structural biomass- set from previous year: kGC per indiv currentCohort%lai = nan ! leaf area index of cohort m2/m2 @@ -765,7 +765,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ if (currentcohort%n < min_n_safemath .and. level == 1) then terminate = itrue if ( debug ) then - write(fates_log(),*) 'terminating cohorts 0',currentCohort%n/currentPatch%area,currentCohort%dbh,call_index + write(fates_log(),*) 'terminating cohorts 0',currentCohort%n/currentPatch%area,currentCohort%dbh,currentCohort%pft,call_index endif endif @@ -778,7 +778,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ (currentCohort%dbh < 0.00001_r8 .and. store_c < 0._r8) ) then terminate = itrue if ( debug ) then - write(fates_log(),*) 'terminating cohorts 1',currentCohort%n/currentPatch%area,currentCohort%dbh,call_index + write(fates_log(),*) 'terminating cohorts 1',currentCohort%n/currentPatch%area,currentCohort%dbh,currentCohort%pft,call_index endif endif @@ -786,7 +786,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ if (currentCohort%canopy_layer > nclmax ) then terminate = itrue if ( debug ) then - write(fates_log(),*) 'terminating cohorts 2', currentCohort%canopy_layer,call_index + write(fates_log(),*) 'terminating cohorts 2', currentCohort%canopy_layer,currentCohort%pft,call_index endif endif @@ -796,7 +796,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ terminate = itrue if ( debug ) then write(fates_log(),*) 'terminating cohorts 3', & - sapw_c,leaf_c,fnrt_c,store_c,call_index + sapw_c,leaf_c,fnrt_c,store_c,currentCohort%pft,call_index endif endif @@ -805,7 +805,7 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_ terminate = itrue if ( debug ) then write(fates_log(),*) 'terminating cohorts 4', & - struct_c,sapw_c,leaf_c,fnrt_c,store_c,call_index + struct_c,sapw_c,leaf_c,fnrt_c,store_c,currentCohort%pft,call_index endif endif @@ -868,13 +868,13 @@ subroutine terminate_cohort(currentSite, currentPatch, currentCohort, bc_in) currentSite%term_nindivs_canopy(currentCohort%size_class,currentCohort%pft) = & currentSite%term_nindivs_canopy(currentCohort%size_class,currentCohort%pft) + currentCohort%n - currentSite%term_carbonflux_canopy = currentSite%term_carbonflux_canopy + & + currentSite%term_carbonflux_canopy(currentCohort%pft) = currentSite%term_carbonflux_canopy(currentCohort%pft) + & currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) else currentSite%term_nindivs_ustory(currentCohort%size_class,currentCohort%pft) = & currentSite%term_nindivs_ustory(currentCohort%size_class,currentCohort%pft) + currentCohort%n - currentSite%term_carbonflux_ustory = currentSite%term_carbonflux_ustory + & + currentSite%term_carbonflux_ustory(currentCohort%pft) = currentSite%term_carbonflux_ustory(currentCohort%pft) + & currentCohort%n * (struct_c+sapw_c+leaf_c+fnrt_c+store_c+repro_c) end if @@ -1072,7 +1072,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) use FatesInterfaceTypesMod , only : hlm_use_cohort_age_tracking use FatesConstantsMod , only : itrue use FatesConstantsMod, only : days_per_year - use EDTypesMod , only : maxCohortsPerPatch ! ! !ARGUMENTS @@ -1196,7 +1195,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) write(fates_log(),*) 'Cohort I, Cohort II' write(fates_log(),*) 'n:',currentCohort%n,nextc%n write(fates_log(),*) 'isnew:',currentCohort%isnew,nextc%isnew - write(fates_log(),*) 'laimemory:',currentCohort%laimemory,nextc%laimemory + write(fates_log(),*) 'leafmemory:',currentCohort%leafmemory,nextc%leafmemory write(fates_log(),*) 'hite:',currentCohort%hite,nextc%hite write(fates_log(),*) 'coage:',currentCohort%coage,nextc%coage write(fates_log(),*) 'dbh:',currentCohort%dbh,nextc%dbh @@ -1234,8 +1233,8 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! ----------------------------------------------------------------- call UpdateCohortBioPhysRates(currentCohort) - currentCohort%laimemory = (currentCohort%n*currentCohort%laimemory & - + nextc%n*nextc%laimemory)/newn + currentCohort%leafmemory = (currentCohort%n*currentCohort%leafmemory & + + nextc%n*nextc%leafmemory)/newn currentCohort%sapwmemory = (currentCohort%n*currentCohort%sapwmemory & + nextc%n*nextc%sapwmemory)/newn @@ -1353,20 +1352,9 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call endrun(msg=errMsg(sourcefile, __LINE__)) end select - leaf_c = currentCohort%prt%GetState(leaf_organ,all_carbon_elements) - - currentCohort%treelai = tree_lai(leaf_c, currentCohort%pft, currentCohort%c_area, newn, & - currentCohort%canopy_layer, currentPatch%canopy_layer_tlai, & - currentCohort%vcmax25top) - - currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & - currentCohort%c_area, newn, currentCohort%canopy_layer, & - currentPatch%canopy_layer_tlai, currentCohort%treelai,currentCohort%vcmax25top,1 ) - call sizetype_class_index(currentCohort%dbh,currentCohort%pft, & currentCohort%size_class,currentCohort%size_by_pft_class) - if(hlm_use_planthydro.eq.itrue) then call FuseCohortHydraulics(currentSite,currentCohort,nextc,bc_in,newn) endif @@ -1532,13 +1520,6 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) ! update hydraulics quantities that are functions of hite & biomasses ! deallocate the hydro structure of nextc if (hlm_use_planthydro.eq.itrue) then - call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) - leaf_c = currentCohort%prt%GetState(leaf_organ, carbon12_element) - currentCohort%treelai = tree_lai(leaf_c, & - currentCohort%pft, currentCohort%c_area, currentCohort%n, & - currentCohort%canopy_layer, currentPatch%canopy_layer_tlai, & - currentCohort%vcmax25top ) call UpdateSizeDepPlantHydProps(currentSite,currentCohort, bc_in) endif @@ -1583,14 +1564,13 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) if ( hlm_use_cohort_age_tracking .eq.itrue) then - if ( nocohorts > maxCohortsPerPatch ) then + if ( nocohorts > max_cohort_per_patch ) then iterate = 1 !---------------------------------------------------------------------! ! Making profile tolerance larger means that more fusion will happen ! !---------------------------------------------------------------------! dynamic_size_fusion_tolerance = dynamic_size_fusion_tolerance * 1.1_r8 dynamic_age_fusion_tolerance = dynamic_age_fusion_tolerance * 1.1_r8 - !write(fates_log(),*) 'maxcohorts exceeded',dynamic_fusion_tolerance else @@ -1599,13 +1579,12 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) else - if (nocohorts > maxCohortsPerPatch) then + if (nocohorts > max_cohort_per_patch) then iterate = 1 !---------------------------------------------------------------------! ! Making profile tolerance larger means that more fusion will happen ! !---------------------------------------------------------------------! dynamic_size_fusion_tolerance = dynamic_size_fusion_tolerance * 1.1_r8 - !write(fates_log(),*) 'maxcohorts exceeded',dynamic_fusion_tolerance else @@ -1828,7 +1807,7 @@ subroutine copy_cohort( currentCohort,copyc ) n%dbh = o%dbh n%coage = o%coage n%hite = o%hite - n%laimemory = o%laimemory + n%leafmemory = o%leafmemory n%sapwmemory = o%sapwmemory n%structmemory = o%structmemory n%lai = o%lai @@ -1989,10 +1968,13 @@ subroutine count_cohorts( currentPatch ) currentCohort => currentCohort%shorter enddo - if (backcount /= currentPatch%countcohorts) then - write(fates_log(),*) 'problem with linked list, not symmetrical' - endif - + if(debug) then + if (backcount /= currentPatch%countcohorts) then + write(fates_log(),*) 'problem with linked list, not symmetrical' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + end if + end subroutine count_cohorts ! =================================================================================== @@ -2107,7 +2089,7 @@ subroutine EvaluateAndCorrectDBH(currentCohort,delta_dbh,delta_hite) delta_dbh = 0._r8 delta_hite = 0._r8 - if( int(prt_params%woody(currentCohort%pft)) == itrue) then + if( prt_params%woody(currentCohort%pft) == itrue) then struct_c = currentCohort%prt%GetState(struct_organ, all_carbon_elements) diff --git a/biogeochem/EDLoggingMortalityMod.F90 b/biogeochem/EDLoggingMortalityMod.F90 index 0f1129282f..ca3ba26f03 100644 --- a/biogeochem/EDLoggingMortalityMod.F90 +++ b/biogeochem/EDLoggingMortalityMod.F90 @@ -74,7 +74,8 @@ module EDLoggingMortalityMod logical, protected :: logging_time ! If true, logging should be ! performed during the current time-step - + logical, parameter :: debug = .false. + ! harvest litter localization specifies how much of the litter from a falling ! tree lands within the newly generated patch, and how much lands outside of ! the new patch, and thus in the original patch. By setting this to zero, @@ -278,7 +279,7 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & ! 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(int(prt_params%woody(pft_i)) == 1)then ! only set logging rates for trees + if(prt_params%woody(pft_i) == itrue)then ! only set logging rates for trees ! direct logging rates, based on dbh min and max criteria if (dbh >= logging_dbhmin .and. .not. & @@ -562,7 +563,7 @@ subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site ! plants that were impacted. Thus, no direct dead can occur ! here, and indirect are impacts. - if(int(prt_params%woody(pft)) == itrue) then + if(prt_params%woody(pft) == itrue) then direct_dead = 0.0_r8 indirect_dead = logging_coll_under_frac * & (1._r8-currentPatch%fract_ldist_not_harvested) * currentCohort%n * & diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index e4a0b3c138..605c377508 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -6,6 +6,8 @@ module EDMortalityFunctionsMod use FatesConstantsMod , only : r8 => fates_r8 use FatesGlobals , only : fates_log + use FatesGlobals , only : endrun => fates_endrun + use FatesGlobals , only : fates_log use EDPftvarcon , only : EDPftvarcon_inst use EDTypesMod , only : ed_cohort_type use EDTypesMod , only : ed_site_type @@ -22,10 +24,15 @@ module EDMortalityFunctionsMod use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : store_organ - + use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private + + logical, parameter :: debug = .false. + character(len=*), parameter, private :: sourcefile = & + __FILE__ public :: mortality_rates public :: Mortality_Derivative @@ -163,6 +170,7 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmor else write(fates_log(),*) 'dbh problem in mortality_rates', & cohort_in%dbh,cohort_in%pft,cohort_in%n,cohort_in%canopy_layer + call endrun(msg=errMsg(sourcefile, __LINE__)) endif !-------------------------------------------------------------------------------- ! Mortality due to cold and freezing stress (frmort), based on ED2 and: diff --git a/biogeochem/EDPatchDynamicsMod.F90 b/biogeochem/EDPatchDynamicsMod.F90 index 9ebdb9132b..56d9cc3b5a 100644 --- a/biogeochem/EDPatchDynamicsMod.F90 +++ b/biogeochem/EDPatchDynamicsMod.F90 @@ -3,7 +3,8 @@ module EDPatchDynamicsMod ! ============================================================================ ! Controls formation, creation, fusing and termination of patch level processes. ! ============================================================================ - use FatesGlobals , only : fates_log + use FatesGlobals , only : fates_log + use FatesGlobals , only : FatesWarn,N2S,A2S use FatesInterfaceTypesMod , only : hlm_freq_day use EDPftvarcon , only : EDPftvarcon_inst use EDPftvarcon , only : GetDecompyFrac @@ -18,8 +19,6 @@ module EDPatchDynamicsMod use EDTypesMod , only : homogenize_seed_pfts use EDTypesMod , only : n_dbh_bins, area, patchfusion_dbhbin_loweredges use EDtypesMod , only : force_patchfuse_min_biomass - use EDTypesMod , only : maxPatchesPerSite - use EDTypesMod , only : maxPatchesPerSite_by_disttype use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type use EDTypesMod , only : site_massbal_type use EDTypesMod , only : site_fluxdiags_type @@ -89,6 +88,9 @@ module EDPatchDynamicsMod use SFParamsMod, only : SF_VAL_CWD_FRAC use EDParamsMod, only : logging_event_code use EDParamsMod, only : logging_export_frac + use EDParamsMod, only : maxpatch_primary + use EDParamsMod, only : maxpatch_secondary + use EDParamsMod, only : maxpatch_total use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa ! CIME globals @@ -135,7 +137,8 @@ module EDPatchDynamicsMod real(r8), parameter :: treefall_localization = 0.0_r8 real(r8), parameter :: burn_localization = 0.0_r8 - + character(len=512) :: msg ! Message string for warnings and logging + ! 10/30/09: Created by Rosie Fisher ! ============================================================================ @@ -324,15 +327,14 @@ subroutine disturbance_rates( site_in, bc_in) end do ! Fires can't burn the whole patch, as this causes /0 errors. - if (debug) then - if (currentPatch%disturbance_rates(dtype_ifire) > 0.98_r8)then - write(fates_log(),*) 'very high fire areas', & - currentPatch%disturbance_rates(dtype_ifire),currentPatch%frac_burnt - endif + if (currentPatch%disturbance_rates(dtype_ifire) > 0.98_r8)then + msg = 'very high fire areas'//trim(A2S(currentPatch%disturbance_rates(:)))//trim(N2S(currentPatch%frac_burnt)) + call FatesWarn(msg,index=2) endif + ! ------------------------------------------------------------------------------------------ ! Determine which disturbance is dominant, and force mortality diagnostics in the upper ! canopy to be zero for the non-dominant mode. Note: upper-canopy tree-fall mortality is @@ -765,7 +767,7 @@ subroutine spawn_patches( currentSite, bc_in) else ! small trees - if( int(prt_params%woody(currentCohort%pft)) == itrue)then + if( prt_params%woody(currentCohort%pft) == itrue)then ! Survivorship of undestory woody plants. Two step process. @@ -789,7 +791,8 @@ subroutine spawn_patches( currentSite, bc_in) nc%n * ED_val_understorey_death / hlm_freq_day - currentSite%imort_carbonflux = currentSite%imort_carbonflux + & + currentSite%imort_carbonflux(currentCohort%pft) = & + currentSite%imort_carbonflux(currentCohort%pft) + & (nc%n * ED_val_understorey_death / hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 @@ -865,7 +868,8 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%fmort_rate_canopy(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%fire_mort / hlm_freq_day - currentSite%fmort_carbonflux_canopy = currentSite%fmort_carbonflux_canopy + & + currentSite%fmort_carbonflux_canopy(currentCohort%pft) = & + currentSite%fmort_carbonflux_canopy(currentCohort%pft) + & (nc%n * currentCohort%fire_mort) * & total_c * g_per_kg * days_per_sec * ha_per_m2 @@ -874,7 +878,8 @@ subroutine spawn_patches( currentSite, bc_in) currentSite%fmort_rate_ustory(currentCohort%size_class, currentCohort%pft) + & nc%n * currentCohort%fire_mort / hlm_freq_day - currentSite%fmort_carbonflux_ustory = currentSite%fmort_carbonflux_ustory + & + currentSite%fmort_carbonflux_ustory(currentCohort%pft) = & + currentSite%fmort_carbonflux_ustory(currentCohort%pft) + & (nc%n * currentCohort%fire_mort) * & total_c * g_per_kg * days_per_sec * ha_per_m2 end if @@ -905,7 +910,7 @@ subroutine spawn_patches( currentSite, bc_in) ! burned off. Here, we remove that mass, and ! tally it in the flux we sent to the atmosphere - if(int(prt_params%woody(currentCohort%pft)) == itrue)then + if(prt_params%woody(currentCohort%pft) == itrue)then leaf_burn_frac = currentCohort%fraction_crown_burned else @@ -983,7 +988,7 @@ subroutine spawn_patches( currentSite, bc_in) ! WHat to do with cohorts in the understory of a logging generated ! disturbance patch? - if(int(prt_params%woody(currentCohort%pft)) == itrue)then + if(prt_params%woody(currentCohort%pft) == itrue)then ! Survivorship of undestory woody plants. Two step process. @@ -1006,7 +1011,8 @@ subroutine spawn_patches( currentSite, bc_in) nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac / hlm_freq_day - currentSite%imort_carbonflux = currentSite%imort_carbonflux + & + currentSite%imort_carbonflux(currentCohort%pft) = & + currentSite%imort_carbonflux(currentCohort%pft) + & (nc%n * currentPatch%fract_ldist_not_harvested * & logging_coll_under_frac/ hlm_freq_day ) * & total_c * g_per_kg * days_per_sec * years_per_day * ha_per_m2 @@ -1893,7 +1899,7 @@ subroutine mortality_litter_fluxes(currentSite, currentPatch, & num_dead = currentCohort%n * min(1.0_r8,currentCohort%dmort * & hlm_freq_day * fates_mortality_disturbance_fraction) - elseif(int(prt_params%woody(pft)) == itrue) then + elseif(prt_params%woody(pft) == itrue) then ! Understorey trees. The total dead is based on their survivorship ! function, and the total area of disturbance. @@ -2302,15 +2308,16 @@ subroutine fuse_patches( csite, bc_in ) ! to let there be one for each type of nocomp PFT on the site. this is likely to lead to problems ! if anthropogenic disturance is enabled. if (hlm_use_nocomp.eq.itrue) then - maxpatches(primaryforest) = max(maxPatchesPerSite_by_disttype(primaryforest), sum(csite%use_this_pft)) - maxpatches(secondaryforest) = maxPatchesPerSite - maxpatches(primaryforest) - if (maxPatchesPerSite .lt. maxpatches(primaryforest)) then + maxpatches(primaryforest) = max(maxpatch_primary, sum(csite%use_this_pft)) + maxpatches(secondaryforest) = maxpatch_total - maxpatches(primaryforest) + if (maxpatch_total .lt. maxpatches(primaryforest)) then write(fates_log(),*) 'too many PFTs and not enough patches for nocomp w/o fixed biogeog' - write(fates_log(),*) 'maxPatchesPerSite,numpft',maxPatchesPerSite,numpft, sum(csite%use_this_pft) + write(fates_log(),*) 'maxpatch_total,numpft',maxpatch_total,numpft, sum(csite%use_this_pft) call endrun(msg=errMsg(sourcefile, __LINE__)) endif else - maxpatches(:) = maxPatchesPerSite_by_disttype(:) + maxpatches(primaryforest) = maxpatch_primary + maxpatches(secondaryforest) = maxpatch_secondary endif currentPatch => currentSite%youngest_patch @@ -2346,7 +2353,7 @@ subroutine fuse_patches( csite, bc_in ) iterate = 1 !---------------------------------------------------------------------! - ! Keep doing this until nopatches <= maxPatchesPerSite ! + ! Keep doing this until nopatches <= maxpatch_total ! !---------------------------------------------------------------------! iterate_eq_1_loop: do while(iterate == 1) @@ -2375,7 +2382,8 @@ subroutine fuse_patches( csite, bc_in ) tpp_loop: do while(associated(tpp)) if(.not.associated(currentPatch))then - write(fates_log(),*) 'ED: issue with currentPatch' + write(fates_log(),*) 'FATES fuse_patches(): currentPatch is not associated?' + call endrun(msg=errMsg(sourcefile, __LINE__)) endif both_associated_if: if(associated(tpp).and.associated(currentPatch))then @@ -2487,19 +2495,20 @@ subroutine fuse_patches( csite, bc_in ) ! a patch x patch loop, reset the patch fusion tolerance to the starting ! ! value so that any subsequent fusions in this loop are done with that ! ! value. otherwise we can end up in a situation where we've loosened the ! - ! fusion tolerance to get nopatches <= maxPatchesPerSite, but then, ! + ! fusion tolerance to get nopatches <= maxpatch_total, but then, ! ! having accomplished that, we continue through all the patch x patch ! ! combinations and then all the patches get fused, ending up with ! - ! nopatches << maxPatchesPerSite and losing all heterogeneity. ! + ! nopatches << maxpatch_total and losing all heterogeneity. ! !------------------------------------------------------------------------! profiletol = ED_val_patch_fusion_tol - + endif fuseflagset_if endif different_patches_if endif nocomp_pft_labels_match_if endif anthro_dist_labels_match_if endif both_associated_if + tpp => tpp%older enddo tpp_loop @@ -2548,7 +2557,7 @@ subroutine fuse_patches( csite, bc_in ) iterate = 0 endif - enddo iterate_eq_1_loop ! iterate .eq. 1 ==> nopatches>maxPatchesPerSite + enddo iterate_eq_1_loop ! iterate .eq. 1 ==> nopatches>maxpatch_total end do disttype_loop diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 5d66f56d39..9a43af3226 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -425,8 +425,8 @@ subroutine trim_canopy( currentSite ) real(r8) :: initial_trim ! Initial trim real(r8) :: optimum_trim ! Optimum trim value - real(r8) :: initial_laimem ! Initial laimemory - real(r8) :: optimum_laimem ! Optimum laimemory + real(r8) :: initial_leafmem ! Initial leafmemory + real(r8) :: optimum_leafmem ! Optimum leafmemory !---------------------------------------------------------------------- @@ -446,15 +446,15 @@ subroutine trim_canopy( currentSite ) currentCohort => currentPatch%tallest do while (associated(currentCohort)) - ! Save off the incoming trim and laimemory + ! Save off the incoming trim and leafmemory initial_trim = currentCohort%canopy_trim - initial_laimem = currentCohort%laimemory + initial_leafmem = currentCohort%leafmemory ! Add debug diagnstic output to determine which cohort if (debug) then write(fates_log(),*) 'Current cohort:', icohort write(fates_log(),*) 'Starting canopy trim:', initial_trim - write(fates_log(),*) 'Starting laimemory:', currentCohort%laimemory + write(fates_log(),*) 'Starting leafmemory:', currentCohort%leafmemory endif trimmed = .false. @@ -467,6 +467,7 @@ subroutine trim_canopy( currentSite ) currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai,currentCohort%vcmax25top ) + ! We don't need check on sp mode here since we don't trim_canopy with sp mode currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, & currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, & currentPatch%canopy_layer_tlai, currentCohort%treelai, & @@ -591,17 +592,12 @@ subroutine trim_canopy( currentSite ) ! Make sure the cohort trim fraction is great than the pft trim limit if (currentCohort%canopy_trim > EDPftvarcon_inst%trim_limit(ipft)) then - ! if ( debug ) then - ! write(fates_log(),*) 'trimming leaves', & - ! currentCohort%canopy_trim,currentCohort%leaf_cost - ! endif - ! keep trimming until none of the canopy is in negative carbon balance. if (currentCohort%hite > EDPftvarcon_inst%hgt_min(ipft)) then currentCohort%canopy_trim = currentCohort%canopy_trim - & EDPftvarcon_inst%trim_inc(ipft) if (prt_params%evergreen(ipft) /= 1)then - currentCohort%laimemory = currentCohort%laimemory * & + currentCohort%leafmemory = currentCohort%leafmemory * & (1.0_r8 - EDPftvarcon_inst%trim_inc(ipft)) endif @@ -621,10 +617,6 @@ subroutine trim_canopy( currentSite ) call dgels(trans, m, n, nrhs, nnu_clai_a, lda, nnu_clai_b, ldb, work, lwork, info) lwork = int(work(1)) ! Pick the optimum. TBD, can work(1) come back with greater than work size? - ! if (debug) then - ! write(fates_log(),*) 'LLSF lwork output (info, lwork):', info, lwork - ! endif - ! Compute the minimum of 2-norm of of the least squares fit to solve for X ! Note that dgels returns the solution by overwriting the nnu_clai_b array. ! The result has the form: X = [b; m] @@ -649,15 +641,15 @@ subroutine trim_canopy( currentSite ) ! optimum_trim = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_trim - optimum_laimem = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_laimem + optimum_leafmem = (nnu_clai_b(1,1) / cumulative_lai_cohort) * initial_leafmem ! Determine if the optimum trim value makes sense. The smallest cohorts tend to have unrealistic fits. if (optimum_trim > 0. .and. optimum_trim < 1.) then currentCohort%canopy_trim = optimum_trim - ! If the cohort pft is not evergreen we reduce the laimemory as well + ! If the cohort pft is not evergreen we reduce the leafmemory as well if (prt_params%evergreen(ipft) /= 1) then - currentCohort%laimemory = optimum_laimem + currentCohort%leafmemory = optimum_leafmem endif trimmed = .true. @@ -700,7 +692,6 @@ subroutine phenology( currentSite, bc_in ) use EDParamsMod, only : ED_val_phen_a, ED_val_phen_b, ED_val_phen_c, ED_val_phen_chiltemp use EDParamsMod, only : ED_val_phen_mindayson, ED_val_phen_ncolddayslim, ED_val_phen_coldtemp - ! ! !ARGUMENTS: type(ed_site_type), intent(inout), target :: currentSite @@ -1123,14 +1114,14 @@ subroutine phenology_leafonoff(currentSite) ! stop flow of carbon out of bstore. if(store_c>nearzero) then - ! flush either the amount required from the laimemory, or -most- of the storage pool + ! flush either the amount required from the leafmemory, or -most- of the storage pool ! RF: added a criterion to stop the entire store pool emptying and triggering termination mortality ! n.b. this might not be necessary if we adopted a more gradual approach to leaf flushing... store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & - currentCohort%laimemory)/store_c,(1.0_r8-carbon_store_buffer)) + currentCohort%leafmemory)/store_c,(1.0_r8-carbon_store_buffer)) if(prt_params%woody(ipft).ne.itrue)then - totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory + totalmemory=currentCohort%leafmemory+currentCohort%sapwmemory+currentCohort%structmemory store_c_transfer_frac = min((EDPftvarcon_inst%phenflush_fraction(ipft)* & totalmemory)/store_c, (1.0_r8-carbon_store_buffer)) endif @@ -1144,7 +1135,7 @@ subroutine phenology_leafonoff(currentSite) if(prt_params%woody(ipft) == itrue) then call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, store_c_transfer_frac) - currentCohort%laimemory = 0.0_r8 + currentCohort%leafmemory = 0.0_r8 else @@ -1152,7 +1143,7 @@ subroutine phenology_leafonoff(currentSite) if (stem_drop_fraction .gt. 0.0_r8) then call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%laimemory/totalmemory) + store_c_transfer_frac*currentCohort%leafmemory/totalmemory) call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) @@ -1167,7 +1158,7 @@ subroutine phenology_leafonoff(currentSite) end if - currentCohort%laimemory = 0.0_r8 + currentCohort%leafmemory = 0.0_r8 currentCohort%structmemory = 0.0_r8 currentCohort%sapwmemory = 0.0_r8 @@ -1188,10 +1179,10 @@ subroutine phenology_leafonoff(currentSite) ! This sets the cohort to the "leaves off" flag currentCohort%status_coh = leaves_off - ! Remember what the lai was (leaf mass actually) was for next year + ! Remember what the leaf mass was for next year ! the same amount back on in the spring... - currentCohort%laimemory = leaf_c + currentCohort%leafmemory = leaf_c ! Drop Leaves (this routine will update the leaf state variables, ! for carbon and any other element that are prognostic. It will @@ -1238,12 +1229,12 @@ subroutine phenology_leafonoff(currentSite) if(store_c>nearzero) then store_c_transfer_frac = & - min((EDPftvarcon_inst%phenflush_fraction(ipft)*currentCohort%laimemory)/store_c, & + min((EDPftvarcon_inst%phenflush_fraction(ipft)*currentCohort%leafmemory)/store_c, & (1.0_r8-carbon_store_buffer)) if(prt_params%woody(ipft).ne.itrue)then - totalmemory=currentCohort%laimemory+currentCohort%sapwmemory+currentCohort%structmemory + totalmemory=currentCohort%leafmemory+currentCohort%sapwmemory+currentCohort%structmemory store_c_transfer_frac = min(EDPftvarcon_inst%phenflush_fraction(ipft)*totalmemory/store_c, & (1.0_r8-carbon_store_buffer)) @@ -1260,7 +1251,7 @@ subroutine phenology_leafonoff(currentSite) call PRTPhenologyFlush(currentCohort%prt, ipft, & leaf_organ, store_c_transfer_frac) - currentCohort%laimemory = 0.0_r8 + currentCohort%leafmemory = 0.0_r8 else @@ -1268,7 +1259,7 @@ subroutine phenology_leafonoff(currentSite) if (stem_drop_fraction .gt. 0.0_r8) then call PRTPhenologyFlush(currentCohort%prt, ipft, leaf_organ, & - store_c_transfer_frac*currentCohort%laimemory/totalmemory) + store_c_transfer_frac*currentCohort%leafmemory/totalmemory) call PRTPhenologyFlush(currentCohort%prt, ipft, sapw_organ, & store_c_transfer_frac*currentCohort%sapwmemory/totalmemory) @@ -1283,7 +1274,7 @@ subroutine phenology_leafonoff(currentSite) end if - currentCohort%laimemory = 0.0_r8 + currentCohort%leafmemory = 0.0_r8 currentCohort%structmemory = 0.0_r8 currentCohort%sapwmemory = 0.0_r8 @@ -1300,8 +1291,8 @@ subroutine phenology_leafonoff(currentSite) ! This sets the cohort to the "leaves off" flag currentCohort%status_coh = leaves_off - ! Remember what the lai (leaf mass actually) was for next year - currentCohort%laimemory = leaf_c + ! Remember what the leaf mass was for next year + currentCohort%leafmemory = leaf_c call PRTDeciduousTurnover(currentCohort%prt,ipft, & leaf_organ, leaf_drop_fraction) @@ -1890,7 +1881,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! Default assumption is that leaves are on cohortstatus = leaves_on - temp_cohort%laimemory = 0.0_r8 + temp_cohort%leafmemory = 0.0_r8 temp_cohort%sapwmemory = 0.0_r8 temp_cohort%structmemory = 0.0_r8 @@ -1899,7 +1890,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! as "cold", then set the cohort's status to leaves_off, and remember the leaf biomass if ((prt_params%season_decid(ft) == itrue) .and. & (any(currentSite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold]))) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf c_leaf = 0.0_r8 ! If plant is not woody then set sapwood and structural biomass as well @@ -1917,7 +1908,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! biomass if ((prt_params%stress_decid(ft) == itrue) .and. & (any(currentSite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff]))) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf c_leaf = 0.0_r8 ! If plant is not woody then set sapwood and structural biomass as well @@ -1950,28 +1941,28 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) case(nitrogen_element) mass_demand = & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) case(phosphorus_element) mass_demand = & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) case default write(fates_log(),*) 'Undefined element type in recruitment' @@ -2025,19 +2016,19 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) case(nitrogen_element) - m_struct = c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) m_repro = 0._r8 case(phosphorus_element) - m_struct = c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) m_store = StorageNutrientTarget(ft, element_id, m_leaf, m_fnrt, m_sapw, m_struct ) m_repro = 0._r8 @@ -2103,7 +2094,7 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) ! This initializes the cohort call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, & temp_cohort%hite, temp_cohort%coage, temp_cohort%dbh, prt, & - temp_cohort%laimemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & + temp_cohort%leafmemory, temp_cohort%sapwmemory, temp_cohort%structmemory, & cohortstatus, recruitstatus, & temp_cohort%canopy_trim,temp_cohort%c_area, & currentPatch%NCL_p, currentSite%spread, bc_in) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 42264ca776..c678fb0dab 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -95,6 +95,7 @@ module FatesAllometryMod use shr_log_mod , only : errMsg => shr_log_errMsg use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun + use FatesGlobals , only : FatesWarn,N2S,A2S,I2S use EDTypesMod , only : nlevleaf, dinc_vai use EDTypesMod , only : nclmax @@ -130,6 +131,8 @@ module FatesAllometryMod logical, parameter :: debug = .false. + + character(len=1024) :: warn_msg ! for defining a warning message ! If testing b4b with older versions, do not remove sapwood ! Our old methods with saldarriaga did not remove sapwood from the @@ -2005,7 +2008,7 @@ subroutine CrownDepth(height,ft,crown_depth) ! Original FATES crown depth heigh used for hydraulics ! crown_depth = min(height,0.1_r8) - crown_depth = prt_params%crown(ft) * height + crown_depth = prt_params%crown_depth_frac(ft) * height return @@ -2370,7 +2373,7 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) integer, parameter :: max_counter = 200 ! Do reduce "if" calls, we break this call into two parts - if ( int(prt_params%woody(ipft)) == itrue ) then + if ( prt_params%woody(ipft) == itrue ) then if(.not.present(bdead)) then write(fates_log(),*) 'woody plants must use structure for dbh reset' @@ -2454,9 +2457,17 @@ subroutine ForceDBH( ipft, canopy_trim, d, h, bdead, bl ) end if call h_allom(d,ipft,h) - if(counter>10)then + + if(counter>20)then write(fates_log(),*) 'dbh counter: ',counter,' is woody: ',& - int(prt_params%woody(ipft))==itrue + (prt_params%woody(ipft) == itrue) + + if(int(prt_params%woody(ipft))==itrue)then + warn_msg = 'dbh counter: '//trim(I2S(counter))//' is woody' + else + warn_msg = 'dbh counter: '//trim(I2S(counter))//' is not woody' + end if + call FatesWarn(warn_msg,index=3) end if diff --git a/biogeochem/FatesSoilBGCFluxMod.F90 b/biogeochem/FatesSoilBGCFluxMod.F90 index d14ce7b005..04c30a2c9d 100644 --- a/biogeochem/FatesSoilBGCFluxMod.F90 +++ b/biogeochem/FatesSoilBGCFluxMod.F90 @@ -55,6 +55,7 @@ module FatesSoilBGCFluxMod use FatesInterfaceTypesMod, only : hlm_nu_com use FatesInterfaceTypesMod, only : hlm_parteh_mode use FatesInterfaceTypesMod, only : hlm_use_ch4 + use FatesInterfaceTypesMod, only : hlm_decomp use FatesConstantsMod , only : prescribed_p_uptake use FatesConstantsMod , only : prescribed_n_uptake use FatesConstantsMod , only : coupled_p_uptake @@ -219,7 +220,8 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) end do ! We can exit if this is a c-only simulation - if(hlm_parteh_mode.eq.prt_carbon_allom_hyp) then + select case (hlm_parteh_mode) + case (prt_carbon_allom_hyp) ! These can now be zero'd do s = 1, nsites bc_in(s)%plant_nh4_uptake_flux(:,:) = 0._r8 @@ -227,7 +229,7 @@ subroutine UnPackNutrientAquisitionBCs(sites, bc_in) bc_in(s)%plant_p_uptake_flux(:,:) = 0._r8 end do return - end if + end select do s = 1, nsites @@ -677,7 +679,7 @@ subroutine PrepNutrientAquisitionBCs(csite, bc_in, bc_out) bc_out%veg_rootc(icomp,id) = bc_out%veg_rootc(icomp,id) + veg_rootc - ! We use a 3 parameter exponential attenuation function to estimate decomposer biomass + ! We use a 2 parameter exponential attenuation function to estimate decomposer biomass ! The parameter EDPftvarcon_inst%decompmicc(pft) is the maximum amount found at depth ! decompmicc_zmax, and the profile attenuates with strength lambda @@ -930,7 +932,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) ! !LOCAL VARIABLES: type (ed_patch_type), pointer :: currentPatch - type (ed_cohort_type), pointer :: currentCohort + type (ed_cohort_type), pointer :: ccohort real(r8), pointer :: flux_cel_si(:) real(r8), pointer :: flux_lab_si(:) real(r8), pointer :: flux_lig_si(:) @@ -954,6 +956,21 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) integer :: ic ! CWD type index integer :: ipft ! PFT index + ! The following are used for the MIMICS ligC/N boundary condition + real(r8) :: leaf_c, sapw_c ! leaf and sapwood carbon, per plant [kg] + real(r8) :: fnrt_c, struct_c ! fineroot and struct carbon, per plant [kg] + real(r8) :: leaf_n, sapw_n ! leaf and sapwood N, per plant [kg] + real(r8) :: fnrt_n, struct_n ! fineroot and struct N, per plant [kg] + real(r8) :: sum_ligC ! Flux of lignin C [kg/m2/s] + real(r8) :: sum_N ! Flux of all N [kg/m2/s] + real(r8) :: tot_leaf_c ! total leaf C of all cohorts in patch [kg/m2] + real(r8) :: tot_leaf_n ! total leaf N of all cohorts in patch [kg/m2] + real(r8) :: tot_fnrt_c ! total fineroot C of all cohorts in patch [kg/m2] + real(r8) :: tot_fnrt_n ! total fineroot N of all cohorts in patch [kg/m2] + real(r8) :: tot_wood_c ! total wood C of all cohorts in patch [kg/m2] + real(r8) :: tot_wood_n ! total wood N of all cohorts in patch [kg/m2] + + ! NOTE(rgk, 201705) this parameter was brought over from SoilBiogeochemVerticalProfile ! how steep profile is for surface components (1/ e_folding depth) (1/m) real(r8), parameter :: surfprof_exp = 10. @@ -986,12 +1003,12 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) do id = 1,nlev_eff_decomp surface_prof(id) = surface_prof(id)/surface_prof_tot end do - + ! Loop over the different elements. do el = 1, num_elements ! Zero out the boundary flux arrays - ! Make a pointer to the cellulose, labile and lignan + ! Make a pointer to the cellulose, labile and lignin ! flux partitions. select case (element_list(el)) @@ -1048,6 +1065,7 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) flux_lig_si(id) = flux_lig_si(id) + & litt%ag_cwd_frag(ic) * ED_val_cwd_flig * area_frac * surface_prof(id) + end do do j = 1, nlev_eff_soil @@ -1063,6 +1081,9 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) end do end do + + + ! leaf and fine root fragmentation fluxes do id = 1,nlev_eff_decomp @@ -1126,6 +1147,102 @@ subroutine FluxIntoLitterPools(csite, bc_in, bc_out) end do ! do elements + ! If we are coupled with MIMICS, then we need some assessment of litter quality + ! ie ligC/totalN. If we are not tracking N in the litter flux (ie C-only model) + ! then we need to approximate this by estimating the mean C:N ratios of each + ! plant organ, and mulitplying that by the different C Fluxes to get a total + ! approximate N flux. Note, in C-only, we will not capture any re-absorption. + + if(trim(hlm_decomp).eq.'MIMICS') then + + ! If we track nitrogen (ie cnp or other) then + ! we diagnose the c-lig/n ratio directly from the pools + if(element_pos(nitrogen_element)>0) then + + ! Sum totalN fluxes over depth [g/m2] + sum_N = sum((bc_out%litt_flux_cel_n_si(1:nlev_eff_soil) + & + bc_out%litt_flux_lig_n_si(1:nlev_eff_soil) + & + bc_out%litt_flux_lab_n_si(1:nlev_eff_soil)) * & + bc_in%dz_sisl(1:nlev_eff_soil)) + + else + + ! In this case (Carbon Only), we use the stoichiometry parameters to estimate + ! the C:N of live vegetation and the seedbank, and use that + ! as a proxy for the C:N of the litter flux + + sum_N = 0._r8 + + currentPatch => csite%oldest_patch + do while (associated(currentPatch)) + + litt => currentPatch%litter(element_pos(carbon12_element)) + area_frac = currentPatch%area*area_inv + + tot_leaf_c = 0._r8 + tot_leaf_n = 0._r8 + tot_fnrt_c = 0._r8 + tot_fnrt_n = 0._r8 + tot_wood_c = 0._r8 + tot_wood_n = 0._r8 + + ccohort => currentPatch%tallest + do while (associated(ccohort)) + ipft = ccohort%pft + leaf_c = ccohort%n * area_inv * ccohort%prt%GetState(leaf_organ, carbon12_element) + sapw_c = ccohort%n * area_inv * ccohort%prt%GetState(sapw_organ, carbon12_element) + fnrt_c = ccohort%n * area_inv * ccohort%prt%GetState(fnrt_organ, carbon12_element) + struct_c = ccohort%n * area_inv * ccohort%prt%GetState(struct_organ, carbon12_element) + leaf_n = leaf_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)) + sapw_n = sapw_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)) + fnrt_n = fnrt_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)) + struct_n = struct_c * prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ)) + tot_leaf_c = tot_leaf_c + leaf_c + tot_leaf_n = tot_leaf_n + leaf_n + tot_fnrt_c = tot_fnrt_c + fnrt_c + tot_fnrt_n = tot_fnrt_n + fnrt_n + tot_wood_c = tot_wood_c + sapw_c + struct_c + tot_wood_n = tot_wood_n + sapw_n + struct_n + ccohort => ccohort%shorter + end do + + if(tot_wood_c>nearzero) then + sum_N = sum_N + area_frac*sum(litt%ag_cwd_frag)*(tot_wood_n/tot_wood_c) + sum_N = sum_N + area_frac*sum(litt%bg_cwd_frag)*(tot_wood_n/tot_wood_c) + end if + if(tot_leaf_c>nearzero)then + sum_N = sum_N + area_frac*sum(litt%leaf_fines_frag)*(tot_leaf_n / tot_leaf_c) + end if + if(tot_fnrt_c>nearzero)then + sum_N = sum_N + area_frac*sum(litt%root_fines_frag)*(tot_fnrt_n / tot_fnrt_c) + end if + do ipft = 1,numpft + sum_N = sum_N + area_frac * prt_params%nitr_recr_stoich(ipft) * & + (litt%seed_decay(ipft) + litt%seed_germ_decay(ipft)) + end do + + currentPatch => currentPatch%younger + end do + + ! Convert from kg/m2/day -> g/m2/s + sum_N = sum_N * days_per_sec * g_per_kg + + end if + + ! Sum over layers and multiply by depth g/m3/s * m -> g/m2/s + sum_ligC = sum(bc_out%litt_flux_lig_c_si(1:nlev_eff_soil) * bc_in%dz_sisl(1:nlev_eff_soil)) + + if(sum_N>nearzero)then + bc_out%litt_flux_ligc_per_n = sum_ligC / sum_N + else + bc_out%litt_flux_ligc_per_n = 0._r8 + end if + + end if + + + + return end subroutine FluxIntoLitterPools diff --git a/biogeophys/EDAccumulateFluxesMod.F90 b/biogeophys/EDAccumulateFluxesMod.F90 index a0fe4dd7df..8eae0f4a50 100644 --- a/biogeophys/EDAccumulateFluxesMod.F90 +++ b/biogeophys/EDAccumulateFluxesMod.F90 @@ -9,7 +9,7 @@ module EDAccumulateFluxesMod ! Rosie Fisher. March 2014. ! ! !USES: - use FatesGlobals, only : fates_endrun + use FatesGlobals, only : endrun => fates_endrun use FatesGlobals, only : fates_log use shr_log_mod , only : errMsg => shr_log_errMsg use FatesConstantsMod , only : r8 => fates_r8 diff --git a/biogeophys/EDBtranMod.F90 b/biogeophys/EDBtranMod.F90 index e36642447e..52577b1b92 100644 --- a/biogeophys/EDBtranMod.F90 +++ b/biogeophys/EDBtranMod.F90 @@ -19,11 +19,16 @@ module EDBtranMod use FatesInterfaceTypesMod , only : hlm_use_planthydro use FatesGlobals , only : fates_log use FatesAllometryMod , only : set_root_fraction + use shr_log_mod , only : errMsg => shr_log_errMsg + use FatesGlobals, only : endrun => fates_endrun ! implicit none private + + logical, parameter :: debug = .false. + public :: btran_ed public :: get_active_suction_layers public :: check_layer_water @@ -231,10 +236,13 @@ subroutine btran_ed( nsites, sites, bc_in, bc_out) temprootr = sum(bc_out(s)%rootr_pasl(ifp,1:bc_in(s)%nlevsoil)) if(abs(1.0_r8-temprootr) > 1.0e-10_r8 .and. temprootr > 1.0e-10_r8)then - write(fates_log(),*) 'error with rootr in canopy fluxes',temprootr,sum_pftgs + + if(debug) write(fates_log(),*) 'error with rootr in canopy fluxes',temprootr,sum_pftgs + do j = 1,bc_in(s)%nlevsoil bc_out(s)%rootr_pasl(ifp,j) = bc_out(s)%rootr_pasl(ifp,j)/temprootr enddo + end if endif ! not bare ground cpatch => cpatch%younger diff --git a/biogeophys/EDSurfaceAlbedoMod.F90 b/biogeophys/EDSurfaceAlbedoMod.F90 index 7799ee4333..ddb25f08a4 100644 --- a/biogeophys/EDSurfaceAlbedoMod.F90 +++ b/biogeophys/EDSurfaceAlbedoMod.F90 @@ -11,7 +11,6 @@ module EDSurfaceRadiationMod #include "shr_assert.h" use EDTypesMod , only : ed_patch_type, ed_site_type - use EDTypesMod , only : maxPatchesPerSite use EDTypesMod , only : maxpft use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : itrue @@ -44,7 +43,8 @@ module EDSurfaceRadiationMod public :: ED_SunShadeFracs logical :: debug = .false. ! for debugging this module - + character(len=*), parameter, private :: sourcefile = & + __FILE__ ! real(r8), public :: albice(maxSWb) = & ! albedo land ice by waveband (1=vis, 2=nir) ! (/ 0.80_r8, 0.55_r8 /) @@ -392,13 +392,16 @@ subroutine PatchNormanRadiation (currentPatch, & end do !iv end do !ft1 end do !L - if (sum(ftweight(1,:,1))<0.999_r8)then - write(fates_log(),*) 'canopy not full',ftweight(1,:,1) - endif - if (sum(ftweight(1,:,1))>1.0001_r8)then - write(fates_log(),*) 'canopy too full',ftweight(1,:,1) - endif + if(debug)then + if (sum(ftweight(1,:,1))<0.999_r8)then + write(fates_log(),*) 'canopy not full',ftweight(1,:,1) + endif + if (sum(ftweight(1,:,1))>1.0001_r8)then + write(fates_log(),*) 'canopy too full',ftweight(1,:,1) + endif + end if + do L = 1,currentPatch%NCL_p !start at the top canopy layer (1 is the top layer.) weighted_dir_tr(L) = 0.0_r8 @@ -450,11 +453,13 @@ subroutine PatchNormanRadiation (currentPatch, & !where there is a partly empty leaf layer, some fluxes go straight through. lai_change(L,ft,iv) = ftweight(L,ft,iv)-ftweight(L,ft,iv+1) endif - if (ftweight(L,ft,iv+1) - ftweight(L,ft,iv) > 1.e-10_r8)then - write(fates_log(),*) 'lower layer has more coverage. This is wrong' , & - ftweight(L,ft,iv),ftweight(L,ft,iv+1),ftweight(L,ft,iv+1)-ftweight(L,ft,iv) - endif - + if(debug)then + if (ftweight(L,ft,iv+1) - ftweight(L,ft,iv) > 1.e-10_r8)then + write(fates_log(),*) 'lower layer has more coverage. This is wrong' , & + ftweight(L,ft,iv),ftweight(L,ft,iv+1),ftweight(L,ft,iv+1)-ftweight(L,ft,iv) + endif + end if + !n.b. in theory lai_change could be calculated daily in the ED code. !This is light coming striaght through the canopy. if (L==1)then @@ -981,26 +986,30 @@ subroutine PatchNormanRadiation (currentPatch, & error = abs(currentPatch%sabs_dir(ib) - (currentPatch%tr_soil_dir(ib) * & (1.0_r8-currentPatch%gnd_alb_dir(ib) ) + & currentPatch%tr_soil_dir_dif(ib) * (1.0_r8-currentPatch%gnd_alb_dif(ib) ))) - if ( abs(error) > 0.0001)then - write(fates_log(),*)'dir ground absorption error',error,currentPatch%sabs_dir(ib), & - currentPatch%tr_soil_dir(ib)* & - (1.0_r8-currentPatch%gnd_alb_dir(ib) ),currentPatch%NCL_p,ib,sum(ftweight(1,1:numpft,1)) - write(fates_log(),*) 'albedos',currentPatch%sabs_dir(ib) ,currentPatch%tr_soil_dir(ib), & - (1.0_r8-currentPatch%gnd_alb_dir(ib) ) - - do ft =1,3 - iv = currentPatch%nrad(1,ft) + 1 - write(fates_log(),*) 'abs soil fluxes', Abs_dir_z(ft,iv),Abs_dif_z(ft,iv) - end do + if(debug)then + if ( abs(error) > 0.0001)then + write(fates_log(),*)'dir ground absorption error',error,currentPatch%sabs_dir(ib), & + currentPatch%tr_soil_dir(ib)* & + (1.0_r8-currentPatch%gnd_alb_dir(ib) ),currentPatch%NCL_p,ib,sum(ftweight(1,1:numpft,1)) + write(fates_log(),*) 'albedos',currentPatch%sabs_dir(ib) ,currentPatch%tr_soil_dir(ib), & + (1.0_r8-currentPatch%gnd_alb_dir(ib) ) + do ft =1,numpft + iv = currentPatch%nrad(1,ft) + 1 + write(fates_log(),*) 'abs soil fluxes', Abs_dir_z(ft,iv),Abs_dif_z(ft,iv) + end do + end if end if + else - if ( abs(currentPatch%sabs_dif(ib)-(currentPatch%tr_soil_dif(ib) * & - (1.0_r8-currentPatch%gnd_alb_dif(ib) ))) > 0.0001_r8)then - write(fates_log(),*)'dif ground absorption error',currentPatch%sabs_dif(ib) , & - (currentPatch%tr_soil_dif(ib)* & - (1.0_r8-currentPatch%gnd_alb_dif(ib) )),currentPatch%NCL_p,ib,sum(ftweight(1,1:numpft,1)) - endif + if (debug) then + if ( abs(currentPatch%sabs_dif(ib)-(currentPatch%tr_soil_dif(ib) * & + (1.0_r8-currentPatch%gnd_alb_dif(ib) ))) > 0.0001_r8)then + write(fates_log(),*)'dif ground absorption error',currentPatch%sabs_dif(ib) , & + (currentPatch%tr_soil_dif(ib)* & + (1.0_r8-currentPatch%gnd_alb_dif(ib) )),currentPatch%NCL_p,ib,sum(ftweight(1,1:numpft,1)) + endif + end if endif if (radtype == idirect)then @@ -1044,16 +1053,18 @@ subroutine PatchNormanRadiation (currentPatch, & ! to the complexity of this code, but where the system generates occasional errors, we ! will deal with them for now. end if + if (abs(error) > 0.15_r8)then - write(fates_log(),*) 'Large Dir Radn consvn error',error ,ib - write(fates_log(),*) 'diags', albd_parb_out(ib), ftdd_parb_out(ib), & - ftid_parb_out(ib), fabd_parb_out(ib) - write(fates_log(),*) 'elai',currentpatch%elai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'esai',currentpatch%esai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'ftweight',ftweight(1,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'cp',currentPatch%area, currentPatch%patchno - write(fates_log(),*) 'ground albedo diffuse (ib)', currentPatch%gnd_alb_dir(ib) - + if(debug)then + write(fates_log(),*) 'Large Dir Radn consvn error',error ,ib + write(fates_log(),*) 'diags', albd_parb_out(ib), ftdd_parb_out(ib), & + ftid_parb_out(ib), fabd_parb_out(ib) + write(fates_log(),*) 'elai',currentpatch%elai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'esai',currentpatch%esai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'ftweight',ftweight(1,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'cp',currentPatch%area, currentPatch%patchno + write(fates_log(),*) 'ground albedo diffuse (ib)', currentPatch%gnd_alb_dir(ib) + end if albd_parb_out(ib) = albd_parb_out(ib) + error end if else @@ -1063,20 +1074,21 @@ subroutine PatchNormanRadiation (currentPatch, & end if if (abs(error) > 0.15_r8)then - write(fates_log(),*) 'lg Dif Radn consvn error',error ,ib - write(fates_log(),*) 'diags', albi_parb_out(ib), ftii_parb_out(ib), & - fabi_parb_out(ib) - !write(fates_log(),*) 'lai_change',lai_change(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - !write(fates_log(),*) 'elai',currentpatch%elai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - !write(fates_log(),*) 'esai',currentpatch%esai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - !write(fates_log(),*) 'ftweight',ftweight(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) - write(fates_log(),*) 'cp',currentPatch%area, currentPatch%patchno - write(fates_log(),*) 'ground albedo diffuse (ib)', currentPatch%gnd_alb_dir(ib) - !write(fates_log(),*) 'rhol',rhol(1:numpft,:) - !write(fates_log(),*) 'ftw',sum(ftweight(1,1:numpft,1)),ftweight(1,1:numpft,1) - !write(fates_log(),*) 'present',currentPatch%canopy_mask(1,1:numpft) - !write(fates_log(),*) 'CAP',currentPatch%canopy_area_profile(1,1:numpft,1) - + if(debug)then + write(fates_log(),*) 'lg Dif Radn consvn error',error ,ib + write(fates_log(),*) 'diags', albi_parb_out(ib), ftii_parb_out(ib), & + fabi_parb_out(ib) + !write(fates_log(),*) 'lai_change',lai_change(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + !write(fates_log(),*) 'elai',currentpatch%elai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + !write(fates_log(),*) 'esai',currentpatch%esai_profile(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + !write(fates_log(),*) 'ftweight',ftweight(currentpatch%ncl_p,1:numpft,1:diag_nlevleaf) + write(fates_log(),*) 'cp',currentPatch%area, currentPatch%patchno + write(fates_log(),*) 'ground albedo diffuse (ib)', currentPatch%gnd_alb_dir(ib) + !write(fates_log(),*) 'rhol',rhol(1:numpft,:) + !write(fates_log(),*) 'ftw',sum(ftweight(1,1:numpft,1)),ftweight(1,1:numpft,1) + !write(fates_log(),*) 'present',currentPatch%canopy_mask(1,1:numpft) + !write(fates_log(),*) 'CAP',currentPatch%canopy_area_profile(1,1:numpft,1) + end if albi_parb_out(ib) = albi_parb_out(ib) + error end if @@ -1088,10 +1100,12 @@ subroutine PatchNormanRadiation (currentPatch, & (fabi_parb_out(ib) + albi_parb_out(ib) + currentPatch%sabs_dif(ib)) endif - if (abs(error) > 0.00000001_r8)then - write(fates_log(),*) 'there is still error after correction',error ,ib + if(debug) then + if (abs(error) > 0.00000001_r8)then + write(fates_log(),*) 'there is still error after correction',error ,ib + end if end if - + end if end do !hlm_numSWb @@ -1198,11 +1212,13 @@ subroutine ED_SunShadeFracs(nsites, sites,bc_in,bc_out) bc_out(s)%fsun_pa(ifp) = 0._r8 endif - if(bc_out(s)%fsun_pa(ifp) > 1._r8)then - write(fates_log(),*) 'too much leaf area in profile', bc_out(s)%fsun_pa(ifp), & - sunlai,shalai - endif - + if(debug)then + if(bc_out(s)%fsun_pa(ifp) > 1._r8)then + write(fates_log(),*) 'too much leaf area in profile', bc_out(s)%fsun_pa(ifp), & + sunlai,shalai + endif + end if + elai = calc_areaindex(cpatch,'elai') bc_out(s)%laisun_pa(ifp) = elai*bc_out(s)%fsun_pa(ifp) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 5571adc089..1882da8b2e 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -48,7 +48,7 @@ module FatesPlantHydraulicsMod use EDParamsMod , only : hydr_psi0 use EDParamsMod , only : hydr_psicap use EDParamsMod , only : hydr_htftype_node - use EDParamsMod , only : hydr_solver_type + use EDParamsMod , only : hydr_solver use EDTypesMod , only : ed_site_type use EDTypesMod , only : ed_patch_type @@ -1468,7 +1468,7 @@ subroutine InitHydrSites(sites,bc_in) case(rhizlayer_aggmeth_none) csite_hydr%nlevrhiz = bc_in(s)%nlevsoil - call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver_type,bc_in(s)%nlevsoil) + call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver,bc_in(s)%nlevsoil) do j=1,csite_hydr%nlevrhiz csite_hydr%map_r2s(j,1) = j @@ -1480,7 +1480,7 @@ subroutine InitHydrSites(sites,bc_in) case(rhizlayer_aggmeth_combine12) csite_hydr%nlevrhiz = max(1,bc_in(s)%nlevsoil-1) - call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver_type,bc_in(s)%nlevsoil) + call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver,bc_in(s)%nlevsoil) csite_hydr%map_r2s(1,1) = 1 j_bc = min(2,bc_in(s)%nlevsoil) ! this protects 1 soil layer @@ -1498,7 +1498,7 @@ subroutine InitHydrSites(sites,bc_in) case(rhizlayer_aggmeth_balN) csite_hydr%nlevrhiz = min(aggN,bc_in(s)%nlevsoil) - call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver_type,bc_in(s)%nlevsoil) + call sites(s)%si_hydr%InitHydrSite(numpft,nlevsclass,hydr_solver,bc_in(s)%nlevsoil) ntoagg = int(ceiling(real(bc_in(s)%nlevsoil)/real(csite_hydr%nlevrhiz)-nearzero)) @@ -2627,21 +2627,21 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) ! from leaf to the current soil layer. This does NOT ! update cohort%th_* - if(hydr_solver_type == hydr_solver_2DNewton) then + if(hydr_solver == hydr_solver_2DNewton) then call MatSolve2D(csite_hydr,ccohort,ccohort_hydr, & dtime,qflx_tran_veg_indiv, & sapflow,rootuptake(1:nlevrhiz),wb_err_plant,dwat_plant, & dth_layershell_col) - elseif(hydr_solver_type == hydr_solver_2DPicard) then + elseif(hydr_solver == hydr_solver_2DPicard) then call PicardSolve2D(csite_hydr,ccohort,ccohort_hydr, & dtime,qflx_tran_veg_indiv, & sapflow,rootuptake(1:nlevrhiz),wb_err_plant,dwat_plant, & dth_layershell_col,csite_hydr%num_nodes) - elseif(hydr_solver_type == hydr_solver_1DTaylor ) then + elseif(hydr_solver == hydr_solver_1DTaylor ) then ! --------------------------------------------------------------------------------- ! Approach: do nlevsoi_hyd sequential solutions to Richards' equation, @@ -2883,20 +2883,21 @@ subroutine hydraulics_bc ( nsites, sites, bc_in, bc_out, dtime) wb_check_site = delta_plant_storage+delta_soil_storage+site_runoff+transp_flux ! Now check on total error - if( abs(wb_check_site) > 1.e-4_r8 ) then - write(fates_log(),*) 'FATES hydro water balance does not add up [kg/m2]' - write(fates_log(),*) 'csite_hydr%errh2o_hyd: ',wb_check_site - write(fates_log(),*) 'delta_plant_storage: ',delta_plant_storage - write(fates_log(),*) 'delta_soil_storage: ',delta_soil_storage - write(fates_log(),*) 'site_runoff: ',site_runoff - write(fates_log(),*) 'transp_flux: ',transp_flux - end if - + if(debug)then + if( abs(wb_check_site) > 1.e-4_r8 ) then + write(fates_log(),*) 'FATES hydro water balance does not add up [kg/m2]' + write(fates_log(),*) 'csite_hydr%errh2o_hyd: ',wb_check_site + write(fates_log(),*) 'delta_plant_storage: ',delta_plant_storage + write(fates_log(),*) 'delta_soil_storage: ',delta_soil_storage + write(fates_log(),*) 'site_runoff: ',site_runoff + write(fates_log(),*) 'transp_flux: ',transp_flux + end if + end if + csite_hydr%h2oveg_hydro_err = csite_hydr%h2oveg_hydro_err + csite_hydr%errh2o_hyd - - call UpdateH2OVeg(sites(s),bc_out(s)) + call UpdateH2OVeg(sites(s),bc_out(s)) enddo !site @@ -4941,7 +4942,7 @@ subroutine MatSolve2D(csite_hydr,cohort,cohort_hydr, & ! This NaN's the scratch arrays - call csite_hydr%FlushSiteScratch(hydr_solver_type) + call csite_hydr%FlushSiteScratch(hydr_solver) ! This is the maximum number of iterations needed for this cohort ! (each soil layer has a different number, this saves the max) @@ -5210,7 +5211,9 @@ subroutine MatSolve2D(csite_hydr,cohort,cohort_hydr, & enddo if ( nwtn_iter > max_newton_iter) then icnv = icnv_fail_round - write(fates_log(),*) 'Newton hydraulics solve failed',residual_amax,nsd,tm + if(debug)then + write(fates_log(),*) 'Newton hydraulics solve failed',residual_amax,nsd,tm + end if endif ! Three scenarios: @@ -5402,10 +5405,12 @@ subroutine MatSolve2D(csite_hydr,cohort,cohort_hydr, & end do outerloop - if(cohort_hydr%iterh1>1._r8) then - write(fates_log(),*) "hydro solve info: i1: ",cohort_hydr%iterh1,"i2: ",cohort_hydr%iterh2 + if(debug)then + if(cohort_hydr%iterh1>1._r8) then + write(fates_log(),*) "hydro solve info: i1: ",cohort_hydr%iterh1,"i2: ",cohort_hydr%iterh2 + end if end if - + ! Save flux diagnostics ! ------------------------------------------------------ @@ -5720,7 +5725,7 @@ subroutine PicardSolve2D(csite_hydr,cohort,cohort_hydr, & ! This NaN's the scratch arrays - call csite_hydr%FlushSiteScratch(hydr_solver_type) + call csite_hydr%FlushSiteScratch(hydr_solver) ! This is the maximum number of iterations needed for this cohort ! (each soil layer has a different number, this saves the max) diff --git a/biogeophys/FatesPlantRespPhotosynthMod.F90 b/biogeophys/FatesPlantRespPhotosynthMod.F90 index adffe67d85..23722bab33 100644 --- a/biogeophys/FatesPlantRespPhotosynthMod.F90 +++ b/biogeophys/FatesPlantRespPhotosynthMod.F90 @@ -22,6 +22,7 @@ module FATESPlantRespPhotosynthMod use FatesGlobals, only : endrun => fates_endrun use FatesGlobals, only : fates_log + use FatesGlobals, only : FatesWarn,N2S,A2S use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : itrue use FatesConstantsMod, only : nearzero @@ -49,7 +50,7 @@ module FATESPlantRespPhotosynthMod use PRTGenericMod, only : store_organ use PRTGenericMod, only : repro_organ use PRTGenericMod, only : struct_organ - use EDParamsMod, only : ED_val_base_mr_20, stomatal_model + use EDParamsMod, only : ED_val_base_mr_20, stomatal_model, stomatal_assim_model use PRTParametersMod, only : prt_params use EDPftvarcon , only : EDPftvarcon_inst @@ -63,6 +64,10 @@ module FATESPlantRespPhotosynthMod character(len=*), parameter, private :: sourcefile = & __FILE__ + + + character(len=1024) :: warn_msg ! for defining a warning message + !------------------------------------------------------------------------------------- ! maximum stomatal resistance [s/m] (used across several procedures) @@ -88,12 +93,9 @@ module FATESPlantRespPhotosynthMod ! Alternatively, Gross Assimilation can be used to estimate ! leaf co2 partial pressure and therefore conductance. The default - !is to use anet - logical, parameter :: use_agross = .false. - - - - + ! is to use anet + integer, parameter :: net_assim_model = 1 + integer, parameter :: gross_assim_model = 2 contains @@ -500,6 +502,7 @@ subroutine FatesPlantRespPhotosynthDrive (nsites, sites,bc_in,bc_out,dtime) end select + ! MLO - Shouldn't these numbers be parameters too? lmr25top = 2.525e-6_r8 * (1.5_r8 ** ((25._r8 - 20._r8)/10._r8)) lmr25top = lmr25top * lnc_top / (umolC_to_kgC * g_per_kg) @@ -1147,7 +1150,7 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in ! using anet in calculating gs this is version B anet = agross - lmr - if (use_agross) then + if ( stomatal_assim_model == gross_assim_model ) then if ( stomatal_model == medlyn_model ) then write (fates_log(),*) 'Gross Assimilation conductance is incompatible with the Medlyn model' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1262,8 +1265,8 @@ subroutine LeafLayerPhotosynthesis(f_sun_lsl, & ! in end if if (abs(gs_mol-gs_mol_err) > 1.e-01_r8) then - write (fates_log(),*) 'Stomatal model error check - stomatal conductance error:' - write (fates_log(),*) gs_mol, gs_mol_err + warn_msg = 'Stomatal conductance error check - weak convergence: '//trim(N2S(gs_mol))//' '//trim(N2S(gs_mol_err)) + call FatesWarn(warn_msg,index=1) end if enddo !sunsha loop diff --git a/fire/SFMainMod.F90 b/fire/SFMainMod.F90 index aedcb4aa7c..7f2c037846 100644 --- a/fire/SFMainMod.F90 +++ b/fire/SFMainMod.F90 @@ -66,8 +66,8 @@ module SFMainMod ! The following parameter represents one of the values of hlm_spitfire_mode ! and more of these appear in subroutine area_burnt_intensity below ! NB. The same parameters are set in /src/biogeochem/CNFireFactoryMod - integer :: write_SF = 0 ! for debugging - logical :: debug = .false. ! for debugging + integer :: write_SF = ifalse ! for debugging + logical :: debug = .false. ! for debugging ! ============================================================================ ! ============================================================================ @@ -95,7 +95,7 @@ subroutine fire_model( currentSite, bc_in) currentPatch => currentPatch%older enddo - if(write_SF==1)then + if(write_SF==itrue)then write(fates_log(),*) 'spitfire_mode', hlm_spitfire_mode endif @@ -192,7 +192,7 @@ subroutine charecteristics_of_fuel ( currentSite ) currentPatch%livegrass = 0.0_r8 currentCohort => currentPatch%tallest do while(associated(currentCohort)) - if( int(prt_params%woody(currentCohort%pft)) == ifalse)then + if( prt_params%woody(currentCohort%pft) == ifalse)then currentPatch%livegrass = currentPatch%livegrass + & currentCohort%prt%GetState(leaf_organ, all_carbon_elements) * & @@ -304,8 +304,10 @@ subroutine charecteristics_of_fuel ( currentSite ) endif currentPatch%fuel_sav = sum(SF_val_SAV(1:nfsc))/(nfsc) ! make average sav to avoid crashing code. - if ( hlm_masterproc == itrue ) write(fates_log(),*) 'problem with spitfire fuel averaging' - + if ( hlm_masterproc == itrue .and. write_SF == itrue)then + write(fates_log(),*) 'problem with spitfire fuel averaging' + end if + ! FIX(SPM,032414) refactor...should not have 0 fuel unless everything is burnt ! off. currentPatch%fuel_eff_moist = 0.0000000001_r8 @@ -374,7 +376,7 @@ subroutine wind_effect ( currentSite, bc_in) do while(associated(currentCohort)) if (debug) write(fates_log(),*) 'SF currentCohort%c_area ',currentCohort%c_area - if( int(prt_params%woody(currentCohort%pft)) == itrue)then + if( prt_params%woody(currentCohort%pft) == itrue)then currentPatch%total_tree_area = currentPatch%total_tree_area + currentCohort%c_area else total_grass_area = total_grass_area + currentCohort%c_area @@ -864,7 +866,7 @@ subroutine crown_scorching ( currentSite ) if (currentPatch%fire == 1) then currentCohort => currentPatch%tallest; do while(associated(currentCohort)) - if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees only + if ( prt_params%woody(currentCohort%pft) == itrue) then !trees only leaf_c = currentCohort%prt%GetState(leaf_organ, all_carbon_elements) sapw_c = currentCohort%prt%GetState(sapw_organ, all_carbon_elements) @@ -878,7 +880,7 @@ subroutine crown_scorching ( currentSite ) enddo !end cohort loop do i_pft=1,numpft - if (tree_ag_biomass > 0.0_r8 .and. int(prt_params%woody(i_pft)) == itrue) then + if (tree_ag_biomass > 0.0_r8 .and. prt_params%woody(i_pft) == itrue) then !Equation 16 in Thonicke et al. 2010 !Van Wagner 1973 EQ8 !2/3 Byram (1959) currentPatch%Scorch_ht(i_pft) = EDPftvarcon_inst%fire_alpha_SH(i_pft) * (currentPatch%FI**0.667_r8) @@ -920,7 +922,7 @@ subroutine crown_damage ( currentSite ) do while(associated(currentCohort)) currentCohort%fraction_crown_burned = 0.0_r8 - if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees only + if ( prt_params%woody(currentCohort%pft) == itrue) then !trees only ! Flames lower than bottom of canopy. ! c%hite is height of cohort @@ -984,7 +986,7 @@ subroutine cambial_damage_kill ( currentSite ) if (currentPatch%fire == 1) then currentCohort => currentPatch%tallest; do while(associated(currentCohort)) - if ( int(prt_params%woody(currentCohort%pft)) == itrue) then !trees only + if ( prt_params%woody(currentCohort%pft) == itrue) then !trees only ! Equation 21 in Thonicke et al 2010 bt = EDPftvarcon_inst%bark_scaler(currentCohort%pft)*currentCohort%dbh ! bark thickness. ! Equation 20 in Thonicke et al. 2010. @@ -1036,7 +1038,7 @@ subroutine post_fire_mortality ( currentSite ) do while(associated(currentCohort)) currentCohort%fire_mort = 0.0_r8 currentCohort%crownfire_mort = 0.0_r8 - if ( int(prt_params%woody(currentCohort%pft)) == itrue) then + if ( prt_params%woody(currentCohort%pft) == itrue) then ! Equation 22 in Thonicke et al. 2010. currentCohort%crownfire_mort = EDPftvarcon_inst%crown_kill(currentCohort%pft)*currentCohort%fraction_crown_burned**3.0_r8 ! Equation 18 in Thonicke et al. 2010. diff --git a/fire/SFParamsMod.F90 b/fire/SFParamsMod.F90 index 02c0ce7756..65849f829d 100644 --- a/fire/SFParamsMod.F90 +++ b/fire/SFParamsMod.F90 @@ -52,8 +52,8 @@ module SFParamsMod character(len=param_string_length),parameter :: SF_name_durat_slope = "fates_fire_durat_slope" character(len=param_string_length),parameter :: SF_name_drying_ratio = "fates_fire_drying_ratio" character(len=param_string_length),parameter :: SF_name_fire_threshold = "fates_fire_threshold" - character(len=param_string_length),parameter :: SF_name_CWD_frac = "fates_CWD_frac" - character(len=param_string_length),parameter :: SF_name_max_decomp = "fates_max_decomp" + character(len=param_string_length),parameter :: SF_name_CWD_frac = "fates_frag_cwd_frac" + character(len=param_string_length),parameter :: SF_name_max_decomp = "fates_frag_maxdecomp" character(len=param_string_length),parameter :: SF_name_SAV = "fates_fire_SAV" character(len=param_string_length),parameter :: SF_name_FBD = "fates_fire_FBD" character(len=param_string_length),parameter :: SF_name_min_moisture = "fates_fire_min_moisture" @@ -260,37 +260,37 @@ subroutine SpitFireReceiveScalars(fates_params) real(r8) :: tmp_real - call fates_params%RetreiveParameter(name=SF_name_fdi_a, & + call fates_params%RetrieveParameter(name=SF_name_fdi_a, & data=SF_val_fdi_a) - call fates_params%RetreiveParameter(name=SF_name_fdi_b, & + call fates_params%RetrieveParameter(name=SF_name_fdi_b, & data=SF_val_fdi_b) - call fates_params%RetreiveParameter(name=SF_name_fdi_alpha, & + call fates_params%RetrieveParameter(name=SF_name_fdi_alpha, & data=SF_val_fdi_alpha) - call fates_params%RetreiveParameter(name=SF_name_miner_total, & + call fates_params%RetrieveParameter(name=SF_name_miner_total, & data=SF_val_miner_total) - call fates_params%RetreiveParameter(name=SF_name_fuel_energy, & + call fates_params%RetrieveParameter(name=SF_name_fuel_energy, & data=SF_val_fuel_energy) - call fates_params%RetreiveParameter(name=SF_name_part_dens, & + call fates_params%RetrieveParameter(name=SF_name_part_dens, & data=SF_val_part_dens) - call fates_params%RetreiveParameter(name=SF_name_miner_damp, & + call fates_params%RetrieveParameter(name=SF_name_miner_damp, & data=SF_val_miner_damp) - call fates_params%RetreiveParameter(name=SF_name_max_durat, & + call fates_params%RetrieveParameter(name=SF_name_max_durat, & data=SF_val_max_durat) - call fates_params%RetreiveParameter(name=SF_name_durat_slope, & + call fates_params%RetrieveParameter(name=SF_name_durat_slope, & data=SF_val_durat_slope) - call fates_params%RetreiveParameter(name=SF_name_drying_ratio, & + call fates_params%RetrieveParameter(name=SF_name_drying_ratio, & data=SF_val_drying_ratio) - call fates_params%RetreiveParameter(name=SF_name_fire_threshold, & + call fates_params%RetrieveParameter(name=SF_name_fire_threshold, & data=SF_val_fire_threshold) @@ -323,7 +323,7 @@ subroutine SpitFireReceiveNCWD(fates_params) class(fates_parameters_type), intent(inout) :: fates_params - call fates_params%RetreiveParameter(name=SF_name_CWD_frac, & + call fates_params%RetrieveParameter(name=SF_name_CWD_frac, & data=SF_val_CWD_frac) @@ -380,31 +380,31 @@ subroutine SpitFireReceiveNFSC(fates_params) class(fates_parameters_type), intent(inout) :: fates_params - call fates_params%RetreiveParameter(name=SF_name_SAV, & + call fates_params%RetrieveParameter(name=SF_name_SAV, & data=SF_val_SAV) - call fates_params%RetreiveParameter(name=SF_name_FBD, & + call fates_params%RetrieveParameter(name=SF_name_FBD, & data=SF_val_FBD) - call fates_params%RetreiveParameter(name=SF_name_min_moisture, & + call fates_params%RetrieveParameter(name=SF_name_min_moisture, & data=SF_val_min_moisture) - call fates_params%RetreiveParameter(name=SF_name_mid_moisture, & + call fates_params%RetrieveParameter(name=SF_name_mid_moisture, & data=SF_val_mid_moisture) - call fates_params%RetreiveParameter(name=SF_name_low_moisture_Coeff, & + call fates_params%RetrieveParameter(name=SF_name_low_moisture_Coeff, & data=SF_val_low_moisture_Coeff) - call fates_params%RetreiveParameter(name=SF_name_low_moisture_Slope, & + call fates_params%RetrieveParameter(name=SF_name_low_moisture_Slope, & data=SF_val_low_moisture_Slope) - call fates_params%RetreiveParameter(name=SF_name_mid_moisture_Coeff, & + call fates_params%RetrieveParameter(name=SF_name_mid_moisture_Coeff, & data=SF_val_mid_moisture_Coeff) - call fates_params%RetreiveParameter(name=SF_name_mid_moisture_Slope, & + call fates_params%RetrieveParameter(name=SF_name_mid_moisture_Slope, & data=SF_val_mid_moisture_Slope) - call fates_params%RetreiveParameter(name=SF_name_max_decomp, & + call fates_params%RetrieveParameter(name=SF_name_max_decomp, & data=SF_val_max_decomp) end subroutine SpitFireReceiveNFSC diff --git a/main/EDInitMod.F90 b/main/EDInitMod.F90 index 7463a2a8a4..451834a9ec 100644 --- a/main/EDInitMod.F90 +++ b/main/EDInitMod.F90 @@ -127,7 +127,13 @@ subroutine init_site_vars( site_in, bc_in, bc_out ) allocate(site_in%growthflux_fusion(1:nlevsclass,1:numpft)) allocate(site_in%mass_balance(1:num_elements)) allocate(site_in%flux_diags(1:num_elements)) - + + allocate(site_in%term_carbonflux_canopy(1:numpft)) + allocate(site_in%term_carbonflux_ustory(1:numpft)) + allocate(site_in%imort_carbonflux(1:numpft)) + allocate(site_in%fmort_carbonflux_canopy(1:numpft)) + allocate(site_in%fmort_carbonflux_ustory(1:numpft)) + site_in%nlevsoil = bc_in%nlevsoil allocate(site_in%rootfrac_scr(site_in%nlevsoil)) allocate(site_in%zi_soil(0:site_in%nlevsoil)) @@ -225,15 +231,15 @@ subroutine zero_site( site_in ) ! termination and recruitment info site_in%term_nindivs_canopy(:,:) = 0._r8 site_in%term_nindivs_ustory(:,:) = 0._r8 - site_in%term_carbonflux_canopy = 0._r8 - site_in%term_carbonflux_ustory = 0._r8 + site_in%term_carbonflux_canopy(:) = 0._r8 + site_in%term_carbonflux_ustory(:) = 0._r8 site_in%recruitment_rate(:) = 0._r8 site_in%imort_rate(:,:) = 0._r8 - site_in%imort_carbonflux = 0._r8 + site_in%imort_carbonflux(:) = 0._r8 site_in%fmort_rate_canopy(:,:) = 0._r8 site_in%fmort_rate_ustory(:,:) = 0._r8 - site_in%fmort_carbonflux_canopy = 0._r8 - site_in%fmort_carbonflux_ustory = 0._r8 + site_in%fmort_carbonflux_canopy(:) = 0._r8 + site_in%fmort_carbonflux_ustory(:) = 0._r8 site_in%fmort_rate_cambial(:,:) = 0._r8 site_in%fmort_rate_crown(:,:) = 0._r8 @@ -345,7 +351,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) 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 - write(fates_log(),*) 'removing small pft patches',s,ft,sites(s)%area_pft(ft) + 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 @@ -376,7 +382,7 @@ subroutine set_site_properties( nsites, sites,bc_in ) 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 @@ -396,6 +402,8 @@ subroutine set_site_properties( nsites, sites,bc_in ) end if !fixed biogeog 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 if(hlm_use_fixed_biogeog.eq.itrue)then if(sites(s)%area_pft(ft).gt.0.0_r8)then @@ -594,13 +602,13 @@ subroutine init_patches( nsites, sites, bc_in) ! remove or add extra area ! if the oldest patch has enough area, use that sites(s)%oldest_patch%area = sites(s)%oldest_patch%area - (tota-area) - write(*,*) 'fixing patch precision - oldest',s, tota-area + if(debug) write(fates_log(),*) 'fixing patch precision - oldest',s, tota-area else ! or otherwise take the area from the youngest patch. sites(s)%youngest_patch%area = sites(s)%oldest_patch%area - (tota-area) - write(*,*) 'fixing patch precision -youngest ',s, tota-area + if(debug) write(fates_log(),*) 'fixing patch precision -youngest ',s, tota-area endif else !this is a big error not just a precision error. - write(*,*) 'issue with patch area in EDinit',tota-area,tota + write(fates_log(),*) 'issue with patch area in EDinit',tota-area,tota call endrun(msg=errMsg(sourcefile, __LINE__)) endif ! big error end if ! too much patch area @@ -786,7 +794,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call bstore_allom(temp_cohort%dbh, pft, temp_cohort%canopy_trim, c_store) - temp_cohort%laimemory = 0._r8 + temp_cohort%leafmemory = 0._r8 temp_cohort%sapwmemory = 0._r8 temp_cohort%structmemory = 0._r8 cstatus = leaves_on @@ -797,7 +805,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) if( prt_params%season_decid(pft) == itrue .and. & any(site_in%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf temp_cohort%sapwmemory = c_sapw * stem_drop_fraction temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 @@ -808,7 +816,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) if ( prt_params%stress_decid(pft) == itrue .and. & any(site_in%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf temp_cohort%sapwmemory = c_sapw * stem_drop_fraction temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 @@ -849,21 +857,21 @@ subroutine init_cohorts( site_in, patch_in, bc_in) case(nitrogen_element) - m_struct = c_struct*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%nitr_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%nitr_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) + m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) case(phosphorus_element) - m_struct = c_struct*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw*prt_params%phos_stoich_p2(pft,prt_params%organ_param_id(sapw_organ)) + m_struct = c_struct*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(struct_organ)) + m_leaf = c_leaf*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(leaf_organ)) + m_fnrt = c_fnrt*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(fnrt_organ)) + m_sapw = c_sapw*prt_params%phos_stoich_p1(pft,prt_params%organ_param_id(sapw_organ)) m_repro = 0._r8 - m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) + m_store = StorageNutrientTarget(pft,element_id,m_leaf,m_fnrt,m_sapw,m_struct) end select @@ -892,7 +900,7 @@ subroutine init_cohorts( site_in, patch_in, bc_in) call prt_obj%CheckInitialConditions() call create_cohort(site_in, patch_in, pft, temp_cohort%n, temp_cohort%hite, & - temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%laimemory, & + temp_cohort%coage, temp_cohort%dbh, prt_obj, temp_cohort%leafmemory, & temp_cohort%sapwmemory, temp_cohort%structmemory, cstatus, rstatus, & temp_cohort%canopy_trim, temp_cohort%c_area,1, site_in%spread, bc_in) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 152911b59c..d05966ef14 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -149,7 +149,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in, bc_out) !----------------------------------------------------------------------- - if ( hlm_masterproc==itrue ) write(fates_log(),'(A,I4,A,I2.2,A,I2.2)') 'FATES Dynamics: ',& + if (debug .and.( hlm_masterproc==itrue)) write(fates_log(),'(A,I4,A,I2.2,A,I2.2)') 'FATES Dynamics: ',& hlm_current_year,'-',hlm_current_month,'-',hlm_current_day ! Consider moving this towards the end, because some of these @@ -349,6 +349,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) if( currentPatch%age < 0._r8 )then write(fates_log(),*) 'negative patch age?',currentPatch%age, & currentPatch%patchno,currentPatch%area + call endrun(msg=errMsg(sourcefile, __LINE__)) endif ! add age increment to secondary forest patches as well @@ -566,6 +567,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out ) currentCohort%coage = currentCohort%coage + hlm_freq_day if(currentCohort%coage < 0.0_r8)then write(fates_log(),*) 'negative cohort age?',currentCohort%coage + call endrun(msg=errMsg(sourcefile, __LINE__)) end if ! update cohort age class and age x pft class diff --git a/main/EDParamsMod.F90 b/main/EDParamsMod.F90 index 8c5e2500e0..2923f59d06 100644 --- a/main/EDParamsMod.F90 +++ b/main/EDParamsMod.F90 @@ -41,7 +41,6 @@ module EDParamsMod real(r8),protected, public :: ED_val_comp_excln real(r8),protected, public :: ED_val_vai_top_bin_width real(r8),protected, public :: ED_val_vai_width_increase_factor - real(r8),protected, public :: ED_val_init_litter real(r8),protected, public :: ED_val_nignitions real(r8),protected, public :: ED_val_understorey_death real(r8),protected, public :: ED_val_cwd_fcel @@ -87,42 +86,32 @@ module EDParamsMod real(r8),protected,allocatable,public :: ED_val_history_ageclass_bin_edges(:) 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(:) + ! Switch that defines the current pressure-volume and pressure-conductivity model ! to be used at each node (compartment/organ) ! 1 = Christofferson et al. 2016 (TFS), 2 = Van Genuchten 1980 integer, protected,allocatable,public :: hydr_htftype_node(:) - ! Switch that defines which hydraulic solver to use - ! 1 = Taylor solution that solves plant fluxes with 1 layer - ! sequentially placing solution on top of previous layer solves - ! 2 = Newton-Raphson solution that solves all fluxes in a plant and - ! the soil simultaneously, 2D: soil x (root + shell) - ! 3 = Picard solution that solves all fluxes in a plant and - ! the soil simultaneously, 2D: soil x (root + shell) - - integer, parameter, public :: hydr_solver_type = 1 ! 1 = hydr_solver_1DTaylor - - character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_photo_temp_acclim_timescale" - character(len=param_string_length),parameter,public :: name_photo_tempsens_model = "fates_photo_tempsens_model" + character(len=param_string_length),parameter,public :: ED_name_photo_temp_acclim_timescale = "fates_leaf_photo_temp_acclim_timescale" + character(len=param_string_length),parameter,public :: name_photo_tempsens_model = "fates_leaf_photo_tempsens_model" character(len=param_string_length),parameter,public :: name_maintresp_model = "fates_maintresp_model" - character(len=param_string_length),parameter,public :: ED_name_hydr_htftype_node = "fates_hydr_htftype_node" + character(len=param_string_length),parameter,public :: ED_name_hydr_htftype_node = "fates_hydro_htftype_node" character(len=param_string_length),parameter,public :: ED_name_mort_disturb_frac = "fates_mort_disturb_frac" character(len=param_string_length),parameter,public :: ED_name_comp_excln = "fates_comp_excln" character(len=param_string_length),parameter,public :: ED_name_vai_top_bin_width = "fates_vai_top_bin_width" character(len=param_string_length),parameter,public :: ED_name_vai_width_increase_factor = "fates_vai_width_increase_factor" - character(len=param_string_length),parameter,public :: ED_name_init_litter = "fates_init_litter" character(len=param_string_length),parameter,public :: ED_name_nignitions = "fates_fire_nignitions" character(len=param_string_length),parameter,public :: ED_name_understorey_death = "fates_mort_understorey_death" - character(len=param_string_length),parameter,public :: ED_name_cwd_fcel= "fates_cwd_fcel" - character(len=param_string_length),parameter,public :: ED_name_cwd_flig= "fates_cwd_flig" + character(len=param_string_length),parameter,public :: ED_name_cwd_fcel= "fates_frag_cwd_fcel" + character(len=param_string_length),parameter,public :: ED_name_cwd_flig= "fates_frag_cwd_flig" character(len=param_string_length),parameter,public :: ED_name_base_mr_20= "fates_base_mr_20" character(len=param_string_length),parameter,public :: ED_name_phen_drought_threshold= "fates_phen_drought_threshold" - character(len=param_string_length),parameter,public :: ED_name_phen_doff_time= "fates_phen_doff_time" - character(len=param_string_length),parameter,public :: ED_name_phen_a= "fates_phen_a" - character(len=param_string_length),parameter,public :: ED_name_phen_b= "fates_phen_b" - character(len=param_string_length),parameter,public :: ED_name_phen_c= "fates_phen_c" - character(len=param_string_length),parameter,public :: ED_name_phen_chiltemp= "fates_phen_chiltemp" + character(len=param_string_length),parameter,public :: ED_name_phen_doff_time= "fates_phen_mindaysoff" + character(len=param_string_length),parameter,public :: ED_name_phen_a= "fates_phen_gddthresh_a" + character(len=param_string_length),parameter,public :: ED_name_phen_b= "fates_phen_gddthresh_b" + character(len=param_string_length),parameter,public :: ED_name_phen_c= "fates_phen_gddthresh_c" + character(len=param_string_length),parameter,public :: ED_name_phen_chiltemp= "fates_phen_chilltemp" character(len=param_string_length),parameter,public :: ED_name_phen_mindayson= "fates_phen_mindayson" character(len=param_string_length),parameter,public :: ED_name_phen_ncolddayslim= "fates_phen_ncolddayslim" character(len=param_string_length),parameter,public :: ED_name_phen_coldtemp= "fates_phen_coldtemp" @@ -132,8 +121,8 @@ module EDParamsMod 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 :: name_theta_cj_c3 = "fates_theta_cj_c3" - character(len=param_string_length),parameter,public :: name_theta_cj_c4 = "fates_theta_cj_c4" + character(len=param_string_length),parameter,public :: name_theta_cj_c3 = "fates_leaf_theta_cj_c3" + character(len=param_string_length),parameter,public :: name_theta_cj_c4 = "fates_leaf_theta_cj_c4" character(len=param_string_length),parameter :: fates_name_q10_mr="fates_q10_mr" character(len=param_string_length),parameter :: fates_name_q10_froz="fates_q10_froz" @@ -143,71 +132,118 @@ module EDParamsMod character(len=param_string_length),parameter,public :: ED_name_history_ageclass_bin_edges= "fates_history_ageclass_bin_edges" 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" ! Hydraulics Control Parameters (ONLY RELEVANT WHEN USE_FATES_HYDR = TRUE) ! ---------------------------------------------------------------------------------------------- real(r8),protected,public :: hydr_kmax_rsurf1 ! maximum conducitivity for unit root surface ! soil to root direction (kg water/m2 root area/Mpa/s) - character(len=param_string_length),parameter,public :: hydr_name_kmax_rsurf1 = "fates_hydr_kmax_rsurf1" + character(len=param_string_length),parameter,public :: hydr_name_kmax_rsurf1 = "fates_hydro_kmax_rsurf1" real(r8),protected,public :: hydr_kmax_rsurf2 ! maximum conducitivity for unit root surface ! root to soil direciton (kg water/m2 root area/Mpa/s) - character(len=param_string_length),parameter,public :: hydr_name_kmax_rsurf2 = "fates_hydr_kmax_rsurf2" + character(len=param_string_length),parameter,public :: hydr_name_kmax_rsurf2 = "fates_hydro_kmax_rsurf2" real(r8),protected,public :: hydr_psi0 ! sapwood water potential at saturation (MPa) - character(len=param_string_length),parameter,public :: hydr_name_psi0 = "fates_hydr_psi0" + character(len=param_string_length),parameter,public :: hydr_name_psi0 = "fates_hydro_psi0" real(r8),protected,public :: hydr_psicap ! sapwood water potential at which capillary reserves exhausted (MPa) - character(len=param_string_length),parameter,public :: hydr_name_psicap = "fates_hydr_psicap" + character(len=param_string_length),parameter,public :: hydr_name_psicap = "fates_hydro_psicap" + + ! Switch that defines which hydraulic solver to use + ! 1 = Taylor solution that solves plant fluxes with 1 layer + ! sequentially placing solution on top of previous layer solves + ! 2 = Picard solution that solves all fluxes in a plant and + ! the soil simultaneously, 2D: soil x (root + shell) + ! 3 = Newton-Raphson (Deprecated) solution that solves all fluxes in a plant and + ! the soil simultaneously, 2D: soil x (root + shell) + + integer,protected,public :: hydr_solver ! switch designating hydraulics numerical solver + character(len=param_string_length),parameter,public :: hydr_name_solver = "fates_hydro_solver" + !Soil BGC parameters, mostly used for testing FATES when not coupled to the dynamics bgc hlm ! ---------------------------------------------------------------------------------------------- real(r8),protected,public :: bgc_soil_salinity ! site-level soil salinity for FATES when not coupled to dynamic soil BGC of salinity character(len=param_string_length),parameter,public :: bgc_name_soil_salinity= "fates_soil_salinity" + + ! Switch designating whether to use net or gross assimilation in the stomata model + integer, protected, public :: stomatal_assim_model + character(len=param_string_length), parameter, public :: stomatal_assim_name = "fates_leaf_stomatal_assim_model" + + ! Integer code that options how damage events are structured + integer, protected, public :: damage_event_code + character(len=param_string_length), parameter, public :: damage_name_event_code = "fates_damage_event_code" + + integer,protected,public :: damage_canopy_layer_code ! Code that changes whether damage affects canopy trees (1), understory trees (2) + character(len=param_string_length),parameter,public :: damage_name_canopy_layer_code = "fates_damage_canopy_layer_code" + + ! Maximum allowable primary and secondary patches + ! These values are USED FOR ALLOCATIONS IN BOTH FATES AND CLM/ELM!!!! + ! The number of patches specified in the parameter file may be over-written. + ! For instance, in SP mode, we want the same number of primary patches as the number of PFTs + ! in the fates parameter file, and zero secondary. + + integer, public :: maxpatch_primary + character(len=param_string_length), parameter, public :: maxpatch_primary_name = "fates_maxpatch_primary" + + integer, public :: maxpatch_secondary + character(len=param_string_length), parameter, public :: maxpatch_secondary_name = "fates_maxpatch_secondary" + + integer, public :: maxpatch_total + + ! Maximum allowable cohorts per patch + integer, protected, public :: max_cohort_per_patch + character(len=param_string_length), parameter, public :: maxcohort_name = "fates_maxcohort" + + ! Logging Control Parameters (ONLY RELEVANT WHEN USE_FATES_LOGGING = TRUE) ! ---------------------------------------------------------------------------------------------- real(r8),protected,public :: logging_dbhmin ! Minimum dbh at which logging is applied (cm) ! Typically associated with harvesting - character(len=param_string_length),parameter,public :: logging_name_dbhmin = "fates_logging_dbhmin" + character(len=param_string_length),parameter,public :: logging_name_dbhmin = "fates_landuse_logging_dbhmin" real(r8),protected,public :: logging_dbhmax ! Maximum dbh at which logging is applied (cm) ! Typically associated with fire suppression - character(len=param_string_length),parameter,public :: logging_name_dbhmax = "fates_logging_dbhmax" + character(len=param_string_length),parameter,public :: logging_name_dbhmax = "fates_landuse_logging_dbhmax" real(r8),protected,public :: logging_collateral_frac ! Ratio of collateral mortality to direct logging mortality - character(len=param_string_length),parameter,public :: logging_name_collateral_frac = "fates_logging_collateral_frac" + character(len=param_string_length),parameter,public :: logging_name_collateral_frac = "fates_landuse_logging_collateral_frac" real(r8),protected,public :: logging_coll_under_frac ! Fraction of understory plants that die when logging disturbance ! is generated - character(len=param_string_length),parameter,public :: logging_name_coll_under_frac = "fates_logging_coll_under_frac" + character(len=param_string_length),parameter,public :: logging_name_coll_under_frac = "fates_landuse_logging_coll_under_frac" real(r8),protected,public :: logging_direct_frac ! Fraction of stems logged per event - character(len=param_string_length),parameter,public :: logging_name_direct_frac = "fates_logging_direct_frac" + character(len=param_string_length),parameter,public :: logging_name_direct_frac = "fates_landuse_logging_direct_frac" real(r8),protected,public :: logging_mechanical_frac ! Fraction of stems logged per event - character(len=param_string_length),parameter,public :: logging_name_mechanical_frac = "fates_logging_mechanical_frac" + character(len=param_string_length),parameter,public :: logging_name_mechanical_frac = "fates_landuse_logging_mechanical_frac" real(r8),protected,public :: logging_event_code ! Code that options how logging events are structured - character(len=param_string_length),parameter,public :: logging_name_event_code = "fates_logging_event_code" + character(len=param_string_length),parameter,public :: logging_name_event_code = "fates_landuse_logging_event_code" real(r8),protected,public :: logging_dbhmax_infra ! "Tree diameter, above which infrastructure from logging does not impact damage or mortality. - character(len=param_string_length),parameter,public :: logging_name_dbhmax_infra = "fates_logging_dbhmax_infra" + character(len=param_string_length),parameter,public :: logging_name_dbhmax_infra = "fates_landuse_logging_dbhmax_infra" real(r8),protected,public :: logging_export_frac ! "fraction of trunk product being shipped offsite, the ! leftovers will be left onsite as large CWD - character(len=param_string_length),parameter,public :: logging_name_export_frac ="fates_logging_export_frac" + 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_pprodharv10_forest_mean" + 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) - character(len=param_string_length),parameter,public :: eca_name_plant_escalar = "fates_eca_plant_escalar" + + + + character(len=param_string_length),parameter,public :: eca_name_plant_escalar = "fates_cnp_eca_plant_escalar" public :: FatesParamsInit public :: FatesRegisterParams @@ -234,7 +270,6 @@ subroutine FatesParamsInit() ED_val_comp_excln = nan ED_val_vai_top_bin_width = nan ED_val_vai_width_increase_factor = nan - ED_val_init_litter = nan ED_val_nignitions = nan ED_val_understorey_death = nan ED_val_cwd_fcel = nan @@ -254,10 +289,15 @@ subroutine FatesParamsInit() ED_val_patch_fusion_tol = nan ED_val_canopy_closure_thresh = nan stomatal_model = -9 + stomatal_assim_model = -9 + maxpatch_primary = -9 + maxpatch_secondary = -9 + max_cohort_per_patch = -9 hydr_kmax_rsurf1 = nan hydr_kmax_rsurf2 = nan hydr_psi0 = nan hydr_psicap = nan + hydr_solver = -9 bgc_soil_salinity = nan logging_dbhmin = nan logging_dbhmax = nan @@ -274,6 +314,8 @@ subroutine FatesParamsInit() theta_cj_c3 = nan theta_cj_c4 = nan dev_arbitrary = nan + damage_event_code = -9 + damage_canopy_layer_code = -9 end subroutine FatesParamsInit !----------------------------------------------------------------------- @@ -285,7 +327,7 @@ subroutine FatesRegisterParams(fates_params) use FatesParametersInterface, only : fates_parameters_type, dimension_name_scalar, dimension_shape_1d 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 + use FatesParametersInterface, only : dimension_name_history_coage_bins, dimension_name_history_damage_bins use FatesParametersInterface, only : dimension_shape_scalar @@ -299,7 +341,8 @@ subroutine FatesRegisterParams(fates_params) character(len=param_string_length), parameter :: dim_names_height(1) = (/dimension_name_history_height_bins/) 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/) + call FatesParamsInit() call fates_params%RegisterParameter(name=ED_name_photo_temp_acclim_timescale, dimension_shape=dimension_shape_scalar, & @@ -329,9 +372,6 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_vai_width_increase_factor, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_init_litter, dimension_shape=dimension_shape_scalar, & - dimension_names=dim_names_scalar) - call fates_params%RegisterParameter(name=ED_name_nignitions, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -388,7 +428,22 @@ 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=stomatal_assim_name, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=maxpatch_primary_name, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=maxpatch_secondary_name, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=maxcohort_name, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=hydr_name_solver, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + call fates_params%RegisterParameter(name=hydr_name_kmax_rsurf1, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) @@ -445,6 +500,12 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=name_dev_arbitrary, dimension_shape=dimension_shape_scalar, & dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=damage_name_event_code, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) + + call fates_params%RegisterParameter(name=damage_name_canopy_layer_code, dimension_shape=dimension_shape_scalar, & + dimension_names=dim_names_scalar) ! non-scalar parameters @@ -469,6 +530,8 @@ subroutine FatesRegisterParams(fates_params) call fates_params%RegisterParameter(name=ED_name_history_coageclass_bin_edges, dimension_shape=dimension_shape_1d, & dimension_names=dim_names_coageclass) + call fates_params%RegisterParameter(name=ED_name_history_damage_bin_edges, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names_damageclass) end subroutine FatesRegisterParams @@ -485,174 +548,204 @@ subroutine FatesReceiveParams(fates_params) real(r8) :: tmpreal ! local real variable for changing type on read real(r8), allocatable :: hydr_htftype_real(:) - call fates_params%RetreiveParameter(name=ED_name_photo_temp_acclim_timescale, & + call fates_params%RetrieveParameter(name=ED_name_photo_temp_acclim_timescale, & data=photo_temp_acclim_timescale) - call fates_params%RetreiveParameter(name=name_photo_tempsens_model, & + call fates_params%RetrieveParameter(name=name_photo_tempsens_model, & data=tmpreal) photo_tempsens_model = nint(tmpreal) - call fates_params%RetreiveParameter(name=name_maintresp_model, & + call fates_params%RetrieveParameter(name=name_maintresp_model, & data=tmpreal) maintresp_model = nint(tmpreal) - call fates_params%RetreiveParameter(name=ED_name_mort_disturb_frac, & + call fates_params%RetrieveParameter(name=ED_name_mort_disturb_frac, & data=fates_mortality_disturbance_fraction) - call fates_params%RetreiveParameter(name=ED_name_comp_excln, & + call fates_params%RetrieveParameter(name=ED_name_comp_excln, & data=ED_val_comp_excln) - call fates_params%RetreiveParameter(name=ED_name_vai_top_bin_width, & + call fates_params%RetrieveParameter(name=ED_name_vai_top_bin_width, & data=ED_val_vai_top_bin_width) - call fates_params%RetreiveParameter(name=ED_name_vai_width_increase_factor, & + call fates_params%RetrieveParameter(name=ED_name_vai_width_increase_factor, & data=ED_val_vai_width_increase_factor) - call fates_params%RetreiveParameter(name=ED_name_init_litter, & - data=ED_val_init_litter) - - call fates_params%RetreiveParameter(name=ED_name_nignitions, & + call fates_params%RetrieveParameter(name=ED_name_nignitions, & data=ED_val_nignitions) - call fates_params%RetreiveParameter(name=ED_name_understorey_death, & + call fates_params%RetrieveParameter(name=ED_name_understorey_death, & data=ED_val_understorey_death) - call fates_params%RetreiveParameter(name=ED_name_cwd_fcel, & + call fates_params%RetrieveParameter(name=ED_name_cwd_fcel, & data=ED_val_cwd_fcel) - call fates_params%RetreiveParameter(name=ED_name_cwd_flig, & + call fates_params%RetrieveParameter(name=ED_name_cwd_flig, & data=ED_val_cwd_flig) - call fates_params%RetreiveParameter(name=ED_name_base_mr_20, & + call fates_params%RetrieveParameter(name=ED_name_base_mr_20, & data=ED_val_base_mr_20) - call fates_params%RetreiveParameter(name=ED_name_phen_drought_threshold, & + call fates_params%RetrieveParameter(name=ED_name_phen_drought_threshold, & data=ED_val_phen_drought_threshold) - call fates_params%RetreiveParameter(name=ED_name_phen_doff_time, & + call fates_params%RetrieveParameter(name=ED_name_phen_doff_time, & data=ED_val_phen_doff_time) - call fates_params%RetreiveParameter(name=ED_name_phen_a, & + call fates_params%RetrieveParameter(name=ED_name_phen_a, & data=ED_val_phen_a) - call fates_params%RetreiveParameter(name=ED_name_phen_b, & + call fates_params%RetrieveParameter(name=ED_name_phen_b, & data=ED_val_phen_b) - call fates_params%RetreiveParameter(name=ED_name_phen_c, & + call fates_params%RetrieveParameter(name=ED_name_phen_c, & data=ED_val_phen_c) - call fates_params%RetreiveParameter(name=ED_name_phen_chiltemp, & + call fates_params%RetrieveParameter(name=ED_name_phen_chiltemp, & data=ED_val_phen_chiltemp) - call fates_params%RetreiveParameter(name=ED_name_phen_mindayson, & + call fates_params%RetrieveParameter(name=ED_name_phen_mindayson, & data=ED_val_phen_mindayson) - call fates_params%RetreiveParameter(name=ED_name_phen_ncolddayslim, & + call fates_params%RetrieveParameter(name=ED_name_phen_ncolddayslim, & data=ED_val_phen_ncolddayslim) - call fates_params%RetreiveParameter(name=ED_name_phen_coldtemp, & + call fates_params%RetrieveParameter(name=ED_name_phen_coldtemp, & data=ED_val_phen_coldtemp) - call fates_params%RetreiveParameter(name=ED_name_cohort_size_fusion_tol, & + call fates_params%RetrieveParameter(name=ED_name_cohort_size_fusion_tol, & data=ED_val_cohort_size_fusion_tol) - call fates_params%RetreiveParameter(name=ED_name_cohort_age_fusion_tol, & + call fates_params%RetrieveParameter(name=ED_name_cohort_age_fusion_tol, & data=ED_val_cohort_age_fusion_tol) - call fates_params%RetreiveParameter(name=ED_name_patch_fusion_tol, & + call fates_params%RetrieveParameter(name=ED_name_patch_fusion_tol, & data=ED_val_patch_fusion_tol) - call fates_params%RetreiveParameter(name=ED_name_canopy_closure_thresh, & + call fates_params%RetrieveParameter(name=ED_name_canopy_closure_thresh, & data=ED_val_canopy_closure_thresh) - call fates_params%RetreiveParameter(name=ED_name_stomatal_model, & + call fates_params%RetrieveParameter(name=ED_name_stomatal_model, & data=tmpreal) stomatal_model = nint(tmpreal) - call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf1, & + call fates_params%RetrieveParameter(name=stomatal_assim_name, & + data=tmpreal) + stomatal_assim_model = nint(tmpreal) + + call fates_params%RetrieveParameter(name=maxpatch_primary_name, & + data=tmpreal) + maxpatch_primary = nint(tmpreal) + + call fates_params%RetrieveParameter(name=maxpatch_secondary_name, & + data=tmpreal) + maxpatch_secondary = nint(tmpreal) + + maxpatch_total = maxpatch_primary+maxpatch_secondary + + call fates_params%RetrieveParameter(name=maxcohort_name, & + data=tmpreal) + max_cohort_per_patch = nint(tmpreal) + + call fates_params%RetrieveParameter(name=hydr_name_kmax_rsurf1, & data=hydr_kmax_rsurf1) - call fates_params%RetreiveParameter(name=hydr_name_kmax_rsurf2, & + call fates_params%RetrieveParameter(name=hydr_name_kmax_rsurf2, & data=hydr_kmax_rsurf2) - call fates_params%RetreiveParameter(name=hydr_name_psi0, & + call fates_params%RetrieveParameter(name=hydr_name_psi0, & data=hydr_psi0) - call fates_params%RetreiveParameter(name=hydr_name_psicap, & + call fates_params%RetrieveParameter(name=hydr_name_psicap, & data=hydr_psicap) - - call fates_params%RetreiveParameter(name=bgc_name_soil_salinity, & + + call fates_params%RetrieveParameter(name=hydr_name_solver, & + data=tmpreal) + hydr_solver = nint(tmpreal) + + call fates_params%RetrieveParameter(name=bgc_name_soil_salinity, & data=bgc_soil_salinity) - call fates_params%RetreiveParameter(name=logging_name_dbhmin, & + call fates_params%RetrieveParameter(name=logging_name_dbhmin, & data=logging_dbhmin) - call fates_params%RetreiveParameter(name=logging_name_dbhmax, & + call fates_params%RetrieveParameter(name=logging_name_dbhmax, & data=logging_dbhmax) - call fates_params%RetreiveParameter(name=logging_name_collateral_frac, & + call fates_params%RetrieveParameter(name=logging_name_collateral_frac, & data=logging_collateral_frac) - call fates_params%RetreiveParameter(name=logging_name_coll_under_frac, & + call fates_params%RetrieveParameter(name=logging_name_coll_under_frac, & data=logging_coll_under_frac) - call fates_params%RetreiveParameter(name=logging_name_direct_frac, & + call fates_params%RetrieveParameter(name=logging_name_direct_frac, & data=logging_direct_frac) - call fates_params%RetreiveParameter(name=logging_name_mechanical_frac, & + call fates_params%RetrieveParameter(name=logging_name_mechanical_frac, & data=logging_mechanical_frac) - call fates_params%RetreiveParameter(name=logging_name_event_code, & + call fates_params%RetrieveParameter(name=logging_name_event_code, & data=logging_event_code) - call fates_params%RetreiveParameter(name=logging_name_dbhmax_infra, & + call fates_params%RetrieveParameter(name=logging_name_dbhmax_infra, & data=logging_dbhmax_infra) - call fates_params%RetreiveParameter(name=logging_name_export_frac, & + call fates_params%RetrieveParameter(name=logging_name_export_frac, & data=logging_export_frac) - call fates_params%RetreiveParameter(name=logging_name_pprodharv10, & - data=pprodharv10_forest_mean) - - call fates_params%RetreiveParameter(name=eca_name_plant_escalar, & + 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) - call fates_params%RetreiveParameter(name=name_theta_cj_c3, & + call fates_params%RetrieveParameter(name=name_theta_cj_c3, & data=theta_cj_c3) - call fates_params%RetreiveParameter(name=name_theta_cj_c4, & + call fates_params%RetrieveParameter(name=name_theta_cj_c4, & data=theta_cj_c4) - call fates_params%RetreiveParameter(name=fates_name_q10_mr, & + call fates_params%RetrieveParameter(name=fates_name_q10_mr, & data=q10_mr) - call fates_params%RetreiveParameter(name=fates_name_q10_froz, & + call fates_params%RetrieveParameter(name=fates_name_q10_froz, & data=q10_froz) - call fates_params%RetreiveParameter(name=name_dev_arbitrary, & + call fates_params%RetrieveParameter(name=name_dev_arbitrary, & data=dev_arbitrary) - call fates_params%RetreiveParameter(name=fates_name_active_crown_fire, & + call fates_params%RetrieveParameter(name=fates_name_active_crown_fire, & data=tmpreal) active_crown_fire = (abs(tmpreal-1.0_r8) max_warnings) then + warn_active(ind) = .false. + write(fates_log(),*) 'FATESWARN: '//trim(ADJUSTL(I2S(ind)))//' has saturated messaging, no longer reporting' + end if + end if + return + end subroutine FatesWarn + + ! ===================================================================================== + + + subroutine FatesReportTotalWarnings() + + integer :: ind + + do ind = 0,max_ids + + if(warn_counts(ind)>0)then + + write(fates_log(),*) 'FATESWARN: '//trim(ADJUSTL(I2S(ind)))//' was triggered ',trim(ADJUSTL(I2S(warn_counts(ind))))//' times' + + end if + + end do + + + end subroutine FatesReportTotalWarnings + + + ! ===================================================================================== + + function N2S(real_in) result(str) + + real(r8) :: real_in + character(len=16) :: str + + !write(str,*) real_in + write(str,'(E12.6)') real_in + + end function N2S + ! ===================================================================================== + function I2S(int_in) result(str) + integer :: int_in + character(len=16) :: str + + !write(str,*) real_in + write(str,'(I15)') int_in + + end function I2S + + ! ===================================================================================== + + function A2S(reals_in) result(str) + + real(r8) :: reals_in(:) + character(len=1024) :: str + integer :: i, nreal + + str = ', ' + do i = 1,ubound(reals_in,1) + str = trim(str)//', '//N2S(reals_in(i)) + end do + + end function A2S + end module FatesGlobals diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 4094b2055d..20b9bc1465 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -220,6 +220,9 @@ module FatesHistoryInterfaceMod integer :: ih_bstor_understory_si_scpf integer :: ih_bleaf_canopy_si_scpf integer :: ih_bleaf_understory_si_scpf + ! Size-class x PFT LAI states + integer :: ih_lai_canopy_si_scpf + integer :: ih_lai_understory_si_scpf @@ -510,6 +513,10 @@ module FatesHistoryInterfaceMod integer :: ih_nindivs_si_pft integer :: ih_recruitment_si_pft integer :: ih_mortality_si_pft + integer :: ih_mortality_carbonflux_si_pft + integer :: ih_hydraulicmortality_carbonflux_si_pft + integer :: ih_cstarvmortality_carbonflux_si_pft + integer :: ih_firemortality_carbonflux_si_pft integer :: ih_crownarea_si_pft integer :: ih_canopycrownarea_si_pft integer :: ih_gpp_si_pft @@ -1108,8 +1115,7 @@ subroutine set_dim_indices(this, dk_name, idim, dim_index) write(fates_log(), *) 'Trying to define dimension size to a dim-type structure' write(fates_log(), *) 'but the dimension index does not exist' write(fates_log(), *) 'type: ',dk_name,' ndims: ',this%dim_kinds(ityp)%ndims,' input dim:',idim - stop - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if (idim == 1) then @@ -1797,6 +1803,10 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_nindivs_si_pft => this%hvars(ih_nindivs_si_pft)%r82d, & hio_recruitment_si_pft => this%hvars(ih_recruitment_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, & @@ -1861,6 +1871,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) 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_understory_si_scpf => this%hvars(ih_mortality_understory_si_scpf)%r82d, & hio_nplant_canopy_si_scpf => this%hvars(ih_nplant_canopy_si_scpf)%r82d, & @@ -2504,7 +2516,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) store_m_net_alloc*n_perm2 / days_per_year / sec_per_day ! Woody State Variables (basal area growth increment) - if ( int(prt_params%woody(ft)) == itrue) then + 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) + & @@ -2558,6 +2570,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) 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 + !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) + & @@ -2585,6 +2598,18 @@ subroutine update_history_dyn(this,nc,nsites,sites) 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) * & + 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 ! number density by size and biomass hio_agb_si_scls(io_si,scls) = hio_agb_si_scls(io_si,scls) + & @@ -2631,6 +2656,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) 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_canopy_biomass_si(io_si) = hio_canopy_biomass_si(io_si) + n_perm2 * total_m @@ -2724,6 +2751,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) 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 !hio_mortality_understory_si_scpf(io_si,scpf) = hio_mortality_understory_si_scpf(io_si,scpf)+ & ! (ccohort%bmort + ccohort%hmort + ccohort%cmort + @@ -2996,14 +3025,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) 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 - ! - ! carbon flux associated with mortality of trees dying by fire - hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & - sites(s)%fmort_carbonflux_canopy / g_per_kg - - hio_understory_mortality_carbonflux_si(io_si) = hio_understory_mortality_carbonflux_si(io_si) + & - sites(s)%fmort_carbonflux_ustory / g_per_kg - ! ! for scag variables, also treat as happening in the newly-disurbed patch @@ -3019,18 +3040,35 @@ subroutine update_history_dyn(this,nc,nsites,sites) 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) + & - sites(s)%imort_carbonflux / g_per_kg - ! + sum(sites(s)%imort_carbonflux(:)) / g_per_kg + + do i_pft = 1, numpft + hio_mortality_carbonflux_si_pft(io_si,i_pft) = hio_mortality_carbonflux_si_pft(io_si,i_pft) + & + (sites(s)%fmort_carbonflux_canopy(i_pft) + & + sites(s)%fmort_carbonflux_ustory(i_pft) + & + sites(s)%imort_carbonflux(i_pft) ) / g_per_kg !cdk + + hio_firemortality_carbonflux_si_pft(io_si,i_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) / g_per_kg + end do + sites(s)%term_nindivs_canopy(:,:) = 0._r8 sites(s)%term_nindivs_ustory(:,:) = 0._r8 - sites(s)%imort_carbonflux = 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_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 @@ -3430,14 +3468,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! mortality-associated carbon fluxes hio_canopy_mortality_carbonflux_si(io_si) = hio_canopy_mortality_carbonflux_si(io_si) + & - sites(s)%term_carbonflux_canopy * days_per_sec * ha_per_m2 + 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) + & - sites(s)%term_carbonflux_ustory * days_per_sec * ha_per_m2 + sum(sites(s)%term_carbonflux_ustory(:)) * days_per_sec * ha_per_m2 ! and 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 ! ! add the site-level disturbance-associated cwd and litter input fluxes to thir respective flux fields @@ -3487,8 +3525,9 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) real(r8) :: npp ! npp for this time-step (adjusted for g resp) [kgC/indiv/step] real(r8) :: aresp ! autotrophic respiration (adjusted for g resp) [kgC/indiv/step] real(r8) :: n_perm2 ! individuals per m2 for the whole column - real(r8) :: patch_area_by_age(nlevage) ! patch area in each bin for normalizing purposes + real(r8) :: patch_area_by_age(nlevage) ! patch area in each bin for normalizing purposes real(r8) :: canopy_area_by_age(nlevage) ! canopy area in each bin for normalizing purposes + real(r8) :: site_area_veg ! area of the site that is not bare-ground real(r8), parameter :: tiny = 1.e-5_r8 ! some small number integer :: ipa2 ! patch incrementer integer :: cnlfpft_indx, cnlf_indx, ipft, ican, ileaf ! more iterators and indices @@ -3583,11 +3622,18 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_hr_si(io_si) = bc_in(s)%tot_het_resp / g_per_kg ipa = 0 - cpatch => sites(s)%oldest_patch - + patch_area_by_age(1:nlevage) = 0._r8 canopy_area_by_age(1:nlevage) = 0._r8 + + ! Calculate the site-level total vegetated area (i.e. non-bareground) + if (hlm_use_nocomp .eq. itrue) then + site_area_veg = area - sites(s)%area_pft(0) + else + site_area_veg = area + end if + cpatch => sites(s)%oldest_patch do while(associated(cpatch)) patch_area_by_age(cpatch%age_class) = & @@ -3613,10 +3659,14 @@ subroutine update_history_hifrq(this,nc,nsites,sites,bc_in,dt_tstep) hio_rad_error_si(io_si) = hio_rad_error_si(io_si) + & cpatch%radiation_error * cpatch%area * AREA_INV + + ! Only accumulate the instantaneous vegetation temperature for vegetated patches + if (cpatch%patchno .ne. 0) then + hio_tveg(io_si) = hio_tveg(io_si) + & + (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm) * & + cpatch%area / site_area_veg + end if - hio_tveg(io_si) = hio_tveg(io_si) + & - (bc_in(s)%t_veg_pa(cpatch%patchno) - t_water_freeze_k_1atm)*cpatch%area*area_inv - ccohort => cpatch%shortest do while(associated(ccohort)) @@ -4042,7 +4092,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) 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) + 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 @@ -4230,11 +4280,8 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,bc_in,dt_tstep) end if if(print_iterations) then -! print*,' Mean solves: ',sum(hio_iterh2_scpf(io_si,:))/real(count(ncohort_scpf(:)>0._r8),r8), & -! ' Mean failures: ',sum(hio_iterh1_scpf(io_si,:))/real(count(ncohort_scpf(:)>0._r8),r8) - write(fmt_char,'(I2)') iterh2_nhist - write(fates_log(),fmt='(A,'//fmt_char//'I5)') 'Solves: ',int(iterh2_histy(:)) - !write(*,*) 'Histogram: ',int(iterh2_histy(:)) + write(fmt_char,'(I2)') iterh2_nhist + write(fates_log(),fmt='(A,'//fmt_char//'I5)') 'Solves: ',int(iterh2_histy(:)) end if @@ -5441,6 +5488,30 @@ subroutine define_history_vars(this, initialize_variables) upfreq=1, ivar=ivar, initialize=initialize_variables, & index = ih_understory_mortality_carbonflux_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_HYDRAULIC_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) + ! size class by age dimensioned variables call this%set_history_var(vname='FATES_NPLANT_SZAP', units = 'm-2', & @@ -5791,6 +5862,14 @@ subroutine define_history_vars(this, initialize_variables) 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, & @@ -5819,6 +5898,13 @@ subroutine define_history_vars(this, initialize_variables) 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', & diff --git a/main/FatesHistoryVariableType.F90 b/main/FatesHistoryVariableType.F90 index c56d1db984..b7bcc52176 100644 --- a/main/FatesHistoryVariableType.F90 +++ b/main/FatesHistoryVariableType.F90 @@ -1,7 +1,8 @@ module FatesHistoryVariableType use FatesConstantsMod, only : r8 => fates_r8 - use FatesGlobals, only : fates_log + use FatesGlobals, only : fates_log + use FatesGlobals , only : endrun => fates_endrun use FatesIODimensionsMod, only : fates_io_dimension_type use FatesIOVariableKindMod, only : fates_io_variable_kind_type use FatesIOVariableKindMod, only : site_r8, site_soil_r8, site_size_pft_r8 @@ -14,12 +15,16 @@ module FatesHistoryVariableType use FatesIOVariableKindMod, only : site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8 use FatesIOVariableKindMod, only : iotype_index, site_agefuel_r8 - + use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private ! By default everything is private ! Make public necessary subroutines and functions + + character(len=*), parameter, private :: sourcefile = & + __FILE__ ! This type is instanteated in the HLM-FATES interface (clmfates_interfaceMod.F90) @@ -196,8 +201,7 @@ subroutine Init(this, vname, units, long, use_default, & case default write(fates_log(),*) 'Incompatible vtype passed to set_history_var' write(fates_log(),*) 'vtype = ',trim(vtype),' ?' - stop - ! end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end subroutine Init @@ -316,8 +320,7 @@ subroutine Flush(this, thread, dim_bounds, dim_kinds) this%r82d(lb1:ub1, lb2:ub2) = this%flushval case default write(fates_log(),*) 'fates history variable type undefined while flushing history variables' - stop - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end subroutine Flush diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 65163e1c8c..57329921b4 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -14,8 +14,8 @@ module FatesHydraulicsMemMod ! Define the various different solver options for hydraulics integer, parameter, public :: hydr_solver_1DTaylor = 1 - integer, parameter, public :: hydr_solver_2DNewton = 2 - integer, parameter, public :: hydr_solver_2DPicard = 3 + integer, parameter, public :: hydr_solver_2DNewton = 3 + integer, parameter, public :: hydr_solver_2DPicard = 2 ! Number of soil layers for indexing cohort fine root quanitities ! NOTE: The hydraulics code does have some capacity to run a single soil diff --git a/main/FatesIODimensionsMod.F90 b/main/FatesIODimensionsMod.F90 index 6760bf0dbe..c8d4c17b85 100644 --- a/main/FatesIODimensionsMod.F90 +++ b/main/FatesIODimensionsMod.F90 @@ -27,6 +27,9 @@ module FatesIODimensionsMod character(*), parameter, public :: levcnlf = 'fates_levcnlf' ! matches histFileMod character(*), parameter, public :: levcnlfpft = 'fates_levcnlfpf' ! matches histFileMod character(*), parameter, public :: levagefuel = 'fates_levagefuel' ! matches histFileMod + character(*), parameter, public :: levcdsc = 'fates_levcdsc' ! matches histFileMod + character(*), parameter, public :: levcdpf = 'fates_levcdpf' ! matches histFileMod + character(*), parameter, public :: levcdam = 'fates_levcdam' ! matches histFileMod character(*), parameter, public :: levelem = 'fates_levelem' character(*), parameter, public :: levelpft = 'fates_levelpft' @@ -93,7 +96,15 @@ module FatesIODimensionsMod ! levelcwd = This records the boundaries for element x cwd ! levelage = This records the boundaries for element x age + ! levcdsc = This is a structure that records the boundaries for the + ! number of crown damage x size classes dimension + ! levcdpf = This is a structure that records the boundaries for the + ! number of crown damage x size classes x pft dimension + + ! levcdam = This is the structure that records the boundaries for the + ! number of crown damage classes dimension + type, public :: fates_bounds_type integer :: cohort_begin integer :: cohort_end @@ -131,6 +142,12 @@ module FatesIODimensionsMod integer :: cnlf_end integer :: cnlfpft_begin integer :: cnlfpft_end + integer :: cdsc_begin + integer :: cdsc_end + integer :: cdpf_begin + integer :: cdpf_end + integer :: cdam_begin + integer :: cdam_end integer :: elem_begin integer :: elem_end integer :: elpft_begin diff --git a/main/FatesIOVariableKindMod.F90 b/main/FatesIOVariableKindMod.F90 index daba4f3c20..853122730e 100644 --- a/main/FatesIOVariableKindMod.F90 +++ b/main/FatesIOVariableKindMod.F90 @@ -3,10 +3,16 @@ module FatesIOVariableKindMod use FatesConstantsMod, only : fates_long_string_length use FatesGlobals, only : fates_log use FatesIODimensionsMod, only : fates_io_dimension_type + use FatesGlobals , only : endrun => fates_endrun + use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private + character(len=*), parameter, private :: sourcefile = & + __FILE__ + ! FIXME(bja, 2016-10) do these need to be strings, or can they be integer enumerations? ! FIXME(rgk, 2016-11) these should probably be moved to varkindmod? @@ -26,6 +32,9 @@ module FatesIOVariableKindMod character(*), parameter, public :: site_cwdsc_r8 = 'SI_CWDSC_R8' character(*), parameter, public :: site_can_r8 = 'SI_CAN_R8' character(*), parameter, public :: site_cnlf_r8 = 'SI_CNLF_R8' + character(*), parameter, public :: site_cdpf_r8 = 'SI_CDPF_R8' + character(*), parameter, public :: site_cdsc_r8 = 'SI_CDSC_R8' + character(*), parameter, public :: site_cdam_r8 = 'SI_CDAM_R8' character(*), parameter, public :: site_cnlfpft_r8 = 'SI_CNLFPFT_R8' character(*), parameter, public :: site_scag_r8 = 'SI_SCAG_R8' character(*), parameter, public :: site_scagpft_r8 = 'SI_SCAGPFT_R8' @@ -118,7 +127,7 @@ function iotype_index(iotype_name, num_dim_kinds, dim_kinds) result(dk_index) end if end do write(fates_log(),*) 'An IOTYPE THAT DOESNT EXIST WAS SPECIFIED' - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end function iotype_index diff --git a/main/FatesInterfaceMod.F90 b/main/FatesInterfaceMod.F90 index e6e73b80df..0ca5aafb63 100644 --- a/main/FatesInterfaceMod.F90 +++ b/main/FatesInterfaceMod.F90 @@ -10,12 +10,15 @@ module FatesInterfaceMod ! ------------------------------------------------------------------------------------ use EDTypesMod , only : ed_site_type - use EDTypesMod , only : maxPatchesPerSite - use EDTypesMod , only : maxCohortsPerPatch use EDTypesMod , only : dinc_vai use EDTypesMod , only : dlower_vai use EDParamsMod , only : ED_val_vai_top_bin_width use EDParamsMod , only : ED_val_vai_width_increase_factor + use EDParamsMod , only : ED_val_history_damage_bin_edges + use EDParamsMod , only : maxpatch_total + use EDParamsMod , only : maxpatch_primary + use EDParamsMod , only : maxpatch_secondary + use EDParamsMod , only : max_cohort_per_patch use EDTypesMod , only : maxSWb use EDTypesMod , only : ivis use EDTypesMod , only : inir @@ -36,6 +39,7 @@ module FatesInterfaceMod use FatesGlobals , only : fates_global_verbose use FatesGlobals , only : fates_log use FatesGlobals , only : endrun => fates_endrun + use FatesConstantsMod , only : fates_unset_r8 use FatesLitterMod , only : ncwd use FatesLitterMod , only : ndcmpy use EDPftvarcon , only : FatesReportPFTParams @@ -142,7 +146,8 @@ module FatesInterfaceMod public :: FatesInterfaceInit public :: set_fates_ctrlparms public :: SetFatesTime - public :: SetFatesGlobalElements + public :: SetFatesGlobalElements1 + public :: SetFatesGlobalElements2 public :: FatesReportParameters public :: allocate_bcin public :: allocate_bcout @@ -304,6 +309,10 @@ subroutine zero_bcs(fates,s) fates%bc_out(s)%rootr_pasl(:,:) = 0.0_r8 fates%bc_out(s)%btran_pa(:) = 0.0_r8 + ! MIMIC litter quality, always initialize to unset + fates%bc_out(s)%litt_flux_ligc_per_n = fates_unset_r8 + + ! Fates -> BGC fragmentation mass fluxes select case(hlm_parteh_mode) case(prt_carbon_allom_hyp) @@ -373,7 +382,7 @@ end subroutine zero_bcs ! =========================================================================== - subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) + subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats,natpft_lb,natpft_ub) ! --------------------------------------------------------------------------------- ! Allocate and Initialze the FATES boundary condition vectors @@ -384,6 +393,7 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) integer,intent(in) :: nlevsoil_in integer,intent(in) :: nlevdecomp_in integer,intent(in) :: num_lu_harvest_cats + integer,intent(in) :: natpft_lb,natpft_ub ! dimension bounds of the array holding surface file pft data ! Allocate input boundaries @@ -469,15 +479,15 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) ! Lightning (or successful ignitions) and population density ! Fire related variables - allocate(bc_in%lightning24(maxPatchesPerSite)) - allocate(bc_in%pop_density(maxPatchesPerSite)) - allocate(bc_in%wind24_pa(maxPatchesPerSite)) - allocate(bc_in%relhumid24_pa(maxPatchesPerSite)) - allocate(bc_in%precip24_pa(maxPatchesPerSite)) + allocate(bc_in%lightning24(maxpatch_total)) + allocate(bc_in%pop_density(maxpatch_total)) + allocate(bc_in%wind24_pa(maxpatch_total)) + allocate(bc_in%relhumid24_pa(maxpatch_total)) + allocate(bc_in%precip24_pa(maxpatch_total)) ! Radiation - allocate(bc_in%solad_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_in%solai_parb(maxPatchesPerSite,hlm_numSWb)) + allocate(bc_in%solad_parb(maxpatch_total,hlm_numSWb)) + allocate(bc_in%solai_parb(maxpatch_total,hlm_numSWb)) ! Hydrology allocate(bc_in%smp_sl(nlevsoil_in)) @@ -494,30 +504,30 @@ subroutine allocate_bcin(bc_in, nlevsoil_in, nlevdecomp_in, num_lu_harvest_cats) ! Photosynthesis - allocate(bc_in%filter_photo_pa(maxPatchesPerSite)) - allocate(bc_in%dayl_factor_pa(maxPatchesPerSite)) - allocate(bc_in%esat_tv_pa(maxPatchesPerSite)) - allocate(bc_in%eair_pa(maxPatchesPerSite)) - allocate(bc_in%oair_pa(maxPatchesPerSite)) - allocate(bc_in%cair_pa(maxPatchesPerSite)) - allocate(bc_in%rb_pa(maxPatchesPerSite)) - allocate(bc_in%t_veg_pa(maxPatchesPerSite)) - allocate(bc_in%tgcm_pa(maxPatchesPerSite)) + allocate(bc_in%filter_photo_pa(maxpatch_total)) + allocate(bc_in%dayl_factor_pa(maxpatch_total)) + allocate(bc_in%esat_tv_pa(maxpatch_total)) + allocate(bc_in%eair_pa(maxpatch_total)) + allocate(bc_in%oair_pa(maxpatch_total)) + allocate(bc_in%cair_pa(maxpatch_total)) + allocate(bc_in%rb_pa(maxpatch_total)) + allocate(bc_in%t_veg_pa(maxpatch_total)) + allocate(bc_in%tgcm_pa(maxpatch_total)) allocate(bc_in%t_soisno_sl(nlevsoil_in)) ! Canopy Radiation - allocate(bc_in%filter_vegzen_pa(maxPatchesPerSite)) - allocate(bc_in%coszen_pa(maxPatchesPerSite)) - allocate(bc_in%fcansno_pa(maxPatchesPerSite)) + allocate(bc_in%filter_vegzen_pa(maxpatch_total)) + allocate(bc_in%coszen_pa(maxpatch_total)) + allocate(bc_in%fcansno_pa(maxpatch_total)) allocate(bc_in%albgr_dir_rb(hlm_numSWb)) allocate(bc_in%albgr_dif_rb(hlm_numSWb)) ! Plant-Hydro BC's if (hlm_use_planthydro.eq.itrue) then - allocate(bc_in%qflx_transp_pa(maxPatchesPerSite)) - allocate(bc_in%swrad_net_pa(maxPatchesPerSite)) - allocate(bc_in%lwrad_net_pa(maxPatchesPerSite)) + allocate(bc_in%qflx_transp_pa(maxpatch_total)) + allocate(bc_in%swrad_net_pa(maxpatch_total)) + allocate(bc_in%lwrad_net_pa(maxpatch_total)) allocate(bc_in%watsat_sisl(nlevsoil_in)) allocate(bc_in%watres_sisl(nlevsoil_in)) @@ -539,13 +549,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(0:maxpft)) + allocate(bc_in%pft_areafrac(natpft_lb:natpft_ub)) ! Variables for SP mode. if(hlm_use_sp.eq.itrue) then - allocate(bc_in%hlm_sp_tlai(0:maxpft)) - allocate(bc_in%hlm_sp_tsai(0:maxpft)) - allocate(bc_in%hlm_sp_htop(0:maxpft)) + 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 return end subroutine allocate_bcin @@ -564,28 +574,28 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) integer,intent(in) :: nlevdecomp_in ! Radiation - allocate(bc_out%fsun_pa(maxPatchesPerSite)) - allocate(bc_out%laisun_pa(maxPatchesPerSite)) - allocate(bc_out%laisha_pa(maxPatchesPerSite)) + allocate(bc_out%fsun_pa(maxpatch_total)) + allocate(bc_out%laisun_pa(maxpatch_total)) + allocate(bc_out%laisha_pa(maxpatch_total)) ! Hydrology allocate(bc_out%active_suction_sl(nlevsoil_in)) - allocate(bc_out%rootr_pasl(maxPatchesPerSite,nlevsoil_in)) - allocate(bc_out%btran_pa(maxPatchesPerSite)) + allocate(bc_out%rootr_pasl(maxpatch_total,nlevsoil_in)) + allocate(bc_out%btran_pa(maxpatch_total)) ! Photosynthesis - allocate(bc_out%rssun_pa(maxPatchesPerSite)) - allocate(bc_out%rssha_pa(maxPatchesPerSite)) + allocate(bc_out%rssun_pa(maxpatch_total)) + allocate(bc_out%rssha_pa(maxpatch_total)) ! Canopy Radiation - allocate(bc_out%albd_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%albi_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%fabd_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%fabi_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%ftdd_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%ftid_parb(maxPatchesPerSite,hlm_numSWb)) - allocate(bc_out%ftii_parb(maxPatchesPerSite,hlm_numSWb)) + 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)) ! We allocate the boundary conditions to the BGC @@ -614,20 +624,19 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) ! Include the bare-ground patch for these patch-level boundary conditions ! (it will always be zero for all of these) if(hlm_use_ch4.eq.itrue) then - allocate(bc_out%annavg_agnpp_pa(0:maxPatchesPerSite));bc_out%annavg_agnpp_pa(:)=nan - allocate(bc_out%annavg_bgnpp_pa(0:maxPatchesPerSite));bc_out%annavg_bgnpp_pa(:)=nan - allocate(bc_out%annsum_npp_pa(0:maxPatchesPerSite));bc_out%annsum_npp_pa(:)=nan - allocate(bc_out%frootc_pa(0:maxPatchesPerSite));bc_out%frootc_pa(:)=nan + allocate(bc_out%annavg_agnpp_pa(0:maxpatch_total));bc_out%annavg_agnpp_pa(:)=nan + allocate(bc_out%annavg_bgnpp_pa(0:maxpatch_total));bc_out%annavg_bgnpp_pa(:)=nan + allocate(bc_out%annsum_npp_pa(0:maxpatch_total));bc_out%annsum_npp_pa(:)=nan + allocate(bc_out%frootc_pa(0:maxpatch_total));bc_out%frootc_pa(:)=nan allocate(bc_out%root_resp(nlevsoil_in));bc_out%root_resp(:)=nan - allocate(bc_out%woody_frac_aere_pa(0:maxPatchesPerSite));bc_out%woody_frac_aere_pa(:)=nan - allocate(bc_out%rootfr_pa(0:maxPatchesPerSite,nlevsoil_in)) + allocate(bc_out%woody_frac_aere_pa(0:maxpatch_total));bc_out%woody_frac_aere_pa(:)=nan + allocate(bc_out%rootfr_pa(0:maxpatch_total,nlevsoil_in)) bc_out%rootfr_pa(:,:)=nan ! Give the bare-ground root fractions a nominal fraction of unity over depth bc_out%rootfr_pa(0,1:nlevsoil_in)=1._r8/real(nlevsoil_in,r8) end if - ! Fates -> BGC fragmentation mass fluxes select case(hlm_parteh_mode) case(prt_carbon_allom_hyp) @@ -658,21 +667,21 @@ subroutine allocate_bcout(bc_out, nlevsoil_in, nlevdecomp_in) ! Canopy Structure - allocate(bc_out%elai_pa(maxPatchesPerSite)) - allocate(bc_out%esai_pa(maxPatchesPerSite)) - allocate(bc_out%tlai_pa(maxPatchesPerSite)) - allocate(bc_out%tsai_pa(maxPatchesPerSite)) - allocate(bc_out%htop_pa(maxPatchesPerSite)) - allocate(bc_out%hbot_pa(maxPatchesPerSite)) - allocate(bc_out%dleaf_pa(maxPatchesPerSite)) + allocate(bc_out%elai_pa(maxpatch_total)) + allocate(bc_out%esai_pa(maxpatch_total)) + allocate(bc_out%tlai_pa(maxpatch_total)) + allocate(bc_out%tsai_pa(maxpatch_total)) + allocate(bc_out%htop_pa(maxpatch_total)) + allocate(bc_out%hbot_pa(maxpatch_total)) + allocate(bc_out%dleaf_pa(maxpatch_total)) - allocate(bc_out%displa_pa(maxPatchesPerSite)) - allocate(bc_out%z0m_pa(maxPatchesPerSite)) + allocate(bc_out%displa_pa(maxpatch_total)) + allocate(bc_out%z0m_pa(maxpatch_total)) - allocate(bc_out%canopy_fraction_pa(maxPatchesPerSite)) - allocate(bc_out%frac_veg_nosno_alb_pa(maxPatchesPerSite)) + allocate(bc_out%canopy_fraction_pa(maxpatch_total)) + allocate(bc_out%frac_veg_nosno_alb_pa(maxpatch_total)) - allocate(bc_out%nocomp_pft_label_pa(maxPatchesPerSite)) + allocate(bc_out%nocomp_pft_label_pa(maxpatch_total)) ! Plant-Hydro BC's if (hlm_use_planthydro.eq.itrue) then @@ -714,37 +723,89 @@ end subroutine set_bcs ! =================================================================================== - subroutine SetFatesGlobalElements(use_fates) + subroutine SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) ! -------------------------------------------------------------------------------- ! ! This is the first FATES routine that is called. ! - ! This subroutine MUST BE CALLED AFTER the FATES PFT parameter file has been read in, - ! and the EDPftvarcon_inst structure has been made. - ! This subroutine MUST BE CALLED AFTER NL VARIABLES ARE READ (ie hlm_parteh_mode,etc) - ! This subroutine must ALSO BE CALLED BEFORE the history file dimensions - ! are set. - ! - ! This routine requires no information from the HLM. This routine is responsible - ! for generating the globals that are required by the HLM that are entirely - ! FATES derived. - ! + ! spmode,biogeog and nocomp mode flags have been passed prior to this call ! -------------------------------------------------------------------------------- implicit none logical,intent(in) :: use_fates ! Is fates turned on? - integer :: i + integer,intent(in) :: surf_numpft ! Number of PFTs in surface dataset + integer,intent(in) :: surf_numcft ! Number of CFTs in surface dataset + + integer :: fates_numpft ! Number of PFTs tracked in FATES if (use_fates) then ! Self explanatory, read the fates parameter file call FatesReadParameters() - ! Identify the number of PFTs by evaluating a pft array - ! Using wood density as that is not expected to be deprecated any time soon + fates_numpft = size(prt_params%wood_density,dim=1) + + if(hlm_use_sp==itrue)then + + ! For an SP run we also just use the primary patches + ! to hold all PFTs. So create the same number of + ! patches as the number of PFTs + + maxpatch_primary = fates_numpft + maxpatch_secondary = 0 + maxpatch_total = fates_numpft + + ! If this is an SP run, we actually need enough patches on the + ! CLM/ELM side of the code to hold the LAI data. This + ! number may be larger than what fates requires. Of course + ! we may have multiple PFTs in the surface datafile mapping + ! to FATES. The surf_numpft includes the bare ground. + ! maxpatch_total does not include the bare ground (so add 1) + + fates_maxPatchesPerSite = max(surf_numpft+surf_numcft,maxpatch_total+1) + + else + + ! If we are using fixed biogeography or no-comp then we + ! can also apply those constraints to maxpatch_primary and secondary + ! and that value will match fates_maxPatchesPerSite + + if(hlm_use_nocomp==itrue) then + + maxpatch_primary = max(maxpatch_primary,fates_numpft) + maxpatch_total = maxpatch_primary + maxpatch_secondary + !if(maxpatch_primary maxSWb) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES sets a maximum number of shortwave bands' - write(fates_log(), *) 'for some scratch-space, maxSWb' - write(fates_log(), *) 'it defaults to 2, but can be increased as needed' - write(fates_log(), *) 'your driver or host model is intending to drive' - write(fates_log(), *) 'FATES with:',hlm_numSWb,' bands.' - write(fates_log(), *) 'please increase maxSWb in EDTypes to match' - write(fates_log(), *) 'or exceed this value' - end if + write(fates_log(), *) 'FATES sets a maximum number of shortwave bands' + write(fates_log(), *) 'for some scratch-space, maxSWb' + write(fates_log(), *) 'it defaults to 2, but can be increased as needed' + write(fates_log(), *) 'your driver or host model is intending to drive' + write(fates_log(), *) 'FATES with:',hlm_numSWb,' bands.' + write(fates_log(), *) 'please increase maxSWb in EDTypes to match' + write(fates_log(), *) 'or exceed this value' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( .not.((hlm_use_planthydro.eq.1).or.(hlm_use_planthydro.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES namelist planthydro flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES namelist planthydro flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) elseif (hlm_use_planthydro.eq.1 ) then write(fates_log(), *) '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' @@ -1347,30 +1421,23 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if if ( (hlm_use_lu_harvest .lt. 0).or.(hlm_use_lu_harvest .gt. 1) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES lu_harvest flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES lu_harvest flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( (hlm_num_lu_harvest_cats .lt. 0) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES number of hlm harvest cats must be >= 0, exiting' - end if + write(fates_log(), *) 'The FATES number of hlm harvest cats must be >= 0, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( .not.((hlm_use_logging .eq.1).or.(hlm_use_logging.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES namelist use_logging flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES namelist use_logging flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( ( ANY(EDPftvarcon_inst%mort_ip_age_senescence < fates_check_param_set )) .and. & (hlm_use_cohort_age_tracking .eq.0 ) ) then - write(fates_log(),*) 'Age dependent mortality cannot be on if' write(fates_log(),*) 'cohort age tracking is off.' write(fates_log(),*) 'Set hlm_use_cohort_age_tracking = .true.' @@ -1378,74 +1445,53 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if ( .not.((hlm_use_ed_st3.eq.1).or.(hlm_use_ed_st3.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES namelist stand structure flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES namelist stand structure flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( .not.((hlm_use_ed_prescribed_phys.eq.1).or.(hlm_use_ed_prescribed_phys.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES namelist prescribed physiology flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES namelist prescribed physiology flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( hlm_use_ed_prescribed_phys.eq.1 .and. hlm_use_ed_st3.eq.1 ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES ST3 and prescribed physiology cannot both be turned on.' - write(fates_log(), *) 'Review the namelist entries, exiting' - end if + write(fates_log(), *) 'FATES ST3 and prescribed physiology cannot both be turned on.' + write(fates_log(), *) 'Review the namelist entries, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if ( hlm_use_inventory_init.eq.1 .and. hlm_use_cohort_age_tracking .eq.1) then - if (fates_global_verbose()) then - write(fates_log(), *) 'Fates inventory init cannot be used with age dependent mortality' - write(fates_log(), *) 'Set hlm_use_cohort_age_tracking to 0 or turn off inventory init' - end if + write(fates_log(), *) 'Fates inventory init cannot be used with age dependent mortality' + write(fates_log(), *) 'Set hlm_use_cohort_age_tracking to 0 or turn off inventory init' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - - if ( .not.((hlm_use_inventory_init.eq.1).or.(hlm_use_inventory_init.eq.0)) ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'The FATES NL inventory flag must be 0 or 1, exiting' - end if + write(fates_log(), *) 'The FATES NL inventory flag must be 0 or 1, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(trim(hlm_inventory_ctrl_file) .eq. 'unset') then - if (fates_global_verbose()) then - write(fates_log(),*) 'namelist entry for fates inventory control file is unset, exiting' - end if + write(fates_log(),*) 'namelist entry for fates inventory control file is unset, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_ivis .ne. ivis) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES assumption about the index of visible shortwave' - write(fates_log(), *) 'radiation is different from the HLM, exiting' - end if + write(fates_log(), *) 'FATES assumption about the index of visible shortwave' + write(fates_log(), *) 'radiation is different from the HLM, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_inir .ne. inir) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES assumption about the index of NIR shortwave' - write(fates_log(), *) 'radiation is different from the HLM, exiting' - end if + write(fates_log(), *) 'FATES assumption about the index of NIR shortwave' + write(fates_log(), *) 'radiation is different from the HLM, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_is_restart .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES parameter unset: hlm_is_restart, exiting' - end if + write(fates_log(), *) 'FATES parameter unset: hlm_is_restart, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1457,112 +1503,99 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if if(trim(hlm_name) .eq. 'unset') then - if (fates_global_verbose()) then - write(fates_log(),*) 'FATES dimension/parameter unset: hlm_name, exiting' - end if + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_name, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(trim(hlm_nu_com) .eq. 'unset') then + if(trim(hlm_decomp) .eq. 'unset') then if (fates_global_verbose()) then - write(fates_log(),*) 'FATES dimension/parameter unset: hlm_nu_com, exiting' + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_decomp, exiting' + write(fates_log(),*) 'valid: MIMICS, CENTURY, CTC' end if call endrun(msg=errMsg(sourcefile, __LINE__)) end if - - if(hlm_nitrogen_spec .eq. unset_int) then + if( .not. ((trim(hlm_decomp) .eq. 'MIMICS') .or. & + (trim(hlm_decomp) .eq. 'CENTURY') .or. & + (trim(hlm_decomp) .eq. 'CTC') .or. & + (trim(hlm_decomp) .eq. 'NONE')) ) then if (fates_global_verbose()) then - write(fates_log(),*) 'FATES parameters unset: hlm_nitrogen_spec, exiting' + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_decomp, exiting' + write(fates_log(),*) 'valid: NONE, MIMICS, CENTURY, CTC, yours: ',trim(hlm_decomp) end if call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(hlm_phosphorus_spec .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(),*) 'FATES parameters unset: hlm_phosphorus_spec, exiting' - end if + ! TEMPORARY TESTING OVERRIDE !!!!!!!! + ! hlm_decomp = 'MIMICS' + + if(trim(hlm_nu_com) .eq. 'unset') then + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_nu_com, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if( abs(hlm_hio_ignore_val-unset_double)<1e-10 ) then - if (fates_global_verbose()) then - write(fates_log(),*) 'FATES dimension/parameter unset: hio_ignore' - end if + if(hlm_use_tree_damage .eq. unset_int .or. hlm_use_tree_damage .eq. itrue) then + write(fates_log(),*) 'FATES dimension/parameter unset: hlm_use_tree_damage, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(hlm_ipedof .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'index for the HLMs pedotransfer function unset: hlm_ipedof, exiting' - end if + if(hlm_use_tree_damage .eq. itrue) then + write(fates_log(),*) 'hlm_use_tree_damage is not available yet, value: ',hlm_use_tree_damage,' ,set to false' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + if(hlm_nitrogen_spec .eq. unset_int) then + write(fates_log(),*) 'FATES parameters unset: hlm_nitrogen_spec, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if(hlm_phosphorus_spec .eq. unset_int) then + write(fates_log(),*) 'FATES parameters unset: hlm_phosphorus_spec, exiting' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - if(hlm_max_patch_per_site .eq. unset_int ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'the number of patch-space per site unset: hlm_max_patch_per_site, exiting' - end if + if( abs(hlm_hio_ignore_val-unset_double)<1e-10 ) then + write(fates_log(),*) 'FATES dimension/parameter unset: hio_ignore' call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif(hlm_max_patch_per_site < maxPatchesPerSite ) then - if (fates_global_verbose()) then - write(fates_log(), *) 'FATES is trying to allocate space for more patches per site, than the HLM has space for.' - write(fates_log(), *) 'hlm_max_patch_per_site (HLM side): ', hlm_max_patch_per_site - write(fates_log(), *) 'maxPatchesPerSite (FATES side): ', maxPatchesPerSite - write(fates_log(), *) - end if + end if + + if(hlm_ipedof .eq. unset_int) then + write(fates_log(), *) 'index for the HLMs pedotransfer function unset: hlm_ipedof, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_parteh_mode .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch deciding which plant reactive transport model to use is unset, hlm_parteh_mode, exiting' - end if + write(fates_log(), *) 'switch deciding which plant reactive transport model to use is unset, hlm_parteh_mode, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_use_ch4 .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch for the HLMs CH4 module unset: hlm_use_ch4, exiting' - end if + write(fates_log(), *) 'switch for the HLMs CH4 module unset: hlm_use_ch4, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - + if(hlm_use_vertsoilc .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch for the HLMs soil carbon discretization unset: hlm_use_vertsoilc, exiting' - end if + write(fates_log(), *) 'switch for the HLMs soil carbon discretization unset: hlm_use_vertsoilc, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_spitfire_mode .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch for SPITFIRE unset: hlm_spitfire_mode, exiting' - end if + write(fates_log(), *) 'switch for SPITFIRE unset: hlm_spitfire_mode, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_sf_nofire_def .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'definition of no-fire mode unset: hlm_sf_nofire_def, exiting' - end if + write(fates_log(), *) 'definition of no-fire mode unset: hlm_sf_nofire_def, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_sf_scalar_lightning_def .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'definition of scalar lightning mode unset: hlm_sf_scalltng_def, exiting' - end if + write(fates_log(), *) 'definition of scalar lightning mode unset: hlm_sf_scalltng_def, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_sf_successful_ignitions_def .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'definition of successful ignition mode unset: hlm_sf_successful, exiting' - end if + write(fates_log(), *) 'definition of successful ignition mode unset: hlm_sf_successful, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_sf_anthro_ignitions_def .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'definition of anthro-ignition mode unset: hlm_sf_anthig_def, exiting' - end if + write(fates_log(), *) 'definition of anthro-ignition mode unset: hlm_sf_anthig_def, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1576,7 +1609,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if end if - if(hlm_use_fixed_biogeog.eq.unset_int) then if(fates_global_verbose()) then write(fates_log(), *) 'switch for fixed biogeog unset: him_use_fixed_biogeog, exiting' @@ -1585,23 +1617,17 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if if(hlm_use_nocomp.eq.unset_int) then - if(fates_global_verbose()) then - write(fates_log(), *) 'switch for no competition mode. ' - end if - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(), *) 'switch for no competition mode. ' + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_use_sp.eq.unset_int) then - if(fates_global_verbose()) then - write(fates_log(), *) 'switch for SP mode. ' - end if - call endrun(msg=errMsg(sourcefile, __LINE__)) + write(fates_log(), *) 'switch for SP mode. ' + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if(hlm_use_cohort_age_tracking .eq. unset_int) then - if (fates_global_verbose()) then - write(fates_log(), *) 'switch for cohort_age_tracking unset: hlm_use_cohort_age_tracking, exiting' - end if + write(fates_log(), *) 'switch for cohort_age_tracking unset: hlm_use_cohort_age_tracking, exiting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1610,7 +1636,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - if(hlm_use_sp.eq.itrue.and.hlm_use_fixed_biogeog.eq.ifalse)then write(fates_log(), *) 'SP cannot be on if fixed biogeog mode is off. Exiting. ' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1619,7 +1644,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) if (fates_global_verbose()) then write(fates_log(), *) 'Checked. All control parameters sent to FATES.' end if - case default @@ -1668,6 +1692,12 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_ipedof = ',ival,' to FATES' end if + case('use_tree_damage') + hlm_use_tree_damage = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_use_tree_damage = ',ival,' to FATES' + end if + case('nitrogen_spec') hlm_nitrogen_spec = ival if (fates_global_verbose()) then @@ -1680,13 +1710,6 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hlm_phosphorus_spec = ',ival,' to FATES' end if - - case('max_patch_per_site') - hlm_max_patch_per_site = ival - if (fates_global_verbose()) then - write(fates_log(),*) 'Transfering hlm_max_patch_per_site = ',ival,' to FATES' - end if - case('use_ch4') hlm_use_ch4 = ival if (fates_global_verbose()) then @@ -1749,10 +1772,10 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if case('use_sp') - hlm_use_sp = ival - if (fates_global_verbose()) then - write(fates_log(),*) 'Transfering hlm_use_sp= ',ival,' to FATES' - end if + hlm_use_sp = ival + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering hlm_use_sp= ',ival,' to FATES' + end if case('use_planthydro') hlm_use_planthydro = ival @@ -1803,11 +1826,8 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if case default - if (fates_global_verbose()) then - write(fates_log(), *) 'tag not recognized:',trim(tag) - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - ! end_run + write(fates_log(), *) 'fates NL tag not recognized:',trim(tag) + !! call endrun(msg=errMsg(sourcefile, __LINE__)) end select end if @@ -1820,10 +1840,8 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering hio_ignore_val = ',rval,' to FATES' end if case default - if (fates_global_verbose()) then - write(fates_log(),*) 'tag not recognized:',trim(tag) - end if - ! end_run + write(fates_log(),*) 'fates NL tag not recognized:',trim(tag) + !! call endrun(msg=errMsg(sourcefile, __LINE__)) end select end if @@ -1842,6 +1860,12 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) write(fates_log(),*) 'Transfering the nutrient competition name = ',trim(cval) end if + case('decomp_method') + hlm_decomp = trim(cval) + if (fates_global_verbose()) then + write(fates_log(),*) 'Transfering the decomp method name = ',trim(cval) + end if + case('inventory_ctrl_file') hlm_inventory_ctrl_file = trim(cval) if (fates_global_verbose()) then @@ -1849,10 +1873,8 @@ subroutine set_fates_ctrlparms(tag,ival,rval,cval) end if case default - if (fates_global_verbose()) then - write(fates_log(),*) 'tag not recognized:',trim(tag) - end if - ! end_run + write(fates_log(),*) 'fates NL tag not recognized:',trim(tag) + !! call endrun(msg=errMsg(sourcefile, __LINE__)) end select end if diff --git a/main/FatesInterfaceTypesMod.F90 b/main/FatesInterfaceTypesMod.F90 index 4acf6db391..f08fba4ce8 100644 --- a/main/FatesInterfaceTypesMod.F90 +++ b/main/FatesInterfaceTypesMod.F90 @@ -46,7 +46,11 @@ module FatesInterfaceTypesMod ! specficially packaged for them. ! This string sets which filter is enacted. - + character(len=16), public :: hlm_decomp ! This string defines which soil decomposition + ! scheme is active + ! expected values are one of CENTURY,MIMICS,CTC + + character(len=16), public :: hlm_nu_com ! This string defines which soil ! nutrient competition scheme is in use. ! current options with @@ -87,15 +91,6 @@ module FatesInterfaceTypesMod ! and how it moves and stores water in its ! rhizosphere shells - integer, public :: hlm_max_patch_per_site ! The HLM needs to exchange some patch - ! level quantities with FATES - ! FATES does not dictate those allocations - ! since it happens pretty early in - ! the model initialization sequence. - ! So we want to at least query it, - ! compare it to our maxpatchpersite, - ! and gracefully halt if we are over-allocating - integer, public :: hlm_parteh_mode ! This flag signals which Plant Allocation and Reactive ! Transport (exensible) Hypothesis (PARTEH) to use @@ -148,17 +143,21 @@ module FatesInterfaceTypesMod ! THIS IS CURRENTLY NOT SUPPORTED integer, public :: hlm_use_cohort_age_tracking ! This flag signals whether or not to use - ! cohort age tracking. 1 = TRUE, 0 = FALSE - - integer, public :: hlm_use_ed_st3 ! This flag signals whether or not to use - ! (ST)atic (ST)and (ST)ructure mode (ST3) - ! Essentially, this gives us the ability - ! to turn off "dynamics", ie growth, disturbance - ! recruitment and mortality. - ! (EXPERIMENTAL!!!!! - RGK 07-2017) - ! 1 = TRUE, 0 = FALSE - ! default should be FALSE (dynamics on) - ! cannot be true with prescribed_phys + ! cohort age tracking. 1 = TRUE, 0 = FALSE + + + integer, public :: hlm_use_tree_damage ! This flag signals whether or not to turn on the + ! tree damage module + + integer, public :: hlm_use_ed_st3 ! This flag signals whether or not to use + ! (ST)atic (ST)and (ST)ructure mode (ST3) + ! Essentially, this gives us the ability + ! to turn off "dynamics", ie growth, disturbance + ! recruitment and mortality. + ! (EXPERIMENTAL!!!!! - RGK 07-2017) + ! 1 = TRUE, 0 = FALSE + ! default should be FALSE (dynamics on) + ! cannot be true with prescribed_phys integer, public :: hlm_use_ed_prescribed_phys ! This flag signals whether or not to use ! prescribed physiology, somewhat the opposite @@ -212,7 +211,16 @@ module FatesInterfaceTypesMod ! data as some fields are arrays where each array is ! associated with one cohort - + ! The number of patches that FATES wants the HLM to allocate + ! for non sp/no-comp, this is the same number of patches that + ! fates tracks, plus 1 for the bare-ground. For sp/nocomp, it is the + ! maximum between the number fates tracks, and the numper of PFTs+CFTs + ! in the surface file. + ! for an SP simulation, if there are more PFTs and CFTs in the surface + ! 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 + integer, public :: max_comp_per_site ! This is the maximum number of nutrient aquisition ! competitors that will be generated on each site @@ -260,7 +268,14 @@ module FatesInterfaceTypesMod integer , public, allocatable :: fates_hdim_pftmap_levelpft(:) ! map of pfts in the element x pft dimension integer , public, allocatable :: fates_hdim_cwdmap_levelcwd(:) ! map of cwds in the element x cwd dimension integer , public, allocatable :: fates_hdim_agemap_levelage(:) ! map of ages in the element x age dimension - + + integer , public, allocatable :: fates_hdim_pftmap_levcdpf(:) ! map of pfts into size x crowndamage x pft dimension + integer , public, allocatable :: fates_hdim_cdmap_levcdpf(:) ! map of crowndamage into size x crowndamage x pft + integer , public, allocatable :: fates_hdim_scmap_levcdpf(:) ! map of size into size x crowndamage x pft + integer , public, allocatable :: fates_hdim_cdmap_levcdsc(:) ! map of crowndamage into size x crowndamage + integer , public, allocatable :: fates_hdim_scmap_levcdsc(:) ! map of size into size x crowndamage + integer , public, allocatable :: fates_hdim_levdamage(:) ! plant damage class lower bound dimension + ! ------------------------------------------------------------------------------------ ! DYNAMIC BOUNDARY CONDITIONS ! ------------------------------------------------------------------------------------ @@ -297,7 +312,8 @@ module FatesInterfaceTypesMod integer, public :: nlevheight ! The total number of height bins output to history integer, public :: nlevcoage ! The total number of cohort age bins output to history integer, public :: nleafage ! The total number of leaf age classes - + integer, public :: nlevdamage ! The total number of damage classes + ! ------------------------------------------------------------------------------------- ! Structured Boundary Conditions (SITE/PATCH SCALE) ! For floating point arrays, it is sometimes the convention to define the arrays as @@ -593,15 +609,21 @@ module FatesInterfaceTypesMod ! Mass fluxes to BGC from fragmentation of litter into decomposing pools real(r8), allocatable :: litt_flux_cel_c_si(:) ! cellulose carbon litter, fates->BGC g/m3/s - real(r8), allocatable :: litt_flux_lig_c_si(:) ! lignan carbon litter, fates->BGC g/m3/s + real(r8), allocatable :: litt_flux_lig_c_si(:) ! lignin carbon litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_lab_c_si(:) ! labile carbon litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_cel_n_si(:) ! cellulose nitrogen litter, fates->BGC g/m3/s - real(r8), allocatable :: litt_flux_lig_n_si(:) ! lignan nitrogen litter, fates->BGC g/m3/s + real(r8), allocatable :: litt_flux_lig_n_si(:) ! lignin nitrogen litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_lab_n_si(:) ! labile nitrogen litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_cel_p_si(:) ! cellulose phosphorus litter, fates->BGC g/m3/s - real(r8), allocatable :: litt_flux_lig_p_si(:) ! lignan phosphorus litter, fates->BGC g/m3/s + real(r8), allocatable :: litt_flux_lig_p_si(:) ! lignin phosphorus litter, fates->BGC g/m3/s real(r8), allocatable :: litt_flux_lab_p_si(:) ! labile phosphorus litter, fates->BGC g/m3/s + + ! MIMICS Boundary Conditions + ! ----------------------------------------------------------------------------------- + real(r8) :: litt_flux_ligc_per_n ! lignin carbon per total nitrogen + ! in the fragmentation flux, per square meter [g/g] + ! Nutrient competition boundary conditions ! (These are all pointer allocations, this is because the host models @@ -641,6 +663,9 @@ module FatesInterfaceTypesMod ! for use in ELMs CTC/RD [g/m2/s] + + + ! CH4 Boundary Conditions ! ----------------------------------------------------------------------------------- real(r8), pointer :: annavg_agnpp_pa(:) ! annual average patch npp above ground (gC/m2/s) @@ -700,7 +725,7 @@ module FatesInterfaceTypesMod ! FATES LULCC real(r8) :: hrv_deadstemc_to_prod10c ! Harvested C flux to 10-yr wood product pool [Site-Level, gC m-2 s-1] real(r8) :: hrv_deadstemc_to_prod100c ! Harvested C flux to 100-yr wood product pool [Site-Level, gC m-2 s-1] - + end type bc_out_type diff --git a/main/FatesInventoryInitMod.F90 b/main/FatesInventoryInitMod.F90 index 507f01dbee..e4b5fe4e2b 100644 --- a/main/FatesInventoryInitMod.F90 +++ b/main/FatesInventoryInitMod.F90 @@ -485,7 +485,7 @@ subroutine initialize_sites_by_inventory(nsites,sites,bc_in) write(fates_log(),*) 'Lat: ',sites(s)%lat,' Lon: ',sites(s)%lon write(fates_log(),*) basal_area_pref,' [m2/ha]' write(fates_log(),*) '-------------------------------------------------------' - + ! Update the patch index numbers and fuse the cohorts in the patches ! ---------------------------------------------------------------------------------------- ipa=1 @@ -734,7 +734,7 @@ subroutine set_inventory_edpatch_type1(newpatch,pss_file_unit,ipa,ios,patch_name ! water (NA) Water content of soil (NOT USED) ! fsc (kg/m2) Fast Soil Carbon ! stsc (kg/m2) Structural Soil Carbon - ! stsl (kg/m2) Structural Soil Lignan + ! stsl (kg/m2) Structural Soil Lignin ! ssc (kg/m2) Slow Soil Carbon ! psc (NA) Passive Soil Carbon (NOT USED) ! msn (kg/m2) Mineralized Soil Nitrogen @@ -763,7 +763,7 @@ subroutine set_inventory_edpatch_type1(newpatch,pss_file_unit,ipa,ios,patch_name real(r8) :: p_water ! Patch water (unused) real(r8) :: p_fsc ! Patch fast soil carbon real(r8) :: p_stsc ! Patch structural soil carbon - real(r8) :: p_stsl ! Patch structural soil lignans + real(r8) :: p_stsl ! Patch structural soil lignins real(r8) :: p_ssc ! Patch slow soil carbon real(r8) :: p_psc ! Patch P soil carbon real(r8) :: p_msn ! Patch mean soil nitrogen @@ -995,9 +995,11 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & end if if (c_pft .eq. 0 ) then - write(fates_log(), *) 'inventory pft: ',c_pft - write(fates_log(), *) 'SPECIAL CASE TRIGGERED: PFT == 0 and therefore this subroutine' - write(fates_log(), *) 'will assign a cohort with n = n_orig/numpft to every cohort in range 1 to numpft' + if(debug_inv)then + write(fates_log(), *) 'inventory pft: ',c_pft + write(fates_log(), *) 'SPECIAL CASE TRIGGERED: PFT == 0 and therefore this subroutine' + write(fates_log(), *) 'will assign a cohort with n = n_orig/numpft to every cohort in range 1 to numpft' + end if ncohorts_to_create = numpft else ncohorts_to_create = 1 @@ -1039,7 +1041,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call bstore_allom(temp_cohort%dbh, temp_cohort%pft, temp_cohort%canopy_trim, c_store) - temp_cohort%laimemory = 0._r8 + temp_cohort%leafmemory = 0._r8 temp_cohort%sapwmemory = 0._r8 temp_cohort%structmemory = 0._r8 cstatus = leaves_on @@ -1048,7 +1050,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & if( prt_params%season_decid(temp_cohort%pft) == itrue .and. & any(csite%cstatus == [phen_cstat_nevercold,phen_cstat_iscold])) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf temp_cohort%sapwmemory = c_sapw * stem_drop_fraction temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 @@ -1059,7 +1061,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & if ( prt_params%stress_decid(temp_cohort%pft) == itrue .and. & any(csite%dstatus == [phen_dstat_timeoff,phen_dstat_moistoff])) then - temp_cohort%laimemory = c_leaf + temp_cohort%leafmemory = c_leaf temp_cohort%sapwmemory = c_sapw * stem_drop_fraction temp_cohort%structmemory = c_struct * stem_drop_fraction c_leaf = 0._r8 @@ -1095,21 +1097,17 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & case(nitrogen_element) ! For inventory runs, initialize nutrient contents half way between max and min stoichiometries - m_struct = c_struct * 0.5_r8 * & - (prt_params%nitr_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(struct_organ)) + & - prt_params%nitr_stoich_p2(temp_cohort%pft,prt_params%organ_param_id(struct_organ))) + m_struct = c_struct * & + prt_params%nitr_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(struct_organ)) - m_leaf = c_leaf * 0.5_r8 * & - (prt_params%nitr_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(leaf_organ)) + & - prt_params%nitr_stoich_p2(temp_cohort%pft,prt_params%organ_param_id(leaf_organ))) + m_leaf = c_leaf * & + prt_params%nitr_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(leaf_organ)) - m_fnrt = c_fnrt * 0.5_r8 * & - (prt_params%nitr_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(fnrt_organ)) + & - prt_params%nitr_stoich_p2(temp_cohort%pft,prt_params%organ_param_id(fnrt_organ))) + m_fnrt = c_fnrt * & + prt_params%nitr_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(fnrt_organ)) - m_sapw = c_sapw * 0.5_r8 * & - (prt_params%nitr_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(sapw_organ)) + & - prt_params%nitr_stoich_p2(temp_cohort%pft,prt_params%organ_param_id(sapw_organ))) + m_sapw = c_sapw * & + prt_params%nitr_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(sapw_organ)) m_repro = 0._r8 @@ -1117,21 +1115,17 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & case(phosphorus_element) - m_struct = c_struct * 0.5_r8 * & - (prt_params%phos_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(struct_organ)) + & - prt_params%phos_stoich_p2(temp_cohort%pft,prt_params%organ_param_id(struct_organ))) - - m_leaf = c_leaf * 0.5_r8 * & - (prt_params%phos_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(leaf_organ)) + & - prt_params%phos_stoich_p2(temp_cohort%pft,prt_params%organ_param_id(leaf_organ))) + m_struct = c_struct * & + prt_params%phos_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(struct_organ)) - m_fnrt = c_fnrt * 0.5_r8 * & - (prt_params%phos_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(fnrt_organ)) + & - prt_params%phos_stoich_p2(temp_cohort%pft,prt_params%organ_param_id(fnrt_organ))) + m_leaf = c_leaf * & + prt_params%phos_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(leaf_organ)) - m_sapw = c_sapw * 0.5_r8 * & - (prt_params%phos_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(sapw_organ)) + & - prt_params%phos_stoich_p2(temp_cohort%pft,prt_params%organ_param_id(sapw_organ))) + m_fnrt = c_fnrt * & + prt_params%phos_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(fnrt_organ)) + + m_sapw = c_sapw * & + prt_params%phos_stoich_p1(temp_cohort%pft,prt_params%organ_param_id(sapw_organ)) m_repro = 0._r8 @@ -1167,7 +1161,7 @@ subroutine set_inventory_edcohort_type1(csite,bc_in,css_file_unit,npatches, & call create_cohort(csite, cpatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, & temp_cohort%coage, temp_cohort%dbh, & - prt_obj, temp_cohort%laimemory,temp_cohort%sapwmemory, temp_cohort%structmemory, & + prt_obj, temp_cohort%leafmemory,temp_cohort%sapwmemory, temp_cohort%structmemory, & cstatus, rstatus, temp_cohort%canopy_trim,temp_cohort%c_area, & 1, csite%spread, bc_in) diff --git a/main/FatesParametersInterface.F90 b/main/FatesParametersInterface.F90 index f69d4ef5bf..aa13150c4a 100644 --- a/main/FatesParametersInterface.F90 +++ b/main/FatesParametersInterface.F90 @@ -29,13 +29,15 @@ module FatesParametersInterface character(len=*), parameter, public :: dimension_name_allpfts = 'fates_allpfts' character(len=*), parameter, public :: dimension_name_variants = 'fates_variants' character(len=*), parameter, public :: dimension_name_hydr_organs = 'fates_hydr_organs' - character(len=*), parameter, public :: dimension_name_prt_organs = 'fates_prt_organs' + character(len=*), parameter, public :: dimension_name_prt_organs = 'fates_plant_organs' character(len=*), parameter, public :: dimension_name_leaf_age = 'fates_leafage_class' character(len=*), parameter, public :: dimension_name_history_size_bins = 'fates_history_size_bins' character(len=*), parameter, public :: dimension_name_history_age_bins = 'fates_history_age_bins' character(len=*), parameter, public :: dimension_name_history_height_bins = 'fates_history_height_bins' character(len=*), parameter, public :: dimension_name_history_coage_bins = 'fates_history_coage_bins' 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' ! Dimensions in the host namespace: character(len=*), parameter, public :: dimension_name_host_allpfts = 'allpfts' @@ -59,8 +61,8 @@ module FatesParametersInterface procedure :: Init procedure :: Destroy procedure :: RegisterParameter - generic :: RetreiveParameter => RetreiveParameterScalar, RetreiveParameter1D, RetreiveParameter2D - generic :: RetreiveParameterAllocate => RetreiveParameter1DAllocate, RetreiveParameter2DAllocate + generic :: RetrieveParameter => RetrieveParameterScalar, RetrieveParameter1D, RetrieveParameter2D + generic :: RetrieveParameterAllocate => RetrieveParameter1DAllocate, RetrieveParameter2DAllocate generic :: SetData => SetDataScalar, SetData1D, SetData2D procedure :: GetUsedDimensions procedure :: SetDimensionSizes @@ -70,11 +72,11 @@ module FatesParametersInterface procedure :: FindIndex ! Private functions - procedure, private :: RetreiveParameterScalar - procedure, private :: RetreiveParameter1D - procedure, private :: RetreiveParameter2D - procedure, private :: RetreiveParameter1DAllocate - procedure, private :: RetreiveParameter2DAllocate + procedure, private :: RetrieveParameterScalar + procedure, private :: RetrieveParameter1D + procedure, private :: RetrieveParameter2D + procedure, private :: RetrieveParameter1DAllocate + procedure, private :: RetrieveParameter2DAllocate procedure, private :: SetDataScalar procedure, private :: SetData1D procedure, private :: SetData2D @@ -151,7 +153,7 @@ subroutine RegisterParameter(this, name, dimension_shape, dimension_names, & end subroutine RegisterParameter !----------------------------------------------------------------------- - subroutine RetreiveParameterScalar(this, name, data) + subroutine RetrieveParameterScalar(this, name, data) implicit none @@ -165,10 +167,10 @@ subroutine RetreiveParameterScalar(this, name, data) ! assert(size(data) == size(this%parameters(i)%data)) data = this%parameters(i)%data(1, 1) - end subroutine RetreiveParameterScalar + end subroutine RetrieveParameterScalar !----------------------------------------------------------------------- - subroutine RetreiveParameter1D(this, name, data) + subroutine RetrieveParameter1D(this, name, data) use abortutils, only : endrun @@ -182,7 +184,7 @@ subroutine RetreiveParameter1D(this, name, data) i = this%FindIndex(name) if (size(data) /= size(this%parameters(i)%data(:, 1))) then - write(fates_log(), *) 'ERROR : retreiveparameter1d : ', name, ' size inconsistent.' + write(fates_log(), *) 'ERROR : RetrieveParameter1d : ', name, ' size inconsistent.' write(fates_log(), *) 'ERROR : expected size = ', size(data) write(fates_log(), *) 'ERROR : data size received from file = ', size(this%parameters(i)%data(:, 1)) write(fates_log(), *) 'ERROR : dimesions received from file' @@ -194,10 +196,10 @@ subroutine RetreiveParameter1D(this, name, data) end if data = this%parameters(i)%data(:, 1) - end subroutine RetreiveParameter1D + end subroutine RetrieveParameter1D !----------------------------------------------------------------------- - subroutine RetreiveParameter2D(this, name, data) + subroutine RetrieveParameter2D(this, name, data) use abortutils, only : endrun @@ -212,7 +214,7 @@ subroutine RetreiveParameter2D(this, name, data) i = this%FindIndex(name) if (size(data, 1) /= size(this%parameters(i)%data, 1) .and. & size(data, 2) /= size(this%parameters(i)%data, 2)) then - write(fates_log(), *) 'ERROR : retreiveparameter2d : ', name, ' size inconsistent.' + write(fates_log(), *) 'ERROR : RetrieveParameter2d : ', name, ' size inconsistent.' write(fates_log(), *) 'ERROR : expected shape = ', shape(data) write(fates_log(), *) 'ERROR : dim 1 expected size = ', size(data, 1) write(fates_log(), *) 'ERROR : dim 2 expected size = ', size(data, 2) @@ -227,10 +229,10 @@ subroutine RetreiveParameter2D(this, name, data) end if data = this%parameters(i)%data - end subroutine RetreiveParameter2D + end subroutine RetrieveParameter2D !----------------------------------------------------------------------- - subroutine RetreiveParameter1DAllocate(this, name, data) + subroutine RetrieveParameter1DAllocate(this, name, data) use abortutils, only : endrun @@ -248,10 +250,10 @@ subroutine RetreiveParameter1DAllocate(this, name, data) allocate(data(lower_bound:upper_bound)) data(lower_bound:upper_bound) = this%parameters(i)%data(:, 1) - end subroutine RetreiveParameter1DAllocate + end subroutine RetrieveParameter1DAllocate !----------------------------------------------------------------------- - subroutine RetreiveParameter2DAllocate(this, name, data) + subroutine RetrieveParameter2DAllocate(this, name, data) use abortutils, only : endrun @@ -271,7 +273,7 @@ subroutine RetreiveParameter2DAllocate(this, name, data) allocate(data(lb_1:ub_1, lb_2:ub_2)) data(lb_1:ub_1, lb_2:ub_2) = this%parameters(i)%data - end subroutine RetreiveParameter2DAllocate + end subroutine RetrieveParameter2DAllocate !----------------------------------------------------------------------- function FindIndex(this, name) result(i) @@ -370,7 +372,6 @@ subroutine SetDimensionSizes(this, is_host_file, num_used_dimensions, dimension_ ! non-empty dimension name, set the size do i = 1, num_used_dimensions if (trim(dimension_names(i)) == trim(dim_name)) then - !write(*, *) '--> ', trim(this%parameters(p)%name), ' setting ', trim(dim_name), ' d = ', d, 'size = ', dimension_sizes(i) this%parameters(p)%dimension_sizes(d) = dimension_sizes(i) exit end if diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 0605767cd6..0c88d90986 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -100,7 +100,7 @@ module FatesRestartInterfaceMod integer :: ir_coage_co integer :: ir_g_sb_laweight_co integer :: ir_height_co - integer :: ir_laimemory_co + integer :: ir_leafmemory_co integer :: ir_sapwmemory_co integer :: ir_structmemory_co integer :: ir_nplant_co @@ -204,13 +204,13 @@ module FatesRestartInterfaceMod integer :: ir_growflx_fusion_siscpf integer :: ir_demorate_sisc integer :: ir_promrate_sisc - integer :: ir_termcflux_cano_si - integer :: ir_termcflux_usto_si + integer :: ir_termcflux_cano_sipft + integer :: ir_termcflux_usto_sipft integer :: ir_democflux_si integer :: ir_promcflux_si - integer :: ir_imortcflux_si - integer :: ir_fmortcflux_cano_si - integer :: ir_fmortcflux_usto_si + integer :: ir_imortcflux_sipft + integer :: ir_fmortcflux_cano_sipft + integer :: ir_fmortcflux_usto_sipft integer :: ir_cwdagin_flxdg integer :: ir_cwdbgin_flxdg integer :: ir_leaflittin_flxdg @@ -420,8 +420,7 @@ subroutine set_dim_indices(this, dk_name, idim, dim_index) write(fates_log(), *) 'Trying to define dimension size to a dim-type structure' write(fates_log(), *) 'but the dimension index does not exist' write(fates_log(), *) 'type: ',dk_name,' ndims: ',this%dim_kinds(ityp)%ndims,' input dim:',idim - stop - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end if if (idim == 1) then @@ -714,10 +713,10 @@ subroutine define_restart_vars(this, initialize_variables) long_name='ed cohort - plant height', units='m', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_height_co ) - call this%set_restart_var(vname='fates_laimemory', vtype=cohort_r8, & + call this%set_restart_var(vname='fates_leafmemory', vtype=cohort_r8, & long_name='ed cohort - target leaf biomass set from prev year', & units='kgC/indiv', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_laimemory_co ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_leafmemory_co ) call this%set_restart_var(vname='fates_sapwmemory', vtype=cohort_r8, & long_name='ed cohort - target sapwood biomass set from prev year', & @@ -1230,30 +1229,30 @@ subroutine define_restart_vars(this, initialize_variables) units='indiv/ha/da', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_promrate_sisc) - call this%set_restart_var(vname='fates_imortcflux', vtype=site_r8, & + call this%set_restart_var(vname='fates_imortcflux', vtype=cohort_r8, & long_name='biomass of indivs killed due to impact mort', & units='kgC/ha/day', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_imortcflux_si) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_imortcflux_sipft) - call this%set_restart_var(vname='fates_fmortcflux_canopy', vtype=site_r8, & + call this%set_restart_var(vname='fates_fmortcflux_canopy', vtype=cohort_r8, & long_name='fates diagnostic biomass of canopy fire', & units='gC/m2/sec', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_cano_si) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_cano_sipft) - call this%set_restart_var(vname='fates_fmortcflux_ustory', vtype=site_r8, & + call this%set_restart_var(vname='fates_fmortcflux_ustory', vtype=cohort_r8, & long_name='fates diagnostic biomass of understory fire', & units='gC/m2/sec', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_usto_si) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_fmortcflux_usto_sipft) - call this%set_restart_var(vname='fates_termcflux_canopy', vtype=site_r8, & + call this%set_restart_var(vname='fates_termcflux_canopy', vtype=cohort_r8, & long_name='fates diagnostic term carbon flux canopy', & units='', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_cano_si ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_cano_sipft ) - call this%set_restart_var(vname='fates_termcflux_ustory', vtype=site_r8, & + call this%set_restart_var(vname='fates_termcflux_ustory', vtype=cohort_r8, & long_name='fates diagnostic term carbon flux understory', & units='', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_usto_si ) + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_termcflux_usto_sipft ) call this%set_restart_var(vname='fates_democflux', vtype=site_r8, & long_name='fates diagnostic demotion carbon flux', & @@ -1769,7 +1768,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_coage_co => this%rvars(ir_coage_co)%r81d, & rio_g_sb_laweight_co => this%rvars(ir_g_sb_laweight_co)%r81d, & rio_height_co => this%rvars(ir_height_co)%r81d, & - rio_laimemory_co => this%rvars(ir_laimemory_co)%r81d, & + rio_leafmemory_co => this%rvars(ir_leafmemory_co)%r81d, & rio_sapwmemory_co => this%rvars(ir_sapwmemory_co)%r81d, & rio_structmemory_co => this%rvars(ir_structmemory_co)%r81d, & rio_nplant_co => this%rvars(ir_nplant_co)%r81d, & @@ -1828,13 +1827,13 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_growflx_fusion_siscpf => this%rvars(ir_growflx_fusion_siscpf)%r81d, & rio_demorate_sisc => this%rvars(ir_demorate_sisc)%r81d, & rio_promrate_sisc => this%rvars(ir_promrate_sisc)%r81d, & - rio_termcflux_cano_si => this%rvars(ir_termcflux_cano_si)%r81d, & - rio_termcflux_usto_si => this%rvars(ir_termcflux_usto_si)%r81d, & + rio_termcflux_cano_sipft => this%rvars(ir_termcflux_cano_sipft)%r81d, & + rio_termcflux_usto_sipft => this%rvars(ir_termcflux_usto_sipft)%r81d, & rio_democflux_si => this%rvars(ir_democflux_si)%r81d, & rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & - rio_imortcflux_si => this%rvars(ir_imortcflux_si)%r81d, & - rio_fmortcflux_cano_si => this%rvars(ir_fmortcflux_cano_si)%r81d, & - rio_fmortcflux_usto_si => this%rvars(ir_fmortcflux_usto_si)%r81d) + rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & + rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & + rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d) totalCohorts = 0 @@ -1997,7 +1996,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_dbh_co(io_idx_co) = ccohort%dbh rio_coage_co(io_idx_co) = ccohort%coage rio_height_co(io_idx_co) = ccohort%hite - rio_laimemory_co(io_idx_co) = ccohort%laimemory + rio_leafmemory_co(io_idx_co) = ccohort%leafmemory rio_sapwmemory_co(io_idx_co) = ccohort%sapwmemory rio_structmemory_co(io_idx_co) = ccohort%structmemory rio_g_sb_laweight_co(io_idx_co)= ccohort%g_sb_laweight @@ -2220,13 +2219,20 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_sc = io_idx_si_sc + 1 end do - rio_termcflux_cano_si(io_idx_si) = sites(s)%term_carbonflux_canopy - rio_termcflux_usto_si(io_idx_si) = sites(s)%term_carbonflux_ustory rio_democflux_si(io_idx_si) = sites(s)%demotion_carbonflux rio_promcflux_si(io_idx_si) = sites(s)%promotion_carbonflux - rio_imortcflux_si(io_idx_si) = sites(s)%imort_carbonflux - rio_fmortcflux_cano_si(io_idx_si) = sites(s)%fmort_carbonflux_canopy - rio_fmortcflux_usto_si(io_idx_si) = sites(s)%fmort_carbonflux_ustory + + io_idx_si_pft = io_idx_co_1st + do i_pft = 1, numpft + rio_termcflux_cano_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_canopy(i_pft) + rio_termcflux_usto_sipft(io_idx_si_pft) = sites(s)%term_carbonflux_ustory(i_pft) + rio_fmortcflux_cano_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_canopy(i_pft) + rio_fmortcflux_usto_sipft(io_idx_si_pft) = sites(s)%fmort_carbonflux_ustory(i_pft) + + rio_imortcflux_sipft(io_idx_si_pft) = sites(s)%imort_carbonflux(i_pft) + + io_idx_si_pft = io_idx_si_pft + 1 + end do rio_cd_status_si(io_idx_si) = sites(s)%cstatus rio_dd_status_si(io_idx_si) = sites(s)%dstatus @@ -2600,7 +2606,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_coage_co => this%rvars(ir_coage_co)%r81d, & rio_g_sb_laweight_co => this%rvars(ir_g_sb_laweight_co)%r81d, & rio_height_co => this%rvars(ir_height_co)%r81d, & - rio_laimemory_co => this%rvars(ir_laimemory_co)%r81d, & + rio_leafmemory_co => this%rvars(ir_leafmemory_co)%r81d, & rio_sapwmemory_co => this%rvars(ir_sapwmemory_co)%r81d, & rio_structmemory_co => this%rvars(ir_structmemory_co)%r81d, & rio_nplant_co => this%rvars(ir_nplant_co)%r81d, & @@ -2659,13 +2665,13 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_growflx_fusion_siscpf => this%rvars(ir_growflx_fusion_siscpf)%r81d, & rio_demorate_sisc => this%rvars(ir_demorate_sisc)%r81d, & rio_promrate_sisc => this%rvars(ir_promrate_sisc)%r81d, & - rio_termcflux_cano_si => this%rvars(ir_termcflux_cano_si)%r81d, & - rio_termcflux_usto_si => this%rvars(ir_termcflux_usto_si)%r81d, & + rio_termcflux_cano_sipft => this%rvars(ir_termcflux_cano_sipft)%r81d, & + rio_termcflux_usto_sipft => this%rvars(ir_termcflux_usto_sipft)%r81d, & rio_democflux_si => this%rvars(ir_democflux_si)%r81d, & rio_promcflux_si => this%rvars(ir_promcflux_si)%r81d, & - rio_imortcflux_si => this%rvars(ir_imortcflux_si)%r81d, & - rio_fmortcflux_cano_si => this%rvars(ir_fmortcflux_cano_si)%r81d, & - rio_fmortcflux_usto_si => this%rvars(ir_fmortcflux_usto_si)%r81d) + rio_imortcflux_sipft => this%rvars(ir_imortcflux_sipft)%r81d, & + rio_fmortcflux_cano_sipft => this%rvars(ir_fmortcflux_cano_sipft)%r81d, & + rio_fmortcflux_usto_sipft => this%rvars(ir_fmortcflux_usto_sipft)%r81d) totalcohorts = 0 @@ -2802,9 +2808,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%coage = rio_coage_co(io_idx_co) ccohort%g_sb_laweight= rio_g_sb_laweight_co(io_idx_co) ccohort%hite = rio_height_co(io_idx_co) - ccohort%laimemory = rio_laimemory_co(io_idx_co) + ccohort%leafmemory = rio_leafmemory_co(io_idx_co) ccohort%sapwmemory = rio_sapwmemory_co(io_idx_co) - ccohort%structmemory= rio_structmemory_co(io_idx_co) + ccohort%structmemory = rio_structmemory_co(io_idx_co) ccohort%n = rio_nplant_co(io_idx_co) ccohort%gpp_acc = rio_gpp_acc_co(io_idx_co) ccohort%npp_acc = rio_npp_acc_co(io_idx_co) @@ -3078,14 +3084,18 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_sc = io_idx_si_sc + 1 end do - sites(s)%term_carbonflux_canopy = rio_termcflux_cano_si(io_idx_si) - sites(s)%term_carbonflux_ustory = rio_termcflux_usto_si(io_idx_si) sites(s)%demotion_carbonflux = rio_democflux_si(io_idx_si) sites(s)%promotion_carbonflux = rio_promcflux_si(io_idx_si) - sites(s)%imort_carbonflux = rio_imortcflux_si(io_idx_si) - sites(s)%fmort_carbonflux_canopy = rio_fmortcflux_cano_si(io_idx_si) - sites(s)%fmort_carbonflux_ustory = rio_fmortcflux_usto_si(io_idx_si) + io_idx_si_pft = io_idx_co_1st + do i_pft = 1, numpft + sites(s)%term_carbonflux_canopy(i_pft) = rio_termcflux_cano_sipft(io_idx_si_pft) + sites(s)%term_carbonflux_ustory(i_pft) = rio_termcflux_usto_sipft(io_idx_si_pft) + sites(s)%fmort_carbonflux_canopy(i_pft) = rio_fmortcflux_cano_sipft(io_idx_si_pft) + sites(s)%fmort_carbonflux_ustory(i_pft) = rio_fmortcflux_usto_sipft(io_idx_si_pft) + sites(s)%imort_carbonflux(i_pft) = rio_imortcflux_sipft(io_idx_si_pft) + io_idx_si_pft = io_idx_si_pft + 1 + end do ! Site level phenology status flags diff --git a/main/FatesRestartVariableType.F90 b/main/FatesRestartVariableType.F90 index 4cec99c349..ac35412adb 100644 --- a/main/FatesRestartVariableType.F90 +++ b/main/FatesRestartVariableType.F90 @@ -3,10 +3,16 @@ module FatesRestartVariableMod use FatesConstantsMod, only : r8 => fates_r8 use FatesGlobals, only : fates_log use FatesIOVariableKindMod, only : fates_io_variable_kind_type - + use FatesGlobals , only : endrun => fates_endrun + use shr_log_mod , only : errMsg => shr_log_errMsg + implicit none private ! Modules are private by default + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + ! This type is instanteated in the HLM-FATES interface (clmfates_interfaceMod.F90) type, public :: fates_restart_variable_type @@ -100,8 +106,7 @@ subroutine Init(this, vname, units, long, vtype, flushval, num_dim_kinds, dim_ki case default write(fates_log(),*) 'Incompatible vtype passed to set_restart_var' write(fates_log(),*) 'vtype = ',trim(vtype),' ?' - stop - ! end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end subroutine Init @@ -188,8 +193,7 @@ subroutine flush(this, thread, dim_bounds, dim_kinds) case default write(fates_log(),*) 'fates history variable type undefined while flushing history variables' - stop - !end_run + call endrun(msg=errMsg(sourcefile, __LINE__)) end select end subroutine Flush diff --git a/main/FatesSynchronizedParamsMod.F90 b/main/FatesSynchronizedParamsMod.F90 index 7f35b8eeec..8cbda3fdb1 100644 --- a/main/FatesSynchronizedParamsMod.F90 +++ b/main/FatesSynchronizedParamsMod.F90 @@ -126,11 +126,11 @@ subroutine ReceiveParamsScalar(this, fates_params) character(len=param_string_length) :: name ! name = 'q10_mr' -! call fates_params%RetreiveParameter(name=name, & +! call fates_params%RetrieveParameter(name=name, & ! data=this%Q10) ! name = 'froz_q10' -! call fates_params%RetreiveParameter(name=name, & +! call fates_params%RetrieveParameter(name=name, & ! data=this%froz_q10) end subroutine ReceiveParamsScalar diff --git a/parameter_files/apichange_23to24.xml b/parameter_files/apichange_23to24.xml new file mode 100644 index 0000000000..0bddd6940d --- /dev/null +++ b/parameter_files/apichange_23to24.xml @@ -0,0 +1,568 @@ + + + + + + + + + + fates_params_default.cdl + fates_params_default_api24.cdl + 1,2,3,4,5,6,7,8,9,10,11,12 + + + fates_history_damage_bins + 2 + + + fates_allom_crown_depth_frac + the depth of a cohort crown as a fraction of its height + + + fates_phen_fnrt_drop_frac + fates_pft + fraction + fraction of fine roots to drop during drought or cold + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + + fates_hydro_solver + scalar + unitless + switch designating which numerical solver for plant hydraulics, 1 = 1D taylor, 2 = 2D Picard, 3 = 2D Newton (deprecated) + 1 + + + fates_history_damage_bin_edges + fates_history_damage_bins + % crown loss + Lower edges for damage class bins used in cohort history output + 0, 80 + + + fates_damage_frac + fates_pft + fraction + fraction of cohort damaged in each damage event (event frequency specified in the is_it_damage_time subroutine) + 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 + fates_pft + fraction + 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 + 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0 + + + fates_damage_mort_p2 + fates_pft + unitless + rate of mortality increase with damage + 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 + fates_pft + unitless + fraction of the cohort that recovers from damage + 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_maxpatch_primary + scalar + count + maximum number of primary vegetation patches per site + 10 + + + fates_maxpatch_secondary + scalar + count + maximum number of secondary vegetation patches per site + 4 + + + + fates_maxcohort + scalar + count + maximum number of cohorts per patch. Actual number of cohorts also depend on cohort fusion tolerances + 100 + + + + fates_phen_drought_model + scalar + unitless + which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like) + 0 + + + fates_phen_drought_threshold + scalar + m3/m3 or mm + threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); 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) + 0.15 + + + fates_phen_moist_threshold + scalar + m3/m3 or mm + upper threshold for drought phenology (only for fates_phen_drought_model=1); 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) + 0.18 + + + fates_landuse_pprodharv10_forest_mean + scalar + fraction + mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types + 0.8125 + + + fates_leaf_stomatal_assim_model + scalar + unitless + a switch designating whether to use net (1) or gross (2) assimilation in the stomatal model + 1 + + + width in VAI units of uppermost leaf+stem layer scattering element in each canopy layer + + + factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) + + + factor by which each leaf+stem scattering element increases in VAI width (1 = uniform spacing) + + + fates_prt_organs + + + fates_plant_organs + 4 + + + fates_alloc_organ_priority + fates_plant_organs, fates_pft + index + Priority level for allocation, 1: replaces turnover from storage, 2: same priority as storage use/replacement, 3: ascending in order of least importance + 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_organ_name + fates_plant_organs, fates_string_length + unitless - string + Name of plant organs (with alloc_organ_id, must match PRTGenericMod.F90) + leaf, fine root, sapwood,structure + + + fates_stoich_nitr + fates_plant_organs, fates_pft + gN/gC + target nitrogen concentration (ratio with carbon) of organs + 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_alloc_organ_id + fates_plant_organs + unitless + This is the global index that the organ in this file is associated with, values match those in parteh/PRTGenericMod.F90 + 1, 2, 3, 6 + + + fates_stoich_phos + fates_plant_organs, fates_pft + gP/gC + target phosphorus concentration (ratio with carbon) of organs + 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_cnp_turnover_nitr_retrans + fates_plant_organs, fates_pft + fraction + retranslocation (reabsorbtion) fraction of nitrogen in turnover of scenescing tissues + 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 + fates_plant_organs, fates_pft + fraction + retranslocation (reabsorbtion) fraction of phosphorus in turnover of scenescing tissues + 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_hydro_organ_name + + + fates_init_litter + + + fates_mort_prescribed_canopy + + + fates_mort_prescribed_understory + + + fates_phen_flush_fraction + + + fates_phen_mindaysoff + + + fates_turb_leaf_diameter + + + fates_turb_displar + + + fates_turb_z0mr + + + fates_landuse_logging_coll_under_frac + + + fates_landuse_logging_collateral_frac + + + fates_landuse_logging_dbhmax + + + fates_landuse_logging_dbhmax_infra + + + fates_landuse_logging_dbhmin + + + fates_landuse_logging_direct_frac + + + fates_landuse_logging_event_code + + + fates_landuse_logging_export_frac + + + fates_landuse_logging_mechanical_frac + + + fates_leaf_photo_temp_acclim_timescale + + + fates_leaf_theta_cj_c3 + + + fates_leaf_theta_cj_c4 + + + fates_leaf_photo_tempsens_model + + + fates_nonhydro_smpsc + + + fates_nonhydro_smpso + + + fates_hydro_htftype_node + + + fates_hydro_kmax_rsurf1 + + + fates_hydro_kmax_rsurf2 + + + fates_hydro_psi0 + + + fates_hydro_psicap + + + fates_hydro_avuln_gs + + + fates_hydro_avuln_node + + + fates_hydro_epsil_node + + + fates_hydro_fcap_node + + + fates_hydro_k_lwp + + + fates_hydro_kmax_node + + + fates_hydro_p50_gs + + + fates_hydro_p50_node + + + fates_hydro_p_taper + + + fates_hydro_pinot_node + + + fates_hydro_pitlp_node + + + fates_hydro_resid_node + + + fates_hydro_rfrac_stem + + + fates_hydro_rs2 + + + fates_hydro_srl + + + fates_hydro_thetas_node + + + fates_hydro_vg_alpha_node + + + fates_hydro_vg_m_node + + + fates_hydro_vg_n_node + + + fates_cnp_eca_alpha_ptase + + + fates_cnp_eca_decompmicc + + + fates_cnp_eca_km_nh4 + + + fates_cnp_eca_km_no3 + + + fates_cnp_eca_km_p + + + fates_cnp_eca_km_ptase + + + fates_cnp_eca_lambda_ptase + + + fates_cnp_eca_vmax_ptase + + + fates_cnp_fnrt_adapt_tscale + fates_pft + days + Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 + + + fates_cnp_nfix1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + + + fates_nfix2 + + + fates_cnp_nitr_store_ratio + storeable (labile) N, as a ratio compared to the N bound in cell structures of other organs (see code) + + + fates_cnp_phos_store_ratio + storeable (labile) P, as a ratio compared to the P bound in cell structures of other organs (see code) + + + fates_cnp_prescribed_nuptake + + + fates_cnp_prescribed_puptake + + + fates_cnp_eca_vmax_nh4 + 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 + + + fates_cnp_eca_vmax_no3 + 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 + + + fates_cnp_rd_vmax_n + fates_pft + gN/gC/s + maximum production rate for compbined (NH4+NO3) uptake (RD) + 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9, 5.e-9 + + + fates_cnp_vmax_p + maximum production rate for phosphorus (ECA and RD) + 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10, 5.e-10 + + + fates_turnover_retrans_mode + + + fates_cnp_eca_plant_escalar + + + fates_alloc_store_priority_frac + for high-priority organs, the fraction of their turnover demand that is gauranteed to be replaced, and if need-be by storage + + + fates_turnover_leaf + + + fates_turnover_fnrt + + + fates_turnover_senleaf_fdrought + + + fates_turnover_branch + + + fates_allom_fnrt_prof_a + + + fates_allom_fnrt_prof_b + + + fates_allom_fnrt_prof_mode + + + fates_frag_maxdecomp + + + fates_frag_cwd_frac + + + fates_frag_fnrt_fcel + + + fates_frag_fnrt_flab + + + fates_frag_fnrt_flig + + + fates_frag_leaf_fcel + + + fates_frag_leaf_flab + + + fates_frag_leaf_flig + + + fates_frag_seed_decay_rate + + + fates_frag_cwd_fcel + + + fates_frag_cwd_flig + + + fates_recruit_seed_alloc + + + fates_recruit_seed_alloc_mature + + + fates_recruit_seed_dbh_repro_threshold + + + fates_recruit_seed_germination_rate + + + fates_recruit_seed_supplement + + + fates_recruit_prescribed_rate + + + fates_recruit_height_min + + + fates_recruit_init_density + + + fates_rad_leaf_clumping_index + + + fates_rad_leaf_xl + + + fates_rad_leaf_rhonir + + + fates_rad_leaf_rhovis + + + fates_rad_stem_rhonir + + + fates_rad_stem_rhovis + + + fates_rad_leaf_taunir + + + fates_rad_leaf_tauvis + + + fates_rad_stem_taunir + + + fates_rad_stem_tauvis + + + fates_damage_event_code + scalar + unitless + Integer code that options how damage events are structured + 1 + + + fates_damage_canopy_layer_code + scalar + unitless + Integer code that decides whether damage affects canopy trees (1), understory trees (2) + 1 + + + fates_phen_gddthresh_a + + + fates_phen_gddthresh_b + + + fates_phen_gddthresh_c + + + fates_phen_chilltemp + + + fates_cnp_store_ovrflw_frac + fates_pft + fraction + size of overflow storage (for excess C,N or P) as a fraction of storage target + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + + + diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index c69b2b8df8..569e6a1ab6 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -1,17 +1,18 @@ -netcdf fates_params_default.c210629_sorted { +netcdf fates_params_default_api24 { 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_history_coage_bins = 2 ; + fates_hlm_pftno = 14 ; fates_hydr_organs = 4 ; fates_leafage_class = 1 ; fates_litterclass = 6 ; fates_pft = 12 ; - fates_prt_organs = 4 ; + fates_plant_organs = 4 ; fates_string_length = 60 ; - fates_hlm_pftno = 14 ; variables: double fates_history_ageclass_bin_edges(fates_history_age_bins) ; fates_history_ageclass_bin_edges:units = "yr" ; @@ -22,31 +23,39 @@ variables: 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_hydr_htftype_node(fates_hydr_organs) ; - fates_hydr_htftype_node:units = "unitless" ; - fates_hydr_htftype_node:long_name = "Switch that defines the hydraulic transfer functions for each organ." ; - fates_hydr_htftype_node:possible_values = "1: Christofferson et al. 2016 (TFS); 2: Van Genuchten 1980" ; - double fates_prt_organ_id(fates_prt_organs) ; - fates_prt_organ_id:units = "index, unitless" ; - fates_prt_organ_id:long_name = "This is the global index the organ in this file is associated with in PRTGenericMod.F90" ; + 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_hydr_organname_node(fates_hydr_organs, fates_string_length) ; - fates_hydr_organname_node:units = "unitless - string" ; - fates_hydr_organname_node:long_name = "Name of plant hydraulics organs (DONT CHANGE, order matches media list in FatesHydraulicsMemMod.F90)" ; + 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" ; - char fates_prt_organ_name(fates_prt_organs, fates_string_length) ; - fates_prt_organ_name:units = "unitless - string" ; - fates_prt_organ_name:long_name = "Name of plant organs (order must match PRTGenericMod.F90)" ; + 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" ; @@ -65,14 +74,15 @@ variables: double fates_allom_amode(fates_pft) ; fates_allom_amode:units = "index" ; fates_allom_amode:long_name = "AGB allometry function index." ; - fates_allom_amode:possible_values = "1: Saldarriaga 1998; 2: 2 parameter power law; 3: Chave 2014" ; 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." ; - fates_allom_cmode:possible_values = "1: Constant fraction on AGB" ; + 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" ; @@ -103,14 +113,21 @@ variables: double fates_allom_fmode(fates_pft) ; fates_allom_fmode:units = "index" ; fates_allom_fmode:long_name = "fine root biomass allometry function index." ; - fates_allom_fmode:possible_values = "1: constant fraction of trimmed bleaf; 2: constant fraction of untrimmed bleaf." ; + 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." ; - fates_allom_hmode:possible_values = "1: OBrien 1995; 2: Poorter 2006; 3: 2 parameter power law; 4: Chave 2014; 5: Martinez-Cano 2019." ; 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" ; @@ -123,18 +140,15 @@ variables: double fates_allom_lmode(fates_pft) ; fates_allom_lmode:units = "index" ; fates_allom_lmode:long_name = "leaf biomass allometry function index." ; - fates_allom_lmode:possible_values = "1: Saldarriaga 1998 (capped-dbh power law); 2: generic power law; 3: generic capped-dbh power law." ; 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." ; - fates_allom_smode:possible_values = "1: sapwood area proportional to leaf area based on target leaf biomass" ; double fates_allom_stmode(fates_pft) ; fates_allom_stmode:units = "index" ; fates_allom_stmode:long_name = "storage allometry function index." ; - fates_allom_stmode:possible_values = "1: target storage proportional to trimmed maximum leaf biomass." ; 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" ; @@ -150,151 +164,181 @@ variables: 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_branch_turnover(fates_pft) ; - fates_branch_turnover:units = "yr" ; - fates_branch_turnover:long_name = "turnover time of branches" ; 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_nh4(fates_pft) ; + fates_cnp_eca_vmax_nh4:units = "gN/gC/s" ; + fates_cnp_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; + double fates_cnp_eca_vmax_no3(fates_pft) ; + fates_cnp_eca_vmax_no3:units = "gN/gC/s" ; + fates_cnp_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (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_fnrt_adapt_tscale(fates_pft) ; + fates_cnp_fnrt_adapt_tscale:units = "days" ; + fates_cnp_fnrt_adapt_tscale:long_name = "Number of days that is shortest possible doubling period for fine-root adaptation to C/N/P balance" ; + double fates_cnp_nfix1(fates_pft) ; + fates_cnp_nfix1:units = "NA" ; + fates_cnp_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; + 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_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_rd_vmax_n(fates_pft) ; + fates_cnp_rd_vmax_n:units = "gN/gC/s" ; + fates_cnp_rd_vmax_n:long_name = "maximum production rate for compbined (NH4+NO3) uptake (RD)" ; + 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" ; + fates_cnp_store_ovrflw_frac:use_case = "None" ; + 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_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_displar(fates_pft) ; - fates_displar:units = "unitless" ; - fates_displar:long_name = "Ratio of displacement height to canopy top height" ; - double fates_eca_alpha_ptase(fates_pft) ; - fates_eca_alpha_ptase:units = "g/m3" ; - fates_eca_alpha_ptase:long_name = "fraction of P from ptase activity sent directly to plant (ECA)" ; - double fates_eca_decompmicc(fates_pft) ; - fates_eca_decompmicc:units = "gC/m3" ; - fates_eca_decompmicc:long_name = "mean soil microbial decomposer biomass (ECA)" ; - double fates_eca_km_nh4(fates_pft) ; - fates_eca_km_nh4:units = "gN/m3" ; - fates_eca_km_nh4:long_name = "half-saturation constant for plant nh4 uptake (ECA)" ; - double fates_eca_km_no3(fates_pft) ; - fates_eca_km_no3:units = "gN/m3" ; - fates_eca_km_no3:long_name = "half-saturation constant for plant no3 uptake (ECA)" ; - double fates_eca_km_p(fates_pft) ; - fates_eca_km_p:units = "gP/m3" ; - fates_eca_km_p:long_name = "half-saturation constant for plant p uptake (ECA)" ; - double fates_eca_km_ptase(fates_pft) ; - fates_eca_km_ptase:units = "gP/m3" ; - fates_eca_km_ptase:long_name = "half-saturation constant for biochemical P (ECA)" ; - double fates_eca_lambda_ptase(fates_pft) ; - fates_eca_lambda_ptase:units = "g/m3" ; - fates_eca_lambda_ptase:long_name = "critical value for biochemical production (ECA)" ; - double fates_eca_vmax_nh4(fates_pft) ; - fates_eca_vmax_nh4:units = "gN/gC/s" ; - fates_eca_vmax_nh4:long_name = "maximum production rate for plant nh4 uptake (ECA)" ; - double fates_eca_vmax_no3(fates_pft) ; - fates_eca_vmax_no3:units = "gN/gC/s" ; - fates_eca_vmax_no3:long_name = "maximum production rate for plant no3 uptake (ECA)" ; - double fates_eca_vmax_p(fates_pft) ; - fates_eca_vmax_p:units = "gP/gC/s" ; - fates_eca_vmax_p:long_name = "maximum production rate for plant p uptake (ECA)" ; - double fates_eca_vmax_ptase(fates_pft) ; - fates_eca_vmax_ptase:units = "gP/m2/s" ; - fates_eca_vmax_ptase:long_name = "maximum production rate for biochemical P (per m2) (ECA)" ; 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_depth_frac(fates_pft) ; - fates_fire_crown_depth_frac:units = "fraction" ; - fates_fire_crown_depth_frac:long_name = "the depth of a cohorts crown as a fraction of its height" ; 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_fnrt_prof_a(fates_pft) ; - fates_fnrt_prof_a:units = "unitless" ; - fates_fnrt_prof_a:long_name = "Fine root profile function, parameter a" ; - double fates_fnrt_prof_b(fates_pft) ; - fates_fnrt_prof_b:units = "unitless" ; - fates_fnrt_prof_b:long_name = "Fine root profile function, parameter b" ; - double fates_fnrt_prof_mode(fates_pft) ; - fates_fnrt_prof_mode:units = "index" ; - fates_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_fr_fcel(fates_pft) ; - fates_fr_fcel:units = "fraction" ; - fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; - double fates_fr_flab(fates_pft) ; - fates_fr_flab:units = "fraction" ; - fates_fr_flab:long_name = "Fine root litter labile fraction" ; - double fates_fr_flig(fates_pft) ; - fates_fr_flig:units = "fraction" ; - fates_fr_flig:long_name = "Fine root litter lignin fraction" ; + 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_hydr_avuln_gs(fates_pft) ; - fates_hydr_avuln_gs:units = "unitless" ; - fates_hydr_avuln_gs:long_name = "shape parameter for stomatal control of water vapor exiting leaf" ; - double fates_hydr_avuln_node(fates_hydr_organs, fates_pft) ; - fates_hydr_avuln_node:units = "unitless" ; - fates_hydr_avuln_node:long_name = "xylem vulnerability curve shape parameter" ; - double fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; - fates_hydr_epsil_node:units = "MPa" ; - fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; - double fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; - fates_hydr_fcap_node:units = "unitless" ; - fates_hydr_fcap_node:long_name = "fraction of non-residual water that is capillary in source" ; - double fates_hydr_k_lwp(fates_pft) ; - fates_hydr_k_lwp:units = "unitless" ; - fates_hydr_k_lwp:long_name = "inner leaf humidity scaling coefficient" ; - fates_hydr_k_lwp:possible_values = "0: turns off leaf humidity effects on conductance. 1-10 activates humidity effects" ; - double fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; - fates_hydr_kmax_node:units = "kg/MPa/m/s" ; - fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; - double fates_hydr_p50_gs(fates_pft) ; - fates_hydr_p50_gs:units = "MPa" ; - fates_hydr_p50_gs:long_name = "water potential at 50% loss of stomatal conductance" ; - double fates_hydr_p50_node(fates_hydr_organs, fates_pft) ; - fates_hydr_p50_node:units = "MPa" ; - fates_hydr_p50_node:long_name = "xylem water potential at 50% loss of conductivity" ; - double fates_hydr_p_taper(fates_pft) ; - fates_hydr_p_taper:units = "unitless" ; - fates_hydr_p_taper:long_name = "xylem taper exponent" ; - double fates_hydr_pinot_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pinot_node:units = "MPa" ; - fates_hydr_pinot_node:long_name = "osmotic potential at full turgor" ; - double fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; - fates_hydr_pitlp_node:units = "MPa" ; - fates_hydr_pitlp_node:long_name = "turgor loss point" ; - double fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; - fates_hydr_resid_node:units = "cm3/cm3" ; - fates_hydr_resid_node:long_name = "residual water conent" ; - double fates_hydr_rfrac_stem(fates_pft) ; - fates_hydr_rfrac_stem:units = "fraction" ; - fates_hydr_rfrac_stem:long_name = "fraction of total tree resistance from troot to canopy" ; - double fates_hydr_rs2(fates_pft) ; - fates_hydr_rs2:units = "m" ; - fates_hydr_rs2:long_name = "absorbing root radius" ; - double fates_hydr_srl(fates_pft) ; - fates_hydr_srl:units = "m g-1" ; - fates_hydr_srl:long_name = "specific root length" ; - double fates_hydr_thetas_node(fates_hydr_organs, fates_pft) ; - fates_hydr_thetas_node:units = "cm3/cm3" ; - fates_hydr_thetas_node:long_name = "saturated water content" ; - double fates_hydr_vg_alpha_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_alpha_node:units = "MPa-1" ; - fates_hydr_vg_alpha_node:long_name = "(used if hydr_htftype_node = 2), capillary length parameter in van Genuchten model" ; - double fates_hydr_vg_m_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_m_node:units = "unitless" ; - fates_hydr_vg_m_node:long_name = "(used if hydr_htftype_node = 2),m in van Genuchten 1980 model, 2nd pore size distribution parameter" ; - double fates_hydr_vg_n_node(fates_hydr_organs, fates_pft) ; - fates_hydr_vg_n_node:units = "unitless" ; - fates_hydr_vg_n_node:long_name = "(used if hydr_htftype_node = 2),n in van Genuchten 1980 model, pore size distribution parameter" ; + 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_clumping_index(fates_pft) ; - fates_leaf_clumping_index:units = "fraction (0-1)" ; - fates_leaf_clumping_index:long_name = "factor describing how much self-occlusion of leaf scattering elements decreases light interception" ; - double fates_leaf_diameter(fates_pft) ; - fates_leaf_diameter:units = "m" ; - fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; double fates_leaf_jmaxha(fates_pft) ; fates_leaf_jmaxha:units = "J/mol" ; fates_leaf_jmaxha:long_name = "activation energy for jmax" ; @@ -304,9 +348,6 @@ variables: double fates_leaf_jmaxse(fates_pft) ; fates_leaf_jmaxse:units = "J/mol/K" ; fates_leaf_jmaxse:long_name = "entropy term for jmax" ; - double fates_leaf_long(fates_leafage_class, fates_pft) ; - fates_leaf_long:units = "yr" ; - fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; 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" ; @@ -322,9 +363,6 @@ variables: double fates_leaf_stomatal_slope_medlyn(fates_pft) ; fates_leaf_stomatal_slope_medlyn:units = "KPa**0.5" ; fates_leaf_stomatal_slope_medlyn:long_name = "stomatal slope parameter, as per Medlyn" ; - double fates_leaf_stor_priority(fates_pft) ; - fates_leaf_stor_priority:units = "unitless" ; - fates_leaf_stor_priority:long_name = "factor governing priority of replacing storage with NPP" ; 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" ; @@ -337,18 +375,6 @@ variables: double fates_leaf_vcmaxse(fates_pft) ; fates_leaf_vcmaxse:units = "J/mol/K" ; fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; - double fates_leaf_xl(fates_pft) ; - fates_leaf_xl:units = "unitless" ; - fates_leaf_xl:long_name = "Leaf/stem orientation index" ; - double fates_lf_fcel(fates_pft) ; - fates_lf_fcel:units = "fraction" ; - fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; - double fates_lf_flab(fates_pft) ; - fates_lf_flab:units = "fraction" ; - fates_lf_flab:long_name = "Leaf litter labile fraction" ; - double fates_lf_flig(fates_pft) ; - fates_lf_flig:units = "fraction" ; - fates_lf_flig:long_name = "Leaf litter lignin fraction" ; 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" ; @@ -373,6 +399,12 @@ variables: 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." ; @@ -388,21 +420,24 @@ variables: 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_nfix1(fates_pft) ; - fates_nfix1:units = "NA" ; - fates_nfix1:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nfix2(fates_pft) ; - fates_nfix2:units = "NA" ; - fates_nfix2:long_name = "place-holder for future n-fixation parameter (NOT IMPLEMENTED)" ; - double fates_nitr_store_ratio(fates_pft) ; - fates_nitr_store_ratio:units = "(gN/gN)" ; - fates_nitr_store_ratio:long_name = "ratio of storeable N, to functional N bound in cell structures of leaf,root,sap" ; + 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_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_frac(fates_pft) ; + fates_phen_fnrt_drop_frac:units = "fraction" ; + fates_phen_fnrt_drop_frac:long_name = "fraction of fine roots to drop during drought or cold" ; 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" ; @@ -412,139 +447,108 @@ variables: 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_phenflush_fraction(fates_pft) ; - fates_phenflush_fraction:units = "fraction" ; - fates_phenflush_fraction:long_name = "Upon bud-burst, the maximum fraction of storage carbon used for flushing leaves" ; - double fates_phos_store_ratio(fates_pft) ; - fates_phos_store_ratio:units = "(gP/gP)" ; - fates_phos_store_ratio:long_name = "ratio of storeable P, to functional P bound in cell structures of leaf,root,sap" ; - double fates_prescribed_mortality_canopy(fates_pft) ; - fates_prescribed_mortality_canopy:units = "1/yr" ; - fates_prescribed_mortality_canopy:long_name = "mortality rate of canopy trees for prescribed physiology mode" ; - double fates_prescribed_mortality_understory(fates_pft) ; - fates_prescribed_mortality_understory:units = "1/yr" ; - fates_prescribed_mortality_understory:long_name = "mortality rate of understory trees for prescribed physiology mode" ; 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_prescribed_nuptake(fates_pft) ; - fates_prescribed_nuptake:units = "fraction" ; - fates_prescribed_nuptake:long_name = "Prescribed N uptake flux. 0=fully coupled simulation >0=prescribed (experimental)" ; - double fates_prescribed_puptake(fates_pft) ; - fates_prescribed_puptake:units = "fraction" ; - fates_prescribed_puptake:long_name = "Prescribed P uptake flux. 0=fully coupled simulation, >0=prescribed (experimental)" ; - double fates_prescribed_recruitment(fates_pft) ; - fates_prescribed_recruitment:units = "n/yr" ; - fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; - double fates_prt_alloc_priority(fates_prt_organs, fates_pft) ; - fates_prt_alloc_priority:units = "index (0-fates_prt_organs)" ; - fates_prt_alloc_priority:long_name = "Priority order for allocation (C storage=2)" ; - double fates_prt_nitr_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p1:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p1:long_name = "nitrogen stoichiometry, parameter 1" ; - double fates_prt_nitr_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_nitr_stoich_p2:units = "(gN/gC)" ; - fates_prt_nitr_stoich_p2:long_name = "nitrogen stoichiometry, parameter 2" ; - double fates_prt_phos_stoich_p1(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p1:units = "(gP/gC)" ; - fates_prt_phos_stoich_p1:long_name = "phosphorous stoichiometry, parameter 1" ; - double fates_prt_phos_stoich_p2(fates_prt_organs, fates_pft) ; - fates_prt_phos_stoich_p2:units = "(gP/gC)" ; - fates_prt_phos_stoich_p2:long_name = "phosphorous stoichiometry, parameter 2" ; - double fates_recruit_hgt_min(fates_pft) ; - fates_recruit_hgt_min:units = "m" ; - fates_recruit_hgt_min:long_name = "the minimum height (ie starting height) of a newly recruited plant" ; - double fates_recruit_initd(fates_pft) ; - fates_recruit_initd:units = "stems/m2" ; - fates_recruit_initd:long_name = "initial seedling density for a cold-start near-bare-ground simulation" ; - double fates_rholnir(fates_pft) ; - fates_rholnir:units = "fraction" ; - fates_rholnir:long_name = "Leaf reflectance: near-IR" ; - double fates_rholvis(fates_pft) ; - fates_rholvis:units = "fraction" ; - fates_rholvis:long_name = "Leaf reflectance: visible" ; - double fates_rhosnir(fates_pft) ; - fates_rhosnir:units = "fraction" ; - fates_rhosnir:long_name = "Stem reflectance: near-IR" ; - double fates_rhosvis(fates_pft) ; - fates_rhosvis:units = "fraction" ; - fates_rhosvis:long_name = "Stem reflectance: visible" ; - double fates_root_long(fates_pft) ; - fates_root_long:units = "yr" ; - fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; - double fates_seed_alloc(fates_pft) ; - fates_seed_alloc:units = "fraction" ; - fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; - double fates_seed_alloc_mature(fates_pft) ; - fates_seed_alloc_mature:units = "fraction" ; - fates_seed_alloc_mature:long_name = "fraction of available carbon balance allocated to seeds in mature plants (adds to fates_seed_alloc)" ; - double fates_seed_dbh_repro_threshold(fates_pft) ; - fates_seed_dbh_repro_threshold:units = "cm" ; - fates_seed_dbh_repro_threshold:long_name = "the diameter (if any) where the plant will start extra clonal allocation to the seed pool" ; - double fates_seed_decay_rate(fates_pft) ; - fates_seed_decay_rate:units = "yr-1" ; - fates_seed_decay_rate:long_name = "fraction of seeds that decay per year" ; - double fates_seed_germination_rate(fates_pft) ; - fates_seed_germination_rate:units = "yr-1" ; - fates_seed_germination_rate:long_name = "fraction of seeds that germinate per year" ; - double fates_seed_suppl(fates_pft) ; - fates_seed_suppl:units = "KgC/m2/yr" ; - fates_seed_suppl:long_name = "Supplemental external seed rain source term (non-mass conserving)" ; - double fates_senleaf_long_fdrought(fates_pft) ; - fates_senleaf_long_fdrought:units = "unitless[0-1]" ; - fates_senleaf_long_fdrought:long_name = "multiplication factor for leaf longevity of senescent leaves during drought" ; - double fates_smpsc(fates_pft) ; - fates_smpsc:units = "mm" ; - fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; - double fates_smpso(fates_pft) ; - fates_smpso:units = "mm" ; - fates_smpso:long_name = "Soil water potential at full stomatal opening" ; - double fates_taulnir(fates_pft) ; - fates_taulnir:units = "fraction" ; - fates_taulnir:long_name = "Leaf transmittance: near-IR" ; - double fates_taulvis(fates_pft) ; - fates_taulvis:units = "fraction" ; - fates_taulvis:long_name = "Leaf transmittance: visible" ; - double fates_tausnir(fates_pft) ; - fates_tausnir:units = "fraction" ; - fates_tausnir:long_name = "Stem transmittance: near-IR" ; - double fates_tausvis(fates_pft) ; - fates_tausvis:units = "fraction" ; - fates_tausvis:long_name = "Stem transmittance: visible" ; + 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" ; + 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 (if any) where the plant will start extra clonal allocation to the seed pool" ; + 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_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_turnover_carb_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_carb_retrans:units = "-" ; - fates_turnover_carb_retrans:long_name = "retranslocation fraction of carbon in turnover" ; - double fates_turnover_nitr_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_nitr_retrans:units = "-" ; - fates_turnover_nitr_retrans:long_name = "retranslocation fraction of nitrogen in turnover" ; - double fates_turnover_phos_retrans(fates_prt_organs, fates_pft) ; - fates_turnover_phos_retrans:units = "-" ; - fates_turnover_phos_retrans:long_name = "retranslocation fraction of phosphorous in turnover, parameter 1" ; - double fates_turnover_retrans_mode(fates_pft) ; - fates_turnover_retrans_mode:units = "index" ; - fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover." ; - fates_turnover_retrans_mode:possible_values = "1: constant fraction." ; + 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)" ; + 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_z0mr(fates_pft) ; - fates_z0mr:units = "unitless" ; - fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; - 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_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" ; @@ -569,18 +573,21 @@ variables: 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_max_decomp(fates_litterclass) ; - fates_max_decomp:units = "yr-1" ; - fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; - double fates_CWD_frac(fates_NCWD) ; - fates_CWD_frac:units = "fraction" ; - fates_CWD_frac:long_name = "fraction of woody (bdead+bsw) biomass destined for CWD pool" ; + 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_base_mr_20 ; fates_base_mr_20:units = "gC/gN/s" ; fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; 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." ; @@ -590,18 +597,15 @@ variables: 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_cwd_fcel ; - fates_cwd_fcel:units = "unitless" ; - fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; - double fates_cwd_flig ; - fates_cwd_flig:units = "unitless" ; - fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + 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_eca_plant_escalar ; - fates_eca_plant_escalar:units = "" ; - fates_eca_plant_escalar:long_name = "scaling factor for plant fine root biomass to calculate nutrient carrier enzyme abundance (ECA)" ; 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" ; @@ -644,57 +648,87 @@ variables: 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_hydr_kmax_rsurf1 ; - fates_hydr_kmax_rsurf1:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf1:long_name = "maximum conducitivity for unit root surface (into root)" ; - double fates_hydr_kmax_rsurf2 ; - fates_hydr_kmax_rsurf2:units = "kg water/m2 root area/Mpa/s" ; - fates_hydr_kmax_rsurf2:long_name = "maximum conducitivity for unit root surface (out of root)" ; - double fates_hydr_psi0 ; - fates_hydr_psi0:units = "MPa" ; - fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; - double fates_hydr_psicap ; - fates_hydr_psicap:units = "MPa" ; - fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; - double fates_init_litter ; - fates_init_litter:units = "NA" ; - fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; + 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_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 (NOT USED)" ; + 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 (NOT USED)" ; + 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_logging_coll_under_frac ; - fates_logging_coll_under_frac:units = "fraction" ; - fates_logging_coll_under_frac:long_name = "Fraction of stems killed in the understory when logging generates disturbance" ; - double fates_logging_collateral_frac ; - fates_logging_collateral_frac:units = "fraction" ; - fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; - double fates_logging_dbhmax ; - fates_logging_dbhmax:units = "cm" ; - fates_logging_dbhmax:long_name = "Maximum dbh below which logging is applied (unset values flag this to be unused)" ; - double fates_logging_dbhmax_infra ; - fates_logging_dbhmax_infra:units = "cm" ; - fates_logging_dbhmax_infra:long_name = "Tree diameter, above which infrastructure from logging does not impact damage or mortality." ; - double fates_logging_dbhmin ; - fates_logging_dbhmin:units = "cm" ; - fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; - double fates_logging_direct_frac ; - fates_logging_direct_frac:units = "fraction" ; - fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; - double fates_logging_event_code ; - fates_logging_event_code:units = "unitless" ; - fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; - double fates_logging_export_frac ; - fates_logging_export_frac:units = "fraction" ; - fates_logging_export_frac:long_name = "fraction of trunk product being shipped offsite, the leftovers will be left onsite as large CWD" ; - double fates_logging_mechanical_frac ; - fates_logging_mechanical_frac:units = "fraction" ; - fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; - double fates_pprodharv10_forest_mean ; - fates_pprodharv10_forest_mean:units = "fraction" ; - fates_pprodharv10_forest_mean:long_name = "mean harvest mortality proportion of deadstem to 10-yr product (pprodharv10) of all woody PFT types." ; + 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_model ; fates_maintresp_model:units = "unitless" ; fates_maintresp_model:long_name = "switch for choosing between maintenance respiration models. 1=Ryan (1991) (NOT USED)" ; + 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)" ; @@ -704,39 +738,39 @@ variables: 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_a ; - fates_phen_a:units = "none" ; - fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_b ; - fates_phen_b:units = "none" ; - fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_c ; - fates_phen_c:units = "none" ; - fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; - double fates_phen_chiltemp ; - fates_phen_chiltemp:units = "degrees C" ; - fates_phen_chiltemp:long_name = "chilling day counting threshold for vegetation" ; + 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_doff_time ; - fates_phen_doff_time:units = "days" ; - fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; + double fates_phen_drought_model ; + fates_phen_drought_model:units = "unitless" ; + fates_phen_drought_model:long_name = "which method to use for drought phenology: 0 - FATES default; 1 - Semi-deciduous (ED2-like)" ; double fates_phen_drought_threshold ; - fates_phen_drought_threshold:units = "m3/m3" ; - fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; + fates_phen_drought_threshold:units = "m3/m3 or mm" ; + fates_phen_drought_threshold:long_name = "threshold for drought phenology (or lower threshold when fates_phen_drought_model = 1); 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_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_mindaysoff ; + fates_phen_mindaysoff:units = "days" ; + fates_phen_mindaysoff:long_name = "day threshold compared against days since leaves became off-allometry" ; 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_moist_threshold ; + fates_phen_moist_threshold:units = "m3/m3 or mm" ; + fates_phen_moist_threshold:long_name = "upper threshold for drought phenology (only for fates_phen_drought_model=1); 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_ncolddayslim ; fates_phen_ncolddayslim:units = "days" ; fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; - double fates_photo_temp_acclim_timescale ; - fates_photo_temp_acclim_timescale:units = "days" ; - fates_photo_temp_acclim_timescale:long_name = "Length of the window for the exponential moving average (ema) of vegetation temperature used in photosynthesis temperature acclimation (NOT USED)" ; - double fates_photo_tempsens_model ; - fates_photo_tempsens_model:units = "unitless" ; - fates_photo_tempsens_model:long_name = "switch for choosing the model that defines the temperature sensitivity of photosynthetic parameters (vcmax, jmax). 1=non-acclimating (NOT USED)" ; double fates_q10_froz ; fates_q10_froz:units = "unitless" ; fates_q10_froz:long_name = "Q10 for frozen-soil respiration rates" ; @@ -746,18 +780,12 @@ variables: 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_theta_cj_c3 ; - fates_theta_cj_c3:units = "unitless" ; - fates_theta_cj_c3:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c3 plants" ; - double fates_theta_cj_c4 ; - fates_theta_cj_c4:units = "unitless" ; - fates_theta_cj_c4:long_name = "Empirical curvature parameter for ac, aj photosynthesis co-limitation in c4 plants" ; 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 (NOT USED)" ; + 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) (NOT USED)" ; + 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 parameter file is maintained in version control\nSee https://github.com/NGEET/fates/blob/master/parameter_files/fates_params_default.cdl \nFor changes, use git blame \n" ; @@ -769,12 +797,14 @@ data: fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; - fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 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_hydr_htftype_node = 1, 1, 1, 1 ; + fates_alloc_organ_id = 1, 2, 3, 6 ; - fates_prt_organ_id = 1, 2, 3, 6 ; + fates_hydro_htftype_node = 1, 1, 1, 1 ; fates_pftname = "broadleaf_evergreen_tropical_tree ", @@ -790,12 +820,18 @@ data: "cool_c3_grass ", "c4_grass " ; - fates_hydr_organname_node = + 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 ", @@ -804,28 +840,31 @@ data: "dead leaves ", "live grass " ; - fates_prt_organ_name = - "leaf ", - "fine root ", - "sapwood ", - "structure " ; + 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, 1.2, 1.2, 1.2, 1.2, 1.2, + fates_alloc_storage_cushion = 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_allom_agb1 = 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, 0.06896, + 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, + 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, + 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, + 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, + 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 ; @@ -834,50 +873,59 @@ data: 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.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, + 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, + 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.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, + 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, + 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, + 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, + 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, 90, 90, 90, 90, 90, 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, + 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, + 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 ; @@ -888,182 +936,224 @@ data: 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, + 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, + 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, + fates_allom_zroot_min_z = 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ; - fates_branch_turnover = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - fates_c2b = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ; - fates_dev_arbitrary_pft = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_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_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.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5 ; - fates_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + fates_cnp_eca_decompmicc = 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280 ; - fates_eca_km_nh4 = 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14, + 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_eca_km_no3 = 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, 0.27, + 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_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_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_nh4 = 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_eca_vmax_no3 = 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_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_fnrt_adapt_tscale = 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100 ; - fates_eca_km_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + fates_cnp_nfix1 = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_eca_lambda_ptase = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + 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_eca_vmax_nh4 = 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, - 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07, 1.5e-07 ; + 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_eca_vmax_no3 = 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, - 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08, 1.5e-08 ; + fates_cnp_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_vmax_p = 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, - 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09, 1.5e-09 ; + fates_cnp_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - fates_eca_vmax_ptase = 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, 5e-09, + fates_cnp_rd_vmax_n = 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_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, + 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_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, + 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_depth_frac = 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.95, 0.95, - 0.95, 1, 1, 1 ; - - fates_fire_crown_kill = 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, 0.775, + 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_fnrt_prof_a = 7, 7, 7, 7, 6, 6, 7, 7, 7, 11, 11, 11 ; + 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_fnrt_prof_b = 1, 2, 2, 1, 2, 2, 1.5, 1.5, 1.5, 2, 2, 2 ; + 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_fnrt_prof_mode = 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 ; + 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_fr_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_fr_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_fr_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, + 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_hydr_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_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_hydr_avuln_node = + 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_hydr_epsil_node = + 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_hydr_fcap_node = + 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_hydr_k_lwp = 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_hydr_kmax_node = + 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_hydr_p50_gs = -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, + 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_hydr_p50_node = - -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, -2.25, + 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, -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_hydr_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_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_hydr_pinot_node = - -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, -1.465984, + 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.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, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478, -1.043478 ; - fates_hydr_pitlp_node = - -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, -1.67, + 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_hydr_resid_node = + 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_hydr_rfrac_stem = 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, 0.625, + 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_hydr_rs2 = 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, 0.0001, + 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_hydr_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; + fates_hydro_srl = 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25 ; - fates_hydr_thetas_node = + 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_hydr_vg_alpha_node = - 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, + 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.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.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.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005, 0.005 ; - fates_hydr_vg_m_node = + 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_hydr_vg_n_node = + 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, @@ -1071,284 +1161,222 @@ data: fates_leaf_c3psn = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ; - fates_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_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_leaf_jmaxha = 43540, 43540, 43540, 43540, 43540, 43540, 43540, 43540, + 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, + 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, + fates_leaf_jmaxse = 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495, 495 ; - fates_leaf_long = - 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - - fates_leaf_slamax = 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.0954, 0.012, + 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.01, 0.024, 0.012, 0.03, 0.03, 0.012, 0.03, + fates_leaf_slatop = 0.012, 0.01, 0.024, 0.012, 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, + 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, + 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_stor_priority = 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_leaf_vcmax25top = 50, 65, 39, 62, 41, 58, 62, 54, 54, 78, 78, 78 ; - fates_leaf_vcmaxha = 65330, 65330, 65330, 65330, 65330, 65330, 65330, 65330, + 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, + 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, + fates_leaf_vcmaxse = 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485, 485 ; - fates_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_lf_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_lf_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_lf_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_maintresp_reduction_curvature = 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, + 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_mort_bmort = 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, 0.014, + 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, -30, -60, -10, -80, -80, + fates_mort_freezetol = 2.5, -55, -80, -30, 2.5, -30, -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, + 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, + 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, + 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, + 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_nfix1 = _, _, _, _, _, _, _, _, _, _, _, _ ; - - fates_nfix2 = _, _, _, _, _, _, _, _, _, _, _, _ ; + fates_nonhydro_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, + -255000, -255000, -255000, -255000, -255000, -255000 ; - fates_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_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_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_frac = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + 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_phenflush_fraction = _, _, 0.5, _, 0.5, 0.5, _, 0.5, 0.5, 0.5, 0.5, 0.5 ; - - fates_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_prescribed_mortality_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_prescribed_mortality_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_prescribed_npp_canopy = 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, 0.4, + 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, + 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_prescribed_nuptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_puptake = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; - - fates_prescribed_recruitment = 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_prt_alloc_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_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_prt_nitr_stoich_p1 = - 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_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_prt_nitr_stoich_p2 = - 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_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_prt_phos_stoich_p1 = - 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_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_prt_phos_stoich_p2 = - 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_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_recruit_hgt_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, - 0.125, 0.125, 0.125 ; + 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_recruit_initd = 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_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_rholnir = 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_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_rholvis = 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_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_rhosnir = 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_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_rhosvis = 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_recruit_height_min = 1.3, 1.3, 1.3, 1.3, 1.3, 1.3, 0.75, 0.75, 0.75, + 0.125, 0.125, 0.125 ; - fates_root_long = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; + 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_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_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_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 = 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_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, 1.47, - 1.47, 1.47 ; + fates_recruit_seed_alloc_mature = 0, 0, 0, 0, 0, 0, 0.9, 0.9, 0.9, 0.9, 0.9, + 0.9 ; - fates_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_recruit_seed_dbh_repro_threshold = 150, 90, 90, 90, 90, 90, 3, 3, 2, + 1.47, 1.47, 1.47 ; - fates_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_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_seed_suppl = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; + fates_recruit_seed_supplement = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; - fates_senleaf_long_fdrought = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; + 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_smpsc = -255000, -255000, -255000, -255000, -255000, -255000, -255000, - -255000, -255000, -255000, -255000, -255000 ; + 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_smpso = -66000, -66000, -66000, -66000, -66000, -66000, -66000, - -66000, -66000, -66000, -66000, -66000 ; + 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_taulnir = 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_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_taulvis = 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_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_tausnir = 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_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_tausvis = 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_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_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_turnover_branch = 150, 150, 150, 150, 150, 150, 150, 150, 150, 0, 0, 0 ; - 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_turnover_fnrt = 1, 2, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_carb_retrans = - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 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_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_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_turnover_leaf = + 1.5, 4, 1, 1.5, 1, 1, 1.5, 1, 1, 1, 1, 1 ; - fates_turnover_retrans_mode = 1, 1, 1, 1, 1, 1, 1, 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.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, + fates_wood_density = 0.7, 0.7, 0.7, 0.7, 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_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_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 ; + 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 ; @@ -1366,28 +1394,28 @@ data: fates_fire_SAV = 13, 3.58, 0.98, 0.2, 66, 66 ; - fates_max_decomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; + fates_frag_maxdecomp = 0.52, 0.383, 0.383, 0.19, 1, 999 ; - fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; + fates_frag_cwd_frac = 0.045, 0.075, 0.21, 0.67 ; fates_base_mr_20 = 2.52e-06 ; 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_cwd_fcel = 0.76 ; + fates_damage_canopy_layer_code = 1 ; - fates_cwd_flig = 0.24 ; + fates_damage_event_code = 1 ; fates_dev_arbitrary = _ ; - fates_eca_plant_escalar = 1.25e-05 ; - fates_fire_active_crown_fire = 0 ; fates_fire_cg_strikes = 0.2 ; @@ -1416,67 +1444,87 @@ data: fates_fire_threshold = 50 ; - fates_hydr_kmax_rsurf1 = 20 ; + fates_frag_cwd_fcel = 0.76 ; - fates_hydr_kmax_rsurf2 = 0.0001 ; + fates_frag_cwd_flig = 0.24 ; - fates_hydr_psi0 = 0 ; + fates_hydro_kmax_rsurf1 = 20 ; - fates_hydr_psicap = -0.6 ; + fates_hydro_kmax_rsurf2 = 0.0001 ; - fates_init_litter = 0.05 ; + fates_hydro_psi0 = 0 ; - fates_leaf_stomatal_model = 1 ; + fates_hydro_psicap = -0.6 ; + + fates_hydro_solver = 1 ; - fates_logging_coll_under_frac = 0.55983 ; + fates_landuse_logging_coll_under_frac = 0.55983 ; - fates_logging_collateral_frac = 0.05 ; + fates_landuse_logging_collateral_frac = 0.05 ; - fates_logging_dbhmax = _ ; + fates_landuse_logging_dbhmax = _ ; - fates_logging_dbhmax_infra = 35 ; + fates_landuse_logging_dbhmax_infra = 35 ; - fates_logging_dbhmin = 50 ; + fates_landuse_logging_dbhmin = 50 ; - fates_logging_direct_frac = 0.15 ; + fates_landuse_logging_direct_frac = 0.15 ; - fates_logging_event_code = -30 ; + fates_landuse_logging_event_code = -30 ; - fates_logging_export_frac = 0.8 ; + fates_landuse_logging_export_frac = 0.8 ; - fates_logging_mechanical_frac = 0.05 ; + fates_landuse_logging_mechanical_frac = 0.05 ; - fates_pprodharv10_forest_mean = 0.8125 ; + fates_landuse_pprodharv10_forest_mean = 0.8125 ; + + 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_model = 1 ; + 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_a = -68 ; + fates_phen_chilltemp = 5 ; - fates_phen_b = 638 ; + fates_phen_coldtemp = 7.5 ; - fates_phen_c = -0.01 ; + fates_phen_drought_model = 0 ; - fates_phen_chiltemp = 5 ; + fates_phen_drought_threshold = 0.15 ; - fates_phen_coldtemp = 7.5 ; + fates_phen_gddthresh_a = -68 ; - fates_phen_doff_time = 100 ; + fates_phen_gddthresh_b = 638 ; - fates_phen_drought_threshold = 0.15 ; + fates_phen_gddthresh_c = -0.01 ; - fates_phen_mindayson = 90 ; + fates_phen_mindaysoff = 100 ; - fates_phen_ncolddayslim = 5 ; + fates_phen_mindayson = 90 ; - fates_photo_temp_acclim_timescale = 30 ; + fates_phen_moist_threshold = 0.18 ; - fates_photo_tempsens_model = 1 ; + fates_phen_ncolddayslim = 5 ; fates_q10_froz = 1.5 ; @@ -1484,10 +1532,6 @@ data: fates_soil_salinity = 0.4 ; - fates_theta_cj_c3 = 0.999 ; - - fates_theta_cj_c4 = 0.999 ; - fates_vai_top_bin_width = 1 ; fates_vai_width_increase_factor = 1 ; diff --git a/parteh/PRTAllometricCNPMod.F90 b/parteh/PRTAllometricCNPMod.F90 index 5617d71e5d..2a18d6d370 100644 --- a/parteh/PRTAllometricCNPMod.F90 +++ b/parteh/PRTAllometricCNPMod.F90 @@ -96,9 +96,11 @@ module PRTAllometricCNPMod ! Global identifiers for the two stoichiometry values integer,public, parameter :: stoich_growth_min = 1 ! Flag for stoichiometry associated with - ! minimum needed for growth + ! minimum needed for growth + + ! This is deprecated until a reasonable hypothesis is in place (RGK) integer,public, parameter :: stoich_max = 2 ! Flag for stoichiometry associated with - ! maximum for that organ + ! maximum for that organ ! This is the ordered list of organs used in this module @@ -1575,10 +1577,10 @@ subroutine CNPAllocateRemainder(this,c_gain, n_gain, p_gain, & do i = 1, num_organs ! Update the nitrogen and phosphorus deficits - target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i),stoich_max) + target_n = this%GetNutrientTarget(nitrogen_element,organ_list(i),stoich_growth_min) deficit_n(i) = max(0._r8,this%GetDeficit(nitrogen_element,organ_list(i),target_n)) - target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i),stoich_max) + target_p = this%GetNutrientTarget(phosphorus_element,organ_list(i),stoich_growth_min) deficit_p(i) = max(0._r8,this%GetDeficit(phosphorus_element,organ_list(i),target_p)) end do @@ -1739,17 +1741,17 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe if( element_id == nitrogen_element) then target_m = StorageNutrientTarget(ipft, element_id, & - leaf_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(leaf_organ)), & - fnrt_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(fnrt_organ)), & - sapw_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(sapw_organ)), & - struct_c_target*prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(struct_organ))) + leaf_c_target*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)), & + fnrt_c_target*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)), & + sapw_c_target*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)), & + struct_c_target*prt_params%nitr_stoich_p1(ipft,prt_params%organ_param_id(struct_organ))) else target_m = StorageNutrientTarget(ipft, element_id, & - leaf_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(leaf_organ)), & - fnrt_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(fnrt_organ)), & - sapw_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(sapw_organ)), & - struct_c_target*prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(struct_organ))) + leaf_c_target*prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(leaf_organ)), & + fnrt_c_target*prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(fnrt_organ)), & + sapw_c_target*prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(sapw_organ)), & + struct_c_target*prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(struct_organ))) end if @@ -1783,11 +1785,15 @@ function GetNutrientTargetCNP(this,element_id,organ_id,stoich_mode) result(targe target_m = target_c * prt_params%phos_stoich_p1(ipft,prt_params%organ_param_id(organ_id)) end if elseif( stoich_mode == stoich_max ) then - if( element_id == nitrogen_element) then - target_m = target_c * prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(organ_id)) - else - target_m = target_c * prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(organ_id)) - end if + !if( element_id == nitrogen_element) then + ! target_m = target_c * prt_params%nitr_stoich_p2(ipft,prt_params%organ_param_id(organ_id)) + !else + ! target_m = target_c * prt_params%phos_stoich_p2(ipft,prt_params%organ_param_id(organ_id)) + !end if + write(fates_log(),*) 'invalid stoichiometry mode specified while getting' + write(fates_log(),*) 'nutrient targets' + write(fates_log(),*) 'stoich_mode: ',stoich_mode + call endrun(msg=errMsg(sourcefile, __LINE__)) else write(fates_log(),*) 'invalid stoichiometry mode specified while getting' write(fates_log(),*) 'nutrient targets' @@ -2222,72 +2228,94 @@ end function AllomCNPGrowthDeriv ! ==================================================================================== - subroutine TargetAllometryCheck(bleaf,bfroot,bsap,bstore,bdead, & - bt_leaf,bt_froot,bt_sap,bt_store,bt_dead, & - grow_leaf,grow_froot,grow_sapw,grow_store) - - ! Arguments - real(r8),intent(in) :: bleaf !actual - real(r8),intent(in) :: bfroot - real(r8),intent(in) :: bsap - real(r8),intent(in) :: bstore - real(r8),intent(in) :: bdead - real(r8),intent(in) :: bt_leaf !target - real(r8),intent(in) :: bt_froot - real(r8),intent(in) :: bt_sap - real(r8),intent(in) :: bt_store - real(r8),intent(in) :: bt_dead - logical,intent(out) :: grow_leaf !growth flag - logical,intent(out) :: grow_froot - logical,intent(out) :: grow_sapw - logical,intent(out) :: grow_store - - if( (bt_leaf - bleaf)>calloc_abs_error) then - write(fates_log(),*) 'leaves are not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bleaf,bt_leaf - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( (bleaf - bt_leaf)>calloc_abs_error) then - ! leaf is above allometry, ignore - grow_leaf = .false. - else - grow_leaf = .true. - end if + subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & + bleaf,bfnrt,bsapw,bstore,bstruct, & + bt_leaf,bt_fnrt,bt_sapw,bt_store,bt_struct, & + carbon_balance,ipft,leaf_status, & + grow_leaf,grow_fnrt,grow_sapw,grow_store,grow_struct) - if( (bt_froot - bfroot)>calloc_abs_error) then - write(fates_log(),*) 'fineroots are not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bfroot, bt_froot - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bfroot-bt_froot)>calloc_abs_error ) then - grow_froot = .false. - else - grow_froot = .true. - end if - - if( (bt_sap - bsap)>calloc_abs_error) then - write(fates_log(),*) 'sapwood is not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bsap, bt_sap - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bsap-bt_sap)>calloc_abs_error ) then - grow_sapw = .false. - else - grow_sapw = .true. - end if - - if( (bt_store - bstore)>calloc_abs_error) then - write(fates_log(),*) 'storage is not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bstore,bt_store - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bstore-bt_store)>calloc_abs_error ) then - grow_store = .false. - else - grow_store = .true. - end if + ! Arguments + real(r8),intent(in) :: b0_leaf !initial + real(r8),intent(in) :: b0_fnrt + real(r8),intent(in) :: b0_sapw + real(r8),intent(in) :: b0_store + real(r8),intent(in) :: b0_struct + real(r8),intent(in) :: bleaf !actual + real(r8),intent(in) :: bfnrt + real(r8),intent(in) :: bsapw + real(r8),intent(in) :: bstore + real(r8),intent(in) :: bstruct + real(r8),intent(in) :: bt_leaf !target + real(r8),intent(in) :: bt_fnrt + real(r8),intent(in) :: bt_sapw + real(r8),intent(in) :: bt_store + real(r8),intent(in) :: bt_struct + real(r8),intent(in) :: carbon_balance !remaining carbon balance + integer,intent(in) :: ipft !Plant functional type + integer,intent(in) :: leaf_status !Phenology status + logical,intent(out) :: grow_leaf !growth flag + logical,intent(out) :: grow_fnrt + logical,intent(out) :: grow_sapw + logical,intent(out) :: grow_store + logical,intent(out) :: grow_struct + ! Local variables + logical :: fine_leaf + logical :: fine_fnrt + logical :: fine_sapw + logical :: fine_store + logical :: fine_struct + logical :: all_fine + ! Local constants + character(len= 3), parameter :: fmth = '(a)' + character(len=27), parameter :: fmtb = '(a,3(1x,es12.5,1x,a),1x,l1)' + character(len=13), parameter :: fmte = '(a,1x,es12.5)' + character(len=10), parameter :: fmti = '(a,1x,i12)' + + + ! First test whether or not each pool looks reasonable. + fine_leaf = (bt_leaf - bleaf ) <= calloc_abs_error + fine_fnrt = (bt_fnrt - bfnrt ) <= calloc_abs_error + fine_sapw = (bt_sapw - bsapw ) <= calloc_abs_error + fine_store = (bt_store - bstore ) <= calloc_abs_error + fine_struct = (bt_struct - bstruct) <= calloc_abs_error + all_fine = fine_leaf .and. fine_fnrt .and. fine_sapw .and. & + fine_store .and. fine_struct + + ! Decide whether or not to grow tissues (but only if all tissues look fine). + ! We grow only when biomass is less than target biomass (with tolerance). + if (all_fine) then + grow_leaf = ( bleaf - bt_leaf ) <= calloc_abs_error + grow_fnrt = ( bfnrt - bt_fnrt ) <= calloc_abs_error + grow_sapw = ( bsapw - bt_sapw ) <= calloc_abs_error + grow_store = ( bstore - bt_store ) <= calloc_abs_error + grow_struct = ( bstruct - bt_struct ) <= calloc_abs_error + else + ! If anything looks not fine, write a detailed report + write(fates_log(),fmt=fmth) '======' + write(fates_log(),fmt=fmth) ' At least one tissue is not on-allometry at the growth step' + write(fates_log(),fmt=fmth) '======' + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) ' Biomass and on-allometry test (''F'' means problem)' + write(fates_log(),fmt=fmth) '------' + write(fates_log(),fmt=fmth) ' Tissue | Initial | Current | Target | On-allometry' + write(fates_log(),fmt=fmtb) ' Leaf |',b0_leaf ,'|',bleaf ,'|',bt_leaf ,'|',fine_leaf + write(fates_log(),fmt=fmtb) ' Fine root |',b0_fnrt ,'|',bfnrt ,'|',bt_fnrt ,'|',fine_fnrt + write(fates_log(),fmt=fmtb) ' Sap wood |',b0_sapw ,'|',bsapw ,'|',bt_sapw ,'|',fine_sapw + write(fates_log(),fmt=fmtb) ' Storage |',b0_store ,'|',bstore ,'|',bt_store ,'|',fine_store + write(fates_log(),fmt=fmtb) ' Structural |',b0_struct ,'|',bstruct ,'|',bt_struct ,'|',fine_struct + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) ' Ancillary information' + write(fates_log(),fmt=fmth) '------' + write(fates_log(),fmt=fmti) ' PFT = ',ipft + write(fates_log(),fmt=fmti) ' leaf_status = ',leaf_status + write(fates_log(),fmt=fmte) ' carbon_balance = ',carbon_balance + write(fates_log(),fmt=fmte) ' calloc_abs_error = ',calloc_abs_error + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) '======' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if - if( (bt_dead - bdead)>calloc_abs_error) then - write(fates_log(),*) 'structure not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bdead,bt_dead - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + return end subroutine TargetAllometryCheck diff --git a/parteh/PRTAllometricCarbonMod.F90 b/parteh/PRTAllometricCarbonMod.F90 index 5bdf624502..b5db420b43 100644 --- a/parteh/PRTAllometricCarbonMod.F90 +++ b/parteh/PRTAllometricCarbonMod.F90 @@ -51,6 +51,9 @@ module PRTAllometricCarbonMod use PRTParametersMod , only : prt_params + use EDTypesMod , only : leaves_on + use EDTypesMod , only : leaves_off + implicit none private @@ -114,7 +117,7 @@ module PRTAllometricCarbonMod ! ------------------------------------------------------------------------------------- - type, public, extends(prt_vartypes) :: callom_prt_vartypes + type, public, extends(prt_vartypes) :: callom_prt_vartypes contains @@ -144,7 +147,7 @@ module PRTAllometricCarbonMod public :: InitPRTGlobalAllometricCarbon -contains + contains subroutine InitPRTGlobalAllometricCarbon() @@ -313,6 +316,9 @@ subroutine DailyPRTAllometricCarbon(this) real(r8) :: struct_below_target ! dead (structural) biomass below target amount [kgC] real(r8) :: total_below_target ! total biomass below the allometric target [kgC] + real(r8) :: allocation_factor ! allocation factor (relative to demand) to + ! reconstruct tissues + real(r8) :: flux_adj ! adjustment made to growth flux term to minimize error [kgC] real(r8) :: store_target_fraction ! ratio between storage and leaf biomass when on allometry [kgC] @@ -376,6 +382,10 @@ subroutine DailyPRTAllometricCarbon(this) integer, parameter :: iexp_leaf = 1 ! index 1 is the expanding (i.e. youngest) ! leaf age class, and therefore ! all new allocation goes into that pool + character(len= 9), parameter :: fmti = '(a,1x,i5)' + character(len=13), parameter :: fmt0 = '(a,1x,es12.5)' + character(len=19), parameter :: fmth = '(a,1x,a5,3(1x,a12))' + character(len=22), parameter :: fmtg = '(a,5x,l1,3(1x,es12.5))' real(r8) :: intgr_params(num_bc_in) ! The boundary conditions to this routine, ! are pressed into an array that is also @@ -451,12 +461,13 @@ subroutine DailyPRTAllometricCarbon(this) call bdead_allom( target_agw_c, target_bgw_c, target_sapw_c, ipft, target_struct_c) ! Target leaf biomass according to allometry and trimming - if(leaf_status==2) then + select case (leaf_status) + case (leaves_on) call bleaf(dbh,ipft,canopy_trim,target_leaf_c) - else + case (leaves_off) target_leaf_c = 0._r8 - end if - + end select + ! Target fine-root biomass and deriv. according to allometry and trimming [kgC, kgC/cm] call bfineroot(dbh,ipft,canopy_trim,target_fnrt_c) @@ -466,43 +477,42 @@ subroutine DailyPRTAllometricCarbon(this) ! ----------------------------------------------------------------------------------- ! III. Prioritize some amount of carbon to replace leaf/root turnover - ! Make sure it isnt a negative payment, and either pay what is available + ! Make sure it isn't a negative payment, and either pay what is available ! or forcefully pay from storage. ! ----------------------------------------------------------------------------------- - if( prt_params%evergreen(ipft) ==1 ) then + if( prt_params%evergreen(ipft) == itrue ) then leaf_c_demand = max(0.0_r8, & prt_params%leaf_stor_priority(ipft)*sum(this%variables(leaf_c_id)%turnover(:))) else leaf_c_demand = 0.0_r8 end if - fnrt_c_demand = max(0.0_r8, & + fnrt_c_demand = max(0.0_r8, & prt_params%leaf_stor_priority(ipft)*this%variables(fnrt_c_id)%turnover(icd)) total_c_demand = leaf_c_demand + fnrt_c_demand - - if (total_c_demand> nearzero ) then + + if (total_c_demand > nearzero) then ! We pay this even if we don't have the carbon ! Just don't pay so much carbon that storage+carbon_balance can't pay for it + allocation_factor = max(0.0_r8,min(1.0_r8,(store_c+carbon_balance)/total_c_demand)) - leaf_c_flux = min(leaf_c_demand, & - max(0.0_r8,(store_c+carbon_balance)* & - (leaf_c_demand/total_c_demand))) - - ! Add carbon to the youngest age pool (i.e iexp_leaf = index 1) - carbon_balance = carbon_balance - leaf_c_flux - leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - - ! If we are testing b4b, then we pay this even if we don't have the carbon - fnrt_c_flux = min(fnrt_c_demand, & - max(0.0_r8, (store_c+carbon_balance)* & - (fnrt_c_demand/total_c_demand))) + ! MLO. Edited the code to switch the order of operations. The previous code would + ! subtract leaf flux from carbon balance before estimating the fine root flux, + ! potentially allowing less fluxes to fine roots than possible. + leaf_c_flux = leaf_c_demand * allocation_factor + fnrt_c_flux = fnrt_c_demand * allocation_factor - carbon_balance = carbon_balance - fnrt_c_flux - fnrt_c = fnrt_c + fnrt_c_flux + ! Add carbon to the youngest age pool (i.e iexp_leaf = index 1) and fine roots + leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + ! Remove fluxes from carbon balance. In case we may have drawn carbon from storage, + ! carbon_balance will become negative, in which case we will deplete carbon from + ! storage in the next step. + carbon_balance = carbon_balance - ( leaf_c_flux + fnrt_c_flux ) end if ! ----------------------------------------------------------------------------------- @@ -511,19 +521,24 @@ subroutine DailyPRTAllometricCarbon(this) ! ----------------------------------------------------------------------------------- if( carbon_balance < 0.0_r8 ) then - + + ! Store_c_flux will be negative, so store_c will be depleted store_c_flux = carbon_balance carbon_balance = carbon_balance - store_c_flux store_c = store_c + store_c_flux else - store_below_target = max(target_store_c - store_c,0.0_r8) + ! Accumulate some carbon in storage. If storage is completely depleted, aim to + ! increase storage, but not to replenish completely so we can still use some + ! carbon for growth. + store_below_target = max(0.0_r8,target_store_c - store_c) store_target_fraction = max(0.0_r8, store_c/target_store_c ) store_c_flux = min(store_below_target,carbon_balance * & max(exp(-1.*store_target_fraction**4._r8) - exp( -1.0_r8 ),0.0_r8)) + ! Move carbon from carbon balance to storage carbon_balance = carbon_balance - store_c_flux store_c = store_c + store_c_flux @@ -533,24 +548,29 @@ subroutine DailyPRTAllometricCarbon(this) ! V. If carbon is still available, prioritize some allocation to replace ! the rest of the leaf/fineroot deficit ! carbon balance is guaranteed to be >=0 beyond this point + ! MLO. Renamed demand with below target to make it consistent with the + ! definitions at the variable declaration part. ! ----------------------------------------------------------------------------------- - - leaf_c_demand = max(0.0_r8,(target_leaf_c - sum(leaf_c(1:nleafage)))) - fnrt_c_demand = max(0.0_r8,(target_fnrt_c - fnrt_c)) - total_c_demand = leaf_c_demand + fnrt_c_demand - - if( (carbon_balance > nearzero ) .and. (total_c_demand>nearzero)) then + leaf_below_target = max(0.0_r8,target_leaf_c - sum(leaf_c(1:nleafage))) + fnrt_below_target = max(0.0_r8,target_fnrt_c - fnrt_c) + + total_below_target = leaf_below_target + fnrt_below_target + + if ( (carbon_balance > nearzero) .and. (total_below_target > nearzero) ) then + ! Find fraction of carbon to be allocated to leaves and fine roots + allocation_factor = min(1.0_r8, carbon_balance / total_below_target) + + ! MLO. Edited the code to switch the order of operations. The previous code would + ! subtract leaf flux from carbon balance before estimating the fine root flux, + ! potentially allowing less fluxes to fine roots than possible. + leaf_c_flux = leaf_below_target * allocation_factor + fnrt_c_flux = fnrt_below_target * allocation_factor - leaf_c_flux = min(leaf_c_demand, & - carbon_balance*(leaf_c_demand/total_c_demand)) - carbon_balance = carbon_balance - leaf_c_flux leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - - fnrt_c_flux = min(fnrt_c_demand, & - carbon_balance*(fnrt_c_demand/total_c_demand)) - carbon_balance = carbon_balance - fnrt_c_flux - fnrt_c = fnrt_c + fnrt_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + + carbon_balance = carbon_balance - ( leaf_c_flux + fnrt_c_flux ) end if @@ -571,31 +591,22 @@ subroutine DailyPRTAllometricCarbon(this) sapw_below_target + store_below_target if ( total_below_target > nearzero ) then - - if( total_below_target > carbon_balance) then - leaf_c_flux = carbon_balance * leaf_below_target/total_below_target - fnrt_c_flux = carbon_balance * fnrt_below_target/total_below_target - sapw_c_flux = carbon_balance * sapw_below_target/total_below_target - store_c_flux = carbon_balance * store_below_target/total_below_target - else - leaf_c_flux = leaf_below_target - fnrt_c_flux = fnrt_below_target - sapw_c_flux = sapw_below_target - store_c_flux = store_below_target - end if - - carbon_balance = carbon_balance - leaf_c_flux - leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux - - carbon_balance = carbon_balance - fnrt_c_flux - fnrt_c = fnrt_c + fnrt_c_flux - - carbon_balance = carbon_balance - sapw_c_flux - sapw_c = sapw_c + sapw_c_flux - - carbon_balance = carbon_balance - store_c_flux - store_c = store_c + store_c_flux - + ! Find allocation factor based on available carbon and total demand to meet target. + allocation_factor = min(1.0_r8, carbon_balance / total_below_target) + + ! Find fluxes to individual pools + leaf_c_flux = leaf_below_target * allocation_factor + fnrt_c_flux = fnrt_below_target * allocation_factor + sapw_c_flux = sapw_below_target * allocation_factor + store_c_flux = store_below_target * allocation_factor + + leaf_c(iexp_leaf) = leaf_c(iexp_leaf) + leaf_c_flux + fnrt_c = fnrt_c + fnrt_c_flux + sapw_c = sapw_c + sapw_c_flux + store_c = store_c + store_c_flux + + carbon_balance = carbon_balance - & + ( leaf_c_flux + fnrt_c_flux + sapw_c_flux + store_c_flux ) end if end if @@ -639,24 +650,15 @@ subroutine DailyPRTAllometricCarbon(this) ! allow actual pools to be above the target, and in these cases, it sends ! a false on the "grow_<>" flag, allowing the plant to grow into these pools. ! It also checks to make sure that structural biomass is not above the target. + ! ( MLO. Removed the check for storage because the same test is done inside + ! sub-routine TargetAllometryCheck.) - if( (target_store_c - store_c)>calloc_abs_error) then - write(fates_log(),*) 'storage is not on-allometry at the growth step' - write(fates_log(),*) 'exiting' - write(fates_log(),*) 'cbal: ',carbon_balance - write(fates_log(),*) 'near-zero',nearzero - write(fates_log(),*) 'store_c: ',store_c - write(fates_log(),*) 'target c: ',target_store_c - write(fates_log(),*) 'store_c0:', store_c0 - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - - call TargetAllometryCheck(sum(leaf_c(1:nleafage)), fnrt_c, sapw_c, & - store_c, struct_c, & - target_leaf_c, target_fnrt_c, & - target_sapw_c, target_store_c, target_struct_c, & - grow_struct, grow_leaf, grow_fnrt, grow_sapw, grow_store) + call TargetAllometryCheck(sum(leaf_c0(1:nleafage)),fnrt_c0,sapw_c0,store_c0,struct_c0, & + sum(leaf_c(1:nleafage)), fnrt_c, sapw_c,store_c, struct_c, & + target_leaf_c, target_fnrt_c, target_sapw_c, & + target_store_c, target_struct_c, & + carbon_balance,ipft,leaf_status, & + grow_leaf, grow_fnrt, grow_sapw, grow_store, grow_struct) ! -------------------------------------------------------------------------------- ! The numerical integration of growth requires that the instantaneous state @@ -690,35 +692,38 @@ subroutine DailyPRTAllometricCarbon(this) c_pool(dbh_id) = dbh ! Only grow leaves if we are in a "leaf-on" status - if(leaf_status==2) then - c_mask(leaf_c_id) = grow_leaf - else - c_mask(leaf_c_id) = .false. - end if + select case (leaf_status) + case (leaves_on) + c_mask(leaf_c_id) = grow_leaf + case default + c_mask(leaf_c_id) = .false. + end select c_mask(fnrt_c_id) = grow_fnrt c_mask(sapw_c_id) = grow_sapw - c_mask(store_c_id) = grow_store c_mask(struct_c_id) = grow_struct + c_mask(store_c_id) = grow_store c_mask(repro_c_id) = .true. ! Always calculate reproduction on growth c_mask(dbh_id) = .true. ! Always increment dbh on growth step - + ! When using the Euler method, we keep things simple. We always try ! to make the first integration step to span the entirety of the integration ! window for the independent variable (available carbon) - if(ODESolve == 2) then + select case (ODESolve) + case (2) this%ode_opt_step = totalC - end if + end select do_solve_check: do while( ierr .ne. 0 ) deltaC = min(totalC,this%ode_opt_step) - if(ODESolve == 1) then + select_ODESolve: select case (ODESolve) + case (1) call RKF45(AllomCGrowthDeriv,c_pool,c_mask,deltaC,totalC, & max_trunc_error,intgr_params,c_pool_out,this%ode_opt_step,step_pass) - elseif(ODESolve == 2) then + case (2) call Euler(AllomCGrowthDeriv,c_pool,c_mask,deltaC,totalC,intgr_params,c_pool_out) ! step_pass = .true. @@ -741,11 +746,11 @@ subroutine DailyPRTAllometricCarbon(this) else this%ode_opt_step = 0.5*deltaC end if - else + case default write(fates_log(),*) 'An integrator was chosen that does not exist' write(fates_log(),*) 'ODESolve = ',ODESolve call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + end select select_ODESolve nsteps = nsteps + 1 @@ -755,17 +760,22 @@ subroutine DailyPRTAllometricCarbon(this) end if if(nsteps > max_substeps ) then - write(fates_log(),*) 'Plant Growth Integrator could not find' - write(fates_log(),*) 'a solution in less than ',max_substeps,' tries' - write(fates_log(),*) 'Aborting' - write(fates_log(),*) 'carbon_balance',carbon_balance - write(fates_log(),*) 'deltaC',deltaC - write(fates_log(),*) 'totalC',totalC - write(fates_log(),*) 'leaf:',grow_leaf,target_leaf_c,target_leaf_c - sum(leaf_c(:)) - write(fates_log(),*) 'fnrt:',grow_fnrt,target_fnrt_c,target_fnrt_c - fnrt_c - write(fates_log(),*) 'sap:',grow_sapw,target_sapw_c, target_sapw_c - sapw_c - write(fates_log(),*) 'store:',grow_store,target_store_c,target_store_c - store_c - write(fates_log(),*) 'dead:',target_struct_c,target_struct_c - struct_c + write(fates_log(),fmt=*) '---~---' + write(fates_log(),fmt=*) 'Plant Growth Integrator could not find' + write(fates_log(),fmt=*) 'a solution in less than ',max_substeps,' tries.' + write(fates_log(),fmt=*) 'Aborting!' + write(fates_log(),fmt=*) '---~---' + write(fates_log(),fmt=fmti) 'Leaf status =',leaf_status + write(fates_log(),fmt=fmt0) 'Carbon_balance =',carbon_balance + write(fates_log(),fmt=fmt0) 'deltaC =',deltaC + write(fates_log(),fmt=fmt0) 'totalC =',totalC + write(fates_log(),fmt=fmth) ' Tissue |', ' Grow',' Current',' Target' ,' Deficit' + write(fates_log(),fmt=fmtg) ' Leaf |', grow_leaf , sum(leaf_c(:)),target_leaf_c , target_leaf_c - sum(leaf_c(:)) + write(fates_log(),fmt=fmtg) ' Fine root |', grow_fnrt , fnrt_c,target_fnrt_c , target_fnrt_c - fnrt_c + write(fates_log(),fmt=fmtg) ' Sapwood |', grow_sapw , sapw_c,target_sapw_c , target_sapw_c - sapw_c + write(fates_log(),fmt=fmtg) ' Storage |', grow_store , store_c,target_store_c , target_store_c - store_c + write(fates_log(),fmt=fmtg) ' Structural |', grow_struct , struct_c,target_struct_c, target_struct_c - struct_c + write(fates_log(),fmt=*) '---~---' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1008,80 +1018,94 @@ end function AllomCGrowthDeriv ! ==================================================================================== - subroutine TargetAllometryCheck(bleaf,bfroot,bsap,bstore,bdead, & - bt_leaf,bt_froot,bt_sap,bt_store,bt_dead, & - grow_dead,grow_leaf,grow_froot,grow_sapw,grow_store) - - ! Arguments - real(r8),intent(in) :: bleaf !actual - real(r8),intent(in) :: bfroot - real(r8),intent(in) :: bsap - real(r8),intent(in) :: bstore - real(r8),intent(in) :: bdead - real(r8),intent(in) :: bt_leaf !target - real(r8),intent(in) :: bt_froot - real(r8),intent(in) :: bt_sap - real(r8),intent(in) :: bt_store - real(r8),intent(in) :: bt_dead - logical,intent(out) :: grow_leaf !growth flag - logical,intent(out) :: grow_froot - logical,intent(out) :: grow_sapw - logical,intent(out) :: grow_store - logical,intent(out) :: grow_dead - - if( (bt_leaf - bleaf)>calloc_abs_error) then - write(fates_log(),*) 'leaves are not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bleaf,bt_leaf - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( (bleaf - bt_leaf)>calloc_abs_error) then - ! leaf is above allometry, ignore - grow_leaf = .false. - else - grow_leaf = .true. - end if - - if( (bt_froot - bfroot)>calloc_abs_error) then - write(fates_log(),*) 'fineroots are not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bfroot, bt_froot - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bfroot-bt_froot)>calloc_abs_error ) then - grow_froot = .false. - else - grow_froot = .true. - end if - - if( (bt_sap - bsap)>calloc_abs_error) then - write(fates_log(),*) 'sapwood is not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bsap, bt_sap - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bsap-bt_sap)>calloc_abs_error ) then - grow_sapw = .false. - else - grow_sapw = .true. - end if - - if( (bt_store - bstore)>calloc_abs_error) then - write(fates_log(),*) 'storage is not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bstore,bt_store - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( ( bstore-bt_store)>calloc_abs_error ) then - grow_store = .false. - else - grow_store = .true. - end if - - if( (bt_dead - bdead)>calloc_abs_error) then - write(fates_log(),*) 'structure not on-allometry at the growth step' - write(fates_log(),*) 'exiting',bdead,bt_dead - call endrun(msg=errMsg(sourcefile, __LINE__)) - elseif( (bdead-bt_dead)> calloc_abs_error) then - grow_dead = .false. - else - grow_dead = .true. - end if - + subroutine TargetAllometryCheck(b0_leaf,b0_fnrt,b0_sapw,b0_store,b0_struct, & + bleaf,bfnrt,bsapw,bstore,bstruct, & + bt_leaf,bt_fnrt,bt_sapw,bt_store,bt_struct, & + carbon_balance,ipft,leaf_status, & + grow_leaf,grow_fnrt,grow_sapw,grow_store,grow_struct) - return + ! Arguments + real(r8),intent(in) :: b0_leaf !initial + real(r8),intent(in) :: b0_fnrt + real(r8),intent(in) :: b0_sapw + real(r8),intent(in) :: b0_store + real(r8),intent(in) :: b0_struct + real(r8),intent(in) :: bleaf !actual + real(r8),intent(in) :: bfnrt + real(r8),intent(in) :: bsapw + real(r8),intent(in) :: bstore + real(r8),intent(in) :: bstruct + real(r8),intent(in) :: bt_leaf !target + real(r8),intent(in) :: bt_fnrt + real(r8),intent(in) :: bt_sapw + real(r8),intent(in) :: bt_store + real(r8),intent(in) :: bt_struct + real(r8),intent(in) :: carbon_balance !remaining carbon balance + integer,intent(in) :: ipft !Plant functional type + integer,intent(in) :: leaf_status !Phenology status + logical,intent(out) :: grow_leaf !growth flag + logical,intent(out) :: grow_fnrt + logical,intent(out) :: grow_sapw + logical,intent(out) :: grow_store + logical,intent(out) :: grow_struct + ! Local variables + logical :: fine_leaf + logical :: fine_fnrt + logical :: fine_sapw + logical :: fine_store + logical :: fine_struct + logical :: all_fine + ! Local constants + character(len= 3), parameter :: fmth = '(a)' + character(len=27), parameter :: fmtb = '(a,3(1x,es12.5,1x,a),1x,l1)' + character(len=13), parameter :: fmte = '(a,1x,es12.5)' + character(len=10), parameter :: fmti = '(a,1x,i12)' + + + ! First test whether or not each pool looks reasonable. + fine_leaf = (bt_leaf - bleaf ) <= calloc_abs_error + fine_fnrt = (bt_fnrt - bfnrt ) <= calloc_abs_error + fine_sapw = (bt_sapw - bsapw ) <= calloc_abs_error + fine_store = (bt_store - bstore ) <= calloc_abs_error + fine_struct = (bt_struct - bstruct) <= calloc_abs_error + all_fine = fine_leaf .and. fine_fnrt .and. fine_sapw .and. & + fine_store .and. fine_struct + + ! Decide whether or not to grow tissues (but only if all tissues look fine). + ! We grow only when biomass is less than target biomass (with tolerance). + if (all_fine) then + grow_leaf = ( bleaf - bt_leaf ) <= calloc_abs_error + grow_fnrt = ( bfnrt - bt_fnrt ) <= calloc_abs_error + grow_sapw = ( bsapw - bt_sapw ) <= calloc_abs_error + grow_store = ( bstore - bt_store ) <= calloc_abs_error + grow_struct = ( bstruct - bt_struct ) <= calloc_abs_error + else + ! If anything looks not fine, write a detailed report + write(fates_log(),fmt=fmth) '======' + write(fates_log(),fmt=fmth) ' At least one tissue is not on-allometry at the growth step' + write(fates_log(),fmt=fmth) '======' + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) ' Biomass and on-allometry test (''F'' means problem)' + write(fates_log(),fmt=fmth) '------' + write(fates_log(),fmt=fmth) ' Tissue | Initial | Current | Target | On-allometry' + write(fates_log(),fmt=fmtb) ' Leaf |',b0_leaf ,'|',bleaf ,'|',bt_leaf ,'|',fine_leaf + write(fates_log(),fmt=fmtb) ' Fine root |',b0_fnrt ,'|',bfnrt ,'|',bt_fnrt ,'|',fine_fnrt + write(fates_log(),fmt=fmtb) ' Sap wood |',b0_sapw ,'|',bsapw ,'|',bt_sapw ,'|',fine_sapw + write(fates_log(),fmt=fmtb) ' Storage |',b0_store ,'|',bstore ,'|',bt_store ,'|',fine_store + write(fates_log(),fmt=fmtb) ' Structural |',b0_struct ,'|',bstruct ,'|',bt_struct ,'|',fine_struct + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) ' Ancillary information' + write(fates_log(),fmt=fmth) '------' + write(fates_log(),fmt=fmti) ' PFT = ',ipft + write(fates_log(),fmt=fmti) ' leaf_status = ',leaf_status + write(fates_log(),fmt=fmte) ' carbon_balance = ',carbon_balance + write(fates_log(),fmt=fmte) ' calloc_abs_error = ',calloc_abs_error + write(fates_log(),fmt=fmth) '' + write(fates_log(),fmt=fmth) '======' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + return end subroutine TargetAllometryCheck ! ===================================================================================== diff --git a/parteh/PRTGenericMod.F90 b/parteh/PRTGenericMod.F90 index 3dab9563a3..35488bd8cc 100644 --- a/parteh/PRTGenericMod.F90 +++ b/parteh/PRTGenericMod.F90 @@ -279,7 +279,7 @@ module PRTGenericMod ! examples are carbon12_element ! nitrogen_element, etc. - integer, public :: element_pos(num_organ_types) ! This is the reverse lookup + integer, public :: element_pos(num_element_types) ! This is the reverse lookup ! for element types. Pick an element ! global index, and it gives you ! the position in the element_list diff --git a/parteh/PRTLossFluxesMod.F90 b/parteh/PRTLossFluxesMod.F90 index 13b09b2e37..6f23924d48 100644 --- a/parteh/PRTLossFluxesMod.F90 +++ b/parteh/PRTLossFluxesMod.F90 @@ -433,16 +433,8 @@ subroutine PRTDeciduousTurnover(prt,ipft,organ_id,mass_fraction) end if - if ( int(prt_params%turnover_retrans_mode(ipft)) == 1 ) then - call DeciduousTurnoverSimpleRetranslocation(prt,ipft,organ_id,mass_fraction) - else - write(fates_log(),*) 'A retranslocation mode was specified for deciduous drop' - write(fates_log(),*) 'that is unknown.' - write(fates_log(),*) 'turnover_retrans_mode= ',prt_params%turnover_retrans_mode(ipft) - write(fates_log(),*) 'pft = ',ipft - call endrun(msg=errMsg(__FILE__, __LINE__)) - end if - + call DeciduousTurnoverSimpleRetranslocation(prt,ipft,organ_id,mass_fraction) + return end subroutine PRTDeciduousTurnover @@ -518,7 +510,7 @@ subroutine DeciduousTurnoverSimpleRetranslocation(prt,ipft,organ_id,mass_fractio retrans = 0._r8 else if ( any(element_id == carbon_elements_list) ) then - retrans = prt_params%turnover_carb_retrans(ipft,prt_params%organ_param_id(organ_id)) + retrans = 0._r8 else if( element_id == nitrogen_element ) then retrans = prt_params%turnover_nitr_retrans(ipft,prt_params%organ_param_id(organ_id)) else if( element_id == phosphorus_element ) then @@ -587,15 +579,8 @@ subroutine PRTMaintTurnover(prt,ipft,is_drought) logical,intent(in) :: is_drought ! Is this plant/cohort operating in a drought ! stress context? - if ( int(prt_params%turnover_retrans_mode(ipft)) == 1 ) then - call MaintTurnoverSimpleRetranslocation(prt,ipft,is_drought) - else - write(fates_log(),*) 'A maintenance/retranslocation mode was specified' - write(fates_log(),*) 'that is unknown.' - write(fates_log(),*) 'turnover_retrans_mode= ',prt_params%turnover_retrans_mode(ipft) - write(fates_log(),*) 'pft = ',ipft - call endrun(msg=errMsg(__FILE__, __LINE__)) - end if + call MaintTurnoverSimpleRetranslocation(prt,ipft,is_drought) + return end subroutine PRTMaintTurnover @@ -729,7 +714,7 @@ subroutine MaintTurnoverSimpleRetranslocation(prt,ipft,is_drought) retrans_frac = 0._r8 else if ( any(element_id == carbon_elements_list) ) then - retrans_frac = prt_params%turnover_carb_retrans(ipft,prt_params%organ_param_id(organ_id)) + retrans_frac = 0._r8 else if( element_id == nitrogen_element ) then retrans_frac = prt_params%turnover_nitr_retrans(ipft,prt_params%organ_param_id(organ_id)) else if( element_id == phosphorus_element ) then diff --git a/parteh/PRTParametersMod.F90 b/parteh/PRTParametersMod.F90 index 04a0f5dda0..23e867a734 100644 --- a/parteh/PRTParametersMod.F90 +++ b/parteh/PRTParametersMod.F90 @@ -26,8 +26,6 @@ module PRTParametersMod ! one class to the next [yr] real(r8), allocatable :: root_long(:) ! root turnover time (longevity) (pft) [yr] real(r8), allocatable :: branch_long(:) ! Turnover time for branchfall on live trees (pft) [yr] - real(r8), allocatable :: turnover_retrans_mode(:) ! Retranslocation method (pft) - real(r8), allocatable :: turnover_carb_retrans(:,:) ! carbon re-translocation fraction (pft x organ) 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 @@ -46,9 +44,7 @@ module PRTParametersMod ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! real(r8), allocatable :: nitr_stoich_p1(:,:) ! Parameter 1 for nitrogen stoichiometry (pft x organ) - real(r8), allocatable :: nitr_stoich_p2(:,:) ! Parameter 2 for nitrogen stoichiometry (pft x organ) real(r8), allocatable :: phos_stoich_p1(:,:) ! Parameter 1 for phosphorus stoichiometry (pft x organ) - real(r8), allocatable :: phos_stoich_p2(:,:) ! Parameter 2 for phosphorus stoichiometry (pft x organ) real(r8), allocatable :: nitr_store_ratio(:) ! This is the ratio of the target nitrogen stored per ! target nitrogen that is bound into the tissues @@ -100,8 +96,8 @@ 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 :: woody(:) ! Does the plant have wood? (1=yes, 0=no) - real(r8), allocatable :: crown(:) ! fraction of the height of the plant + 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] diff --git a/parteh/PRTParamsFATESMod.F90 b/parteh/PRTParamsFATESMod.F90 index 208ff848fb..66033a3194 100644 --- a/parteh/PRTParamsFATESMod.F90 +++ b/parteh/PRTParamsFATESMod.F90 @@ -104,7 +104,7 @@ subroutine PRTRegisterOrgan(fates_params) integer, parameter :: dim_lower_bound(1) = (/ lower_bound_general /) character(len=param_string_length) :: name - name = 'fates_prt_organ_id' + name = 'fates_alloc_organ_id' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -126,8 +126,8 @@ subroutine PRTReceiveOrgan(fates_params) real(r8), allocatable :: tmpreal(:) ! Temporary variable to hold floats - name = 'fates_prt_organ_id' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_alloc_organ_id' + call fates_params%RetrieveParameterAllocate(name=name, & data=tmpreal) allocate(prt_params%organ_id(size(tmpreal,dim=1))) call ArrayNint(tmpreal,prt_params%organ_id) @@ -163,15 +163,15 @@ 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_fnrt_prof_a' + name = 'fates_allom_fnrt_prof_a' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_fnrt_prof_b' + name = 'fates_allom_fnrt_prof_b' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_fnrt_prof_mode' + name = 'fates_allom_fnrt_prof_mode' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -179,7 +179,7 @@ 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_fire_crown_depth_frac' + 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) @@ -199,7 +199,7 @@ 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_seed_dbh_repro_threshold' + name = 'fates_recruit_seed_dbh_repro_threshold' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -207,23 +207,23 @@ 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_leaf_stor_priority' + name = 'fates_alloc_store_priority_frac' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_senleaf_long_fdrought' + name = 'fates_turnover_senleaf_fdrought' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_root_long' + name = 'fates_turnover_fnrt' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_seed_alloc_mature' + 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) - name = 'fates_seed_alloc' + name = 'fates_recruit_seed_alloc' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -355,21 +355,17 @@ 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_turnover_retrans_mode' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_branch_turnover' + name = 'fates_turnover_branch' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_nitr_store_ratio' + name = 'fates_cnp_nitr_store_ratio' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_phos_store_ratio' + name = 'fates_cnp_phos_store_ratio' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -391,232 +387,231 @@ subroutine PRTReceivePFT(fates_params) ! that are converted to ints name = 'fates_phen_stress_decid' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=tmpreal) allocate(prt_params%stress_decid(size(tmpreal,dim=1))) call ArrayNint(tmpreal,prt_params%stress_decid) deallocate(tmpreal) name = 'fates_phen_season_decid' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=tmpreal) allocate(prt_params%season_decid(size(tmpreal,dim=1))) call ArrayNint(tmpreal,prt_params%season_decid) deallocate(tmpreal) name = 'fates_phen_evergreen' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=tmpreal) allocate(prt_params%evergreen(size(tmpreal,dim=1))) call ArrayNint(tmpreal,prt_params%evergreen) deallocate(tmpreal) name = 'fates_leaf_slamax' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%slamax) name = 'fates_leaf_slatop' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%slatop) name = 'fates_allom_sai_scaler' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_sai_scaler) - name = 'fates_fnrt_prof_a' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_allom_fnrt_prof_a' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%fnrt_prof_a) - name = 'fates_fnrt_prof_b' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_allom_fnrt_prof_b' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%fnrt_prof_b) - name = 'fates_fnrt_prof_mode' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_allom_fnrt_prof_mode' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%fnrt_prof_mode) - name = 'fates_fire_crown_depth_frac' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%crown) + name = 'fates_allom_crown_depth_frac' + call fates_params%RetrieveParameterAllocate(name=name, & + data=prt_params%crown_depth_frac) name = 'fates_woody' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%woody) + call fates_params%RetrieveParameterAllocate(name=name, & + data=tmpreal) + allocate(prt_params%woody(size(tmpreal,dim=1))) + call ArrayNint(tmpreal,prt_params%woody) + deallocate(tmpreal) name = 'fates_wood_density' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%wood_density) - name = 'fates_seed_dbh_repro_threshold' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_recruit_seed_dbh_repro_threshold' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%dbh_repro_threshold) name = 'fates_alloc_storage_cushion' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%cushion) - name = 'fates_leaf_stor_priority' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_alloc_store_priority_frac' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%leaf_stor_priority) - name = 'fates_senleaf_long_fdrought' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_turnover_senleaf_fdrought' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%senleaf_long_fdrought) - name = 'fates_root_long' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_turnover_fnrt' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%root_long) - name = 'fates_seed_alloc_mature' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_recruit_seed_alloc_mature' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%seed_alloc_mature) - name = 'fates_seed_alloc' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_recruit_seed_alloc' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%seed_alloc) name = 'fates_c2b' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%c2b) name = 'fates_grperc' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%grperc) name = 'fates_allom_dbh_maxheight' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_dbh_maxheight) name = 'fates_allom_hmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_hmode) name = 'fates_allom_lmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_lmode) name = 'fates_allom_fmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_fmode) name = 'fates_allom_amode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_amode) name = 'fates_allom_stmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_stmode) name = 'fates_allom_cmode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_cmode) name = 'fates_allom_smode' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_smode) name = 'fates_allom_la_per_sa_int' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_la_per_sa_int) name = 'fates_allom_la_per_sa_slp' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_la_per_sa_slp) name = 'fates_allom_l2fr' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_l2fr) name = 'fates_allom_agb_frac' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb_frac) name = 'fates_allom_d2h1' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2h1) name = 'fates_allom_d2h2' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2h2) name = 'fates_allom_d2h3' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2h3) name = 'fates_allom_d2bl1' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2bl1) name = 'fates_allom_d2bl2' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2bl2) name = 'fates_allom_d2bl3' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2bl3) name = 'fates_allom_blca_expnt_diff' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_blca_expnt_diff) name = 'fates_allom_d2ca_coefficient_max' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2ca_coefficient_max) name = 'fates_allom_d2ca_coefficient_min' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_d2ca_coefficient_min) name = 'fates_allom_agb1' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb1) name = 'fates_allom_agb2' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb2) name = 'fates_allom_agb3' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb3) name = 'fates_allom_agb4' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_agb4) name = 'fates_allom_zroot_max_dbh' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_max_dbh) name = 'fates_allom_zroot_max_z' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_max_z) name = 'fates_allom_zroot_min_dbh' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_min_dbh) name = 'fates_allom_zroot_min_z' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_min_z) name = 'fates_allom_zroot_k' - call fates_params%RetreiveParameterAllocate(name=name, & + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%allom_zroot_k) - name = 'fates_branch_turnover' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_turnover_branch' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%branch_long) - name = 'fates_turnover_retrans_mode' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%turnover_retrans_mode) - - name = 'fates_nitr_store_ratio' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_cnp_nitr_store_ratio' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%nitr_store_ratio) - name = 'fates_phos_store_ratio' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_cnp_phos_store_ratio' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%phos_store_ratio) @@ -641,7 +636,7 @@ subroutine PRTRegisterPFTLeafAge(fates_params) dim_names(1) = dimension_name_pft dim_names(2) = dimension_name_leaf_age - name = 'fates_leaf_long' + name = 'fates_turnover_leaf' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -703,7 +698,7 @@ subroutine Receive_PFT_nvariants(fates_params) character(len=param_string_length) :: name !X! name = '' - !X! call fates_params%RetreiveParameter(name=name, & + !X! call fates_params%RetrieveParameter(name=name, & !X! data=this%) end subroutine Receive_PFT_nvariants @@ -721,8 +716,8 @@ subroutine PRTReceivePFTLeafAge(fates_params) character(len=param_string_length) :: name - name = 'fates_leaf_long' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_turnover_leaf' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%leaf_long) return @@ -750,35 +745,23 @@ subroutine PRTRegisterPFTOrgans(fates_params) dim_names(1) = dimension_name_pft dim_names(2) = dimension_name_prt_organs - name = 'fates_prt_nitr_stoich_p1' + name = 'fates_stoich_nitr' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prt_nitr_stoich_p2' + name = 'fates_stoich_phos' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prt_phos_stoich_p1' + name = 'fates_alloc_organ_priority' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_prt_phos_stoich_p2' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_prt_alloc_priority' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_turnover_carb_retrans' - call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & - dimension_names=dim_names, lower_bounds=dim_lower_bound) - - name = 'fates_turnover_nitr_retrans' + name = 'fates_cnp_turnover_nitr_retrans' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - name = 'fates_turnover_phos_retrans' + name = 'fates_cnp_turnover_phos_retrans' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_2d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -798,36 +781,24 @@ subroutine PRTReceivePFTOrgans(fates_params) character(len=param_string_length) :: name - name = 'fates_prt_nitr_stoich_p1' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_stoich_nitr' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%nitr_stoich_p1) - name = 'fates_prt_nitr_stoich_p2' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%nitr_stoich_p2) - - name = 'fates_prt_phos_stoich_p1' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_stoich_phos' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%phos_stoich_p1) - name = 'fates_prt_phos_stoich_p2' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%phos_stoich_p2) - - name = 'fates_prt_alloc_priority' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_alloc_organ_priority' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%alloc_priority) - name = 'fates_turnover_carb_retrans' - call fates_params%RetreiveParameterAllocate(name=name, & - data=prt_params%turnover_carb_retrans) - - name = 'fates_turnover_nitr_retrans' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_cnp_turnover_nitr_retrans' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%turnover_nitr_retrans) - name = 'fates_turnover_phos_retrans' - call fates_params%RetreiveParameterAllocate(name=name, & + name = 'fates_cnp_turnover_phos_retrans' + call fates_params%RetrieveParameterAllocate(name=name, & data=prt_params%turnover_phos_retrans) end subroutine PRTReceivePFTOrgans @@ -905,17 +876,14 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'allom_zroot_min_z = ',prt_params%allom_zroot_min_z write(fates_log(),fmt0) 'allom_zroot_k = ',prt_params%allom_zroot_k - write(fates_log(),fmt0) 'prt_nitr_stoich_p1 = ',prt_params%nitr_stoich_p1 - write(fates_log(),fmt0) 'prt_nitr_stoich_p2 = ',prt_params%nitr_stoich_p2 - write(fates_log(),fmt0) 'prt_phos_stoich_p1 = ',prt_params%phos_stoich_p1 - write(fates_log(),fmt0) 'prt_phos_stoich_p2 = ',prt_params%phos_stoich_p2 - write(fates_log(),fmt0) 'prt_alloc_priority = ',prt_params%alloc_priority + write(fates_log(),fmt0) 'stoich_nitr = ',prt_params%nitr_stoich_p1 + 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 = ',prt_params%crown + 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 - write(fates_log(),fmt0) 'turnover_carb_retrans = ',prt_params%turnover_carb_retrans write(fates_log(),fmt0) 'turnover_nitr_retrans = ',prt_params%turnover_nitr_retrans write(fates_log(),fmt0) 'turnover_phos_retrans = ',prt_params%turnover_phos_retrans write(fates_log(),fmt0) 'organ_id = ',prt_params%organ_id @@ -1014,29 +982,31 @@ subroutine PRTCheckParams(is_master) ! Check to make sure the organ ids are valid if this is the ! cnp_flex_allom_hypothesis - if ((hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) .or. & - (hlm_parteh_mode .eq. prt_carbon_allom_hyp) ) then + select case (hlm_parteh_mode) + case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp) do io = 1,norgans if(prt_params%organ_id(io) == repro_organ) then - write(fates_log(),*) 'with flexible cnp or c-only alloc hypothesese' + 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__)) end if if(prt_params%organ_id(io) == store_organ) then - write(fates_log(),*) 'with flexible cnp or c-only alloc hypothesese' + 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__)) end if - + end do - end if + end select pftloop: do ipft = 1,npft @@ -1076,13 +1046,13 @@ subroutine PRTCheckParams(is_master) ! Check if woody plants have a structural biomass (agb) intercept ! ---------------------------------------------------------------------------------- if ( ( prt_params%allom_agb1(ipft) <= tiny(prt_params%allom_agb1(ipft)) ) .and. & - ( int(prt_params%woody(ipft)) .eq. 1 ) ) then + ( prt_params%woody(ipft) .eq. 1 ) ) then 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: ',int(prt_params%woody(ipft)) + write(fates_log(),*) ' woody: ',prt_params%woody(ipft) write(fates_log(),*) ' Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -1091,7 +1061,7 @@ subroutine PRTCheckParams(is_master) ! Check if non-woody plants have structural biomass (agb) intercept ! ---------------------------------------------------------------------------------- ! if ( ( prt_params%allom_agb1(ipft) > tiny(prt_params%allom_agb1(ipft)) ) .and. & -! ( int(prt_params%woody(ipft)) .ne. 1 ) ) then +! ( iprt_params%woody(ipft) .ne. 1 ) ) then ! ! write(fates_log(),*) 'Non-woody plants are expected to have a zero intercept' ! write(fates_log(),*) ' in the diameter to AGB allometry equations' @@ -1100,7 +1070,7 @@ subroutine PRTCheckParams(is_master) ! write(fates_log(),*) ' woody tissues (sap and structural dead wood).' ! write(fates_log(),*) ' PFT#: ',ipft ! write(fates_log(),*) ' allom_agb1: ',prt_params%allom_agb1(ipft) -! write(fates_log(),*) ' woody: ',int(prt_params%woody(ipft)) +! write(fates_log(),*) ' woody: ',prt_params%woody(ipft) ! write(fates_log(),*) ' Aborting' ! call endrun(msg=errMsg(sourcefile, __LINE__)) ! @@ -1122,53 +1092,9 @@ subroutine PRTCheckParams(is_master) end if + select case (hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) - ! Check re-translocations - ! Seems reasonable to assume that sapwood, structure and reproduction - ! should not be re-translocating mass upon turnover. - ! Note to advanced users. Feel free to remove these checks... - ! ------------------------------------------------------------------- - - if ((hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) .or. & - (hlm_parteh_mode .eq. prt_carbon_allom_hyp) ) then - - do i = 1,norgans - io = prt_params%organ_id(i) - - if(io == sapw_organ) then - if ((prt_params%turnover_carb_retrans(ipft,i) > nearzero)) then - write(fates_log(),*) ' Retranslocation of sapwood tissues should be zero.' - write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' carbon retrans: ',prt_params%turnover_carb_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - elseif(io == struct_organ) then - if ((prt_params%turnover_carb_retrans(ipft,i) > nearzero)) then - write(fates_log(),*) ' Retranslocation of structural tissues should be zero.' - write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' carbon retrans: ',prt_params%turnover_carb_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end if - - ! Otherwise, all other retranslocations should be between 0 and 1 - if ( (prt_params%turnover_carb_retrans(ipft,i) > 1.0_r8) .or. & - (prt_params%turnover_carb_retrans(ipft,i) < 0.0_r8) ) then - write(fates_log(),*) ' Retranslocation rates should be between 0 and 1.' - write(fates_log(),*) ' PFT#: ',ipft - write(fates_log(),*) ' parameter file index: ',i,' global index: ',io - write(fates_log(),*) ' retranslocation rate: ',prt_params%turnover_carb_retrans(ipft,i) - write(fates_log(),*) ' Aborting' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - end do - end if - - if (hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then - ! Make sure nutrient storage fractions are positive if( prt_params%nitr_store_ratio(ipft) < 0._r8 ) then write(fates_log(),*) 'With parteh allometric CNP hypothesis' @@ -1235,9 +1161,9 @@ subroutine PRTCheckParams(is_master) end if end do - - end if - + + end select + ! Growth respiration ! if (parteh_mode .eq. prt_carbon_allom_hyp) then @@ -1258,8 +1184,8 @@ subroutine PRTCheckParams(is_master) ! end if ! end if - if ((hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) .or. & - (hlm_parteh_mode .eq. prt_carbon_allom_hyp) ) then + select case (hlm_parteh_mode) + case (prt_carbon_allom_hyp,prt_cnp_flex_allom_hyp) ! 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 @@ -1269,32 +1195,25 @@ subroutine PRTCheckParams(is_master) write(fates_log(),*) ' Aborting' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - end if + end select - if(hlm_parteh_mode .eq. prt_cnp_flex_allom_hyp) then + select case (hlm_parteh_mode) + case (prt_cnp_flex_allom_hyp) do i = 1,norgans if ( (prt_params%nitr_stoich_p1(ipft,i) < 0._r8) .or. & - (prt_params%nitr_stoich_p2(ipft,i) < 0._r8) .or. & (prt_params%phos_stoich_p1(ipft,i) < 0._r8) .or. & - (prt_params%phos_stoich_p2(ipft,i) < 0._r8) .or. & (prt_params%nitr_stoich_p1(ipft,i) > 1._r8) .or. & - (prt_params%nitr_stoich_p2(ipft,i) > 1._r8) .or. & - (prt_params%phos_stoich_p1(ipft,i) > 1._r8) .or. & - (prt_params%phos_stoich_p2(ipft,i) > 1._r8) ) then + (prt_params%phos_stoich_p1(ipft,i) > 1._r8) ) then 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,' write(fates_log(),*) 'and less than 1 (probably way less than 1).' - write(fates_log(),*) 'Setting both p1 and p2 parameters to zero will turn' - write(fates_log(),*) 'off nutrient dynamics for the given species.' write(fates_log(),*) 'You specified an organ/pft less than zero.' write(fates_log(),*) 'PFT: ',ipft write(fates_log(),*) 'organ index (see head of PRTGenericMod): ',io - write(fates_log(),*) 'nitr_stoich_p1: ',prt_params%nitr_stoich_p1(ipft,i) - write(fates_log(),*) 'nitr_stoich_p2: ',prt_params%phos_stoich_p1(ipft,i) - write(fates_log(),*) 'phos_stoich_p1: ',prt_params%nitr_stoich_p2(ipft,i) - write(fates_log(),*) 'phos_stoich_p2: ',prt_params%phos_stoich_p2(ipft,i) + 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__)) end if @@ -1309,7 +1228,7 @@ subroutine PRTCheckParams(is_master) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - end if + end select ! Check turnover time-scales @@ -1476,28 +1395,28 @@ function NewRecruitTotalStoichiometry(ft,element_id) result(recruit_stoich) case(nitrogen_element) nutr_total = & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%nitr_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + c_leaf*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%nitr_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) case(phosphorus_element) nutr_total = & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ)) + & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)) + & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)) + & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)) + & + c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ)) + & + c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)) + & + c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)) + & + c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)) + & StorageNutrientTarget(ft, element_id, & - c_leaf*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(leaf_organ)), & - c_fnrt*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(fnrt_organ)), & - c_sapw*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(sapw_organ)), & - c_struct*prt_params%phos_stoich_p2(ft,prt_params%organ_param_id(struct_organ))) + c_leaf*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(leaf_organ)), & + c_fnrt*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(fnrt_organ)), & + c_sapw*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(sapw_organ)), & + c_struct*prt_params%phos_stoich_p1(ft,prt_params%organ_param_id(struct_organ))) end select diff --git a/tools/FatesPFTIndexSwapper.py b/tools/FatesPFTIndexSwapper.py index 7e39056fa8..e1a71d4334 100755 --- a/tools/FatesPFTIndexSwapper.py +++ b/tools/FatesPFTIndexSwapper.py @@ -24,7 +24,7 @@ # ======================================================================================= pft_dim_name = 'fates_pft' -prt_dim_name = 'fates_prt_organs' +prt_dim_name = 'fates_plant_organs' hydro_dim_name = 'fates_hydr_organs' litt_dim_name = 'fates_litterclass' string_dim_name = 'fates_string_length' diff --git a/tools/UpdateParamAPI.py b/tools/UpdateParamAPI.py new file mode 100755 index 0000000000..fe35d6a0c9 --- /dev/null +++ b/tools/UpdateParamAPI.py @@ -0,0 +1,465 @@ +#!/usr/bin/env python + +# ======================================================================================= +# This script modifies any FATES parameter file to update it to a new API spec. +# It can change variable names +# It can add new variables +# It can add attributes +# It can update attributes +# It can add new dimensions +# ======================================================================================= + +import os +import argparse +import code # For development: code.interact(local=dict(globals(), **locals())) +from scipy.io import netcdf +import xml.etree.ElementTree as et +import numpy as np + +# ======================================================================================= + +def load_xml(xmlfile): + + # This routine parses the XML tree + + xmlroot = et.parse(xmlfile).getroot() + print("\nOpened: {}\n".format(xmlfile)) + + base_cdl = xmlroot.find('base_file').text + new_cdl = xmlroot.find('new_file').text + + pft_list = xmlroot.find('pft_list').text.replace(" ","") + + modroot = xmlroot.find('mods') + + return(base_cdl,new_cdl,pft_list,modroot) + +# ======================================================================================= + +def str2fvec(numstr): + + # Convert a list of strings into floating point numbers + + numvec = [float(i) for i in numstr.split(',')] + return(numvec) + +# ======================================================================================= + +def str2ivec(numstr): + + # Convert a list of strings into integer numbers + + intvec = [int(i) for i in numstr.split(',')] + return(intvec) + +# ======================================================================================= + +def createvar(ncfile,paramname,dimnames,units,longname,usecase,dcode,sel_values): + + # Create a new netcdf variable inside an existing netcdf dataset (append) + + ncvar = ncfile.createVariable(paramname,dcode,dimnames) + ncvar.units = units + ncvar.long_name = longname + ncvar.use_case = usecase + if( not dimnames): + ncvar.assignValue(sel_values) + else: + ncvar[:] = sel_values + ncfile.flush() + + return(ncfile,ncvar) + +# ======================================================================================= + +def selectvalues(ncfile,dimnames,ipft_list,values,dtype): + + # Reduce a list of values so that onlythe chosen pft values are left. This + # only works on float arrays currently. We need to pass in a file + # so that we can get the dimension sizes associated with the dimension names. + + if(len(ipft_list) != ncfile.dimensions['fates_pft']): + print('you list of pfts in the xml file must be') + print('the same size as the fates_pft dimension') + print('in your destination file. exiting') + print('len(ipft_list) = {}'.format(len(ipft_list))) + print('fates_pft dim = {}'.format(ncfile.dimensions['fates_pft'])) + exit(2) + + # shift the pft list to a base of 0 instead of 1 + + pft_dim = -1 + dim_size = [0 for i in range(0,len(dimnames))] + + for idim, name in enumerate(dimnames): + dim_size[idim] = ncfile.dimensions[name] + if(name=='fates_pft'): + pft_dim = idim + pft_dim_size = ncfile.dimensions['fates_pft'] + + if(len(dimnames) == 1): + + if(pft_dim==0): + dim1_list = ipft_list + else: + dim1_list = range(0,dim_size[0]) + + sel_values = np.zeros([len(dim1_list)]) + for i,ipft in enumerate(dim1_list): + sel_values[i] = values[ipft] + + elif(len(dimnames) == 2 ): + + if(dtype=="c"): + + if(pft_dim>0): + print("problem with pft_dim: {},{}".format(dimnames[0],dimnames[1]));exit(2) + + if(pft_dim==0): + dim1_list = ipft_list + else: + dim1_list = range(0,dim_size[0]) + + sel_values = np.chararray([len(dim1_list),dim_size[1]]) + sel_values[:] = "" + for i,ipft in enumerate(dim1_list): + for j,cc in enumerate(values[ipft]): + sel_values[i][j] = cc + + + elif(dtype=="d"): + + if(pft_dim==0): + print("problem with pft_dim: {},{}".format(dimnames[0],dimnames[1]));exit(2) + + if(pft_dim==1): + dim1_list = ipft_list + else: + dim1_list = range(0,dim_size[1]) + + sel_values = np.zeros([dim_size[0],len(dim1_list)]) + for i,ipft in enumerate(dim1_list): + for i2 in range(0,dim_size[0]): + id = i2*len(dim1_list)+ipft + sel_values[i2,i] = values[id] + + else: + + # Scalar + #code.interact(local=dict(globals(), **locals())) + sel_values = float(values[0]) + + return(sel_values) + +# ======================================================================================= + +def removevar(base_nc,varname): + + # Remove a variable from a dataset. This is actually the hardest thing to do! + # The trick here, is to copy the whole file, minus the variable of interest + # into a temp file. Then completely remove the old file, and + + fp_base = netcdf.netcdf_file(base_nc, 'r',mmap=False) + + new_nc = os.popen('mktemp').read().rstrip('\n') + fp_new = netcdf.netcdf_file(new_nc, 'w',mmap=False) + + found = False + for key, value in sorted(fp_base.dimensions.items()): + if( key == varname ): + found = True + else: + fp_new.createDimension(key,int(value)) + + for key, value in fp_base.variables.items(): + + if(key == varname): + found = True + else: + datatype = value.typecode() + new_var = fp_new.createVariable(key,datatype,value.dimensions) + if(value.data.size == 1): + new_var.assignValue(float(value.data)) + else: + new_var[:] = value[:].copy() + + new_var.units = value.units + new_var.long_name = value.long_name + #try: + # new_var.use_case = value.use_case + #except: + # new_var.use_case = "undefined" + + fp_new.history = fp_base.history + + if(not found): + print("was not able to find variable: ()".format(varname)) + exit(2) + + fp_new.flush() + fp_base.close() + fp_new.close() + + mvcmd = "(rm -f "+base_nc+";mv "+new_nc+" "+base_nc+")" + os.system(mvcmd) + + +# ======================================================================================= + +def main(): + + # Parse arguments + parser = argparse.ArgumentParser(description='Parse command line arguments to this script.') + parser.add_argument('--f', dest='xmlfile', type=str, help="XML control file Required.", required=True) + args = parser.parse_args() + + + # Load the xml file, which contains the base cdl, the output cdl, + # and the parameters to be modified + [base_cdl,new_cdl,pft_list,modroot] = load_xml(args.xmlfile) + + ipft_list = str2ivec(pft_list) + + for i,ipft in enumerate(ipft_list): + ipft_list[i] = ipft_list[i]-1 + + # Convert the base cdl file into a temp nc binary + base_nc = os.popen('mktemp').read().rstrip('\n') + gencmd = "ncgen -o "+base_nc+" "+base_cdl + os.system(gencmd) + + modlist = [] + for mod in modroot: + if(not('type' in mod.attrib.keys())): + print("mod tag must have attribute type") + print("exiting") + exit(2) + + if(mod.attrib['type'].strip() == 'dimension_add'): + + try: + dimname = mod.find('di').text.strip() + except: + print("{}, no dimension (di), exiting".format(mod.attrib['type']));exit(2) + + try: + values = str2ivec(mod.find('val').text.strip()) + except: + print("no values (val), exiting");exit(2) + + if(len(values)>1): + print("The dimension size should be a scalar") + exit(2) + + ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) + ncfile.createDimension(dimname, values[0]) + ncfile.flush() + ncfile.close() + + print("dimension: {}, size: {}, added".format(dimname,values[0])) + + elif(mod.attrib['type'].strip() == 'dimension_del'): + + try: + dimname = mod.find('di').text.strip() + except: + print('define the dimension name to delete using a tag') + exit(2) + + # Find which parameters use this dimension + ncfile = netcdf.netcdf_file(base_nc,"r",mmap=False) + found = False + for key, value in sorted(ncfile.dimensions.items()): + if(key==dimname): + found=True + + if(not found): + print("could not find {} for deletion".format(dimname));exit(2) + + for key, value in sorted(ncfile.variables.items()): + hasdim = any([dim == dimname for dim in list(value.dimensions) ]) + + if (hasdim): + print("parameter: {}, removed (to accomodate dimension removal)".format(key)) + removevar(base_nc,key) + + ncfile.close() + + removevar(base_nc,dimname) + print("dimension: {}, removed".format(dimname)) + + elif(mod.attrib['type'].strip() == 'variable_add'): + + try: + paramname = mod.find('na').text.strip() + except: + print("no name (na), exiting");exit(2) + + #try: + # dtype = mod.find('dt').text.strip() + #except: + # print("no data type (dt), exiting");exit(2) + + try: + dimnames = tuple(mod.find('di').text.replace(" ","").split(',')) + except: + print("no data type (di), exiting");exit(2) + + try: + units = mod.find('un').text.strip() + except: + print("no units (un), exiting");exit(2) + + try: + longname = mod.find('ln').text.strip() + except: + print("no long-name (ln), exiting");exit(2) + + #try: + # usecase = mod.find('uc').text.strip() + #except: + # print("no use case (uc), exiting");exit(2) + + try: + values = str2fvec(mod.find('val').text.strip()) + except: + try: + values = mod.find('val').text.strip() + except: + print("no values (val), exiting");exit(2) + + #code.interact(local=dict(globals(), **locals())) + + if(dimnames[0]=='scalar' or dimnames[0]=='none' or dimnames[0]==''): + dimnames = () + + if(isinstance(values[0],str)): + dcode = "c" + values = values.split(',') + for i,val in enumerate(values): + values[i] = val.strip() + elif(isinstance(values[0],float)): + dcode = "d" + else: + print("Unknown value type: {} {}".format(type(values[0]),paramname));exit(2) + + + sel_values = selectvalues(ncfile,list(dimnames),ipft_list,values,dcode) + + ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) + [ncfile,ncvar] = createvar(ncfile,paramname,dimnames,units,longname,usecase,dcode,sel_values) + ncfile.flush() + ncfile.close() + + print("parameter: {}, added".format(paramname)) + + + elif(mod.attrib['type'] == 'variable_del'): + try: + paramname = mod.find('na').text.strip() + except: + print('must define the parameter name to delete, using name attribute') + exit(2) + removevar(base_nc,paramname) + print("parameter: {}, removed".format(paramname)) + + + elif(mod.attrib['type'] == 'variable_change'): + + try: + paramname_o = mod.attrib['name'].strip() + except: + print("to change a parameter, the field must have a name attribute") + exit(2) + + ncfile = netcdf.netcdf_file(base_nc,"a",mmap=False) + ncvar_o = ncfile.variables[paramname_o] + dims_o = ncvar_o.dimensions + dtype_o = ncvar_o.typecode() + units_o = ncvar_o.units.decode("utf-8") + longname_o = ncvar_o.long_name.decode("utf-8") + try: + usecase_o = ncvar_o.use_case.decode("utf-8") + except: + usecase_o = 'undefined' + + try: + paramname = mod.find('na').text.strip() + except: + paramname = None + + # Change the parameter's name + if(not isinstance(paramname,type(None))): + if not dims_o: + [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,usecase_o,dtype_o,float(ncvar_o.data)) + else: + [ncfile,ncvar] = createvar(ncfile,paramname,dims_o,units_o,longname_o,usecase_o,dtype_o,ncvar_o[:].copy()) + else: + ncvar = ncvar_o + + # Change the metadata: + try: + units = mod.find('un').text.strip() + except: + units = None + if(not isinstance(units,type(None))): + ncvar.units = units + + try: + longname = mod.find('ln').text.strip() + except: + longname = None + if(not isinstance(longname,type(None))): + ncvar.long_name = longname + + #try: + # usecase = mod.find('uc').text.strip() + #except: + usecase = None + #if(not isinstance(usecase,type(None))): + # ncvar.use_case = use_case + + try: + values = str2fvec(mod.find('val').text.strip()) + except: + values = None + + if(not isinstance(values,type(None))): + sel_values = selectvalues(ncfile,list(dims_o),ipft_list,values,dtype_o) + + # Scalars have their own thing + if(ncvar.data.size == 1): + ncvar.assignValue(sel_values) + else: + ncvar[:] = sel_values[:] + + + ncfile.flush() + ncfile.close() + + # Finally, if we did perform a re-name, and + # created a new variable. We need to delete the + # old one + if(not isinstance(paramname,type(None))): + removevar(base_nc,paramname_o) + paramname = paramname_o + + print("parameter: {}, modified".format(paramname)) + + + # Sort the new file + new_nc = os.popen('mktemp').read().rstrip('\n') + os.system("../tools/ncvarsort.py --silent --fin "+base_nc+" --fout "+new_nc+" --overwrite") + + # Dump the new file to the cdl + os.system("ncdump "+new_nc+" > "+new_cdl) + + + + print("\nAPI update complete, see file: {}\n".format(new_cdl)) + + +# This is the actual call to main + +if __name__ == "__main__": + main() diff --git a/tools/ncvarsort.py b/tools/ncvarsort.py index e9cdc422b4..327dd84a96 100755 --- a/tools/ncvarsort.py +++ b/tools/ncvarsort.py @@ -20,6 +20,7 @@ def main(): parser.add_argument('--fout','--output', dest='fnameout', type=str, help="Output filename. Required.", required=True) parser.add_argument('--O','--overwrite', dest='overwrite', help="If present, automatically overwrite the output file.", action="store_true") parser.add_argument('--debug', dest='debug', help="If present, output more diagnostics", action="store_true") + parser.add_argument('--silent', dest='silent', help="If present, prevents printing messages", action="store_true") # args = parser.parse_args() # @@ -38,16 +39,20 @@ def main(): (u'fates_history_coage_bins',):1, (u'fates_history_height_bins',):2, (u'fates_history_size_bins',):3, + (u'fates_history_damage_bins',):3, (u'fates_hydr_organs',):4, (u'fates_prt_organs',):4, + (u'fates_plant_organs',):4, (u'fates_pft', u'fates_string_length'):5, (u'fates_hydr_organs', u'fates_string_length'):6, (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_pft',):8, (u'fates_hydr_organs', u'fates_pft'):8, (u'fates_leafage_class', u'fates_pft'):8, (u'fates_prt_organs', u'fates_pft'):8, + (u'fates_plant_organs', u'fates_pft'):8, (u'fates_hlm_pftno', u'fates_pft'):9, (u'fates_litterclass',):10, (u'fates_NCWD',):11, @@ -64,17 +69,28 @@ def main(): for i in range(len(varnames_list)): varnames_list[i] = sorted(varnames_list[i], key=lambda L: (L.lower(), L)) varnames_list_sorted.extend(varnames_list[i]) - # + + if args.silent: + verbose = False + else: + verbose = True + # write list of variables in ourput order if args.debug: - print(varnames_list_sorted) - # + if (not verbose): + print("cant run debug and silent in ncvarsort") + exit(2) + else: + print(varnames_list_sorted) + + + # open the output filename, deleting it if it exists already. if os.path.isfile(args.fnameout): if args.fnameout == args.fnamein: raise ValueError('Error: output file name is the same as the input file name.') elif args.overwrite: - print('replacing file: '+args.fnameout) + if (verbose): print('replacing file: '+args.fnameout) os.remove(args.fnameout) else: raise ValueError('Output file already exists and overwrite flag not specified for filename: '+args.fnameout) @@ -84,15 +100,15 @@ def main(): #Copy dimensions for dname, the_dim in dsin.dimensions.items(): if args.debug: - print(dname, the_dim.size) + if (verbose): print(dname, the_dim.size) dsout.createDimension(dname, the_dim.size ) # - print() + if (verbose): print() # try: dsout.history = dsin.history except: - print('no history!') + if (verbose): print('no history!') # # # go through each variable in the order of the sorted master list, and copy the variable @@ -102,7 +118,7 @@ def main(): varin = dsin.variables[v_name] outVar = dsout.createVariable(v_name, varin.datatype, varin.dimensions) if args.debug: - print(v_name) + if (verbose): print(v_name) # outVar.setncatts({k: varin.getncattr(k) for k in varin.ncattrs()}) outVar[:] = varin[:]