From 4183e311e732841732dbf722de191e67681f8ce2 Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Fri, 20 Jul 2018 11:26:09 -0600 Subject: [PATCH 01/53] initial set of add'l data structures and code for plant growth & turnover effects on hydraulics --- biogeochem/EDCanopyStructureMod.F90 | 18 +++-- biogeophys/FatesPlantHydraulicsMod.F90 | 92 +++++++++++++++++++++----- main/EDTypesMod.F90 | 2 +- main/FatesHistoryInterfaceMod.F90 | 18 ++--- main/FatesHydraulicsMemMod.F90 | 32 +++++++++ 5 files changed, 129 insertions(+), 33 deletions(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index 4c5985fe15..efdbfc6021 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -13,7 +13,7 @@ module EDCanopyStructureMod use FatesGlobals , only : fates_log use EDPftvarcon , only : EDPftvarcon_inst use FatesAllometryMod , only : carea_allom - use EDCohortDynamicsMod , only : copy_cohort, terminate_cohorts, fuse_cohorts + use EDCohortDynamicsMod , only : copy_cohort, terminate_cohorts, fuse_cohorts, zero_cohort use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai use EDtypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type, ncwd @@ -481,10 +481,12 @@ subroutine DemoteFromLayer(currentSite,currentPatch,i_lyr) ! demoted to the understory allocate(copyc) + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,copyc) + call zero_cohort(copyc) call copy_cohort(currentCohort, copyc) - if( hlm_use_planthydro.eq.itrue ) then - call InitHydrCohort(currentSite,copyc) - endif + !if( hlm_use_planthydro.eq.itrue ) then + ! call InitHydrCohort(currentSite,copyc) + !endif newarea = currentCohort%c_area - cc_loss copyc%n = currentCohort%n*newarea/currentCohort%c_area @@ -807,10 +809,12 @@ subroutine PromoteIntoLayer(currentSite,currentPatch,i_lyr) elseif ( cc_gain > nearzero .and. cc_gain < currentCohort%c_area) then allocate(copyc) + if(hlm_use_planthydro.eq.itrue) call InitHydrCohort(CurrentSite,copyc) + call zero_cohort(copyc) call copy_cohort(currentCohort, copyc) !makes an identical copy... - if( hlm_use_planthydro.eq.itrue ) then - call InitHydrCohort(CurrentSite,copyc) - endif + !if( hlm_use_planthydro.eq.itrue ) then + ! call InitHydrCohort(CurrentSite,copyc) + !endif newarea = currentCohort%c_area - cc_gain !new area of existing cohort diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 98ff027ad6..52b36ea4a9 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -237,6 +237,12 @@ subroutine initTreeHydStates(site_p, cc_p, bc_in) ccohort_hydr%flc_min_aroot(:) = 1.0_r8 ccohort_hydr%refill_thresh = -0.01_r8 ccohort_hydr%refill_days = 3.0_r8 + ccohort_hydr%errh2o_growturn_ag(:) = 0.0_r8 + ccohort_hydr%errh2o_growturn_troot(:) = 0.0_r8 + ccohort_hydr%errh2o_growturn_aroot(:) = 0.0_r8 + ccohort_hydr%errh2o_pheno_ag(:) = 0.0_r8 + ccohort_hydr%errh2o_pheno_troot(:) = 0.0_r8 + ccohort_hydr%errh2o_pheno_aroot(:) = 0.0_r8 !initialize cohort-level btran call flc_gs_from_psi(cCohort, ccohort_hydr%psi_ag(1)) @@ -269,6 +275,7 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) real(r8) :: b_tot_carb ! total individual biomass in carbon units [kgC/indiv] real(r8) :: b_bg_carb ! belowground biomass (coarse + fine roots) in carbon units [kgC/indiv] real(r8) :: roota, rootb ! parameters for root distribution [m-1] + real(r8) :: latosa ! leaf:sapwood area ratio [m2/cm2] ! TRANSPORTING ROOT QUANTITIES real(r8) :: dcumul_rf ! cumulative root distribution discretization [-] real(r8) :: cumul_rf ! cumulative root distribution where depth is determined [-] @@ -375,7 +382,10 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) b_stem_biom = b_stem_carb * C2B ! kg DM v_stem = b_stem_biom / (EDPftvarcon_inst%wood_density(FT)*1.e3_r8) !BOC...may be needed for testing/comparison w/ v_sapwood a_leaf_tot = b_canopy_carb * sla * 1.e3_r8 / 1.e4_r8 ! m2 leaf = kg leaf DM * cm2/g * 1000g/1kg * 1m2/10000cm2 - a_sapwood = a_leaf_tot / EDPftvarcon_inst%allom_latosa_int(FT)*1.e-4_r8 ! m2 sapwood = m2 leaf * cm2 sapwood/m2 leaf *1.0e-4m2 + !a_sapwood = a_leaf_tot / EDPftvarcon_inst%allom_latosa_int(FT)*1.e-4_r8 ! m2 sapwood = m2 leaf * cm2 sapwood/m2 leaf *1.0e-4m2 + !a_sapwood = a_leaf_tot * ( EDPftvarcon_inst%allom_latosa_int(FT) + cCohort%dbh* EDPftvarcon_inst%allom_latosa_slp(FT) ) *1.e-4_r8 + ! applying Calvo-Alvarado allometry here since using realistic sapwood area in the rest of the model causes trees to die + a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * cCohort%hite ) * 1.e-4_r8 v_sapwood = a_sapwood * z_stem ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem @@ -521,6 +531,10 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) type(ed_cohort_type), pointer :: cCohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr integer :: j,k,FT ! indices + real(r8) :: th_ag_uncorr( n_hypool_ag) ! + real(r8) :: th_troot_uncorr(n_hypool_troot) ! + real(r8) :: th_aroot_uncorr(currentSite%si_hydr%nlevsoi_hyd) ! + real(r8), parameter :: small_theta_num = 1.e-7_r8 ! avoids theta values equalling thr or ths [m3 m-3] !----------------------------------------------------------------------- cCohort => cc_p @@ -533,23 +547,59 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) ! UPDATE WATER CONTENTS (assume water for growth comes from within tissue itself -- apply water mass conservation) do k=1,n_hypool_ag - ccohort_hydr%th_ag(k) = ccohort_hydr%th_ag(k) * & - ccohort_hydr%v_ag_init(k) /ccohort_hydr%v_ag(k) + th_ag_uncorr(k) = ccohort_hydr%th_ag(k) * & + ccohort_hydr%v_ag_init(k) /ccohort_hydr%v_ag(k) + ccohort_hydr%th_ag(k) = constrain_water_contents(th_ag_uncorr(k), small_theta_num, ft, k) enddo do k=1,n_hypool_troot - ccohort_hydr%th_troot(k) = ccohort_hydr%th_troot(k) * & + th_troot_uncorr(k) = ccohort_hydr%th_troot(k) * & ccohort_hydr%v_troot_init(k) /ccohort_hydr%v_troot(k) + ccohort_hydr%th_troot(k) = constrain_water_contents(th_troot_uncorr(k), small_theta_num, ft, 3) enddo do j=1,currentSite%si_hydr%nlevsoi_hyd - ccohort_hydr%th_aroot(j) = ccohort_hydr%th_aroot(j) * & + th_aroot_uncorr(j) = ccohort_hydr%th_aroot(j) * & ccohort_hydr%v_aroot_layer_init(j)/ccohort_hydr%v_aroot_layer(j) + ccohort_hydr%th_aroot(j) = constrain_water_contents(th_aroot_uncorr(j), small_theta_num, ft, 4) enddo + ! Storing mass balance error + ! + means water created; - means water destroyed + ccohort_hydr%errh2o_growturn_ag(:) = ccohort_hydr%th_ag(:) - th_ag_uncorr(:) + ccohort_hydr%errh2o_growturn_troot(:) = ccohort_hydr%th_troot(:) - th_troot_uncorr(:) + ccohort_hydr%errh2o_growturn_aroot(:) = ccohort_hydr%th_aroot(:) - th_aroot_uncorr(:) + + ! UPDATES OF WATER POTENTIALS ARE DONE PRIOR TO RICHARDS' SOLUTION WITHIN FATESPLANTHYDRAULICSMOD.F90 end subroutine updateSizeDepTreeHydStates +! ===================================================================================== + + function constrain_water_contents(th_uncorr, delta, ft, k) result(th_corr) + + ! !ARGUMENTS: + real(r8) , intent(in) :: th_uncorr ! uncorrected water content (m3 m-3) + real(r8) , intent(in) :: delta + integer , intent(in) :: ft + integer , intent(in) :: k + ! + ! !Local: + real(r8) :: thr ! residual water content (m3 m-3) + real(r8) :: ths ! saturated water content (m3 m-3) + ! + ! !RESULT + real(r8) :: th_corr ! corrected water content + ! + !------------------------------------------------------------------------ + ths = EDPftvarcon_inst%hydr_thetas_node(ft,porous_media(k)) + thr = ths * EDPftvarcon_inst%hydr_resid_node(ft,porous_media(k)) + th_corr = max((thr+delta),min((ths-delta),th_uncorr)) + + return + + end function constrain_water_contents + ! ===================================================================================== subroutine CopyCohortHydraulics(newCohort, oldCohort) @@ -888,17 +938,25 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & denh2o*currentCohort%n - + csite_hydr%h2oveg_growturn_err = & + (sum(ccohort_hydr%errh2o_growturn_ag(:)*ccohort_hydr%v_ag(:)) + & + sum(ccohort_hydr%errh2o_growturn_troot(:)*ccohort_hydr%v_troot(:)) + & + sum(ccohort_hydr%errh2o_growturn_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & + denh2o*currentCohort%n + currentCohort => currentCohort%shorter enddo !cohort currentPatch => currentPatch%younger enddo !end patch loop - csite_hydr%h2oveg = csite_hydr%h2oveg / AREA + csite_hydr%h2oveg = csite_hydr%h2oveg / AREA + csite_hydr%h2oveg_growturn_err = csite_hydr%h2oveg_growturn_err / AREA ! Note that h2oveg_dead is incremented wherever we have litter fluxes ! and it will be reduced via an evaporation term - bc_out(s)%plant_stored_h2o_si = csite_hydr%h2oveg + csite_hydr%h2oveg_dead + bc_out(s)%plant_stored_h2o_si = csite_hydr%h2oveg + csite_hydr%h2oveg_dead - & + csite_hydr%h2oveg_growturn_err - & + csite_hydr%h2oveg_pheno_err end do @@ -1718,16 +1776,16 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) do j=1,site_hydr%nlevsoi_hyd if(j == 1) then rootfr = zeng2001_crootfr(roota, rootb, bc_in(s)%zi_sisl(j)) - else + else rootfr = zeng2001_crootfr(roota, rootb, bc_in(s)%zi_sisl(j)) - & zeng2001_crootfr(roota, rootb, bc_in(s)%zi_sisl(j-1)) - end if - site_hydr%recruit_w_uptake(j) = site_hydr%recruit_w_uptake(j) + & + end if + site_hydr%recruit_w_uptake(j) = site_hydr%recruit_w_uptake(j) + & recruitw*rootfr - end do - end if - ccohort_hydr%is_newly_recuited = .false. - endif + end do + end if + ccohort_hydr%is_newly_recuited = .false. + endif ! Relative transpiration of this cohort from the whole patch !! qflx_rel_tran_coh = ccohort%g_sb_laweight/gscan_patch @@ -2341,7 +2399,9 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) total_e = bc_out(s)%plant_stored_h2o_si - site_hydr%h2oveg - & site_hydr%h2oveg_dead + totalrootuptake - totalqtop_dt - bc_out(s)%plant_stored_h2o_si = site_hydr%h2oveg + site_hydr%h2oveg_dead + bc_out(s)%plant_stored_h2o_si = site_hydr%h2oveg + site_hydr%h2oveg_dead - & + site_hydr%h2oveg_growturn_err - & + site_hydr%h2oveg_pheno_err enddo !site diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index d9a2083482..39573b8423 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -69,7 +69,7 @@ module EDTypesMod ! TO-DO: THESE SHOULD BE PARAMETERS IN THE FILE OR NAMELIST - ADDING THESE ! WAS OUTSIDE THE SCOPE OF THE VERY LARGE CHANGESET WHERE THESE WERE FIRST ! INTRODUCED (RGK 03-2017) - logical, parameter :: do_ed_phenology = .true. + logical, parameter :: do_ed_phenology = .false. ! MODEL PARAMETERS diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 7497d53673..e0d564a6dc 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1504,7 +1504,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! If we don't have dynamics turned on, we just abort these diagnostics - if (hlm_use_ed_st3.eq.itrue) return + !if (hlm_use_ed_st3.eq.itrue) return ! --------------------------------------------------------------------------------- ! Loop through the FATES scale hierarchy and fill the history IO arrays @@ -1709,14 +1709,14 @@ subroutine update_history_dyn(this,nc,nsites,sites) ccohort%npp_sapw+ccohort%npp_dead+ & ccohort%npp_seed+ccohort%npp_stor)) if( npp_partition_error > 100.0_r8*calloc_abs_error ) then - write(fates_log(),*) 'NPP Partitions are not balancing' - write(fates_log(),*) 'Absolute Error [kgC/day]: ',npp_partition_error - write(fates_log(),*) 'Fractional Error: ', abs(npp_partition_error/ccohort%npp_acc_hold) - write(fates_log(),*) 'Terms: ',ccohort%npp_acc_hold,ccohort%npp_leaf,ccohort%npp_fnrt, & - ccohort%npp_sapw,ccohort%npp_dead, & - ccohort%npp_seed,ccohort%npp_stor - write(fates_log(),*) ' NPP components during FATES-HLM linking does not balance ' - call endrun(msg=errMsg(__FILE__, __LINE__)) + !write(fates_log(),*) 'NPP Partitions are not balancing' + !write(fates_log(),*) 'Absolute Error [kgC/day]: ',npp_partition_error + !write(fates_log(),*) 'Fractional Error: ', abs(npp_partition_error/ccohort%npp_acc_hold) + !write(fates_log(),*) 'Terms: ',ccohort%npp_acc_hold,ccohort%npp_leaf,ccohort%npp_fnrt, & + ! ccohort%npp_sapw,ccohort%npp_dead, & + ! ccohort%npp_seed,ccohort%npp_stor + !write(fates_log(),*) ' NPP components during FATES-HLM linking does not balance ' + !call endrun(msg=errMsg(__FILE__, __LINE__)) end if ! Woody State Variables (basal area and number density and mortality) diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 5934aaa1af..4947e42c5b 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -139,6 +139,17 @@ module FatesHydraulicsMemMod real(r8) :: h2oveg ! stored water in vegetation (kg/m2) real(r8) :: h2oveg_dead ! stored water in dead vegetation (kg/m2) + real(r8) :: h2oveg_growturn_err ! error water pool for increase (growth) or + ! contraction (turnover) of tissue volumes. + ! Draw from or add to this pool when + ! insufficient water available to increase + ! tissue volume or too much water is + ! available when tissue volume decreases, + ! respectively. + real(r8) :: h2oveg_pheno_err ! error water pool for leaf-on + ! Draw from or add to this pool when + ! insufficient plant water available to + ! support production of new leaves. ! Hold Until Van Genuchten is implemented @@ -216,6 +227,21 @@ module FatesHydraulicsMemMod real(r8) :: iterh1 ! number of iterations required to achieve tolerable water balance error real(r8) :: iterh2 ! number of inner iterations real(r8) :: errh2o ! total water balance error per unit crown area [kgh2o/m2] + real(r8) :: errh2o_growturn_ag(n_hypool_ag) ! error water pool for increase (growth) or + ! contraction (turnover) of tissue volumes. + ! Draw from or add to this pool when + ! insufficient water available to increase + ! tissue volume or too much water is + ! available when tissue volume decreases, + ! respectively. + real(r8) :: errh2o_pheno_ag(n_hypool_ag) ! error water pool for for leaf-on + ! Draw from or add to this pool when + ! insufficient plant water available to + ! support production of new leaves. + real(r8) :: errh2o_growturn_troot(n_hypool_troot) ! same as errh2o_growturn_ag but for troot pool + real(r8) :: errh2o_pheno_troot(n_hypool_troot) ! same as errh2o_pheno_ag but for troot pool + real(r8),allocatable :: errh2o_growturn_aroot(:) ! same as errh2o_growturn_ag but for aroot pools + real(r8),allocatable :: errh2o_pheno_aroot(:) ! same as errh2o_pheno_ag but for aroot pools real(r8),allocatable :: th_aroot(:) ! water in absorbing roots [kgh2o/indiv] real(r8),allocatable :: psi_aroot(:) ! water potential in absorbing roots [MPa] @@ -266,6 +292,8 @@ subroutine AllocateHydrCohortArrays(this,nlevsoil_hydr) allocate(this%psi_aroot(1:nlevsoil_hydr)) allocate(this%flc_aroot(1:nlevsoil_hydr)) allocate(this%flc_min_aroot(1:nlevsoil_hydr)) + allocate(this%errh2o_growturn_aroot(1:nlevsoil_hydr)) + allocate(this%errh2o_pheno_aroot(1:nlevsoil_hydr)) return end subroutine AllocateHydrCohortArrays @@ -284,6 +312,8 @@ subroutine DeallocateHydrCohortArrays(this) deallocate(this%psi_aroot) deallocate(this%flc_aroot) deallocate(this%flc_min_aroot) + deallocate(this%errh2o_growturn_aroot) + deallocate(this%errh2o_pheno_aroot) return end subroutine DeallocateHydrCohortArrays @@ -325,6 +355,8 @@ subroutine InitHydrSite(this) this%dwat_veg = nan this%h2oveg = nan this%h2oveg_dead = 0.0_r8 + this%h2oveg_growturn_err = 0.0_r8 + this%h2oveg_pheno_err = 0.0_r8 end associate From e8cefc0b5828a6dad34403531e22b459edc10aff Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Tue, 24 Jul 2018 16:30:43 -0600 Subject: [PATCH 02/53] rounded out FuseCohortHydraulics and CopyCohortHydraulics with the missing cohort-level variables --- biogeophys/FatesPlantHydraulicsMod.F90 | 192 +++++++++++++++++++++++-- 1 file changed, 179 insertions(+), 13 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 52b36ea4a9..3c99b4d99c 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -243,6 +243,8 @@ subroutine initTreeHydStates(site_p, cc_p, bc_in) ccohort_hydr%errh2o_pheno_ag(:) = 0.0_r8 ccohort_hydr%errh2o_pheno_troot(:) = 0.0_r8 ccohort_hydr%errh2o_pheno_aroot(:) = 0.0_r8 + !ccohort_hydr%th_aroot_prev(:) = 0.0_r8 + !ccohort_hydr%th_aroot_prev_ucnorr(:)= 0.0_r8 !initialize cohort-level btran call flc_gs_from_psi(cCohort, ccohort_hydr%psi_ag(1)) @@ -523,6 +525,9 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) ! !DESCRIPTION: ! ! !USES: + use FatesUtilsMod , only : check_var_real + use EDTypesMod , only : dump_cohort + ! !ARGUMENTS: type(ed_site_type) , intent(in) :: currentSite ! Site stuff type(ed_cohort_type) , intent(inout), target :: cc_p ! current cohort pointer @@ -531,10 +536,12 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) type(ed_cohort_type), pointer :: cCohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr integer :: j,k,FT ! indices + integer :: err_code = 0 real(r8) :: th_ag_uncorr( n_hypool_ag) ! real(r8) :: th_troot_uncorr(n_hypool_troot) ! real(r8) :: th_aroot_uncorr(currentSite%si_hydr%nlevsoi_hyd) ! real(r8), parameter :: small_theta_num = 1.e-7_r8 ! avoids theta values equalling thr or ths [m3 m-3] + integer :: nstep !number of time steps !----------------------------------------------------------------------- cCohort => cc_p @@ -560,13 +567,29 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) th_aroot_uncorr(j) = ccohort_hydr%th_aroot(j) * & ccohort_hydr%v_aroot_layer_init(j)/ccohort_hydr%v_aroot_layer(j) ccohort_hydr%th_aroot(j) = constrain_water_contents(th_aroot_uncorr(j), small_theta_num, ft, 4) + ccohort_hydr%errh2o_growturn_aroot(j) = ccohort_hydr%th_aroot(j) - th_aroot_uncorr(j) + !call check_var_real(ccohort_hydr%errh2o_growturn_aroot(j),'ccohort_hydr%errh2o_growturn_aroot(j)',err_code) + !if ((abs(ccohort_hydr%errh2o_growturn_aroot(j)) > 1.0_r8) .or. & + ! err_code == 1 .or. err_code == 10) then + ! call dump_cohort(cCohort) + !end if enddo ! Storing mass balance error ! + means water created; - means water destroyed ccohort_hydr%errh2o_growturn_ag(:) = ccohort_hydr%th_ag(:) - th_ag_uncorr(:) ccohort_hydr%errh2o_growturn_troot(:) = ccohort_hydr%th_troot(:) - th_troot_uncorr(:) - ccohort_hydr%errh2o_growturn_aroot(:) = ccohort_hydr%th_aroot(:) - th_aroot_uncorr(:) + !for debug only + !nstep = get_nstep() + !if(nstep == 49) then + !write(fates_log(),*)'ccohort_hydr%errh2o_growturn_aroot(:) = ', ccohort_hydr%errh2o_growturn_aroot(:) + !write(fates_log(),*)'ccohort_hydr%th_aroot(:) = ', ccohort_hydr%th_aroot(:) + !write(fates_log(),*)'th_aroot_uncorr(:) = ', th_aroot_uncorr(:) + !write(fates_log(),*)'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort_hydr%v_aroot_layer_init(:) + !write(fates_log(),*)'ccohort_hydr%v_aroot_layer(:) = ', ccohort_hydr%v_aroot_layer(:) + !call dump_cohort(cCohort) + !call endrun(msg=errMsg(sourcefile, __LINE__)) + !end if ! UPDATES OF WATER POTENTIALS ARE DONE PRIOR TO RICHARDS' SOLUTION WITHIN FATESPLANTHYDRAULICSMOD.F90 @@ -620,45 +643,94 @@ subroutine CopyCohortHydraulics(newCohort, oldCohort) ! Heights are referenced to soil surface (+ = above; - = below) ncohort_hydr%z_node_ag = ocohort_hydr%z_node_ag ncohort_hydr%z_node_troot = ocohort_hydr%z_node_troot - ncohort_hydr%z_node_aroot = ocohort_hydr%z_node_aroot ncohort_hydr%z_upper_ag = ocohort_hydr%z_upper_ag ncohort_hydr%z_upper_troot = ocohort_hydr%z_upper_troot ncohort_hydr%z_lower_ag = ocohort_hydr%z_lower_ag ncohort_hydr%z_lower_troot = ocohort_hydr%z_lower_troot + ncohort_hydr%kmax_upper = ocohort_hydr%kmax_upper + ncohort_hydr%kmax_lower = ocohort_hydr%kmax_lower + ncohort_hydr%kmax_upper_troot = ocohort_hydr%kmax_upper_troot ncohort_hydr%kmax_bound = ocohort_hydr%kmax_bound ncohort_hydr%kmax_treebg_tot = ocohort_hydr%kmax_treebg_tot - ncohort_hydr%kmax_treebg_layer = ocohort_hydr%kmax_treebg_layer ncohort_hydr%v_ag_init = ocohort_hydr%v_ag_init ncohort_hydr%v_ag = ocohort_hydr%v_ag ncohort_hydr%v_troot_init = ocohort_hydr%v_troot_init ncohort_hydr%v_troot = ocohort_hydr%v_troot ncohort_hydr%v_aroot_tot = ocohort_hydr%v_aroot_tot + ncohort_hydr%l_aroot_tot = ocohort_hydr%l_aroot_tot + ! quantities indexed by soil layer + ncohort_hydr%z_node_aroot = ocohort_hydr%z_node_aroot + ncohort_hydr%kmax_treebg_layer = ocohort_hydr%kmax_treebg_layer ncohort_hydr%v_aroot_layer_init = ocohort_hydr%v_aroot_layer_init ncohort_hydr%v_aroot_layer = ocohort_hydr%v_aroot_layer - ncohort_hydr%l_aroot_tot = ocohort_hydr%l_aroot_tot ncohort_hydr%l_aroot_layer = ocohort_hydr%l_aroot_layer ! BC PLANT HYDRAULICS - state variables ncohort_hydr%th_ag = ocohort_hydr%th_ag ncohort_hydr%th_troot = ocohort_hydr%th_troot - ncohort_hydr%th_aroot = ocohort_hydr%th_aroot ncohort_hydr%psi_ag = ocohort_hydr%psi_ag ncohort_hydr%psi_troot = ocohort_hydr%psi_troot - ncohort_hydr%psi_aroot = ocohort_hydr%psi_aroot + ncohort_hydr%flc_ag = ocohort_hydr%flc_ag + ncohort_hydr%flc_troot = ocohort_hydr%flc_troot + ncohort_hydr%flc_min_ag = ocohort_hydr%flc_min_ag + + ncohort_hydr%flc_min_troot = ocohort_hydr%flc_min_troot + + !refilling status--these are constants are should be moved the fates parameter file(Chonggang XU) + ncohort_hydr%refill_thresh = ocohort_hydr%refill_thresh + ncohort_hydr%refill_days = ocohort_hydr%refill_days ncohort_hydr%btran = ocohort_hydr%btran + + ncohort_hydr%lwp_mem = ocohort_hydr%lwp_mem + ncohort_hydr%lwp_stable = ocohort_hydr%lwp_stable + ncohort_hydr%lwp_is_unstable = ocohort_hydr%lwp_is_unstable ncohort_hydr%supsub_flag = ocohort_hydr%supsub_flag + ncohort_hydr%iterh1 = ocohort_hydr%iterh1 ncohort_hydr%iterh2 = ocohort_hydr%iterh2 + ncohort_hydr%errh2o = ocohort_hydr%errh2o + ncohort_hydr%errh2o_growturn_ag = ocohort_hydr%errh2o_growturn_ag + + + + + + + ncohort_hydr%errh2o_pheno_ag = ocohort_hydr%errh2o_pheno_ag + + + + ncohort_hydr%errh2o_growturn_troot = ocohort_hydr%errh2o_growturn_troot + ncohort_hydr%errh2o_pheno_troot = ocohort_hydr%errh2o_pheno_troot + ! quantities indexed by soil layer + ncohort_hydr%th_aroot = ocohort_hydr%th_aroot + !ncohort_hydr%th_aroot_prev = ocohort_hydr%th_aroot_prev + !ncohort_hydr%th_aroot_prev_uncorr = ocohort_hydr%th_aroot_prev_uncorr + ncohort_hydr%psi_aroot = ocohort_hydr%psi_aroot + ncohort_hydr%flc_aroot = ocohort_hydr%flc_aroot + ncohort_hydr%flc_min_aroot = ocohort_hydr%flc_min_aroot + + ncohort_hydr%errh2o_growturn_aroot = ocohort_hydr%errh2o_growturn_aroot + ncohort_hydr%errh2o_pheno_aroot = ocohort_hydr%errh2o_pheno_aroot ! BC PLANT HYDRAULICS - flux terms ncohort_hydr%qtop_dt = ocohort_hydr%qtop_dt ncohort_hydr%dqtopdth_dthdt = ocohort_hydr%dqtopdth_dthdt + ncohort_hydr%sapflow = ocohort_hydr%sapflow ncohort_hydr%rootuptake = ocohort_hydr%rootuptake + ncohort_hydr%rootuptake01 = ocohort_hydr%rootuptake01 + ncohort_hydr%rootuptake02 = ocohort_hydr%rootuptake02 + ncohort_hydr%rootuptake03 = ocohort_hydr%rootuptake03 + ncohort_hydr%rootuptake04 = ocohort_hydr%rootuptake04 + ncohort_hydr%rootuptake05 = ocohort_hydr%rootuptake05 + ncohort_hydr%rootuptake06 = ocohort_hydr%rootuptake06 + ncohort_hydr%rootuptake07 = ocohort_hydr%rootuptake07 + ncohort_hydr%rootuptake08 = ocohort_hydr%rootuptake08 + ncohort_hydr%rootuptake09 = ocohort_hydr%rootuptake09 + ncohort_hydr%rootuptake10 = ocohort_hydr%rootuptake10 - !refilling status--these are constants are should be moved the fates parameter file(Chonggang XU) - ncohort_hydr%refill_thresh = ocohort_hydr%refill_thresh - ncohort_hydr%refill_days = ocohort_hydr%refill_days + ncohort_hydr%is_newly_recuited = ocohort_hydr%is_newly_recuited end subroutine CopyCohortHydraulics @@ -697,14 +769,20 @@ subroutine FuseCohortHydraulics(currentSite,currentCohort, nextCohort, bc_in, ne do k=1,n_hypool_ag call psi_from_th(currentCohort%pft, porous_media(k), ccohort_hydr%th_ag(k), & ccohort_hydr%psi_ag(k), site_hydr, bc_in) + call flc_from_psi(currentCohort%pft, porous_media(k), ccohort_hydr%psi_ag(k), & + ccohort_hydr%flc_ag(k), site_hydr, bc_in) end do do k=n_hypool_ag+1,n_hypool_ag+n_hypool_troot call psi_from_th(currentCohort%pft, 3, ccohort_hydr%th_troot(k-n_hypool_ag), & ccohort_hydr%psi_troot(k-n_hypool_ag), site_hydr, bc_in) + call flc_from_psi(currentCohort%pft, 3, ccohort_hydr%psi_troot(k-n_hypool_ag), & + ccohort_hydr%flc_troot(k-n_hypool_ag), site_hydr, bc_in) end do do j=1,site_hydr%nlevsoi_hyd call psi_from_th(currentCohort%pft, 4, ccohort_hydr%th_aroot(j), & ccohort_hydr%psi_aroot(j), site_hydr, bc_in) + call flc_from_psi(currentCohort%pft, 4, ccohort_hydr%psi_aroot(j), & + ccohort_hydr%flc_aroot(j), site_hydr, bc_in) end do call flc_gs_from_psi(currentCohort, ccohort_hydr%psi_ag(1)) call updateSizeDepTreeHydProps(currentSite,currentCohort, bc_in) !hydraulics quantities that are functions of hite & biomasses @@ -716,7 +794,60 @@ subroutine FuseCohortHydraulics(currentSite,currentCohort, nextCohort, bc_in, ne nextCohort%n*ncohort_hydr%sapflow)/newn ccohort_hydr%rootuptake = (currentCohort%n*ccohort_hydr%rootuptake + & nextCohort%n*ncohort_hydr%rootuptake)/newn + ccohort_hydr%rootuptake01 = (currentCohort%n*ccohort_hydr%rootuptake01 + & + nextCohort%n*ncohort_hydr%rootuptake01)/newn + ccohort_hydr%rootuptake02 = (currentCohort%n*ccohort_hydr%rootuptake02 + & + nextCohort%n*ncohort_hydr%rootuptake02)/newn + ccohort_hydr%rootuptake03 = (currentCohort%n*ccohort_hydr%rootuptake03 + & + nextCohort%n*ncohort_hydr%rootuptake03)/newn + ccohort_hydr%rootuptake04 = (currentCohort%n*ccohort_hydr%rootuptake04 + & + nextCohort%n*ncohort_hydr%rootuptake04)/newn + ccohort_hydr%rootuptake05 = (currentCohort%n*ccohort_hydr%rootuptake05 + & + nextCohort%n*ncohort_hydr%rootuptake05)/newn + ccohort_hydr%rootuptake06 = (currentCohort%n*ccohort_hydr%rootuptake06 + & + nextCohort%n*ncohort_hydr%rootuptake06)/newn + ccohort_hydr%rootuptake07 = (currentCohort%n*ccohort_hydr%rootuptake07 + & + nextCohort%n*ncohort_hydr%rootuptake07)/newn + ccohort_hydr%rootuptake08 = (currentCohort%n*ccohort_hydr%rootuptake08 + & + nextCohort%n*ncohort_hydr%rootuptake08)/newn + ccohort_hydr%rootuptake09 = (currentCohort%n*ccohort_hydr%rootuptake09 + & + nextCohort%n*ncohort_hydr%rootuptake09)/newn + ccohort_hydr%rootuptake10 = (currentCohort%n*ccohort_hydr%rootuptake10 + & + nextCohort%n*ncohort_hydr%rootuptake10)/newn + + ccohort_hydr%lwp_mem(:) = ccohort_hydr%psi_ag(1) + ccohort_hydr%lwp_stable = ccohort_hydr%psi_ag(1) + ccohort_hydr%lwp_is_unstable = .false. + ccohort_hydr%flc_min_ag(:) = (currentCohort%n*ccohort_hydr%flc_min_ag(:) + & + nextCohort%n*ncohort_hydr%flc_min_ag(:))/newn + ccohort_hydr%flc_min_troot(:) = (currentCohort%n*ccohort_hydr%flc_min_troot(:) + & + nextCohort%n*ncohort_hydr%flc_min_troot(:))/newn + ccohort_hydr%flc_min_aroot(:) = (currentCohort%n*ccohort_hydr%flc_min_aroot(:) + & + nextCohort%n*ncohort_hydr%flc_min_aroot(:))/newn + + ! need to be migrated to parmeter file (BOC 07/24/2018) + ccohort_hydr%refill_thresh = -0.01_r8 + ccohort_hydr%refill_days = 3.0_r8 + ccohort_hydr%errh2o = (currentCohort%n*ccohort_hydr%errh2o + & + nextCohort%n*ncohort_hydr%errh2o)/newn + ccohort_hydr%errh2o_growturn_ag(:) = (currentCohort%n*ccohort_hydr%errh2o_growturn_ag(:) + & + nextCohort%n*ncohort_hydr%errh2o_growturn_ag(:))/newn + ccohort_hydr%errh2o_pheno_ag(:) = (currentCohort%n*ccohort_hydr%errh2o_pheno_ag(:) + & + nextCohort%n*ncohort_hydr%errh2o_pheno_ag(:))/newn + ccohort_hydr%errh2o_growturn_troot(:) = (currentCohort%n*ccohort_hydr%errh2o_growturn_troot(:) + & + nextCohort%n*ncohort_hydr%errh2o_growturn_troot(:))/newn + ccohort_hydr%errh2o_pheno_troot(:) = (currentCohort%n*ccohort_hydr%errh2o_pheno_troot(:) + & + nextCohort%n*ncohort_hydr%errh2o_pheno_troot(:))/newn + ccohort_hydr%errh2o_growturn_aroot(:) = (currentCohort%n*ccohort_hydr%errh2o_growturn_aroot(:) + & + nextCohort%n*ncohort_hydr%errh2o_growturn_aroot(:))/newn + ccohort_hydr%errh2o_pheno_aroot(:) = (currentCohort%n*ccohort_hydr%errh2o_pheno_aroot(:) + & + nextCohort%n*ncohort_hydr%errh2o_pheno_aroot(:))/newn + + !ccohort_hydr%th_aroot_prev(:) + !ccohort_hydr%th_aroot_prev_uncorr(:) + + ccohort_hydr%is_newly_recuited = .false. end subroutine FuseCohortHydraulics @@ -895,6 +1026,7 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) ! ---------------------------------------------------------------------------------- use EDTypesMod, only : AREA + use EDTypesMod , only : dump_cohort ! Arguments integer, intent(in) :: nsites @@ -908,6 +1040,10 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) type(ed_site_hydr_type), pointer :: csite_hydr integer :: s real(r8) :: balive_patch + integer :: nstep !number of time steps + + !for debug only + nstep = get_nstep() do s = 1,nsites bc_out(s)%plant_stored_h2o_si = 0.0_r8 @@ -938,6 +1074,14 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & denh2o*currentCohort%n + + !if(nstep == 49) then ! .and. & + !(maxval(ccohort_hydr%errh2o_growturn_aroot(:)) > 1.0_r8 .or. & + ! minval(ccohort_hydr%errh2o_growturn_aroot(:)) < -1.0_r8)) then + !write(fates_log(),*)'ccohort_hydr%errh2o_growturn_aroot(:)', ccohort_hydr%errh2o_growturn_aroot(:) + !write(fates_log(),*)'ccohort_hydr%v_aroot_layer(:)', ccohort_hydr%v_aroot_layer(:) + !call dump_cohort(currentCohort) + !endif csite_hydr%h2oveg_growturn_err = & (sum(ccohort_hydr%errh2o_growturn_ag(:)*ccohort_hydr%v_ag(:)) + & sum(ccohort_hydr%errh2o_growturn_troot(:)*ccohort_hydr%v_troot(:)) + & @@ -959,6 +1103,13 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) csite_hydr%h2oveg_pheno_err end do + + !if(nstep == 49) then + !write(fates_log(),*)'csite_hydr%h2oveg', csite_hydr%h2oveg + !write(fates_log(),*)'csite_hydr%h2oveg_dead', csite_hydr%h2oveg_dead + !write(fates_log(),*)'csite_hydr%h2oveg_growturn_err', csite_hydr%h2oveg_growturn_err + !write(fates_log(),*)'csite_hydr%h2oveg_pheno_err', csite_hydr%h2oveg_pheno_err + !endif return end subroutine UpdateH2OVeg @@ -1533,6 +1684,8 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) !s ! !USES: use EDTypesMod , only : AREA + use FatesUtilsMod , only : check_var_real + use EDTypesMod , only : dump_cohort ! ARGUMENTS: ! ----------------------------------------------------------------------------------- @@ -1667,6 +1820,7 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) real(r8) :: rootfr ! root fraction at different soil layers type(ed_site_hydr_type), pointer :: site_hydr type(ed_cohort_hydr_type), pointer :: ccohort_hydr + integer :: err_code = 0 ! ---------------------------------------------------------------------------------- ! Important note: We are interested in calculating the total fluxes in and out of the @@ -1680,11 +1834,11 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) ! Input: [real(r8) (:,:,:)] soil matric potential (MPa) by layer and rhizosphere shell !for debug only - !nstep = get_nstep() + nstep = get_nstep() - !if(nstep == 837)then - ! write(fates_log(),*) 'debug' - !endif + if(nstep == 98)then + write(fates_log(),*) 'debug' + endif do s = 1, nsites @@ -2284,6 +2438,18 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) end if end do do j=1,site_hydr%nlevsoi_hyd + if(nstep == 98)then + !call check_var_real(ccohort_hydr%flc_min_aroot(j),'ccohort_hydr%flc_min_aroot(j)',err_code) + !if (err_code == 1 .or. err_code == 10 .or. err_code == 100) then + !write(fates_log(),*)'ccohort_hydr%flc_min_aroot(j)', ccohort_hydr%flc_min_aroot(j) + ! call dump_cohort(ccohort) + !end if + !call check_var_real(ccohort_hydr%flc_aroot(j),'ccohort_hydr%flc_aroot(j)',err_code) + !if (err_code == 1 .or. err_code == 10 .or. err_code == 100) then + !write(fates_log(),*)'ccohort_hydr%flc_aroot(j)', ccohort_hydr%flc_aroot(j) + ! call dump_cohort(ccohort) + !end if + endif ccohort_hydr%flc_min_aroot(j) = min(ccohort_hydr%flc_min_aroot(j), ccohort_hydr%flc_aroot(j)) if(ccohort_hydr%psi_aroot(j) >= ccohort_hydr%refill_thresh .and. & ccohort_hydr%flc_aroot(j) > ccohort_hydr%flc_min_aroot(j)) then ! then refilling From 3e9f81498e427f66e1ab8b095cf444bcbfdff9e8 Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Tue, 24 Jul 2018 16:33:27 -0600 Subject: [PATCH 03/53] added some hydraulics variables to dump_cohort(). Beware, there is no check for the hydraulics switch to be true, so will prob cause crash when hydraulics turned off --- main/EDTypesMod.F90 | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index 39573b8423..b1303b6f01 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -5,6 +5,7 @@ module EDTypesMod use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) use FatesHydraulicsMemMod, only : ed_cohort_hydr_type use FatesHydraulicsMemMod, only : ed_site_hydr_type + !use FatesInterfaceMod, only : hlm_use_planthydro implicit none save @@ -821,8 +822,34 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%cambial_mort = ', ccohort%cambial_mort write(fates_log(),*) 'co%size_class = ', ccohort%size_class write(fates_log(),*) 'co%size_by_pft_class = ', ccohort%size_by_pft_class + !if ( hlm_use_planthydro.eq.itrue ) then + ! call dump_cohort_hydr(ccohort) + !end if + write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', ccohort%co_hydr%th_aroot(:) + !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev(:) = ', ccohort%co_hydr%th_aroot_prev(:) + !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev_uncorr(:) = ', ccohort%co_hydr%th_aroot_prev_uncorr(:) + write(fates_log(),*) 'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort%co_hydr%v_aroot_layer_init(:) + write(fates_log(),*) 'ccohort_hydr%v_aroot_layer(:) = ', ccohort%co_hydr%v_aroot_layer(:) write(fates_log(),*) '----------------------------------------' return end subroutine dump_cohort + ! ===================================================================================== + + !subroutine dump_cohort_hydr(ccohort) +! +! + ! type(ed_cohort_type),intent(in),target :: ccohort + ! type(ed_cohort_hydr_type), pointer :: ccohort_hydr + ! ccohort_hydr => ccohort%co_hydr + + ! write(fates_log(),*) '--------------------------------------------' + ! write(fates_log(),*) ' Dumping Cohort Plant Hydraulic Information ' + ! write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', ccohort_hydr%th_aroot(:) + ! write(fates_log(),*) 'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort_hydr%v_aroot_layer_init(:) + ! write(fates_log(),*) 'ccohort_hydr%v_aroot_layer(:) = ', ccohort_hydr%v_aroot_layer(:) + ! write(fates_log(),*) '--------------------------------------------' + ! return + ! end subroutine dump_cohort_hydr + end module EDTypesMod From ded6cccb4cc14cb4b16dca7e164cb5af4de253ad Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Tue, 24 Jul 2018 16:35:31 -0600 Subject: [PATCH 04/53] shuffled order of a few cohort-level hydraulics variables, for visual ease of matching additions made to CopyCohortHydraulics --- main/FatesHydraulicsMemMod.F90 | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 4947e42c5b..ebe5d6f53e 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -197,8 +197,7 @@ module FatesHydraulicsMemMod real(r8) :: v_troot(n_hypool_troot) ! volume of belowground water storage compartments [m3] real(r8) :: v_aroot_tot ! total volume of absorbing roots [m3] real(r8) :: l_aroot_tot ! total length of absorbing roots [m] - - + ! quantities indexed by soil layer real(r8),allocatable :: z_node_aroot(:) ! nodal height of absorbing root water storage compartments [m] real(r8),allocatable :: kmax_treebg_layer(:) ! total belowground tree kmax partitioned by soil layer [kg s-1 MPa-1] real(r8),allocatable :: v_aroot_layer_init(:) ! previous day's volume of absorbing roots by soil layer [m3] @@ -208,9 +207,6 @@ module FatesHydraulicsMemMod ! BC PLANT HYDRAULICS - state variables real(r8) :: th_ag(n_hypool_ag) ! water in aboveground compartments [kgh2o/indiv] real(r8) :: th_troot(n_hypool_troot) ! water in belowground compartments [kgh2o/indiv] - real(r8) :: lwp_mem(numLWPmem) ! leaf water potential over the previous numLWPmem timesteps [MPa] - real(r8) :: lwp_stable ! leaf water potential just before it became unstable [MPa] - logical :: lwp_is_unstable ! flag for instability of leaf water potential over previous timesteps real(r8) :: psi_ag(n_hypool_ag) ! water potential in aboveground compartments [MPa] real(r8) :: psi_troot(n_hypool_troot) ! water potential in belowground compartments [MPa] real(r8) :: flc_ag(n_hypool_ag) ! fractional loss of conductivity in aboveground compartments [-] @@ -219,9 +215,14 @@ module FatesHydraulicsMemMod ! aboveground compartments (for tracking xylem refilling dynamics) [-] real(r8) :: flc_min_troot(n_hypool_troot) ! min attained fractional loss of conductivity in ! belowground compartments (for tracking xylem refilling dynamics) [-] + !refilling status--these are constants are should be moved the fates parameter file(Chonggang XU) real(r8) :: refill_thresh ! water potential threshold for xylem refilling to occur [MPa] real(r8) :: refill_days ! number of days required for 50% of xylem refilling to occur [days] real(r8) :: btran(nlevcan_hyd) ! leaf water potential limitation on gs [0-1] + + real(r8) :: lwp_mem(numLWPmem) ! leaf water potential over the previous numLWPmem timesteps [MPa] + real(r8) :: lwp_stable ! leaf water potential just before it became unstable [MPa] + logical :: lwp_is_unstable ! flag for instability of leaf water potential over previous timesteps real(r8) :: supsub_flag ! k index of last node to encounter supersaturation or ! sub-residual water content (+ supersaturation; - subsaturation) real(r8) :: iterh1 ! number of iterations required to achieve tolerable water balance error @@ -240,14 +241,16 @@ module FatesHydraulicsMemMod ! support production of new leaves. real(r8) :: errh2o_growturn_troot(n_hypool_troot) ! same as errh2o_growturn_ag but for troot pool real(r8) :: errh2o_pheno_troot(n_hypool_troot) ! same as errh2o_pheno_ag but for troot pool - real(r8),allocatable :: errh2o_growturn_aroot(:) ! same as errh2o_growturn_ag but for aroot pools - real(r8),allocatable :: errh2o_pheno_aroot(:) ! same as errh2o_pheno_ag but for aroot pools - + ! quantities indexed by soil layer real(r8),allocatable :: th_aroot(:) ! water in absorbing roots [kgh2o/indiv] + !real(r8),allocatable :: th_aroot_prev(:) ! water in absorbing roots, prev timestep (debug) [kgh2o/indiv] + !real(r8),allocatable :: th_aroot_prev_uncorr(:) ! water in absorbing roots, prev timestep, initial guess (debug) [kgh2o/indiv] real(r8),allocatable :: psi_aroot(:) ! water potential in absorbing roots [MPa] real(r8),allocatable :: flc_aroot(:) ! fractional loss of conductivity in absorbing roots [-] real(r8),allocatable :: flc_min_aroot(:) ! min attained fractional loss of conductivity in absorbing roots ! (for tracking xylem refilling dynamics) [-] + real(r8),allocatable :: errh2o_growturn_aroot(:) ! same as errh2o_growturn_ag but for aroot pools + real(r8),allocatable :: errh2o_pheno_aroot(:) ! same as errh2o_pheno_ag but for aroot pools ! BC PLANT HYDRAULICS - fluxes real(r8) :: qtop_dt ! transpiration boundary condition (+ to atm) [kg/indiv/timestep] @@ -289,6 +292,8 @@ subroutine AllocateHydrCohortArrays(this,nlevsoil_hydr) allocate(this%v_aroot_layer(1:nlevsoil_hydr)) allocate(this%l_aroot_layer(1:nlevsoil_hydr)) allocate(this%th_aroot(1:nlevsoil_hydr)) + !allocate(this%th_aroot_prev(1:nlevsoil_hydr)) + !allocate(this%th_aroot_prev_uncorr(1:nlevsoil_hydr)) allocate(this%psi_aroot(1:nlevsoil_hydr)) allocate(this%flc_aroot(1:nlevsoil_hydr)) allocate(this%flc_min_aroot(1:nlevsoil_hydr)) @@ -309,6 +314,8 @@ subroutine DeallocateHydrCohortArrays(this) deallocate(this%v_aroot_layer) deallocate(this%l_aroot_layer) deallocate(this%th_aroot) + !deallocate(this%th_aroot_prev) + !deallocate(this%th_aroot_prev_uncorr) deallocate(this%psi_aroot) deallocate(this%flc_aroot) deallocate(this%flc_min_aroot) From c8f8243e87e2e97b5ef0bb1a109b867ca58cab5f Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Fri, 3 Aug 2018 11:05:55 -0600 Subject: [PATCH 05/53] added numpft to InitHydraulicsDerived to enable initializing derived pft-specifc parameters; added back in original code for innermost rhiz shell kmax for testing purposes --- biogeophys/FatesPlantHydraulicsMod.F90 | 68 +++++++++++++++++--------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 3c99b4d99c..fdfd970408 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -127,6 +127,7 @@ module FatesPlantHydraulicsMod public :: updateSizeDepTreeHydStates public :: initTreeHydStates public :: updateSizeDepRhizHydProps + public :: updateSizeDepRhizHydStates !------------------------------------------------------------------------------ ! 01/18/16: Created by Brad Christoffersen @@ -887,11 +888,12 @@ end subroutine DeallocateHydrCohort ! ===================================================================================== - subroutine InitHydrSites(sites,bc_in) + subroutine InitHydrSites(sites,bc_in,numpft) ! Arguments type(ed_site_type),intent(inout),target :: sites(:) type(bc_in_type),intent(in) :: bc_in(:) + integer,intent(in) :: numpft ! Locals integer :: nsites @@ -902,7 +904,7 @@ subroutine InitHydrSites(sites,bc_in) if ( hlm_use_planthydro.eq.ifalse ) return ! Initialize any derived hydraulics parameters - call InitHydraulicsDerived() + call InitHydraulicsDerived(numpft) nsites = ubound(sites,1) do s=1,nsites @@ -1189,7 +1191,7 @@ subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) hksat_s = bc_in%hksat_sisl(j) * 1.e-3_r8 * 1/grav * 1.e6_r8 - ! proceed only if l_aroot_coh has changed + ! proceed only if the total absorbing root length (site-level) has changed in this layer if( csite_hydr%l_aroot_layer(j) /= csite_hydr%l_aroot_layer_init(j) ) then do k = 1,nshell @@ -1197,33 +1199,51 @@ subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) kmax_root_surf_total = kmax_root_surf*2._r8*pi_const *csite_hydr%rs1(j)* & csite_hydr%l_aroot_layer(j) if(csite_hydr%r_node_shell(j,k) <= csite_hydr%rs1(j)) then - csite_hydr%kmax_upper_shell(j,k) = kmax_root_surf_total - csite_hydr%kmax_bound_shell(j,k) = kmax_root_surf_total - csite_hydr%kmax_lower_shell(j,k) = kmax_root_surf_total + !csite_hydr%kmax_upper_shell(j,k) = kmax_root_surf_total + !csite_hydr%kmax_bound_shell(j,k) = kmax_root_surf_total + !csite_hydr%kmax_lower_shell(j,k) = kmax_root_surf_total + csite_hydr%kmax_upper_shell(j,k) = large_kmax_bound + csite_hydr%kmax_bound_shell(j,k) = large_kmax_bound + csite_hydr%kmax_lower_shell(j,k) = large_kmax_bound else kmax_soil_total = 2._r8*pi_const*csite_hydr%l_aroot_layer(j) / & log(csite_hydr%r_node_shell(j,k)/csite_hydr%rs1(j))*hksat_s - csite_hydr%kmax_upper_shell(j,k) = (1._r8/kmax_root_surf_total + & - 1._r8/kmax_soil_total)**-1._r8 - csite_hydr%kmax_bound_shell(j,k) = (1._r8/kmax_root_surf_total + & - 1._r8/kmax_soil_total)**-1._r8 - csite_hydr%kmax_lower_shell(j,k) = (1._r8/kmax_root_surf_total + & - 1._r8/kmax_soil_total)**-1._r8 + !csite_hydr%kmax_upper_shell(j,k) = (1._r8/kmax_root_surf_total + & + ! 1._r8/kmax_soil_total)**-1._r8 + !csite_hydr%kmax_bound_shell(j,k) = (1._r8/kmax_root_surf_total + & + ! 1._r8/kmax_soil_total)**-1._r8 + !csite_hydr%kmax_lower_shell(j,k) = (1._r8/kmax_root_surf_total + & + ! 1._r8/kmax_soil_total)**-1._r8 + csite_hydr%kmax_upper_shell(j,k) = 2._r8*pi_const*csite_hydr%l_aroot_layer(j) / & + log(csite_hydr%r_node_shell(j,k)/csite_hydr%rs1(j))*hksat_s + csite_hydr%kmax_bound_shell(j,k) = 2._r8*pi_const*csite_hydr%l_aroot_layer(j) / & + log(csite_hydr%r_node_shell(j,k)/csite_hydr%rs1(j))*hksat_s + csite_hydr%kmax_lower_shell(j,k) = 2._r8*pi_const*csite_hydr%l_aroot_layer(j) / & + log(csite_hydr%r_node_shell(j,k)/csite_hydr%rs1(j))*hksat_s end if if(j == 1) then if(csite_hydr%r_node_shell(j,k) <= csite_hydr%rs1(j)) then csite_hydr%kmax_upper_shell_1D(k) = kmax_root_surf_total csite_hydr%kmax_bound_shell_1D(k) = kmax_root_surf_total csite_hydr%kmax_lower_shell_1D(k) = kmax_root_surf_total + csite_hydr%kmax_upper_shell_1D(k) = large_kmax_bound + csite_hydr%kmax_bound_shell_1D(k) = large_kmax_bound + csite_hydr%kmax_lower_shell_1D(k) = large_kmax_bound else kmax_soil_total = 2._r8*pi_const*csite_hydr%l_aroot_1D / & log(csite_hydr%r_node_shell_1D(k)/csite_hydr%rs1(j))*hksat_s csite_hydr%kmax_upper_shell_1D(k) = (1._r8/kmax_root_surf_total + & - 1._r8/kmax_soil_total)**-1._r8 + 1._r8/kmax_soil_total)**-1._r8 csite_hydr%kmax_bound_shell_1D(k) = (1._r8/kmax_root_surf_total + & - 1._r8/kmax_soil_total)**-1._r8 + 1._r8/kmax_soil_total)**-1._r8 csite_hydr%kmax_lower_shell_1D(k) = (1._r8/kmax_root_surf_total + & - 1._r8/kmax_soil_total)**-1._r8 + 1._r8/kmax_soil_total)**-1._r8 + !csite_hydr%kmax_upper_shell_1D(k) = 2._r8*pi_const*csite_hydr%l_aroot_1D / & + ! log(csite_hydr%r_node_shell_1D(k)/csite_hydr%rs1(j))*hksat_s + !csite_hydr%kmax_bound_shell_1D(k) = 2._r8*pi_const*csite_hydr%l_aroot_1D / & + ! log(csite_hydr%r_node_shell_1D(k)/csite_hydr%rs1(j))*hksat_s + !csite_hydr%kmax_lower_shell_1D(k) = 2._r8*pi_const*csite_hydr%l_aroot_1D / & + ! log(csite_hydr%r_node_shell_1D(k)/csite_hydr%rs1(j))*hksat_s end if end if else @@ -1240,13 +1260,13 @@ subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) log(csite_hydr%r_node_shell_1D(k)/csite_hydr%r_node_shell_1D(k-1))*hksat_s csite_hydr%kmax_lower_shell_1D(k) = 2._r8*pi_const*csite_hydr%l_aroot_1D / & log(csite_hydr%r_out_shell_1D( k)/csite_hydr%r_node_shell_1D(k ))*hksat_s - end if - end if - enddo - end if !has l_aroot_layer changed? - enddo + end if + end if + enddo ! loop over rhizosphere shells + end if !has l_aroot_layer changed? + enddo ! loop over soil layers - end subroutine updateSizeDepRhizHydProps + end subroutine updateSizeDepRhizHydProps ! ================================================================================= @@ -2947,11 +2967,11 @@ subroutine Hydraulics_1DSolve(cc_p, ft, z_node, v_node, ths_node, thr_node, kmax !dump the error water to the bin with largest water storage max_l = maxloc(th_node(:)*v_node(:),dim=1) th_node(max_l) = th_node(max_l)- & - we_tot_outer/(v_node(max_l)*denh2o) + we_tot_outer/(v_node(max_l)*denh2o) th_node(max_l) = min (th_node(max_l),& - ths_node(max_l)-small_theta_num) + ths_node(max_l)-small_theta_num) th_node(max_l) = max(th_node(max_l),& - thr_node(max_l)+small_theta_num) + thr_node(max_l)+small_theta_num) w_tot_end_outer = sum(th_node(:)*v_node(:))*denh2o ! kg dw_tot_outer = w_tot_end_outer - w_tot_beg_outer ! kg/timestep we_tot_outer = dw_tot_outer + (qtop_dt + dqtopdth_dthdt) ! kg/timestep From 931ca5f6a1a7a2050400b6cc0f4d445638413dd5 Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Fri, 3 Aug 2018 11:08:45 -0600 Subject: [PATCH 06/53] uncommented call to updateSizeDepRhizHydStates --- main/EDMainMod.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main/EDMainMod.F90 b/main/EDMainMod.F90 index 817adf0850..98ff26526b 100644 --- a/main/EDMainMod.F90 +++ b/main/EDMainMod.F90 @@ -47,7 +47,7 @@ module EDMainMod use FatesPlantHydraulicsMod , only : initTreeHydStates use FatesPlantHydraulicsMod , only : updateSizeDepRhizHydProps use FatesAllometryMod , only : h_allom -! use FatesPlantHydraulicsMod , only : updateSizeDepRhizHydStates + use FatesPlantHydraulicsMod , only : updateSizeDepRhizHydStates use EDLoggingMortalityMod , only : IsItLoggingTime use FatesGlobals , only : endrun => fates_endrun use ChecksBalancesMod , only : SiteCarbonStock @@ -199,7 +199,7 @@ subroutine ed_ecosystem_dynamics(currentSite, bc_in) ! density --> node radii and volumes) if( (hlm_use_planthydro.eq.itrue) .and. do_growthrecruiteffects) then call updateSizeDepRhizHydProps(currentSite, bc_in) - ! call updateSizeDepRhizHydStates(currentSite, bc_in) + call updateSizeDepRhizHydStates(currentSite, bc_in) ! if(nshell > 1) then (THIS BEING CHECKED INSIDE OF the update) ! call updateSizeDepRhizHydStates(currentSite, c, soilstate_inst, & ! waterstate_inst) From 97a0dc67e46516fdc9c93645fe9fa6b38e92eac5 Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Fri, 3 Aug 2018 11:09:36 -0600 Subject: [PATCH 07/53] added soil water content by layer and rhizosphere shell, h2osoi_shsl. Hijacked the scagpft dimension (temporary measure) --- main/FatesHistoryInterfaceMod.F90 | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index e0d564a6dc..fdaf55b447 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -309,6 +309,7 @@ module FatesHistoryInterfaceMod integer, private :: ih_errh2o_scpf integer, private :: ih_tran_scpf integer, private :: ih_rootuptake_scpf + integer, private :: ih_h2osoi_si_scagpft ! hijacking the scagpft dimension instead of creating a new shsl dimension integer, private :: ih_rootuptake01_scpf integer, private :: ih_rootuptake02_scpf integer, private :: ih_rootuptake03_scpf @@ -2630,7 +2631,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) ed_patch_type, & AREA - use FatesHydraulicsMemMod, only : ed_cohort_hydr_type + use FatesHydraulicsMemMod, only : ed_cohort_hydr_type, nshell use EDTypesMod , only : maxpft @@ -2649,6 +2650,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) integer :: io_pa1 ! The first patch index in the IO array for each site integer :: ft ! functional type index integer :: scpf + integer :: io_shsl ! The combined "SH"ell "S"oil "L"ayer index in the IO array real(r8) :: n_density ! individual of cohort per m2. real(r8) :: n_perm2 ! individuals per m2 for the whole column real(r8), parameter :: tiny = 1.e-5_r8 ! some small number @@ -2658,6 +2660,8 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) real(r8) :: number_fraction_rate integer :: ipa2 ! patch incrementer integer :: iscpf ! index of the scpf group + integer :: j ! soil layer index + integer :: k ! rhizosphere shell index type(ed_patch_type),pointer :: cpatch type(ed_cohort_type),pointer :: ccohort @@ -2692,6 +2696,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) hio_rootuptake08_scpf => this%hvars(ih_rootuptake08_scpf)%r82d, & hio_rootuptake09_scpf => this%hvars(ih_rootuptake09_scpf)%r82d, & hio_rootuptake10_scpf => this%hvars(ih_rootuptake10_scpf)%r82d, & + hio_h2osoi_shsl => this%hvars(ih_h2osoi_si_scagpft)%r82d, & hio_sapflow_scpf => this%hvars(ih_sapflow_scpf)%r82d, & hio_iterh1_scpf => this%hvars(ih_iterh1_scpf)%r82d, & hio_iterh2_scpf => this%hvars(ih_iterh2_scpf)%r82d, & @@ -2942,6 +2947,14 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) cpatch => cpatch%younger end do !patch loop + io_shsl = 0 + do j=1,sites(s)%si_hydr%nlevsoi_hyd + do k=1, nshell + io_shsl = io_shsl + 1 + hio_h2osoi_shsl(io_si,io_shsl) = sites(s)%si_hydr%h2osoi_liqvol_shell(j,k) + end do + end do + if(hlm_use_ed_st3.eq.ifalse) then do scpf=1,nlevsclass*numpft if( abs(hio_nplant_si_scpf(io_si, scpf)-ncohort_scpf(scpf)) > 1.0E-8_r8 ) then @@ -4467,6 +4480,11 @@ subroutine define_history_vars(this, initialize_variables) avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=4, ivar=ivar, initialize=initialize_variables, index = ih_rootuptake10_scpf ) + call this%set_history_var(vname='FATES_H2OSOI_COL_SHSL', units='m3/m3', & + long='volumetric soil moisture by layer and shell', use_default='inactive', & + avgflag='A', vtype=site_scagpft_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=4, ivar=ivar, initialize=initialize_variables, index = ih_h2osoi_si_scagpft ) + call this%set_history_var(vname='FATES_SAPFLOW_COL_SCPF', units='kg/indiv/s', & long='individual sap flow rate', use_default='inactive', & avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & From 3cd6830d1750ceede5c1ba59ca8b50c38e77e70f Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Fri, 3 Aug 2018 11:13:31 -0600 Subject: [PATCH 08/53] added calculation of derived pinot pft-specific hydraulics parameter, but left commented out due to circular dependency issues with EDPftvarcon --- main/FatesHydraulicsMemMod.F90 | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index ebe5d6f53e..978faad747 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -372,9 +372,14 @@ end subroutine InitHydrSite ! =================================================================================== - subroutine InitHydraulicsDerived() + subroutine InitHydraulicsDerived(numpft) + + !use EDPftvarcon, only : EDPftvarcon_inst + ! Arguments + integer,intent(in) :: numpft integer :: k ! Pool counting index + integer :: ft do k = 1,n_porous_media @@ -388,6 +393,14 @@ subroutine InitHydraulicsDerived() cap_corr(k) = -cap_int(k)/cap_slp(k) end if end do + + do ft=1,numpft + ! this needs a -999 check (BOC) + !EDPftvarcon_inst%hydr_pinot_node(ft,:) = EDPftvarcon_inst%hydr_pitlp_node(ft,:) * & + ! EDPftvarcon_inst%hydr_epsil_node(ft,:) / & + ! (EDPftvarcon_inst%hydr_epsil_node(ft,:) - & + ! EDPftvarcon_inst%hydr_pitlp_node(ft,:)) + end do return end subroutine InitHydraulicsDerived From c5f2edf3446642553233984f08c4617575eb4f62 Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Tue, 7 Aug 2018 07:24:54 -0600 Subject: [PATCH 09/53] added call to new subroutine RecruitWaterStorage(), which calculates the amount of water in new recruits --- biogeochem/EDCanopyStructureMod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/biogeochem/EDCanopyStructureMod.F90 b/biogeochem/EDCanopyStructureMod.F90 index efdbfc6021..dfb7db5adf 100644 --- a/biogeochem/EDCanopyStructureMod.F90 +++ b/biogeochem/EDCanopyStructureMod.F90 @@ -24,7 +24,7 @@ module EDCanopyStructureMod use FatesInterfaceMod , only : hlm_days_per_year use FatesInterfaceMod , only : hlm_use_planthydro use FatesInterfaceMod , only : numpft - use FatesPlantHydraulicsMod, only : UpdateH2OVeg,InitHydrCohort + use FatesPlantHydraulicsMod, only : UpdateH2OVeg,InitHydrCohort, RecruitWaterStorage ! CIME Globals @@ -1698,6 +1698,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out) ! If hydraulics is turned on, update the amount of water bound in vegetation if (hlm_use_planthydro.eq.itrue) then + call RecruitWaterStorage(nsites,sites,bc_out) call UpdateH2OVeg(nsites,sites,bc_out) end if From 6be39955992f88245484929291791ccf6fdfeed1 Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Tue, 7 Aug 2018 07:26:52 -0600 Subject: [PATCH 10/53] added subroutine RecruitWaterStorage which caluclates site-level amount of water in new recruits. Subtract this from bc_out%plant_stored_h2o_si in UpdateH2OVeg call only. --- biogeophys/FatesPlantHydraulicsMod.F90 | 64 ++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index fdfd970408..99f9b86374 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -114,6 +114,7 @@ module FatesPlantHydraulicsMod ! ! !PUBLIC MEMBER FUNCTIONS: public :: AccumulateMortalityWaterStorage + public :: RecruitWaterStorage public :: hydraulics_drive public :: InitHydrSites public :: HydrSiteColdStart @@ -1084,7 +1085,7 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) !write(fates_log(),*)'ccohort_hydr%v_aroot_layer(:)', ccohort_hydr%v_aroot_layer(:) !call dump_cohort(currentCohort) !endif - csite_hydr%h2oveg_growturn_err = & + csite_hydr%h2oveg_growturn_err = csite_hydr%h2oveg_growturn_err + & (sum(ccohort_hydr%errh2o_growturn_ag(:)*ccohort_hydr%v_ag(:)) + & sum(ccohort_hydr%errh2o_growturn_troot(:)*ccohort_hydr%v_troot(:)) + & sum(ccohort_hydr%errh2o_growturn_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & @@ -1101,6 +1102,7 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) ! Note that h2oveg_dead is incremented wherever we have litter fluxes ! and it will be reduced via an evaporation term bc_out(s)%plant_stored_h2o_si = csite_hydr%h2oveg + csite_hydr%h2oveg_dead - & + csite_hydr%h2oveg_recruit - & csite_hydr%h2oveg_growturn_err - & csite_hydr%h2oveg_pheno_err @@ -1542,8 +1544,8 @@ subroutine FillDrainRhizShells(nsites, sites, bc_in, bc_out) ! The approach used is heuristic, but based on the principle that water ! fluxing out of a layer will preferentially come from rhizosphere ! shells with higher water contents/potentials within that layer, and - ! alternatively, that water fluxing into a layer will preferentially come - ! from shells with lower water contents/potentials. + ! alternatively, that water fluxing into a layer will preferentially go + ! into shells with lower water contents/potentials. ! ! This principle is implemented by filling (draining) the rhizosphere ! shells in order from the driest (wettest) shell to the wettest (driest). @@ -2635,9 +2637,65 @@ subroutine AccumulateMortalityWaterStorage(csite,ccohort,delta_n) return end subroutine AccumulateMortalityWaterStorage + !-------------------------------------------------------------------------------! + subroutine RecruitWaterStorage(nsites,sites,bc_out) + + ! --------------------------------------------------------------------------- + ! This subroutine accounts for the water bound in plants that have + ! just recruited. This water is accumulated at the site level for all plants + ! that recruit. + ! Because this water is taken from the soil in hydraulics_bc, which will not + ! be called until the next timestep, this water is subtracted out of + ! plant_stored_h2o_si to ensure HLM water balance at the beg_curr_day timestep. + ! plant_stored_h2o_si will include this water when calculated in hydraulics_bc + ! at the next timestep, when it gets pulled from the soil water. + ! --------------------------------------------------------------------------- + use EDTypesMod, only : AREA + + ! Arguments + integer, intent(in) :: nsites + type(ed_site_type), intent(inout), target :: sites(nsites) + type(bc_out_type), intent(inout) :: bc_out(nsites) + + ! Locals + type(ed_cohort_type), pointer :: currentCohort + type(ed_patch_type), pointer :: currentPatch + type(ed_cohort_hydr_type), pointer :: ccohort_hydr + type(ed_site_hydr_type), pointer :: csite_hydr + integer :: s + if( hlm_use_planthydro.eq.ifalse ) return + do s = 1,nsites + + csite_hydr => sites(s)%si_hydr + csite_hydr%h2oveg_recruit = 0.0_r8 + currentPatch => sites(s)%oldest_patch + do while(associated(currentPatch)) + currentCohort=>currentPatch%tallest + do while(associated(currentCohort)) + ccohort_hydr => currentCohort%co_hydr + if(ccohort_hydr%is_newly_recuited) then + csite_hydr%h2oveg_recruit = csite_hydr%h2oveg_recruit + & + (sum(ccohort_hydr%th_ag(:)*ccohort_hydr%v_ag(:)) + & + sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & + sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & + denh2o*currentCohort%n + end if + currentCohort => currentCohort%shorter + enddo !cohort + currentPatch => currentPatch%younger + enddo !end patch loop + + csite_hydr%h2oveg_recruit = csite_hydr%h2oveg_recruit / AREA + + end do + + return + end subroutine RecruitWaterStorage + + !-------------------------------------------------------------------------------! subroutine Hydraulics_1DSolve(cc_p, ft, z_node, v_node, ths_node, thr_node, kmax_bound, & From 257c1e4a81ce2d4cdb403e9d817104bf91dffec0 Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Tue, 7 Aug 2018 07:28:20 -0600 Subject: [PATCH 11/53] added H2OVEG_RECRUIT as a history output variable --- main/FatesHistoryInterfaceMod.F90 | 46 +++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index fdaf55b447..f78d6a3190 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -145,6 +145,11 @@ module FatesHistoryInterfaceMod integer, private :: ih_froot_mr_si integer, private :: ih_livestem_mr_si integer, private :: ih_livecroot_mr_si + integer, private :: ih_h2oveg_si + integer, private :: ih_h2oveg_dead_si + integer, private :: ih_h2oveg_recruit_si + integer, private :: ih_h2oveg_growturn_err_si + integer, private :: ih_h2oveg_pheno_err_si ! Indices to (site x scpf) variables integer, private :: ih_nplant_si_scpf @@ -1494,7 +1499,11 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_ddbh_canopy_si_scag => this%hvars(ih_ddbh_canopy_si_scag)%r82d, & hio_ddbh_understory_si_scag => this%hvars(ih_ddbh_understory_si_scag)%r82d, & hio_mortality_canopy_si_scag => this%hvars(ih_mortality_canopy_si_scag)%r82d, & - hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d) + hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d, & + hio_h2oveg_dead_si => this%hvars(ih_h2oveg_dead_si)%r81d, & + hio_h2oveg_recruit_si => this%hvars(ih_h2oveg_recruit_si)%r81d, & + hio_h2oveg_growturn_err_si => this%hvars(ih_h2oveg_growturn_err_si)%r81d, & + hio_h2oveg_pheno_err_si => this%hvars(ih_h2oveg_pheno_err_si)%r81d) ! --------------------------------------------------------------------------------- @@ -2179,6 +2188,11 @@ subroutine update_history_dyn(this,nc,nsites,sites) sites(s)%leaf_litter_diagnostic_input_carbonflux(:) = 0._r8 sites(s)%root_litter_diagnostic_input_carbonflux(:) = 0._r8 + hio_h2oveg_dead_si(io_si) = sites(s)%si_hydr%h2oveg_dead + hio_h2oveg_recruit_si(io_si) = sites(s)%si_hydr%h2oveg_recruit + hio_h2oveg_growturn_err_si(io_si) = sites(s)%si_hydr%h2oveg_growturn_err + hio_h2oveg_pheno_err_si(io_si) = sites(s)%si_hydr%h2oveg_pheno_err + enddo ! site loop end associate @@ -2610,7 +2624,7 @@ subroutine update_history_prod(this,nc,nsites,sites,dt_tstep) hio_c_stomata_si(io_si) = 0._r8 hio_c_lblayer_si(io_si) = 0._r8 end if - + enddo ! site loop end associate @@ -2713,6 +2727,7 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) hio_sflc_scpf => this%hvars(ih_sflc_scpf)%r82d, & hio_lflc_scpf => this%hvars(ih_lflc_scpf)%r82d, & hio_btran_scpf => this%hvars(ih_btran_scpf)%r82d, & + hio_h2oveg_si => this%hvars(ih_h2oveg_si)%r81d, & hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d ) ! Flush the relevant history variables @@ -2964,6 +2979,8 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) end do end if + hio_h2oveg_si(io_si) = sites(s)%si_hydr%h2oveg + enddo ! site loop end associate @@ -4572,6 +4589,31 @@ subroutine define_history_vars(this, initialize_variables) ! avgflag='A', vtype=site_size_pft_r8, hlms='CLM:ALM', flushval=0.0_r8, & ! upfreq=4, ivar=ivar, initialize=initialize_variables, index = ih_laroot_scpf) + call this%set_history_var(vname='H2OVEG', units = 'kg/m2', & + long='water stored inside vegetation tissues (leaf, stem, roots)', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=4, ivar=ivar, initialize=initialize_variables, index = ih_h2oveg_si ) + + call this%set_history_var(vname='H2OVEG_DEAD', units = 'kg/m2', & + long='cumulative plant_stored_h2o in dead biomass due to mortality', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_h2oveg_dead_si ) + + call this%set_history_var(vname='H2OVEG_RECRUIT', units = 'kg/m2', & + long='amount of water in new recruits', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_h2oveg_recruit_si ) + + call this%set_history_var(vname='H2OVEG_GROWTURN_ERR', units = 'kg/m2', & + long='cumulative net borrowed (+) or lost (-) from plant_stored_h2o due to combined growth & turnover', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_h2oveg_growturn_err_si ) + + call this%set_history_var(vname='H2OVEG_PHENO_ERR', units = 'kg/m2', & + long='cumulative net borrowed (+) from plant_stored_h2o due to leaf emergence', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_h2oveg_pheno_err_si ) + end if ! Must be last thing before return From 9134ac4510aba6c060fc8699ea5d5e110fca5e1c Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Tue, 7 Aug 2018 07:29:01 -0600 Subject: [PATCH 12/53] added site-level variable h2oveg_recruit --- main/FatesHydraulicsMemMod.F90 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 978faad747..a761f74b02 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -138,15 +138,16 @@ module FatesHydraulicsMemMod ! column level (kg) real(r8) :: h2oveg ! stored water in vegetation (kg/m2) + real(r8) :: h2oveg_recruit ! stored water in recruits (kg/m2) real(r8) :: h2oveg_dead ! stored water in dead vegetation (kg/m2) - real(r8) :: h2oveg_growturn_err ! error water pool for increase (growth) or + real(r8) :: h2oveg_growturn_err ! error water pool (kg/m2) for increase (growth) or ! contraction (turnover) of tissue volumes. ! Draw from or add to this pool when ! insufficient water available to increase ! tissue volume or too much water is ! available when tissue volume decreases, ! respectively. - real(r8) :: h2oveg_pheno_err ! error water pool for leaf-on + real(r8) :: h2oveg_pheno_err ! error water pool (kg/m2) for leaf-on ! Draw from or add to this pool when ! insufficient plant water available to ! support production of new leaves. @@ -361,6 +362,7 @@ subroutine InitHydrSite(this) this%errh2o_hyd = nan this%dwat_veg = nan this%h2oveg = nan + this%h2oveg_recruit = 0.0_r8 this%h2oveg_dead = 0.0_r8 this%h2oveg_growturn_err = 0.0_r8 this%h2oveg_pheno_err = 0.0_r8 From a8481ea0f0b0c0c2b6968d1bd32bd8bc90466c92 Mon Sep 17 00:00:00 2001 From: Bradley O'Donnell Christoffersen Date: Thu, 18 Oct 2018 20:34:32 -0600 Subject: [PATCH 13/53] adds a call to AccumulateMortalityWaterStorage from within terminate_cohorts and fixes a bug elsewhere in a call to this subroutine --- biogeochem/EDCohortDynamicsMod.F90 | 5 ++++- biogeochem/EDPhysiologyMod.F90 | 4 +++- biogeophys/FatesPlantHydraulicsMod.F90 | 8 +++++--- main/FatesHydraulicsMemMod.F90 | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index e102495a4e..45696d185d 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -8,6 +8,7 @@ module EDCohortDynamicsMod use FatesGlobals , only : fates_log use FatesInterfaceMod , only : hlm_freq_day use FatesInterfaceMod , only : bc_in_type + use FatesInterfaceMod , only : hlm_use_planthydro use FatesConstantsMod , only : r8 => fates_r8 use FatesConstantsMod , only : fates_unset_int use FatesConstantsMod , only : itrue,ifalse @@ -498,7 +499,9 @@ subroutine terminate_cohorts( currentSite, currentPatch, level ) currentSite%termination_carbonflux(levcan) = currentSite%termination_carbonflux(levcan) + & currentCohort%n * currentCohort%b_total() - + if( hlm_use_planthydro == itrue ) then + call AccumulateMortalityWaterStorage(currentSite,currentCohort,currentCohort%n) + end if !put the litter from the terminated cohorts straight into the fragmenting pools if (currentCohort%n.gt.0.0_r8) then diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 0065031905..8710ae7d83 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1810,7 +1810,9 @@ subroutine CWD_Input( currentSite, currentPatch) hlm_freq_day * currentPatch%area if( hlm_use_planthydro == itrue ) then - call AccumulateMortalityWaterStorage(currentSite,currentCohort,dead_n) + !call AccumulateMortalityWaterStorage(currentSite,currentCohort,dead_n) + call AccumulateMortalityWaterStorage(currentSite,currentCohort,& + -1.0_r8 * currentCohort%dndt * hlm_freq_day) end if diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 99f9b86374..98c64306d7 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -1870,7 +1870,7 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) dth_layershell_col(:,:) = 0._r8 site_hydr%dwat_veg = 0._r8 site_hydr%errh2o_hyd = 0._r8 - site_hydr%recruit_w_uptake = 0._r8 + site_hydr%recruit_w_uptake(:) = 0._r8 ncoh_col = 0 ! Calculate the mean site level transpiration flux @@ -2537,7 +2537,8 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) bc_out(s)%qflx_soil2root_sisl(bc_in(s)%nlevsoil) = & -(sum(dth_layershell_col(j,:)*site_hydr%v_shell_1D(:)) * & - site_hydr%l_aroot_1D/bc_in(s)%dz_sisl(j)/AREA*denh2o/dtime)- & + !site_hydr%l_aroot_1D/bc_in(s)%dz_sisl(j)/AREA*denh2o/dtime)- & !BOC(10/02/2018)...error - should be plus + site_hydr%l_aroot_1D/bc_in(s)%dz_sisl(j)/AREA*denh2o/dtime)+ & site_hydr%recruit_w_uptake(site_hydr%nlevsoi_hyd) ! h2osoi_liqvol = min(bc_in(s)%eff_porosity_sl(bc_in(s)%nlevsoil), & @@ -2551,7 +2552,8 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) !qflx_rootsoi(c,j) = -(sum(dth_layershell_col(j,:))*bc_in(s)%dz_sisl(j)*denh2o/dtime) bc_out(s)%qflx_soil2root_sisl(j) = & -(sum(dth_layershell_col(j,:)*site_hydr%v_shell(j,:)) * & - site_hydr%l_aroot_layer(j)/bc_in(s)%dz_sisl(j)/AREA*denh2o/dtime)- & + !site_hydr%l_aroot_layer(j)/bc_in(s)%dz_sisl(j)/AREA*denh2o/dtime)- & !BOC(10/02/2018)...error - should be plus + site_hydr%l_aroot_layer(j)/bc_in(s)%dz_sisl(j)/AREA*denh2o/dtime)+ & site_hydr%recruit_w_uptake(j) ! h2osoi_liqvol = min(bc_in(s)%eff_porosity_sl(j), & diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index a761f74b02..ad28b8deb2 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -361,7 +361,7 @@ subroutine InitHydrSite(this) this%l_aroot_1D = nan this%errh2o_hyd = nan this%dwat_veg = nan - this%h2oveg = nan + this%h2oveg = 0.0_r8 this%h2oveg_recruit = 0.0_r8 this%h2oveg_dead = 0.0_r8 this%h2oveg_growturn_err = 0.0_r8 From eb5d4cbf471eaf37b3807cc412052b5f68f3b115 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Tue, 6 Nov 2018 12:14:34 -0700 Subject: [PATCH 14/53] update the recruit water uptake,veg water storage and a typo correction --- biogeochem/EDCohortDynamicsMod.F90 | 2 +- biogeophys/FatesPlantHydraulicsMod.F90 | 172 ++++++++++++++----------- main/FatesHydraulicsMemMod.F90 | 2 +- 3 files changed, 100 insertions(+), 76 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 45696d185d..0d1881d99f 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -189,7 +189,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, dbh, bleaf, bfine call updateSizeDepTreeHydProps(CurrentSite,new_cohort, bc_in) call initTreeHydStates(CurrentSite,new_cohort, bc_in) if(recruitstatus==1)then - new_cohort%co_hydr%is_newly_recuited = .true. + new_cohort%co_hydr%is_newly_recruited = .true. endif endif diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 98c64306d7..36b7a6bc2f 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -732,7 +732,7 @@ subroutine CopyCohortHydraulics(newCohort, oldCohort) ncohort_hydr%rootuptake09 = ocohort_hydr%rootuptake09 ncohort_hydr%rootuptake10 = ocohort_hydr%rootuptake10 - ncohort_hydr%is_newly_recuited = ocohort_hydr%is_newly_recuited + ncohort_hydr%is_newly_recruited = ocohort_hydr%is_newly_recruited end subroutine CopyCohortHydraulics @@ -849,7 +849,7 @@ subroutine FuseCohortHydraulics(currentSite,currentCohort, nextCohort, bc_in, ne !ccohort_hydr%th_aroot_prev(:) !ccohort_hydr%th_aroot_prev_uncorr(:) - ccohort_hydr%is_newly_recuited = .false. + ccohort_hydr%is_newly_recruited = .false. end subroutine FuseCohortHydraulics @@ -867,7 +867,7 @@ subroutine InitHydrCohort(currentSite,currentCohort) allocate(ccohort_hydr) currentCohort%co_hydr => ccohort_hydr call ccohort_hydr%AllocateHydrCohortArrays(currentSite%si_hydr%nlevsoi_hyd) - ccohort_hydr%is_newly_recuited = .false. + ccohort_hydr%is_newly_recruited = .false. end subroutine InitHydrCohort @@ -1029,7 +1029,7 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) ! ---------------------------------------------------------------------------------- use EDTypesMod, only : AREA - use EDTypesMod , only : dump_cohort + use EDTypesMod , only : dump_cohort ! Arguments integer, intent(in) :: nsites @@ -1072,24 +1072,20 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) currentCohort=>currentPatch%tallest do while(associated(currentCohort)) ccohort_hydr => currentCohort%co_hydr - csite_hydr%h2oveg = csite_hydr%h2oveg + & + !only account for the water for not newly recruit for mass balance + if(.not.ccohort_hydr%is_newly_recruited) then + csite_hydr%h2oveg = csite_hydr%h2oveg + & (sum(ccohort_hydr%th_ag(:)*ccohort_hydr%v_ag(:)) + & sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & denh2o*currentCohort%n - !if(nstep == 49) then ! .and. & - !(maxval(ccohort_hydr%errh2o_growturn_aroot(:)) > 1.0_r8 .or. & - ! minval(ccohort_hydr%errh2o_growturn_aroot(:)) < -1.0_r8)) then - !write(fates_log(),*)'ccohort_hydr%errh2o_growturn_aroot(:)', ccohort_hydr%errh2o_growturn_aroot(:) - !write(fates_log(),*)'ccohort_hydr%v_aroot_layer(:)', ccohort_hydr%v_aroot_layer(:) - !call dump_cohort(currentCohort) - !endif - csite_hydr%h2oveg_growturn_err = csite_hydr%h2oveg_growturn_err + & + csite_hydr%h2oveg_growturn_err = csite_hydr%h2oveg_growturn_err + & (sum(ccohort_hydr%errh2o_growturn_ag(:)*ccohort_hydr%v_ag(:)) + & sum(ccohort_hydr%errh2o_growturn_troot(:)*ccohort_hydr%v_troot(:)) + & sum(ccohort_hydr%errh2o_growturn_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & denh2o*currentCohort%n + endif currentCohort => currentCohort%shorter enddo !cohort @@ -1101,22 +1097,88 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) ! Note that h2oveg_dead is incremented wherever we have litter fluxes ! and it will be reduced via an evaporation term + ! growturn_err is a term to accomodate error in growth or turnover. need to be improved for future(CX) bc_out(s)%plant_stored_h2o_si = csite_hydr%h2oveg + csite_hydr%h2oveg_dead - & - csite_hydr%h2oveg_recruit - & csite_hydr%h2oveg_growturn_err - & csite_hydr%h2oveg_pheno_err end do - !if(nstep == 49) then - !write(fates_log(),*)'csite_hydr%h2oveg', csite_hydr%h2oveg - !write(fates_log(),*)'csite_hydr%h2oveg_dead', csite_hydr%h2oveg_dead - !write(fates_log(),*)'csite_hydr%h2oveg_growturn_err', csite_hydr%h2oveg_growturn_err - !write(fates_log(),*)'csite_hydr%h2oveg_pheno_err', csite_hydr%h2oveg_pheno_err - !endif - + return end subroutine UpdateH2OVeg + + !===================================================================================== + subroutine RecruitWUptake(nsites,sites,bc_in,dtime) + + ! ---------------------------------------------------------------------------------- + ! This subroutine is called to caluate the water requirement for newly recruited cohorts + ! The water update is allocated proportionally to the root biomass, which could be updated + ! to accomodate the soil moisture and rooting depth for small seedlings (Chonggang XU). + ! After the root water uptake, is_newly_recruited flag is set to false. + ! ---------------------------------------------------------------------------------- + + use EDTypesMod, only : AREA + ! Arguments + integer, intent(in) :: nsites + type(ed_site_type), intent(inout), target :: sites(nsites) + type(bc_in_type), intent(in) :: bc_in(nsites) + real(r8), intent(in) :: dtime !time (seconds) + + ! Locals + type(ed_cohort_type), pointer :: currentCohort + type(ed_patch_type), pointer :: currentPatch + type(ed_cohort_hydr_type), pointer :: ccohort_hydr + type(ed_site_hydr_type), pointer :: csite_hydr + integer :: s, j, ft + integer :: nstep !number of time steps + real(r8) :: roota !root distriubiton parameter a + real(r8) :: rootb !root distriubiton parameter b + real(r8) :: rootfr !fraction of root in different soil layer + real(r8) :: recruitw !water for newly recruited cohorts (kg water/m2/s) + + do s = 1,nsites + csite_hydr => sites(s)%si_hydr + csite_hydr%recruit_w_uptake = 0.0_r8 + currentPatch => sites(s)%oldest_patch + do while(associated(currentPatch)) + currentCohort=>currentPatch%tallest + do while(associated(currentCohort)) + ccohort_hydr => currentCohort%co_hydr + ft = currentCohort%pft + !----------------------------------------------------------- + ! recruitment water uptake + if(ccohort_hydr%is_newly_recruited) then + roota = EDPftvarcon_inst%roota_par(ft) + rootb = EDPftvarcon_inst%rootb_par(ft) + recruitw = (sum(ccohort_hydr%th_ag(:)*ccohort_hydr%v_ag(:)) + & + sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & + sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & + denh2o*currentCohort%n/AREA/dtime + if( csite_hydr%nlevsoi_hyd == 1) then + csite_hydr%recruit_w_uptake(1) = csite_hydr%recruit_w_uptake(1)+ & + recruitw + else + do j=1,csite_hydr%nlevsoi_hyd + if(j == 1) then + rootfr = zeng2001_crootfr(roota, rootb, bc_in(s)%zi_sisl(j)) + else + rootfr = zeng2001_crootfr(roota, rootb, bc_in(s)%zi_sisl(j)) - & + zeng2001_crootfr(roota, rootb, bc_in(s)%zi_sisl(j-1)) + end if + csite_hydr%recruit_w_uptake(j) = csite_hydr%recruit_w_uptake(j) + & + recruitw*rootfr + end do + end if + ccohort_hydr%is_newly_recruited = .false. + endif + currentCohort=>currentCohort%shorter + end do !cohort loop + currentPatch => currentPatch%younger + end do !patch + end do ! site loop + + end subroutine RecruitWUptake ! ===================================================================================== @@ -1272,7 +1334,7 @@ end subroutine updateSizeDepRhizHydProps ! ================================================================================= - subroutine updateSizeDepRhizHydStates(currentSite, bc_in) + subroutine updateSizeDepRhizHydStates(currentSite, bc_in) ! ! !DESCRIPTION: Updates size of 'representative' rhizosphere -- node radii, volumes. ! As fine root biomass (and thus absorbing root length) increases, this characteristic @@ -1481,13 +1543,13 @@ subroutine updateSizeDepRhizHydStates(currentSite, bc_in) end if end if enddo - end if !nshell > 1 + end if !nshell > 1 -end subroutine updateSizeDepRhizHydStates + end subroutine updateSizeDepRhizHydStates - ! ==================================================================================== - subroutine BTranForHLMDiagnosticsFromCohortHydr(nsites,sites,bc_out) + ! ==================================================================================== + subroutine BTranForHLMDiagnosticsFromCohortHydr(nsites,sites,bc_out) ! Arguments integer,intent(in) :: nsites @@ -1827,9 +1889,8 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) ! as it regards the fraction of canopy area as the relevant ! area, and assumes that the HLM has it's own patch ! that is not tracked by FATES which accounts for all - ! non-canopy areas across all patches - - real(r8) :: recruitw !water uptake due to recruitment (kg/m2/s) + ! non-canopy areas across all patches + real(r8) :: smp ! temporary for matric potential (MPa) integer :: tmp real(r8) :: tmp1 @@ -1842,7 +1903,7 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) real(r8) :: rootfr ! root fraction at different soil layers type(ed_site_hydr_type), pointer :: site_hydr type(ed_cohort_hydr_type), pointer :: ccohort_hydr - integer :: err_code = 0 + integer :: err_code = 0 ! ---------------------------------------------------------------------------------- ! Important note: We are interested in calculating the total fluxes in and out of the @@ -1856,11 +1917,13 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) ! Input: [real(r8) (:,:,:)] soil matric potential (MPa) by layer and rhizosphere shell !for debug only - nstep = get_nstep() + !nstep = get_nstep() - if(nstep == 98)then - write(fates_log(),*) 'debug' - endif + !For newly recruited cohorts, add the water uptake demand to csite_hydr%recruit_w_uptake + call RecruitWUptake(nsites,sites,bc_in,dtime) + + !update water storage in veg after incorporating newly recuited cohorts + call UpdateH2OVeg(nsites,sites,bc_out) do s = 1, nsites @@ -1870,7 +1933,6 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) dth_layershell_col(:,:) = 0._r8 site_hydr%dwat_veg = 0._r8 site_hydr%errh2o_hyd = 0._r8 - site_hydr%recruit_w_uptake(:) = 0._r8 ncoh_col = 0 ! Calculate the mean site level transpiration flux @@ -1936,32 +1998,6 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) ccohort_hydr%dqtopdth_dthdt = 0._r8 ccohort_hydr%sapflow = 0._r8 ccohort_hydr%rootuptake = 0._r8 - !----------------------------------------------------------- - ! recruitment water uptake - if(ccohort_hydr%is_newly_recuited) then - roota = EDPftvarcon_inst%roota_par(ft) - rootb = EDPftvarcon_inst%rootb_par(ft) - recruitw = (sum(ccohort_hydr%th_ag(:)*ccohort_hydr%v_ag(:)) + & - sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & - sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & - denh2o*ccohort%n/AREA/dtime - if( site_hydr%nlevsoi_hyd == 1) then - site_hydr%recruit_w_uptake(1) = site_hydr%recruit_w_uptake(1)+ & - recruitw - else - do j=1,site_hydr%nlevsoi_hyd - if(j == 1) then - rootfr = zeng2001_crootfr(roota, rootb, bc_in(s)%zi_sisl(j)) - else - rootfr = zeng2001_crootfr(roota, rootb, bc_in(s)%zi_sisl(j)) - & - zeng2001_crootfr(roota, rootb, bc_in(s)%zi_sisl(j-1)) - end if - site_hydr%recruit_w_uptake(j) = site_hydr%recruit_w_uptake(j) + & - recruitw*rootfr - end do - end if - ccohort_hydr%is_newly_recuited = .false. - endif ! Relative transpiration of this cohort from the whole patch !! qflx_rel_tran_coh = ccohort%g_sb_laweight/gscan_patch @@ -2460,18 +2496,6 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) end if end do do j=1,site_hydr%nlevsoi_hyd - if(nstep == 98)then - !call check_var_real(ccohort_hydr%flc_min_aroot(j),'ccohort_hydr%flc_min_aroot(j)',err_code) - !if (err_code == 1 .or. err_code == 10 .or. err_code == 100) then - !write(fates_log(),*)'ccohort_hydr%flc_min_aroot(j)', ccohort_hydr%flc_min_aroot(j) - ! call dump_cohort(ccohort) - !end if - !call check_var_real(ccohort_hydr%flc_aroot(j),'ccohort_hydr%flc_aroot(j)',err_code) - !if (err_code == 1 .or. err_code == 10 .or. err_code == 100) then - !write(fates_log(),*)'ccohort_hydr%flc_aroot(j)', ccohort_hydr%flc_aroot(j) - ! call dump_cohort(ccohort) - !end if - endif ccohort_hydr%flc_min_aroot(j) = min(ccohort_hydr%flc_min_aroot(j), ccohort_hydr%flc_aroot(j)) if(ccohort_hydr%psi_aroot(j) >= ccohort_hydr%refill_thresh .and. & ccohort_hydr%flc_aroot(j) > ccohort_hydr%flc_min_aroot(j)) then ! then refilling @@ -2678,7 +2702,7 @@ subroutine RecruitWaterStorage(nsites,sites,bc_out) currentCohort=>currentPatch%tallest do while(associated(currentCohort)) ccohort_hydr => currentCohort%co_hydr - if(ccohort_hydr%is_newly_recuited) then + if(ccohort_hydr%is_newly_recruited) then csite_hydr%h2oveg_recruit = csite_hydr%h2oveg_recruit + & (sum(ccohort_hydr%th_ag(:)*ccohort_hydr%v_ag(:)) + & sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index ad28b8deb2..a1d2fbfd71 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -270,7 +270,7 @@ module FatesHydraulicsMemMod real(r8) :: rootuptake09 ! net flow into roots (+ into roots), soil layer 9 [kg/indiv/timestep] real(r8) :: rootuptake10 ! net flow into roots (+ into roots), soil layer 10 [kg/indiv/timestep] ! BC PLANT HYDRAULICS - flags - logical :: is_newly_recuited !whether the new cohort is newly recuited + logical :: is_newly_recruited !whether the new cohort is newly recruited contains From 0a96285f8cfb7d74c8de804061be161f9e22110b Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Tue, 6 Nov 2018 13:37:29 -0700 Subject: [PATCH 15/53] update the HYDRO warning --- biogeophys/FatesPlantHydraulicsMod.F90 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index d979845bd8..8773420e49 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -15,8 +15,7 @@ module FatesPlantHydraulicsMod ! ! WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ! - ! PLANT HYDRAULICS IS AN EXPERIMENTAL OPTION THAT IS STILL UNDERGOING TESTING. THERE IS - ! ABSOLUTELY NO SUPPORT ON THIS FEATURE FOR THE TIME BEING> + ! PLANT HYDRAULICS IS AN EXPERIMENTAL OPTION THAT IS STILL UNDERGOING TESTING. ! ! WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING ! @@ -1564,7 +1563,7 @@ subroutine updateSizeDepRhizHydStates(currentSite, bc_in) do j = 1,csite_hydr%nlevsoi_hyd ! BOC: PLEASE CHECK UNITS ON h2o_liq_sisl(j) (RGK) errh2o(j) = h2osoi_liq_col_new(j) - bc_in%h2o_liq_sisl(j) - if (abs(errh2o(j)) > 1.e-9_r8) then + if (abs(errh2o(j)) > 1.e-4_r8) then found = .true. indexj = j if( found ) then From 2933859302982c983c06ab16b297a264944e1e8d Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Tue, 6 Nov 2018 14:02:06 -0700 Subject: [PATCH 16/53] Upudate the dump_cohort statement for hydro --- main/EDTypesMod.F90 | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index dd702fba48..a61b60cd0f 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -812,14 +812,13 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%cambial_mort = ', ccohort%cambial_mort write(fates_log(),*) 'co%size_class = ', ccohort%size_class write(fates_log(),*) 'co%size_by_pft_class = ', ccohort%size_by_pft_class - !if ( hlm_use_planthydro.eq.itrue ) then - ! call dump_cohort_hydr(ccohort) - !end if - write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', ccohort%co_hydr%th_aroot(:) - !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev(:) = ', ccohort%co_hydr%th_aroot_prev(:) - !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev_uncorr(:) = ', ccohort%co_hydr%th_aroot_prev_uncorr(:) - write(fates_log(),*) 'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort%co_hydr%v_aroot_layer_init(:) - write(fates_log(),*) 'ccohort_hydr%v_aroot_layer(:) = ', ccohort%co_hydr%v_aroot_layer(:) + if ( hlm_use_planthydro.eq.itrue ) then + write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', ccohort%co_hydr%th_aroot(:) + !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev(:) = ', ccohort%co_hydr%th_aroot_prev(:) + !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev_uncorr(:) = ', ccohort%co_hydr%th_aroot_prev_uncorr(:) + write(fates_log(),*) 'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort%co_hydr%v_aroot_layer_init(:) + write(fates_log(),*) 'ccohort_hydr%v_aroot_layer(:) = ', ccohort%co_hydr%v_aroot_layer(:) + endif write(fates_log(),*) '----------------------------------------' return end subroutine dump_cohort From 45c31febf751950b9da0d7ab95e21d30492fc21a Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Tue, 6 Nov 2018 14:07:08 -0700 Subject: [PATCH 17/53] using associated(ccohort_hydr%th_aroot) instead of hlm_use_planthydro for the dump_cohort for hydro to avoid cycirlar module references --- main/EDTypesMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index a61b60cd0f..aec0c02bed 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -812,7 +812,7 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%cambial_mort = ', ccohort%cambial_mort write(fates_log(),*) 'co%size_class = ', ccohort%size_class write(fates_log(),*) 'co%size_by_pft_class = ', ccohort%size_by_pft_class - if ( hlm_use_planthydro.eq.itrue ) then + if (associated(ccohort_hydr%th_aroot) ) then write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', ccohort%co_hydr%th_aroot(:) !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev(:) = ', ccohort%co_hydr%th_aroot_prev(:) !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev_uncorr(:) = ', ccohort%co_hydr%th_aroot_prev_uncorr(:) From 790db87b8ae700e896918646ce82caa3de3b9720 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Wed, 7 Nov 2018 10:53:58 -0700 Subject: [PATCH 18/53] update the fill rhizosphere drainage filling for mass balance --- biogeophys/FatesPlantHydraulicsMod.F90 | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 36b7a6bc2f..e4a4879e6c 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -230,7 +230,7 @@ subroutine initTreeHydStates(site_p, cc_p, bc_in) ccohort_hydr%lwp_mem(:) = ccohort_hydr%psi_ag(1) ! initializes the leaf water potential memory ccohort_hydr%lwp_stable = ccohort_hydr%psi_ag(1) - ccohort_hydr%lwp_is_unstable = .false. ! inital value for leaf water potential stability flag + ccohort_hydr%lwp_is_unstable = .false. ! inital value for leaf water potential stability flag ccohort_hydr%flc_ag(:) = 1.0_r8 ccohort_hydr%flc_troot(:) = 1.0_r8 ccohort_hydr%flc_aroot(:) = 1.0_r8 @@ -539,9 +539,9 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) type(ed_cohort_hydr_type), pointer :: ccohort_hydr integer :: j,k,FT ! indices integer :: err_code = 0 - real(r8) :: th_ag_uncorr( n_hypool_ag) ! - real(r8) :: th_troot_uncorr(n_hypool_troot) ! - real(r8) :: th_aroot_uncorr(currentSite%si_hydr%nlevsoi_hyd) ! + real(r8) :: th_ag_uncorr( n_hypool_ag) ! uncorrected aboveground water content[m3 m-3] + real(r8) :: th_troot_uncorr(n_hypool_troot) ! uncorrected transporting root water content[m3 m-3] + real(r8) :: th_aroot_uncorr(currentSite%si_hydr%nlevsoi_hyd) ! uncorrected absorbing root water content[m3 m-3] real(r8), parameter :: small_theta_num = 1.e-7_r8 ! avoids theta values equalling thr or ths [m3 m-3] integer :: nstep !number of time steps !----------------------------------------------------------------------- @@ -1635,8 +1635,9 @@ subroutine FillDrainRhizShells(nsites, sites, bc_in, bc_out) real(r8) :: dwat_kg ! water remaining to be distributed across shells [kg] real(r8) :: thdiff ! water content difference between ordered adjacent rhiz shells [m3 m-3] real(r8) :: wdiff ! mass of water represented by thdiff over previous k shells [kg] - real(r8) :: errh2o(nlevsoi_hyd_max) ! water budget error after updating [kg/m2] - real(r8) :: h2osoi_liq_shell(nlevsoi_hyd_max,nshell) ! + real(r8) :: errh2o(nlevsoi_hyd_max) ! water budget error after updating [kg/m2] + real(r8) :: cumShellH2O ! sum of water in all the shells of a specific layer [kg/m2] + real(r8) :: h2osoi_liq_shell(nlevsoi_hyd_max,nshell) !water in the rhizosphere shells [kg] integer :: tmp ! temporary logical :: found ! flag in search loop !----------------------------------------------------------------------- @@ -1654,12 +1655,14 @@ subroutine FillDrainRhizShells(nsites, sites, bc_in, bc_out) csite_hydr => sites(s)%si_hydr - do j = 1,csite_hydr%nlevsoi_hyd + do j = 1,csite_hydr%nlevsoi_hyd + cumShellH2O=sum(csite_hydr%h2osoi_liqvol_shell(j,:) *csite_hydr%v_shell(j,:)) & + / bc_in(s)%dz_sisl(j) * csite_hydr%l_aroot_layer(j) * denh2o/AREA if(csite_hydr%nlevsoi_hyd == 1) then - dwat_kgm2 = bc_in(s)%h2o_liq_sisl(bc_in(s)%nlevsoil) - csite_hydr%h2osoi_liq_prev(csite_hydr%nlevsoi_hyd) + dwat_kgm2 = bc_in(s)%h2o_liq_sisl(bc_in(s)%nlevsoil) - cumShellH2O else ! if(csite_hydr%nlevsoi_hyd == bc_in(s)%nlevsoil ) then - dwat_kgm2 = bc_in(s)%h2o_liq_sisl(j) - csite_hydr%h2osoi_liq_prev(j) + dwat_kgm2 = bc_in(s)%h2o_liq_sisl(j) - cumShellH2O end if dwat_kg = dwat_kgm2 * AREA From 8162bc1efe2a9e0b4af3f5b8d3f742ac891ce35e Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Wed, 7 Nov 2018 10:53:58 -0700 Subject: [PATCH 19/53] update the rhizosphere drainage refilling for improvement of mass balance --- biogeophys/FatesPlantHydraulicsMod.F90 | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 8773420e49..f43cdb17ae 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -234,7 +234,7 @@ subroutine initTreeHydStates(site_p, cc_p, bc_in) ccohort_hydr%lwp_mem(:) = ccohort_hydr%psi_ag(1) ! initializes the leaf water potential memory ccohort_hydr%lwp_stable = ccohort_hydr%psi_ag(1) - ccohort_hydr%lwp_is_unstable = .false. ! inital value for leaf water potential stability flag + ccohort_hydr%lwp_is_unstable = .false. ! inital value for leaf water potential stability flag ccohort_hydr%flc_ag(:) = 1.0_r8 ccohort_hydr%flc_troot(:) = 1.0_r8 ccohort_hydr%flc_aroot(:) = 1.0_r8 @@ -564,9 +564,9 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) type(ed_cohort_hydr_type), pointer :: ccohort_hydr integer :: j,k,FT ! indices integer :: err_code = 0 - real(r8) :: th_ag_uncorr( n_hypool_ag) ! - real(r8) :: th_troot_uncorr(n_hypool_troot) ! - real(r8) :: th_aroot_uncorr(currentSite%si_hydr%nlevsoi_hyd) ! + real(r8) :: th_ag_uncorr( n_hypool_ag) ! uncorrected aboveground water content[m3 m-3] + real(r8) :: th_troot_uncorr(n_hypool_troot) ! uncorrected transporting root water content[m3 m-3] + real(r8) :: th_aroot_uncorr(currentSite%si_hydr%nlevsoi_hyd) ! uncorrected absorbing root water content[m3 m-3] real(r8), parameter :: small_theta_num = 1.e-7_r8 ! avoids theta values equalling thr or ths [m3 m-3] integer :: nstep !number of time steps !----------------------------------------------------------------------- @@ -1670,8 +1670,9 @@ subroutine FillDrainRhizShells(nsites, sites, bc_in, bc_out) real(r8) :: dwat_kg ! water remaining to be distributed across shells [kg] real(r8) :: thdiff ! water content difference between ordered adjacent rhiz shells [m3 m-3] real(r8) :: wdiff ! mass of water represented by thdiff over previous k shells [kg] - real(r8) :: errh2o(nlevsoi_hyd_max) ! water budget error after updating [kg/m2] - real(r8) :: h2osoi_liq_shell(nlevsoi_hyd_max,nshell) ! + real(r8) :: errh2o(nlevsoi_hyd_max) ! water budget error after updating [kg/m2] + real(r8) :: cumShellH2O ! sum of water in all the shells of a specific layer [kg/m2] + real(r8) :: h2osoi_liq_shell(nlevsoi_hyd_max,nshell) !water in the rhizosphere shells [kg] integer :: tmp ! temporary logical :: found ! flag in search loop !----------------------------------------------------------------------- @@ -1689,12 +1690,14 @@ subroutine FillDrainRhizShells(nsites, sites, bc_in, bc_out) csite_hydr => sites(s)%si_hydr - do j = 1,csite_hydr%nlevsoi_hyd + do j = 1,csite_hydr%nlevsoi_hyd + cumShellH2O=sum(csite_hydr%h2osoi_liqvol_shell(j,:) *csite_hydr%v_shell(j,:)) & + / bc_in(s)%dz_sisl(j) * csite_hydr%l_aroot_layer(j) * denh2o/AREA if(csite_hydr%nlevsoi_hyd == 1) then - dwat_kgm2 = bc_in(s)%h2o_liq_sisl(bc_in(s)%nlevsoil) - csite_hydr%h2osoi_liq_prev(csite_hydr%nlevsoi_hyd) + dwat_kgm2 = bc_in(s)%h2o_liq_sisl(bc_in(s)%nlevsoil) - cumShellH2O else ! if(csite_hydr%nlevsoi_hyd == bc_in(s)%nlevsoil ) then - dwat_kgm2 = bc_in(s)%h2o_liq_sisl(j) - csite_hydr%h2osoi_liq_prev(j) + dwat_kgm2 = bc_in(s)%h2o_liq_sisl(j) - cumShellH2O end if dwat_kg = dwat_kgm2 * AREA From b9a88e44fdcc25f772a33e0340bd39f0435ac335 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Fri, 9 Nov 2018 11:22:33 -0700 Subject: [PATCH 20/53] avoid the reference to site%hydr for Fates History when hydro is not turned on --- main/FatesHistoryInterfaceMod.F90 | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index f78d6a3190..5c0baff79d 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -2187,11 +2187,13 @@ subroutine update_history_dyn(this,nc,nsites,sites) sites(s)%CWD_BG_diagnostic_input_carbonflux(:) = 0._r8 sites(s)%leaf_litter_diagnostic_input_carbonflux(:) = 0._r8 sites(s)%root_litter_diagnostic_input_carbonflux(:) = 0._r8 - - hio_h2oveg_dead_si(io_si) = sites(s)%si_hydr%h2oveg_dead - hio_h2oveg_recruit_si(io_si) = sites(s)%si_hydr%h2oveg_recruit - hio_h2oveg_growturn_err_si(io_si) = sites(s)%si_hydr%h2oveg_growturn_err - hio_h2oveg_pheno_err_si(io_si) = sites(s)%si_hydr%h2oveg_pheno_err + + if(hlm_use_planthydro==itrue)then + hio_h2oveg_dead_si(io_si) = sites(s)%si_hydr%h2oveg_dead + hio_h2oveg_recruit_si(io_si) = sites(s)%si_hydr%h2oveg_recruit + hio_h2oveg_growturn_err_si(io_si) = sites(s)%si_hydr%h2oveg_growturn_err + hio_h2oveg_pheno_err_si(io_si) = sites(s)%si_hydr%h2oveg_pheno_err + endif enddo ! site loop From dc04ffedc1d14eb8e0a5bd1830589b4441588f49 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Fri, 9 Nov 2018 11:59:29 -0700 Subject: [PATCH 21/53] update the dump_cohort for hydro --- main/EDTypesMod.F90 | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/main/EDTypesMod.F90 b/main/EDTypesMod.F90 index aec0c02bed..901ad2f52c 100644 --- a/main/EDTypesMod.F90 +++ b/main/EDTypesMod.F90 @@ -812,12 +812,8 @@ subroutine dump_cohort(ccohort) write(fates_log(),*) 'co%cambial_mort = ', ccohort%cambial_mort write(fates_log(),*) 'co%size_class = ', ccohort%size_class write(fates_log(),*) 'co%size_by_pft_class = ', ccohort%size_by_pft_class - if (associated(ccohort_hydr%th_aroot) ) then - write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', ccohort%co_hydr%th_aroot(:) - !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev(:) = ', ccohort%co_hydr%th_aroot_prev(:) - !write(fates_log(),*) 'ccohort_hydr%th_aroot_prev_uncorr(:) = ', ccohort%co_hydr%th_aroot_prev_uncorr(:) - write(fates_log(),*) 'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort%co_hydr%v_aroot_layer_init(:) - write(fates_log(),*) 'ccohort_hydr%v_aroot_layer(:) = ', ccohort%co_hydr%v_aroot_layer(:) + if (associated(ccohort%co_hydr) ) then + call dump_cohort_hydr(ccohort) endif write(fates_log(),*) '----------------------------------------' return @@ -825,20 +821,20 @@ end subroutine dump_cohort ! ===================================================================================== - !subroutine dump_cohort_hydr(ccohort) -! -! - ! type(ed_cohort_type),intent(in),target :: ccohort - ! type(ed_cohort_hydr_type), pointer :: ccohort_hydr - ! ccohort_hydr => ccohort%co_hydr + subroutine dump_cohort_hydr(ccohort) + + + type(ed_cohort_type),intent(in),target :: ccohort + type(ed_cohort_hydr_type), pointer :: ccohort_hydr + ccohort_hydr => ccohort%co_hydr - ! write(fates_log(),*) '--------------------------------------------' - ! write(fates_log(),*) ' Dumping Cohort Plant Hydraulic Information ' - ! write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', ccohort_hydr%th_aroot(:) - ! write(fates_log(),*) 'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort_hydr%v_aroot_layer_init(:) - ! write(fates_log(),*) 'ccohort_hydr%v_aroot_layer(:) = ', ccohort_hydr%v_aroot_layer(:) - ! write(fates_log(),*) '--------------------------------------------' - ! return - ! end subroutine dump_cohort_hydr + write(fates_log(),*) '--------------------------------------------' + write(fates_log(),*) ' Dumping Cohort Plant Hydraulic Information ' + write(fates_log(),*) 'ccohort_hydr%th_aroot(:) = ', ccohort_hydr%th_aroot(:) + write(fates_log(),*) 'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort_hydr%v_aroot_layer_init(:) + write(fates_log(),*) 'ccohort_hydr%v_aroot_layer(:) = ', ccohort_hydr%v_aroot_layer(:) + write(fates_log(),*) '--------------------------------------------' + return + end subroutine dump_cohort_hydr end module EDTypesMod From 13ada94c7eea2afe58a1d1bbba5eb8de196169c8 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Fri, 9 Nov 2018 12:24:20 -0700 Subject: [PATCH 22/53] simply the rhizosphere kmax code by avoiding duplicate calculations --- biogeophys/FatesPlantHydraulicsMod.F90 | 28 +++++++------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index f43cdb17ae..fdef2bf356 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -413,7 +413,7 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) ! a_sapwood = a_leaf_tot / EDPftvarcon_inst%allom_latosa_int(FT)*1.e-4_r8 ! m2 sapwood = m2 leaf * cm2 sapwood/m2 leaf *1.0e-4m2 ! or ... - ! a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * cCohort%hite ) * 1.e-4_r8 + a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * cCohort%hite ) * 1.e-4_r8 v_sapwood = a_sapwood * z_stem ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem @@ -1317,27 +1317,13 @@ subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) end if if(j == 1) then if(csite_hydr%r_node_shell(j,k) <= csite_hydr%rs1(j)) then - csite_hydr%kmax_upper_shell_1D(k) = kmax_root_surf_total - csite_hydr%kmax_bound_shell_1D(k) = kmax_root_surf_total - csite_hydr%kmax_lower_shell_1D(k) = kmax_root_surf_total - csite_hydr%kmax_upper_shell_1D(k) = large_kmax_bound - csite_hydr%kmax_bound_shell_1D(k) = large_kmax_bound - csite_hydr%kmax_lower_shell_1D(k) = large_kmax_bound + csite_hydr%kmax_upper_shell_1D(k) = csite_hydr%kmax_upper_shell(1,k) + csite_hydr%kmax_bound_shell_1D(k) = csite_hydr%kmax_bound_shell(1,k) + csite_hydr%kmax_lower_shell_1D(k) = csite_hydr%kmax_lower_shell(1,k) else - kmax_soil_total = 2._r8*pi_const*csite_hydr%l_aroot_1D / & - log(csite_hydr%r_node_shell_1D(k)/csite_hydr%rs1(j))*hksat_s - !csite_hydr%kmax_upper_shell_1D(k) = 2._r8*pi_const*csite_hydr%l_aroot_1D / & - ! log(csite_hydr%r_node_shell_1D(k)/csite_hydr%rs1(j))*hksat_s - !csite_hydr%kmax_bound_shell_1D(k) = 2._r8*pi_const*csite_hydr%l_aroot_1D / & - ! log(csite_hydr%r_node_shell_1D(k)/csite_hydr%rs1(j))*hksat_s - !csite_hydr%kmax_lower_shell_1D(k) = 2._r8*pi_const*csite_hydr%l_aroot_1D / & - ! log(csite_hydr%r_node_shell_1D(k)/csite_hydr%rs1(j))*hksat_s - csite_hydr%kmax_upper_shell_1D(k) = (1._r8/kmax_root_surf_total + & - 1._r8/kmax_soil_total)**(-1._r8) - csite_hydr%kmax_bound_shell_1D(k) = (1._r8/kmax_root_surf_total + & - 1._r8/kmax_soil_total)**(-1._r8) - csite_hydr%kmax_lower_shell_1D(k) = (1._r8/kmax_root_surf_total + & - 1._r8/kmax_soil_total)**(-1._r8) + csite_hydr%kmax_upper_shell_1D(k) = csite_hydr%kmax_upper_shell(1,k) + csite_hydr%kmax_bound_shell_1D(k) = csite_hydr%kmax_bound_shell(1,k) + csite_hydr%kmax_lower_shell_1D(k) = csite_hydr%kmax_lower_shell(1,k) end if end if else From 26e3db8a9cea7fd6eda67e8c3741a1d21e002216 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Fri, 9 Nov 2018 12:43:29 -0700 Subject: [PATCH 23/53] turn on the default sapwood area calculation for hydro --- biogeophys/FatesPlantHydraulicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index fdef2bf356..4a1404d292 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -413,7 +413,7 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) ! a_sapwood = a_leaf_tot / EDPftvarcon_inst%allom_latosa_int(FT)*1.e-4_r8 ! m2 sapwood = m2 leaf * cm2 sapwood/m2 leaf *1.0e-4m2 ! or ... - a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * cCohort%hite ) * 1.e-4_r8 + !a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * cCohort%hite ) * 1.e-4_r8 v_sapwood = a_sapwood * z_stem ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem From aa868207404553aef5a0417a49a0575d00d11237 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 12 Nov 2018 12:32:57 -0800 Subject: [PATCH 24/53] Starting to scratch out variable dependencies for hydro restarts --- main/FatesRestartInterfaceMod.F90 | 133 +++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index a710fd922e..af9ec2a77b 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -846,7 +846,7 @@ subroutine define_restart_vars(this, initialize_variables) end subroutine define_restart_vars - ! ===================================================================================== + ! ===================================================================================== subroutine DefinePRTRestartVars(this,initialize_variables,ivar) @@ -978,6 +978,137 @@ end subroutine DefinePRTRestartVars ! ===================================================================================== + subroutine DefineHydroVecCohortRestartVars(this,initialize_variables,ivar) + + ! ---------------------------------------------------------------------------------- + ! Plant Hydraulics has many variables that are bound to the cohort + ! and are vectors. To prevent absolutely massive restart files + ! we will actually split the restart information of these different + ! vector indices into different saved variables. + ! ----------------------------------------------------------------------------------- + + + use FatesIOVariableKindMod, only : cohort_r8 + + class(fates_restart_interface_type) :: this + logical, intent(in) :: initialize_variables + integer,intent(inout) :: ivar ! global variable counter + + integer :: dummy_out ! dummy index for variable + ! position in global file + integer :: i_var ! loop counter for prt variables + integer :: i_pos ! loop counter for discrete position + + character(len=32) :: symbol_base ! Symbol name without position or flux type + character(len=128) :: name_base ! name without position or flux type + character(len=4) :: pos_symbol + character(len=128) :: symbol + character(len=256) :: long_name + + ! NEED FOR RESTARTS + ccohort_hydr%v_ag_init(:) = ccohort_hydr%v_ag(:) + ccohort_hydr%v_troot_init(:) = ccohort_hydr%v_troot(:) + ccohort_hydr%v_aroot_layer_init(:) = ccohort_hydr%v_aroot_layer(:) + + + ! CAN BE REMOVED ALTOGETHER + ccohort_hydr%z_node_aroot(1:nlevsoi_hyd) = -bc_in%z_sisl(1:nlevsoi_hyd) + + + do i_var = 1, prt_global%num_vars + + + + + + ! The base symbol name + symbol_base = prt_global%state_descriptor(i_var)%symbol + + ! The long name of the variable + name_base = prt_global%state_descriptor(i_var)%longname + + do i_pos = 1, prt_global%state_descriptor(i_var)%num_pos + + ! String describing the physical position of the variable + write(pos_symbol, '(I3.3)') i_pos + + ! Register the instantaneous state variable "val" + ! ---------------------------------------------------------------------------- + + ! The symbol that is written to file + symbol = trim(symbol_base)//'_val_'//trim(pos_symbol) + + ! The expanded long name of the variable + long_name = trim(name_base)//', state var, position:'//trim(pos_symbol) + + call this%set_restart_var(vname=trim(symbol), & + vtype=cohort_r8, & + long_name=trim(long_name), & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, & + ivar=ivar, index = dummy_out ) + + ! Register the turnover flux variables + ! ---------------------------------------------------------------------------- + + ! The symbol that is written to file + symbol = trim(symbol_base)//'_turn_'//trim(pos_symbol) + + ! The expanded long name of the variable + long_name = trim(name_base)//', turnover, position:'//trim(pos_symbol) + + call this%set_restart_var(vname=trim(symbol), & + vtype=cohort_r8, & + long_name=trim(long_name), & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, & + ivar=ivar, index = dummy_out ) + + + + ! Register the net allocation flux variable + ! ---------------------------------------------------------------------------- + + ! The symbol that is written to file + symbol = trim(symbol_base)//'_net_'//trim(pos_symbol) + + ! The expanded long name of the variable + long_name = trim(name_base)//', net allocation/transp, position:'//trim(pos_symbol) + + call this%set_restart_var(vname=trim(symbol), & + vtype=cohort_r8, & + long_name=trim(long_name), & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, & + ivar=ivar, index = dummy_out ) + + + + ! Register the burn flux variable + ! ---------------------------------------------------------------------------- + ! The symbol that is written to file + symbol = trim(symbol_base)//'_burned_'//trim(pos_symbol) + + ! The expanded long name of the variable + long_name = trim(name_base)//', burned mass:'//trim(pos_symbol) + + call this%set_restart_var(vname=symbol, & + vtype=cohort_r8, & + long_name=trim(long_name), & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, & + ivar=ivar, index = dummy_out ) + + end do + end do + + return + end subroutine DefineHydroRestartVars + + ! ===================================================================================== + + + subroutine set_restart_var(this,vname,vtype,long_name,units,flushval, & hlms,initialize,ivar,index) From 977c6c7e2744c974aad33ebbe81418278cecbbda Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 12 Nov 2018 14:41:31 -0800 Subject: [PATCH 25/53] Spacing out and listing hydro variables that will be added to restarts. --- main/FatesRestartInterfaceMod.F90 | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index af9ec2a77b..c1b2814b0c 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1005,11 +1005,25 @@ subroutine DefineHydroVecCohortRestartVars(this,initialize_variables,ivar) character(len=128) :: symbol character(len=256) :: long_name - ! NEED FOR RESTARTS + ! From update props ccohort_hydr%v_ag_init(:) = ccohort_hydr%v_ag(:) ccohort_hydr%v_troot_init(:) = ccohort_hydr%v_troot(:) ccohort_hydr%v_aroot_layer_init(:) = ccohort_hydr%v_aroot_layer(:) + ! From update states + ccohort_hydr%th_ag(:) + ccohort_hydr%th_troot(k) + ccohort_hydr%th_aroot(j) + + ! From update rhiz props + csite_hydr%l_aroot_layer_init(:) = csite_hydr%l_aroot_layer(:) + csite_hydr%r_node_shell_init(:,:) = csite_hydr%r_node_shell(:,:) + csite_hydr%v_shell_init(:,:) = csite_hydr%v_shell(:,:) + + + ! From update rhiz states + csite_hydr%h2osoi_liqvol_shell(j,k) + ! CAN BE REMOVED ALTOGETHER ccohort_hydr%z_node_aroot(1:nlevsoi_hyd) = -bc_in%z_sisl(1:nlevsoi_hyd) From b84261ad2151cfdb979e31296f1c59ecbb3ac383 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Nov 2018 12:26:04 -0800 Subject: [PATCH 26/53] First pass at incorporating hydraulics variables into restarts --- main/FatesHydraulicsMemMod.F90 | 6 +- main/FatesRestartInterfaceMod.F90 | 444 ++++++++++++++++++++---------- 2 files changed, 305 insertions(+), 145 deletions(-) diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index a1d2fbfd71..8bc0e2f8af 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -81,9 +81,9 @@ module FatesHydraulicsMemMod ! may or may not cross that with a simple or ! non-simple layering - real(r8),allocatable :: v_shell(:,:) ! Volume of rhizosphere compartment (m) - real(r8),allocatable :: v_shell_init(:,:) ! Previous volume of rhizosphere compartment (m) - real(r8),allocatable :: v_shell_1D(:) ! Volume of rhizosphere compartment (m) + real(r8),allocatable :: v_shell(:,:) ! Volume of rhizosphere compartment (m3) + real(r8),allocatable :: v_shell_init(:,:) ! Previous volume of rhizosphere compartment (m3) + real(r8),allocatable :: v_shell_1D(:) ! Volume of rhizosphere compartment (m3) real(r8),allocatable :: r_node_shell(:,:) ! Nodal radius of rhizosphere compartment (m) real(r8),allocatable :: r_node_shell_init(:,:) ! Previous Nodal radius of rhizosphere compartment (m) real(r8),allocatable :: l_aroot_layer(:) ! Total length (across cohorts) of absorbing diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index c1b2814b0c..19ad6f0ce8 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -14,6 +14,7 @@ module FatesRestartInterfaceMod use FatesRestartVariableMod, only : fates_restart_variable_type use FatesInterfaceMod, only : bc_in_type use FatesInterfaceMod, only : bc_out_type + use FatesInterfaceMod, only : hlm_use_planthydro use FatesSizeAgeTypeIndicesMod, only : get_sizeage_class_index use PRTGenericMod, only : prt_global @@ -134,6 +135,18 @@ module FatesRestartInterfaceMod integer, private :: ir_prt_base ! Base index for all PRT variables + ! Hydraulic indices + integer, private :: ir_hydro_v_ag_covec + integer, private :: ir_hydro_v_troot_covec + integer, private :: ir_hydro_v_aroot_layer_covec + integer, private :: ir_hydro_th_ag_covec + integer, private :: ir_hydro_th_troot_covec + integer, private :: ir_hydro_th_aroot_covec + integer, private :: ir_hydro_aroot_layer_si + integer, private :: ir_hydro_r_node_shell_si + integer, private :: ir_hydro_v_shell_si + integer, private :: ir_hydro_liqvol_shell_si + ! The number of variable dim/kind types we have defined (static) integer, parameter :: fates_restart_num_dimensions = 2 !(cohort,column) @@ -824,6 +837,65 @@ subroutine define_restart_vars(this, initialize_variables) hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_area_pa ) + if(hlm_use_planthydro==itrue) then + + call RegisterCohortVectors('fates_hydro_v_ag', vtype=cohort_r8, & + long_name='maximum storage volume of hydraulic compartments (above ground)', & + units='m3', n_hypool_ag, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_ag_covec) + + call RegisterCohortVectors('fates_hydro_v_troot', vtype=cohort_r8, & + long_name='maximum storage volume of transporting root compartments', & + units='m3', n_hypool_troot, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_troot_covec) + + call RegisterCohortVectors('fates_hydro_v_aroot_layer', vtype=cohort_r8, & + long_name='maximum storage volume of absorbing roots hydraulic compartments by soil layer', & + units='m3', nlevsoi_hyd_max, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_aroot_layer_covec) + + call RegisterCohortVectors('fates_hydro_th_ag', vtype=cohort_r8, & + long_name='water in aboveground compartments', & + units='kg/plant', n_hypool_ag, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_th_ag_covec) + + call RegisterCohortVectors('fates_hydro_th_troot', vtype=cohort_r8, & + long_name='water in transporting roots', & + units='kg/plant', n_hypool_troot, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_th_troot_covec) + + call RegisterCohortVectors('fates_hydro_th_aroot', vtype=cohort_r8, & + long_name='water in absorbing roots', & + units='kg/plant', nlevsoi_hyd_max, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_th_aroot_covec) + + ! Site-level absorbing root maximum volume + call this%set_restart_var(vname='fates_hydro_l_aroot_layer', vtype=cohort_r8, & + long_name='Total length (across cohorts) of absorbing roots by soil layer', & + units='m', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_l_aroot_layer_si ) + + ! Site-level Nodal Radius of rhizosphere compartments + call this%set_restart_var(vname='fates_hydro_r_node_shell', vtype=cohort_r8, & + long_name='Nodal Radius of rhizosphere compartments (layerxshell)', & + units='m', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_r_node_shell_si ) + + ! Site-level volume of rhizosphere compartments + call this%set_restart_var(vname='fates_hydro_v_shell', vtype=cohort_r8, & + long_name='Volume of rhizosphere compartments (layerxshell)', & + units='m3', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_shell_si ) + + ! Site-level volumentric liquid water content (shell x layer) + call this%set_restart_var(vname='fates_hydro_liqvol_shell', vtype=cohort_r8, & + long_name='Volumetric water content of rhizosphere compartments (layerxshell)', & + units='m3/m3', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_liqvol_shell_si ) + + end if + + ! ! site x time level vars ! @@ -976,152 +1048,117 @@ subroutine DefinePRTRestartVars(this,initialize_variables,ivar) return end subroutine DefinePRTRestartVars - ! ===================================================================================== - - subroutine DefineHydroVecCohortRestartVars(this,initialize_variables,ivar) - - ! ---------------------------------------------------------------------------------- - ! Plant Hydraulics has many variables that are bound to the cohort - ! and are vectors. To prevent absolutely massive restart files - ! we will actually split the restart information of these different - ! vector indices into different saved variables. - ! ----------------------------------------------------------------------------------- - - use FatesIOVariableKindMod, only : cohort_r8 + subroutine RegisterCohortVector(this,symbol_base, vtype_in, long_name_base, & + units_in, veclength, flushval, hlms_in, & + initialize=initialize_variables, & + ivar=ivar_inout, index = index_out) - class(fates_restart_interface_type) :: this - logical, intent(in) :: initialize_variables - integer,intent(inout) :: ivar ! global variable counter - - integer :: dummy_out ! dummy index for variable - ! position in global file - integer :: i_var ! loop counter for prt variables - integer :: i_pos ! loop counter for discrete position - - character(len=32) :: symbol_base ! Symbol name without position or flux type - character(len=128) :: name_base ! name without position or flux type - character(len=4) :: pos_symbol - character(len=128) :: symbol - character(len=256) :: long_name - - ! From update props - ccohort_hydr%v_ag_init(:) = ccohort_hydr%v_ag(:) - ccohort_hydr%v_troot_init(:) = ccohort_hydr%v_troot(:) - ccohort_hydr%v_aroot_layer_init(:) = ccohort_hydr%v_aroot_layer(:) - - ! From update states - ccohort_hydr%th_ag(:) - ccohort_hydr%th_troot(k) - ccohort_hydr%th_aroot(j) - - ! From update rhiz props - csite_hydr%l_aroot_layer_init(:) = csite_hydr%l_aroot_layer(:) - csite_hydr%r_node_shell_init(:,:) = csite_hydr%r_node_shell(:,:) - csite_hydr%v_shell_init(:,:) = csite_hydr%v_shell(:,:) - - - ! From update rhiz states - csite_hydr%h2osoi_liqvol_shell(j,k) - - - ! CAN BE REMOVED ALTOGETHER - ccohort_hydr%z_node_aroot(1:nlevsoi_hyd) = -bc_in%z_sisl(1:nlevsoi_hyd) - - - do i_var = 1, prt_global%num_vars - - - - - - ! The base symbol name - symbol_base = prt_global%state_descriptor(i_var)%symbol - - ! The long name of the variable - name_base = prt_global%state_descriptor(i_var)%longname - - do i_pos = 1, prt_global%state_descriptor(i_var)%num_pos - - ! String describing the physical position of the variable - write(pos_symbol, '(I3.3)') i_pos - - ! Register the instantaneous state variable "val" - ! ---------------------------------------------------------------------------- - - ! The symbol that is written to file - symbol = trim(symbol_base)//'_val_'//trim(pos_symbol) - - ! The expanded long name of the variable - long_name = trim(name_base)//', state var, position:'//trim(pos_symbol) - - call this%set_restart_var(vname=trim(symbol), & - vtype=cohort_r8, & - long_name=trim(long_name), & - units='kg', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, & - ivar=ivar, index = dummy_out ) - - ! Register the turnover flux variables - ! ---------------------------------------------------------------------------- - - ! The symbol that is written to file - symbol = trim(symbol_base)//'_turn_'//trim(pos_symbol) - - ! The expanded long name of the variable - long_name = trim(name_base)//', turnover, position:'//trim(pos_symbol) - - call this%set_restart_var(vname=trim(symbol), & - vtype=cohort_r8, & - long_name=trim(long_name), & - units='kg', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, & - ivar=ivar, index = dummy_out ) - - - - ! Register the net allocation flux variable - ! ---------------------------------------------------------------------------- - - ! The symbol that is written to file - symbol = trim(symbol_base)//'_net_'//trim(pos_symbol) - - ! The expanded long name of the variable - long_name = trim(name_base)//', net allocation/transp, position:'//trim(pos_symbol) - - call this%set_restart_var(vname=trim(symbol), & - vtype=cohort_r8, & - long_name=trim(long_name), & - units='kg', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, & - ivar=ivar, index = dummy_out ) - - - - ! Register the burn flux variable - ! ---------------------------------------------------------------------------- - ! The symbol that is written to file - symbol = trim(symbol_base)//'_burned_'//trim(pos_symbol) - - ! The expanded long name of the variable - long_name = trim(name_base)//', burned mass:'//trim(pos_symbol) - - call this%set_restart_var(vname=symbol, & - vtype=cohort_r8, & - long_name=trim(long_name), & - units='kg', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, & - ivar=ivar, index = dummy_out ) - - end do - end do - - return - end subroutine DefineHydroRestartVars + + ! The basic idea here is that instead of saving cohorts with vector data + ! as long arrays in the restart file, we give each index of the vector + ! its own variable. This helps reduce the size of the restart files + ! considerably. + + + use FatesIOVariableKindMod, only : cohort_r8 + + class(fates_restart_interface_type) :: this + character(*),intent(in) :: symbol_base ! Symbol name without position + character(*),intent(in) :: vtype_in ! String defining variable type + character(*),intent(in) :: long_name_base ! name without position + character(*),intent(in) :: units_in ! units for this variable + integer,intent(in) :: veclength ! length of the vector + real(r8),intent(in) :: flushval_in ! Value to flush to + character(*),intent(in) :: hlms_in ! The HLMs this works in + logical, intent(in) :: init_var_in ! Is this registering or counting? + integer,intent(inout) :: ivar_inout ! global variable counter + integer,intent(out) :: index_out ! The variable index for this variable + + ! Local Variables + character(len=4) :: pos_symbol ! vectors need text strings for each position + character(len=128) :: symbol ! symbol name written to file + character(len=256) :: long_name ! long name written to file + integer :: i_pos ! loop counter for discrete position + + ! We give each vector its own index + + index_out = ivar_inout + 1 + + do i_pos = 1, veclength + + ! String describing the physical position of the variable + write(pos_symbol, '(I3.3)') i_pos + + ! The symbol that is written to file + symbol = trim(symbol_base)//'_vec_'//trim(pos_symbol) + + ! The expanded long name of the variable + long_name = trim(long_name_base)//', position:'//trim(pos_symbol) + + call this%set_restart_var(vname=trim(symbol), & + vtype=vtype_in, & + long_name=trim(long_name), & + units=units_in, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, & + ivar=ivar, index = index_out ) + + end do + + end subroutine RegisterCohortVector ! ===================================================================================== + + subroutine RetrieveCohortRealVector(this, state_vector, len_state_vector, & + variable_index_base, co_global_index) + + ! This subroutine walks through global cohort vector indices + ! and pulls from the different associated restart variables + + class(fates_restart_interface_type) , intent(inout) :: this + real(r8),intent(inout) :: state_vector(len_state_vector) + integer,intent(in) :: len_state_vector + integer,intent(in) :: variable_index_base + integer,intent(in) :: co_global_index + + integer :: i_pos ! vector position loop index + integer :: ir_pos_var ! global variable index + + ir_pos_var = variable_index_base + do i_pos = 1, len_state_vector + state_vector(i_pos) = this%rvars(ir_pos_var)%r81d(co_global_index) + ir_pos_var = ir_pos_var + 1 + end do + return + end subroutine RetrieveCohortRealVector + + ! ===================================================================================== + + subroutine SetCohortRealVector(this, state_vector, len_state_vector, & + variable_index_base, co_global_index) + ! This subroutine walks through global cohort vector indices + ! and pushes into the restart arrays the different associated restart variables + + class(fates_restart_interface_type) , intent(inout) :: this + real(r8),intent(in) :: state_vector(len_state_vector) + integer,intent(in) :: len_state_vector + integer,intent(in) :: variable_index_base + integer,intent(in) :: co_global_index + + integer :: i_pos ! vector position loop index + integer :: ir_pos_var ! global variable index + + ir_pos_var = variable_index_base + do i_pos = 1, len_state_vector + this%rvars(ir_pos_var)%r81d(co_global_index) = state_vector(i_pos) + ir_pos_var = ir_pos_var + 1 + end do + return + end subroutine SetCohortRealVector + + ! ===================================================================================== subroutine set_restart_var(this,vname,vtype,long_name,units,flushval, & hlms,initialize,ivar,index) @@ -1295,7 +1332,12 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_livegrass_pa => this%rvars(ir_livegrass_pa)%r81d, & rio_age_pa => this%rvars(ir_age_pa)%r81d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & - rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d ) + rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & + rio_hydro_l_aroot_layer_si => this%rvars(ir_hydro_l_aroot_layer_si)%r81d, & + rio_hydro_r_node_shell_si => this%rvars(ir_hydro_r_node_shell_si)%r81d, & + rio_hydro_v_shell_si => this%rvars(ir_hydro_v_shell_si)%r81d, & + rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d + ) totalCohorts = 0 @@ -1320,6 +1362,12 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_pa_cwd = io_idx_co_1st io_idx_pa_ib = io_idx_co_1st io_idx_si_wmem = io_idx_co_1st + + ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell + io_idx_si_lyr = io_idx_co_1st + io_idx_si_lyr_shell = io_idx_co_1st + + ! write seed_bank info(site-level, but PFT-resolved) do i = 1,numpft @@ -1385,6 +1433,19 @@ subroutine set_restart_vectors(this,nc,nsites,sites) end do end do + + if(hlm_use_planthydro==itrue)then + + ! Load the storage compartment volumes + call this%SetCohortRealVector(cohort%hydr_co%v_ag,n_hypool_ag,ir_hydro_v_ag_covec,io_idx_co) + call this%SetCohortRealVector(cohort%hydr_co%v_troot,n_hypool_troot,ir_hydro_v_troot_covec,io_idx_co) + call this%SetCohortRealVector(cohort%hydr_co%v_aroot_layer,site(s)%si_hydr%nlevsoi_hyd,ir_hydro_v_aroot_layer_covec,io_idx_co) + + ! Load the water contents + call this%SetCohortRealVector(cohort%hydr_co%th_ag,n_hypool_ag,ir_hydro_th_ag_covec,io_idx_co) + call this%SetCohortRealVector(cohort%hydr_co%th_troot,n_hypool_troot,ir_hydro_th_troot_covec,io_idx_co) + call this%SetCohortRealVector(cohort%hydr_co%th_aroot_layer,site(s)%si_hydr%nlevsoi_hyd,ir_hydro_th_aroot_layer_covec,io_idx_co) + end if rio_canopy_layer_co(io_idx_co) = ccohort%canopy_layer rio_canopy_layer_yesterday_co(io_idx_co) = ccohort%canopy_layer_yesterday @@ -1536,6 +1597,35 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_watermem_siwm( io_idx_si_wmem ) = sites(s)%water_memory(i) io_idx_si_wmem = io_idx_si_wmem + 1 end do + + ! ----------------------------------------------------------------------------- + ! Set site-level hydraulics arrays + ! ----------------------------------------------------------------------------- + + if(hlm_use_planthydro==itrue)then + + ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell + do i = 1, site_hydr%nlevsoi_hyd + + ! Loop shells + do k = 1, nshell + + rio_hydro_r_node_shell_si(io_idx_si_lyr_shell) = & + sites(s)%si_hydr%r_node_shell(i,k) + + rio_hydro_v_shell_si(io_idx_si_lyr_shell) = & + sites(s)%si_hydr%v_shell(i,k) + + rio_hydro_liqvol_shell_si(io_idx_si_lyr_shell) = & + sites(s)%si_hydr%h2osoi_liqvol_shell(i,k) + + io_idx_si_lyr_shell = io_idx_si_lyr_shell + 1 + end do + + rio_hydro_l_aroot_layer_si(io_idx_si_lyr) = sites(s)%si_hydr%l_aroot_layer(i) + io_idx_si_lyr = io_idx_si_lyr + 1 + end do + end if enddo @@ -1557,6 +1647,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in) ! subroutine is called prior to the transfer of the restart vectors into the ! linked-list state structure. ! --------------------------------------------------------------------------------- + use EDTypesMod, only : ed_site_type use EDTypesMod, only : ed_cohort_type use EDTypesMod, only : ed_patch_type @@ -1695,6 +1786,9 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in) b_fineroot = 0.0_r8 b_sapwood = 0.0_r8 site_spread = 0.5_r8 + + ! Hydraulics - if turned on, the hydraulics arrays are being allocated in create_cohort as well. + call create_cohort(sites(s),newp, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, temp_cohort%dbh, & b_leaf, b_fineroot, b_sapwood, b_dead, b_store, & temp_cohort%laimemory, cohortstatus,recruitstatus, temp_cohort%canopy_trim, newp%NCL_p, & @@ -1871,7 +1965,12 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_livegrass_pa => this%rvars(ir_livegrass_pa)%r81d, & rio_age_pa => this%rvars(ir_age_pa)%r81d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & - rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d ) + rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & + rio_hydro_l_aroot_layer_si => this%rvars(ir_hydro_l_aroot_layer_si)%r81d, & + rio_hydro_r_node_shell_si => this%rvars(ir_hydro_r_node_shell_si)%r81d, & + rio_hydro_v_shell_si => this%rvars(ir_hydro_v_shell_si)%r81d, & + rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d + ) totalcohorts = 0 @@ -1895,6 +1994,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! Perform a check on the number of patches per site patchespersite = 0 + + cpatch => sites(s)%oldest_patch do while(associated(cpatch)) @@ -1942,6 +2043,28 @@ subroutine get_restart_vectors(this, nc, nsites, sites) this%rvars(ir_prt_var)%r81d(io_idx_co) end do end do + + + if(hlm_use_planthydro==itrue)then + + ! Load the storage compartment volumes + call this%RetrieveCohortRealVector(cohort%hydr_co%v_ag,n_hypool_ag, & + ir_hydro_v_ag_covec,io_idx_co) + call this%RetrieveCohortRealVector(cohort%hydr_co%v_troot,n_hypool_troot, & + ir_hydro_v_troot_covec,io_idx_co) + call this%RetrieveCohortRealVector(cohort%hydr_co%v_aroot_layer,site(s)%si_hydr%nlevsoi_hyd, & + ir_hydro_v_aroot_layer_covec,io_idx_co) + + ! Load the water contents + call this%RetrieveCohortRealVector(cohort%hydr_co%th_ag,n_hypool_ag, & + ir_hydro_th_ag_covec,io_idx_co) + call this%RetrieveCohortRealVector(cohort%hydr_co%th_troot,n_hypool_troot, & + ir_hydro_th_troot_covec,io_idx_co) + call this%RetrieveCohortRealVector(cohort%hydr_co%th_aroot_layer,site(s)%si_hydr%nlevsoi_hyd, & + ir_hydro_th_aroot_layer_covec,io_idx_co) + end if + + ccohort%canopy_layer = rio_canopy_layer_co(io_idx_co) ccohort%canopy_layer_yesterday = rio_canopy_layer_yesterday_co(io_idx_co) @@ -2069,6 +2192,43 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%water_memory(i) = rio_watermem_siwm( io_idx_si_wmem ) io_idx_si_wmem = io_idx_si_wmem + 1 end do + + ! ----------------------------------------------------------------------------- + ! Retrieve site-level hydraulics arrays + ! Note that Hydraulics structures, their allocations, and the length + ! declaration nlevsoi_hyd should be allocated early on when the code first + ! allocates sites (before restart info), and when the soils layer is + ! first known. + ! ----------------------------------------------------------------------------- + + if(hlm_use_planthydro==itrue)then + + ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell + do i = 1, site(s)%si_hydr%nlevsoi_hyd + + ! Loop shells + do k = 1, nshell + + sites(s)%si_hydr%r_node_shell(i,k) = & + rio_hydro_r_node_shell_si(io_idx_si_lyr_shell) + + sites(s)%si_hydr%v_shell(i,k) = & + rio_hydro_v_shell_si(io_idx_si_lyr_shell) + + sites(s)%si_hydr%h2osoi_liqvol_shell(i,k) = & + rio_hydro_liqvol_shell_si(io_idx_si_lyr_shell) + + io_idx_si_lyr_shell = io_idx_si_lyr_shell + 1 + end do + + sites(s)%si_hydr%l_aroot_layer(i) = & + rio_hydro_l_aroot_layer_si(io_idx_si_lyr) + + io_idx_si_lyr = io_idx_si_lyr + 1 + end do + + end if + sites(s)%old_stock = rio_old_stock_si(io_idx_si) sites(s)%status = rio_cd_status_si(io_idx_si) From 37291fc469da6f9ab5b28ccade507cbf6a83b4b4 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 13 Nov 2018 14:40:21 -0800 Subject: [PATCH 27/53] syntax and bug fixes for hydro restarts, code compiles, un-tested --- main/FatesRestartInterfaceMod.F90 | 164 ++++++++++++++++++------------ 1 file changed, 101 insertions(+), 63 deletions(-) diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 19ad6f0ce8..5e59e55137 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -15,8 +15,12 @@ module FatesRestartInterfaceMod use FatesInterfaceMod, only : bc_in_type use FatesInterfaceMod, only : bc_out_type use FatesInterfaceMod, only : hlm_use_planthydro + use FatesInterfaceMod, only : fates_maxElementsPerSite use FatesSizeAgeTypeIndicesMod, only : get_sizeage_class_index - + use FatesHydraulicsMemMod, only : nshell + use FatesHydraulicsMemMod, only : n_hypool_ag + use FatesHydraulicsMemMod, only : n_hypool_troot + use FatesHydraulicsMemMod, only : nlevsoi_hyd_max use PRTGenericMod, only : prt_global @@ -142,7 +146,7 @@ module FatesRestartInterfaceMod integer, private :: ir_hydro_th_ag_covec integer, private :: ir_hydro_th_troot_covec integer, private :: ir_hydro_th_aroot_covec - integer, private :: ir_hydro_aroot_layer_si + integer, private :: ir_hydro_l_aroot_layer_si integer, private :: ir_hydro_r_node_shell_si integer, private :: ir_hydro_v_shell_si integer, private :: ir_hydro_liqvol_shell_si @@ -221,6 +225,9 @@ module FatesRestartInterfaceMod procedure, private :: define_restart_vars procedure, private :: set_restart_var procedure, private :: DefinePRTRestartVars + procedure, private :: GetCohortRealVector + procedure, private :: SetCohortRealVector + procedure, private :: RegisterCohortVector end type fates_restart_interface_type @@ -836,37 +843,52 @@ subroutine define_restart_vars(this, initialize_variables) long_name='are of the ED patch', units='m2', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_area_pa ) - + + ! Only register hydraulics restart variables if it is turned on! + if(hlm_use_planthydro==itrue) then - call RegisterCohortVectors('fates_hydro_v_ag', vtype=cohort_r8, & - long_name='maximum storage volume of hydraulic compartments (above ground)', & - units='m3', n_hypool_ag, flushval = flushzero, & + if ( fates_maxElementsPerSite < (nshell * nlevsoi_hyd_max) ) then + write(fates_log(), *) ' Ftes plant hydraulics needs space to store site-level hydraulics info.' + write(fates_log(), *) ' It uses array spaces typically reserved for cohorts to hold this.' + write(fates_log(), *) ' However, that space defined by fates_maxElementsPerSite must be larger' + write(fates_log(), *) ' than the product of maximum soil layers x rhizosphere shells' + write(fates_log(), *) ' See FatesInterfaceMod.F90 for how this array is set' + write(fates_log(), *) ' fates_maxElementsPerSite = ',fates_maxElementsPerSite + write(fates_log(), *) ' nshell = ',nshell + write(fates_log(), *) ' nlevsoi_hyd_max = ',nlevsoi_hyd_max + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + + call this%RegisterCohortVector(symbol_base='fates_hydro_v_ag', vtype=cohort_r8, & + long_name_base='maximum storage volume of hydraulic compartments (above ground)', & + units='m3', veclength=n_hypool_ag, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_ag_covec) - call RegisterCohortVectors('fates_hydro_v_troot', vtype=cohort_r8, & - long_name='maximum storage volume of transporting root compartments', & - units='m3', n_hypool_troot, flushval = flushzero, & + call this%RegisterCohortVector(symbol_base='fates_hydro_v_troot', vtype=cohort_r8, & + long_name_base='maximum storage volume of transporting root compartments', & + units='m3', veclength=n_hypool_troot, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_troot_covec) - call RegisterCohortVectors('fates_hydro_v_aroot_layer', vtype=cohort_r8, & - long_name='maximum storage volume of absorbing roots hydraulic compartments by soil layer', & - units='m3', nlevsoi_hyd_max, flushval = flushzero, & + call this%RegisterCohortVector(symbol_base='fates_hydro_v_aroot_layer', vtype=cohort_r8, & + long_name_base='maximum storage volume of absorbing roots hydraulic compartments by layer', & + units='m3', veclength=nlevsoi_hyd_max, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_aroot_layer_covec) - call RegisterCohortVectors('fates_hydro_th_ag', vtype=cohort_r8, & - long_name='water in aboveground compartments', & - units='kg/plant', n_hypool_ag, flushval = flushzero, & + call this%RegisterCohortVector(symbol_base='fates_hydro_th_ag', vtype=cohort_r8, & + long_name_base='water in aboveground compartments', & + units='kg/plant', veclength=n_hypool_ag, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_th_ag_covec) - call RegisterCohortVectors('fates_hydro_th_troot', vtype=cohort_r8, & - long_name='water in transporting roots', & - units='kg/plant', n_hypool_troot, flushval = flushzero, & + call this%RegisterCohortVector(symbol_base='fates_hydro_th_troot', vtype=cohort_r8, & + long_name_base='water in transporting roots', & + units='kg/plant', veclength=n_hypool_troot, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_th_troot_covec) - call RegisterCohortVectors('fates_hydro_th_aroot', vtype=cohort_r8, & - long_name='water in absorbing roots', & - units='kg/plant', nlevsoi_hyd_max, flushval = flushzero, & + call this%RegisterCohortVector(symbol_base='fates_hydro_th_aroot', vtype=cohort_r8, & + long_name_base='water in absorbing roots', & + units='kg/plant', veclength=nlevsoi_hyd_max, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_th_aroot_covec) ! Site-level absorbing root maximum volume @@ -1048,11 +1070,11 @@ subroutine DefinePRTRestartVars(this,initialize_variables,ivar) return end subroutine DefinePRTRestartVars + ! ===================================================================================== - subroutine RegisterCohortVector(this,symbol_base, vtype_in, long_name_base, & - units_in, veclength, flushval, hlms_in, & - initialize=initialize_variables, & - ivar=ivar_inout, index = index_out) + subroutine RegisterCohortVector(this,symbol_base, vtype, long_name_base, & + units, veclength, flushval, hlms, & + initialize, ivar, index) ! The basic idea here is that instead of saving cohorts with vector data @@ -1065,25 +1087,27 @@ subroutine RegisterCohortVector(this,symbol_base, vtype_in, long_name_base, & class(fates_restart_interface_type) :: this character(*),intent(in) :: symbol_base ! Symbol name without position - character(*),intent(in) :: vtype_in ! String defining variable type + character(*),intent(in) :: vtype ! String defining variable type character(*),intent(in) :: long_name_base ! name without position - character(*),intent(in) :: units_in ! units for this variable + character(*),intent(in) :: units ! units for this variable integer,intent(in) :: veclength ! length of the vector - real(r8),intent(in) :: flushval_in ! Value to flush to - character(*),intent(in) :: hlms_in ! The HLMs this works in - logical, intent(in) :: init_var_in ! Is this registering or counting? - integer,intent(inout) :: ivar_inout ! global variable counter - integer,intent(out) :: index_out ! The variable index for this variable + real(r8),intent(in) :: flushval ! Value to flush to + character(*),intent(in) :: hlms ! The HLMs this works in + logical, intent(in) :: initialize ! Is this registering or counting? + integer,intent(inout) :: ivar ! global variable counter + integer,intent(out) :: index ! The variable index for this variable ! Local Variables character(len=4) :: pos_symbol ! vectors need text strings for each position character(len=128) :: symbol ! symbol name written to file character(len=256) :: long_name ! long name written to file integer :: i_pos ! loop counter for discrete position + integer :: dummy_index - ! We give each vector its own index + + ! We give each vector its own index that points to the first position - index_out = ivar_inout + 1 + index = ivar + 1 do i_pos = 1, veclength @@ -1097,11 +1121,11 @@ subroutine RegisterCohortVector(this,symbol_base, vtype_in, long_name_base, & long_name = trim(long_name_base)//', position:'//trim(pos_symbol) call this%set_restart_var(vname=trim(symbol), & - vtype=vtype_in, & + vtype=vtype, & long_name=trim(long_name), & - units=units_in, flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, & - ivar=ivar, index = index_out ) + units=units, flushval = flushval, & + hlms='CLM:ALM', initialize=initialize, & + ivar=ivar, index = dummy_index ) end do @@ -1109,8 +1133,8 @@ end subroutine RegisterCohortVector ! ===================================================================================== - subroutine RetrieveCohortRealVector(this, state_vector, len_state_vector, & - variable_index_base, co_global_index) + subroutine GetCohortRealVector(this, state_vector, len_state_vector, & + variable_index_base, co_global_index) ! This subroutine walks through global cohort vector indices ! and pulls from the different associated restart variables @@ -1130,7 +1154,7 @@ subroutine RetrieveCohortRealVector(this, state_vector, len_state_vector, & ir_pos_var = ir_pos_var + 1 end do return - end subroutine RetrieveCohortRealVector + end subroutine GetCohortRealVector ! ===================================================================================== @@ -1248,7 +1272,9 @@ subroutine set_restart_vectors(this,nc,nsites,sites) integer :: io_idx_pa_cwd ! each cwd class within each patch (pa_cwd) integer :: io_idx_pa_ib ! each SW band (vis/ir) per patch (pa_ib) integer :: io_idx_si_wmem ! each water memory class within each site - + integer :: io_idx_si_lyr ! site - layer x index + integer :: io_idx_si_lyr_shell ! site - layer x shell index + ! Some counters (for checking mostly) integer :: totalcohorts ! total cohort count on this thread (diagnostic) integer :: patchespersite ! number of patches per site @@ -1266,7 +1292,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) associate( rio_npatch_si => this%rvars(ir_npatch_si)%int1d, & - rio_old_stock_si => this%rvars(ir_oldstock_si)%r81d, & + rio_old_stock_si => this%rvars(ir_oldstock_si)%r81d, & rio_cd_status_si => this%rvars(ir_cd_status_si)%r81d, & rio_dd_status_si => this%rvars(ir_dd_status_si)%r81d, & rio_nchill_days_si => this%rvars(ir_nchill_days_si)%r81d, & @@ -1336,8 +1362,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_hydro_l_aroot_layer_si => this%rvars(ir_hydro_l_aroot_layer_si)%r81d, & rio_hydro_r_node_shell_si => this%rvars(ir_hydro_r_node_shell_si)%r81d, & rio_hydro_v_shell_si => this%rvars(ir_hydro_v_shell_si)%r81d, & - rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d - ) + rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d ) totalCohorts = 0 @@ -1437,14 +1462,20 @@ subroutine set_restart_vectors(this,nc,nsites,sites) if(hlm_use_planthydro==itrue)then ! Load the storage compartment volumes - call this%SetCohortRealVector(cohort%hydr_co%v_ag,n_hypool_ag,ir_hydro_v_ag_covec,io_idx_co) - call this%SetCohortRealVector(cohort%hydr_co%v_troot,n_hypool_troot,ir_hydro_v_troot_covec,io_idx_co) - call this%SetCohortRealVector(cohort%hydr_co%v_aroot_layer,site(s)%si_hydr%nlevsoi_hyd,ir_hydro_v_aroot_layer_covec,io_idx_co) + call this%SetCohortRealVector(ccohort%co_hydr%v_ag,n_hypool_ag, & + ir_hydro_v_ag_covec,io_idx_co) + call this%SetCohortRealVector(ccohort%co_hydr%v_troot,n_hypool_troot, & + ir_hydro_v_troot_covec,io_idx_co) + call this%SetCohortRealVector(ccohort%co_hydr%v_aroot_layer,sites(s)%si_hydr%nlevsoi_hyd, & + ir_hydro_v_aroot_layer_covec,io_idx_co) ! Load the water contents - call this%SetCohortRealVector(cohort%hydr_co%th_ag,n_hypool_ag,ir_hydro_th_ag_covec,io_idx_co) - call this%SetCohortRealVector(cohort%hydr_co%th_troot,n_hypool_troot,ir_hydro_th_troot_covec,io_idx_co) - call this%SetCohortRealVector(cohort%hydr_co%th_aroot_layer,site(s)%si_hydr%nlevsoi_hyd,ir_hydro_th_aroot_layer_covec,io_idx_co) + call this%SetCohortRealVector(ccohort%co_hydr%th_ag,n_hypool_ag, & + ir_hydro_th_ag_covec,io_idx_co) + call this%SetCohortRealVector(ccohort%co_hydr%th_troot,n_hypool_troot, & + ir_hydro_th_troot_covec,io_idx_co) + call this%SetCohortRealVector(ccohort%co_hydr%th_aroot,sites(s)%si_hydr%nlevsoi_hyd, & + ir_hydro_th_aroot_covec,io_idx_co) end if rio_canopy_layer_co(io_idx_co) = ccohort%canopy_layer @@ -1605,7 +1636,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) if(hlm_use_planthydro==itrue)then ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell - do i = 1, site_hydr%nlevsoi_hyd + do i = 1, sites(s)%si_hydr%nlevsoi_hyd ! Loop shells do k = 1, nshell @@ -1654,6 +1685,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in) use EDTypesMod, only : ncwd use EDTypesMod, only : maxSWb use FatesInterfaceMod, only : fates_maxElementsPerPatch + use EDTypesMod, only : maxpft use EDTypesMod, only : area use EDPatchDynamicsMod, only : zero_patch @@ -1888,6 +1920,8 @@ subroutine get_restart_vectors(this, nc, nsites, sites) integer :: io_idx_pa_cwd ! each cwd class within each patch (pa_cwd) integer :: io_idx_pa_ib ! each SW radiation band per patch (pa_ib) integer :: io_idx_si_wmem ! each water memory class within each site + integer :: io_idx_si_lyr ! site - layer x index + integer :: io_idx_si_lyr_shell ! site - layer x shell index ! Some counters (for checking mostly) integer :: totalcohorts ! total cohort count on this thread (diagnostic) @@ -1969,8 +2003,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_hydro_l_aroot_layer_si => this%rvars(ir_hydro_l_aroot_layer_si)%r81d, & rio_hydro_r_node_shell_si => this%rvars(ir_hydro_r_node_shell_si)%r81d, & rio_hydro_v_shell_si => this%rvars(ir_hydro_v_shell_si)%r81d, & - rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d - ) + rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d ) totalcohorts = 0 @@ -1984,7 +2017,12 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_pa_cwd = io_idx_co_1st io_idx_pa_ib = io_idx_co_1st io_idx_si_wmem = io_idx_co_1st - + + ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell + io_idx_si_lyr = io_idx_co_1st + io_idx_si_lyr_shell = io_idx_co_1st + + ! read seed_bank info(site-level, but PFT-resolved) do i = 1,numpft sites(s)%seed_bank(i) = rio_seed_bank_sift(io_idx_co_1st+i-1) @@ -2048,20 +2086,20 @@ subroutine get_restart_vectors(this, nc, nsites, sites) if(hlm_use_planthydro==itrue)then ! Load the storage compartment volumes - call this%RetrieveCohortRealVector(cohort%hydr_co%v_ag,n_hypool_ag, & + call this%GetCohortRealVector(ccohort%co_hydr%v_ag,n_hypool_ag, & ir_hydro_v_ag_covec,io_idx_co) - call this%RetrieveCohortRealVector(cohort%hydr_co%v_troot,n_hypool_troot, & + call this%GetCohortRealVector(ccohort%co_hydr%v_troot,n_hypool_troot, & ir_hydro_v_troot_covec,io_idx_co) - call this%RetrieveCohortRealVector(cohort%hydr_co%v_aroot_layer,site(s)%si_hydr%nlevsoi_hyd, & + call this%GetCohortRealVector(ccohort%co_hydr%v_aroot_layer,sites(s)%si_hydr%nlevsoi_hyd, & ir_hydro_v_aroot_layer_covec,io_idx_co) ! Load the water contents - call this%RetrieveCohortRealVector(cohort%hydr_co%th_ag,n_hypool_ag, & + call this%GetCohortRealVector(ccohort%co_hydr%th_ag,n_hypool_ag, & ir_hydro_th_ag_covec,io_idx_co) - call this%RetrieveCohortRealVector(cohort%hydr_co%th_troot,n_hypool_troot, & + call this%GetCohortRealVector(ccohort%co_hydr%th_troot,n_hypool_troot, & ir_hydro_th_troot_covec,io_idx_co) - call this%RetrieveCohortRealVector(cohort%hydr_co%th_aroot_layer,site(s)%si_hydr%nlevsoi_hyd, & - ir_hydro_th_aroot_layer_covec,io_idx_co) + call this%GetCohortRealVector(ccohort%co_hydr%th_aroot,sites(s)%si_hydr%nlevsoi_hyd, & + ir_hydro_th_aroot_covec,io_idx_co) end if @@ -2204,7 +2242,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) if(hlm_use_planthydro==itrue)then ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell - do i = 1, site(s)%si_hydr%nlevsoi_hyd + do i = 1, sites(s)%si_hydr%nlevsoi_hyd ! Loop shells do k = 1, nshell From ffd5e4f4663413f30d9262211445b6212c51bdce Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 14 Nov 2018 12:35:58 -0800 Subject: [PATCH 28/53] SPlitting up hydraulic props routine --- biogeochem/EDCohortDynamicsMod.F90 | 4 +- biogeochem/FatesAllometryMod.F90 | 28 +++ biogeophys/FatesPlantHydraulicsMod.F90 | 274 ++++++++++++++++--------- 3 files changed, 203 insertions(+), 103 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 939360388a..f2fdf22d14 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -243,8 +243,8 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, dbh, bleaf, bfine if( hlm_use_planthydro.eq.itrue ) then call InitHydrCohort(CurrentSite,new_cohort) - call updateSizeDepTreeHydProps(CurrentSite,new_cohort, bc_in) - call initTreeHydStates(CurrentSite,new_cohort, bc_in) +! call updateSizeDepTreeHydProps(CurrentSite,new_cohort, bc_in) +! call initTreeHydStates(CurrentSite,new_cohort, bc_in) if(recruitstatus==1)then new_cohort%co_hydr%is_newly_recruited = .true. endif diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index 81881a190a..d1a0eb8fa9 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -117,6 +117,7 @@ module FatesAllometryMod public :: decay_coeff_kn public :: StructureResetOfDH ! Method to set DBH to sync with structure biomass public :: CheckIntegratedAllometries + public :: CrownDepth public :: set_root_fraction ! Generic wrapper to calculate normalized ! root profiles @@ -1843,6 +1844,33 @@ subroutine h2d_martcano(h,p1,p2,p3,d,dddh) return end subroutine h2d_martcano + ! ===================================================================================== + + + subroutine CrownDepth(hite,crown_depth) + + ! ----------------------------------------------------------------------------------- + ! This routine returns the depth of a plant's crown. Which is the length + ! from the bottom of the crown to the top in the vertical dimension. + ! + ! This code may be used as a wrapper if different hypotheses are wished to be + ! optioned. + ! ----------------------------------------------------------------------------------- + + real(r8),intent(in) :: height ! The height of the plant [m] + real(r8),intent(out) :: crown_depth ! The depth of the crown [m] + + ! Alternative Hypothesis: + ! crown depth from Poorter, Bongers & Bongers + ! crown_depth = exp(-1.169_r8)*cCohort%hite**1.098_r8 + + crown_depth = min(cCohort%hite,0.1_r8) + + return + end subroutine CrownDepth + + + ! ============================================================================= ! Specific diameter to crown area allometries ! ============================================================================= diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 4a1404d292..17523e7947 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -173,15 +173,22 @@ end subroutine Hydraulics_Drive ! ===================================================================================== subroutine initTreeHydStates(site_p, cc_p, bc_in) + + ! REQUIRED INPUTS: ! + ! csite%si_hydr%psisoi_liq_innershell(:) + ! ccohort_hydr%z_node_troot(:) + ! ccohort_hydr%z_node_aroot + ! ccohort_hydr%z_node_ag + ! ! !DESCRIPTION: ! ! !USES: ! !ARGUMENTS: - type(ed_site_type), intent(inout), target :: site_p ! current cohort pointer - type(ed_cohort_type), intent(inout), target :: cc_p ! current cohort pointer - type(bc_in_type) , intent(in) :: bc_in + type(ed_site_type), intent(inout), target :: site_p ! current cohort pointer + type(ed_cohort_type), intent(inout), target :: cc_p ! current cohort pointer + type(bc_in_type) , intent(in) :: bc_in ! ! !LOCAL VARIABLES: type(ed_cohort_type), pointer :: cCohort @@ -257,14 +264,118 @@ subroutine initTreeHydStates(site_p, cc_p, bc_in) end subroutine initTreeHydStates + + ! ===================================================================================== + + + subroutine UpdateTreeHydrNodes(ccohort_hydr,pft,plant_height,nlevsoi_hyd) + + ! -------------------------------------------------------------------------------- + ! This subroutine calculates the nodal heights critical to hydraulics in the plant + ! + ! Inputs: Plant height + ! Plant functional type + ! Number of soil hydraulic layers + ! + ! Outputs: cohort_hydr%z_node_ag(:) + ! %z_lower_ag(:) + ! %z_upper_ag(:) + ! %z_node_troot(:) + ! %z_lower_troot(:) + ! %z_upper_troot(:) + ! %z_node_aroot(:) + ! -------------------------------------------------------------------------------- + + ! Arguments + type(ed_cohort_hydr_type), intent(inout) :: ccohort_hydr + integer,intent(in) :: pft ! plant functional type index + real(r8), intent(in) :: plant_height ! [m] + integer,intent(in) :: nlevsoi_hyd ! number of soil hydro layers + + ! Locals + + real(r8) :: roota ! root profile parameter a zeng2001_crootfr + real(r8) :: rootb ! root profile parameter b zeng2001_crootfr + real(r8) :: crown_depth ! crown depth for the plant [m] + real(r8) :: dz_canopy ! discrete crown depth intervals [m] + real(r8) :: z_stem ! the height of the plants stem below crown [m] + real(r8) :: dcumul_rf ! cumulative root distribution discretization [-] + real(r8) :: cumul_rf ! cumulative root distribution where depth is determined [-] + real(r8) :: z_cumul_rf ! depth at which cumul_rf occurs [m] + integer :: k ! Loop counter for compartments + + ! Crown Nodes + ! in special case where n_hypool_leaf = 1, the node height of the canopy + ! water pool is 1/2 the distance from the bottom of the canopy to the top of the tree + + call CrownDepth(plant_height,crown_depth) + + dz_canopy = crown_depth / real(n_hypool_leaf,r8) + do k=1,n_hypool_leaf + ccohort_hydr%z_lower_ag(k) = plant_height - dz_canopy*real(k,r8) + ccohort_hydr%z_node_ag(k) = ccohort_hydr%z_lower_ag(k) + 0.5_r8*dz_canopy + ccohort_hydr%z_upper_ag(k) = ccohort_hydr%z_lower_ag(k) + dz_canopy + enddo + + + ! Stem Nodes + ! in special case where n_hypool_stem = 1, the node height of the stem water pool is + ! 1/2 the height from the ground to the bottom of the canopy + z_stem = plant_height - crown_depth + dz_stem = z_stem / real(n_hypool_stem,r8) + do k=n_hypool_leaf+1,n_hypool_ag + ccohort_hydr%z_upper_ag(k) = real(n_hypool_stem - (k - 1 - n_hypool_leaf),r8)*dz_stem + ccohort_hydr%z_node_ag(k) = ccohort_hydr%z_upper_ag(k) - 0.5_r8*dz_stem + ccohort_hydr%z_lower_ag(k) = ccohort_hydr%z_upper_ag(k) - dz_stem + enddo + + ! Transporting Root Nodes + ! in special case where n_hypool_troot = 1, the node depth of the single troot pool + ! is the depth at which 50% total root distribution is attained + dcumul_rf = 1._r8/real(n_hypool_troot,r8) + + do k=1,n_hypool_troot + cumul_rf = dcumul_rf*real(k,r8) + call bisect_rootfr(roota, rootb, 0._r8, 1.E10_r8, & + 0.001_r8, 0.001_r8, cumul_rf, z_cumul_rf) + z_cumul_rf = min(z_cumul_rf, abs(bc_in%zi_sisl(nlevsoi_hyd))) + ccohort_hydr%z_lower_troot(k) = -z_cumul_rf + call bisect_rootfr(roota, rootb, 0._r8, 1.E10_r8, & + 0.001_r8, 0.001_r8, cumul_rf-0.5_r8*dcumul_rf, z_cumul_rf) + z_cumul_rf = min(z_cumul_rf, abs(bc_in%zi_sisl(nlevsoi_hyd))) + ccohort_hydr%z_node_troot(k) = -z_cumul_rf + call bisect_rootfr(roota, rootb, 0._r8, 1.E10_r8, & + 0.001_r8, 0.001_r8, cumul_rf-1.0_r8*dcumul_rf+1.E-10_r8, z_cumul_rf) + z_cumul_rf = min(z_cumul_rf, abs(bc_in%zi_sisl(nlevsoi_hyd))) + ccohort_hydr%z_upper_troot(k) = -z_cumul_rf + enddo + + + ! Absorbing root depth + ccohort_hydr%z_node_aroot(1:nlevsoi_hyd) = -bc_in%z_sisl(1:nlevsoi_hyd) + + + ! Shouldn't this be updating the upper and lower values as well? + ! (RGK 12-2018) + if(nlevsoi_hyd == 1) then + ccohort_hydr%z_node_troot(:) = ccohort_hydr%z_node_aroot(nlevsoi_hyd) + end if + + + + return + end subroutine UpdateTreeHydrNodes + + ! ===================================================================================== - subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) + + subroutine updateSizeDepTreeHydProps(currentSite,ccohort,bc_in) ! - ! !DESCRIPTION: Updates absorbing root length (total and its vertical distribution) - ! as well as the consequential change in the size of the 'representative' rhizosphere - ! shell radii, volumes + ! DESCRIPTION: Updates absorbing root length (total and its vertical distribution) + ! as well as the consequential change in the size of the 'representative' rhizosphere + ! shell radii, volumes, and compartment volumes of plant tissues ! ! !USES: use FatesConstantsMod , only : pi_const @@ -272,22 +383,19 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) ! ! !ARGUMENTS: type(ed_site_type) , intent(in) :: currentSite ! Site stuff - type(ed_cohort_type) , intent(inout), target :: cc_p ! current cohort pointer - type(bc_in_type) , intent(in) :: bc_in ! Boundary Conditions + type(ed_cohort_type) , intent(inout) :: ccohort ! current cohort pointer + type(bc_in_type) , intent(in) :: bc_in ! Boundary Conditions ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: cCohort + type(ed_patch_type), pointer :: cPatch - integer :: i,j,k,FT ! indices + integer :: i,j,k,ft ! indices real(r8) :: b_tot_carb ! total individual biomass in carbon units [kgC/indiv] real(r8) :: b_bg_carb ! belowground biomass (coarse + fine roots) in carbon units [kgC/indiv] real(r8) :: roota, rootb ! parameters for root distribution [m-1] real(r8) :: latosa ! leaf:sapwood area ratio [m2/cm2] ! TRANSPORTING ROOT QUANTITIES - real(r8) :: dcumul_rf ! cumulative root distribution discretization [-] - real(r8) :: cumul_rf ! cumulative root distribution where depth is determined [-] - real(r8) :: z_cumul_rf ! depth at which cumul_rf occurs [m] real(r8) :: b_troot_carb ! transporting root biomass in carbon units [kgC/indiv] real(r8) :: b_troot_biom ! transporting root biomass in dry wt units [kg/indiv] real(r8) :: v_troot ! transporting root volume [m3/indiv] @@ -326,142 +434,107 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) real(r8) :: kmax_tot ! total tree (leaf to root tip) hydraulic conductance [kg s-1 MPa-1] real(r8) :: dz_node1_nodekplus1 ! cumulative distance between canopy node and node k + 1 [m] real(r8) :: dz_node1_lowerk ! cumulative distance between canopy node and upper boundary of node k [m] - real(r8) :: leaf_c - real(r8) :: fnrt_c - real(r8) :: sapw_c - real(r8) :: struct_c + real(r8) :: leaf_c ! Current amount of leaf carbon in the plant [kg] + real(r8) :: fnrt_c ! Current amount of fine-root carbon in the plant [kg] + real(r8) :: sapw_c ! Current amount of sapwood carbon in the plant [kg] + real(r8) :: struct_c ! Current amount of structural carbon in the plant [kg] integer :: nlevsoi_hyd ! Number of soil hydraulic layers integer :: nlevsoil ! Number of total soil layers type(ed_cohort_hydr_type), pointer :: ccohort_hydr !----------------------------------------------------------------------- + nlevsoi_hyd = currentSite%si_hydr%nlevsoi_hyd nlevsoil = bc_in%nlevsoil - cCohort => cc_p + ccohort => cc_p ccohort_hydr => cc_p%co_hydr - cPatch => cCohort%patchptr - FT = cCohort%pft - roota = EDPftvarcon_inst%roota_par(FT) - rootb = EDPftvarcon_inst%rootb_par(FT) + cPatch => ccohort%patchptr + ft = ccohort%pft + + ! This updates all of the z_node positions + call UpdateTreeHydrNodes(ccohort_hydr,ft,ccohort%hite,nlevsoi_hyd) - leaf_c = cCohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = cCohort%prt%GetState(sapw_organ, all_carbon_elements) - fnrt_c = cCohort%prt%GetState(fnrt_organ, all_carbon_elements) - struct_c = cCohort%prt%GetState(struct_organ, all_carbon_elements) + ! SAVE INITIAL VOLUMES + ccohort_hydr%v_ag_init(:) = ccohort_hydr%v_ag(:) + ccohort_hydr%v_troot_init(:) = ccohort_hydr%v_troot(:) + ccohort_hydr%v_aroot_layer_init(:) = ccohort_hydr%v_aroot_layer(:) + + + ! Pre-process biomass pools + + leaf_c = ccohort%prt%GetState(leaf_organ, all_carbon_elements) + sapw_c = ccohort%prt%GetState(sapw_organ, all_carbon_elements) + fnrt_c = ccohort%prt%GetState(fnrt_organ, all_carbon_elements) + struct_c = ccohort%prt%GetState(struct_organ, all_carbon_elements) !roota = 4.372_r8 ! TESTING: deep (see Zeng 2001 Table 1) !rootb = 0.978_r8 ! TESTING: deep (see Zeng 2001 Table 1) !roota = 8.992_r8 ! TESTING: shallow (see Zeng 2001 Table 1) !rootb = 8.992_r8 ! TESTING: shallow (see Zeng 2001 Table 1) - if(leaf_c>0.0) then !only update when bleaf >0 - b_woody_carb = sapw_c + struct_c - b_woody_bg_carb = (1.0_r8-EDPftvarcon_inst%allom_agb_frac(FT)) * b_woody_carb + if(leaf_c > 0._r8) then + + b_woody_carb = sapw_c + struct_c + b_woody_bg_carb = (1.0_r8-EDPftvarcon_inst%allom_agb_frac(ft)) * b_woody_carb b_tot_carb = sapw_c + struct_c + leaf_c + fnrt_c b_canopy_carb = leaf_c - b_bg_carb = (1.0_r8-EDPftvarcon_inst%allom_agb_frac(FT)) * b_tot_carb - - ! SAVE INITIAL VOLUMES - ccohort_hydr%v_ag_init(:) = ccohort_hydr%v_ag(:) - ccohort_hydr%v_troot_init(:) = ccohort_hydr%v_troot(:) - ccohort_hydr%v_aroot_layer_init(:) = ccohort_hydr%v_aroot_layer(:) - - ! CANOPY HEIGHT & CANOPY LEAF VOLUME - !in special case where n_hypool_leaf = 1, the node height of the canopy water pool is - !1/2 the distance from the bottom of the canopy to the top of the tree - !depth_canopy = exp(-1.169_r8)*cCohort%hite**1.098_r8 !! crown depth from Poorter, Bongers & Bongers - depth_canopy = min(cCohort%hite,0.1_r8) ! 0.0_r8 was default, now changed 01/14/2017 (BOC) - dz_canopy = depth_canopy / n_hypool_leaf - do k=1,n_hypool_leaf - ccohort_hydr%z_lower_ag(k) = cCohort%hite - dz_canopy*k - ccohort_hydr%z_node_ag(k) = ccohort_hydr%z_lower_ag(k) + 0.5_r8*dz_canopy - ccohort_hydr%z_upper_ag(k) = ccohort_hydr%z_lower_ag(k) + dz_canopy - enddo + b_bg_carb = (1.0_r8-EDPftvarcon_inst%allom_agb_frac(ft)) * b_tot_carb b_canopy_biom = b_canopy_carb * C2B ! NOTE: SLATOP currently does not use any vertical scaling functions ! but that may not be so forever. ie sla = slatop (RGK-082017) - sla = EDPftvarcon_inst%slatop(FT) * cm2_per_m2 ! m2/gC * cm2/m2 -> cm2/gC + sla = EDPftvarcon_inst%slatop(ft) * cm2_per_m2 ! m2/gC * cm2/m2 -> cm2/gC denleaf = -2.3231_r8*sla/C2B + 781.899_r8 ! empirical regression data from leaves at Caxiuana (~ 8 spp) v_canopy = b_canopy_biom / denleaf - ccohort_hydr%v_ag(1:n_hypool_leaf) = v_canopy / n_hypool_leaf + ccohort_hydr%v_ag(1:n_hypool_leaf) = v_canopy / real(n_hypool_leaf,r8) - ! STEM HEIGHT & VOLUME - !in special case where n_hypool_stem = 1, the node height of the stem water pool is - !1/2 the height from the ground to the bottom of the canopy - z_stem = cCohort%hite - depth_canopy - dz_stem = z_stem / n_hypool_stem - do k=n_hypool_leaf+1,n_hypool_ag - ccohort_hydr%z_upper_ag(k) = (n_hypool_stem - (k - 1 - n_hypool_leaf))*dz_stem - ccohort_hydr%z_node_ag(k) = ccohort_hydr%z_upper_ag(k) - 0.5_r8*dz_stem - ccohort_hydr%z_lower_ag(k) = ccohort_hydr%z_upper_ag(k) - dz_stem - enddo + b_stem_carb = b_tot_carb - b_bg_carb - b_canopy_carb b_stem_biom = b_stem_carb * C2B ! kg DM - v_stem = b_stem_biom / (EDPftvarcon_inst%wood_density(FT)*1.e3_r8) !BOC...may be needed for testing/comparison w/ v_sapwood + v_stem = b_stem_biom / (EDPftvarcon_inst%wood_density(ft)*1.e3_r8) !BOC...may be needed for testing/comparison w/ v_sapwood a_leaf_tot = b_canopy_carb * sla * 1.e3_r8 / 1.e4_r8 ! m2 leaf = kg leaf DM * cm2/g * 1000g/1kg * 1m2/10000cm2 - call bsap_allom(cCohort%dbh,cCohort%pft,cCohort%canopy_trim,a_sapwood_target,bsw_target) + call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim,a_sapwood_target,bsw_target) a_sapwood = a_sapwood_target ! or .... ! a_sapwood = a_sapwood_target * ccohort%bsw / bsw_target - ! a_sapwood = a_leaf_tot / EDPftvarcon_inst%allom_latosa_int(FT)*1.e-4_r8 + ! a_sapwood = a_leaf_tot / EDPftvarcon_inst%allom_latosa_int(ft)*1.e-4_r8 ! m2 sapwood = m2 leaf * cm2 sapwood/m2 leaf *1.0e-4m2 ! or ... - !a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * cCohort%hite ) * 1.e-4_r8 + !a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * ccohort%hite ) * 1.e-4_r8 v_sapwood = a_sapwood * z_stem ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem - ! TRANSPORTING ROOT DEPTH & VOLUME - !in special case where n_hypool_troot = 1, the node depth of the single troot pool - !is the depth at which 50% total root distribution is attained - dcumul_rf = 1._r8/real(n_hypool_troot,r8) - - do k=1,n_hypool_troot - cumul_rf = dcumul_rf*k - call bisect_rootfr(roota, rootb, 0._r8, 1.E10_r8, & - 0.001_r8, 0.001_r8, cumul_rf, z_cumul_rf) - z_cumul_rf = min(z_cumul_rf, abs(bc_in%zi_sisl(nlevsoi_hyd))) - ccohort_hydr%z_lower_troot(k) = -z_cumul_rf - call bisect_rootfr(roota, rootb, 0._r8, 1.E10_r8, & - 0.001_r8, 0.001_r8, cumul_rf-0.5_r8*dcumul_rf, z_cumul_rf) - z_cumul_rf = min(z_cumul_rf, abs(bc_in%zi_sisl(nlevsoi_hyd))) - ccohort_hydr%z_node_troot(k) = -z_cumul_rf - call bisect_rootfr(roota, rootb, 0._r8, 1.E10_r8, & - 0.001_r8, 0.001_r8, cumul_rf-1.0_r8*dcumul_rf+1.E-10_r8, z_cumul_rf) - z_cumul_rf = min(z_cumul_rf, abs(bc_in%zi_sisl(nlevsoi_hyd))) - ccohort_hydr%z_upper_troot(k) = -z_cumul_rf - enddo + !Determine belowground biomass as a function of total (sapwood, heartwood, leaf, fine root) biomass !then subtract out the fine root biomass to get coarse (transporting) root biomass b_troot_carb = b_woody_bg_carb b_troot_biom = b_troot_carb * C2B - v_troot = b_troot_biom / (EDPftvarcon_inst%wood_density(FT)*1.e3_r8) + v_troot = b_troot_biom / (EDPftvarcon_inst%wood_density(ft)*1.e3_r8) ccohort_hydr%v_troot(:) = v_troot / n_hypool_troot !! BOC not sure if/how we should multiply this by the sapwood fraction - ! ABSORBING ROOT DEPTH, LENGTH & VOLUME - ccohort_hydr%z_node_aroot(1:nlevsoi_hyd) = -bc_in%z_sisl(1:nlevsoi_hyd) + - ccohort_hydr%l_aroot_tot = fnrt_c*C2B*EDPftvarcon_inst%hydr_srl(FT) - !ccohort_hydr%v_aroot_tot = fnrt_c/EDecophyscon%ccontent(FT)/EDecophyscon%rootdens(FT) - ccohort_hydr%v_aroot_tot = pi_const*(EDPftvarcon_inst%hydr_rs2(FT)**2._r8)*ccohort_hydr%l_aroot_tot - !ccohort_hydr%l_aroot_tot = ccohort_hydr%v_aroot_tot/(pi_const*EDecophyscon%rs2(FT)**2) + ccohort_hydr%l_aroot_tot = fnrt_c*C2B*EDPftvarcon_inst%hydr_srl(ft) + !ccohort_hydr%v_aroot_tot = fnrt_c/EDecophyscon%ccontent(ft)/EDecophyscon%rootdens(ft) + ccohort_hydr%v_aroot_tot = pi_const*(EDPftvarcon_inst%hydr_rs2(ft)**2._r8)*ccohort_hydr%l_aroot_tot + !ccohort_hydr%l_aroot_tot = ccohort_hydr%v_aroot_tot/(pi_const*EDecophyscon%rs2(ft)**2) if(nlevsoi_hyd == 1) then ccohort_hydr%l_aroot_layer(nlevsoi_hyd) = ccohort_hydr%l_aroot_tot ccohort_hydr%v_aroot_layer(nlevsoi_hyd) = ccohort_hydr%v_aroot_tot else - ! ccohort_hydr%l_aroot_layer(:) = cPatch%rootfr_ft(FT,:)*ccohort_hydr%l_aroot_tot - ! ccohort_hydr%v_aroot_layer(:) = cPatch%rootfr_ft(FT,:)*ccohort_hydr%v_aroot_tot + ! ccohort_hydr%l_aroot_layer(:) = cPatch%rootfr_ft(ft,:)*ccohort_hydr%l_aroot_tot + ! ccohort_hydr%v_aroot_layer(:) = cPatch%rootfr_ft(ft,:)*ccohort_hydr%v_aroot_tot do j=1,nlevsoi_hyd if(j == 1) then rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) @@ -473,9 +546,7 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) ccohort_hydr%v_aroot_layer(j) = rootfr*ccohort_hydr%v_aroot_tot end do end if - if(nlevsoi_hyd == 1) then - ccohort_hydr%z_node_troot(:) = ccohort_hydr%z_node_aroot(nlevsoi_hyd) - end if + ! MAXIMUM (SIZE-DEPENDENT) HYDRAULIC CONDUCTANCES ! first estimate cumulative (petiole to node k) conductances without taper as well as the chi taper function @@ -486,12 +557,13 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) else dz_node1_nodekplus1 = ccohort_hydr%z_node_ag(n_hypool_leaf) - ccohort_hydr%z_node_troot(1) end if - kmax_node1_nodekplus1(k) = EDPftvarcon_inst%hydr_kmax_node(FT,2) * a_sapwood / dz_node1_nodekplus1 - kmax_node1_lowerk(k) = EDPftvarcon_inst%hydr_kmax_node(FT,2) * a_sapwood / dz_node1_lowerk + kmax_node1_nodekplus1(k) = EDPftvarcon_inst%hydr_kmax_node(ft,2) * a_sapwood / dz_node1_nodekplus1 + kmax_node1_lowerk(k) = EDPftvarcon_inst%hydr_kmax_node(ft,2) * a_sapwood / dz_node1_lowerk chi_node1_nodekplus1(k) = xylemtaper(p, dz_node1_nodekplus1) chi_node1_lowerk(k) = xylemtaper(p, dz_node1_lowerk) if(.not.do_kbound_upstream) then - if(depth_canopy == 0._r8) then + call CrownDepth(ccohort%hite,crown_depth) + if(crown_depth == 0._r8) then write(fates_log(),*) 'do_kbound_upstream requires a nonzero canopy depth ' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -528,10 +600,10 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) enddo ! finally, estimate the remaining tree conductance belowground as a residual kmax_treeag_tot = sum(1._r8/ccohort_hydr%kmax_bound(n_hypool_leaf:n_hypool_ag))**(-1._r8) - kmax_tot = EDPftvarcon_inst%hydr_rfrac_stem(FT) * kmax_treeag_tot + kmax_tot = EDPftvarcon_inst%hydr_rfrac_stem(ft) * kmax_treeag_tot ccohort_hydr%kmax_treebg_tot = ( 1._r8/kmax_tot - 1._r8/kmax_treeag_tot ) ** (-1._r8) if(nlevsoi_hyd == 1) then - ccohort_hydr%kmax_treebg_layer(:) = ccohort_hydr%kmax_treebg_tot * cPatch%rootfr_ft(FT,:) + ccohort_hydr%kmax_treebg_layer(:) = ccohort_hydr%kmax_treebg_tot * cPatch%rootfr_ft(ft,:) else do j=1,nlevsoi_hyd if(j == 1) then From 56de48280a423b9fe8b4d730ad4b9c5d5d9451bf Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Wed, 14 Nov 2018 14:36:20 -0700 Subject: [PATCH 29/53] update the c_area and treelai for fusecohort in hydraulics --- biogeochem/EDCohortDynamicsMod.F90 | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 0d1881d99f..281b688641 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -724,8 +724,15 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) call sizetype_class_index(currentCohort%dbh,currentCohort%pft, & currentCohort%size_class,currentCohort%size_by_pft_class) - - if(hlm_use_planthydro.eq.itrue) call FuseCohortHydraulics(currentSite,currentCohort,nextc,bc_in,newn) + + + if(hlm_use_planthydro.eq.itrue) then + call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & + currentCohort%pft,currentCohort%c_area) + currentCohort%treelai = tree_lai(currentCohort%bl, currentCohort%status_coh, & + currentCohort%pft, currentCohort%c_area, currentCohort%n ) + call FuseCohortHydraulics(currentSite,currentCohort,nextc,bc_in,newn) + endif ! recent canopy history currentCohort%canopy_layer_yesterday = (currentCohort%n*currentCohort%canopy_layer_yesterday + & From 0a2e40d9777c9b254a3cfdda19a400513e1d0e86 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Wed, 14 Nov 2018 14:41:25 -0700 Subject: [PATCH 30/53] use the profile-based leaf area for hydraulics for code consistency --- biogeophys/FatesPlantHydraulicsMod.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index e4a4879e6c..c16c92dd7c 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -385,7 +385,8 @@ subroutine updateSizeDepTreeHydProps(currentSite,cc_p,bc_in) b_stem_carb = b_tot_carb - b_bg_carb - b_canopy_carb b_stem_biom = b_stem_carb * C2B ! kg DM v_stem = b_stem_biom / (EDPftvarcon_inst%wood_density(FT)*1.e3_r8) !BOC...may be needed for testing/comparison w/ v_sapwood - a_leaf_tot = b_canopy_carb * sla * 1.e3_r8 / 1.e4_r8 ! m2 leaf = kg leaf DM * cm2/g * 1000g/1kg * 1m2/10000cm2 + !a_leaf_tot = b_canopy_carb * sla * 1.e3_r8 / 1.e4_r8 ! m2 leaf = kg leaf DM * cm2/g * 1000g/1kg * 1m2/10000cm2 + a_leaf_tot = cCohort%treelai * cCohort%c_area/cCohort%n ! calculate the leaf area based on the leaf profile !a_sapwood = a_leaf_tot / EDPftvarcon_inst%allom_latosa_int(FT)*1.e-4_r8 ! m2 sapwood = m2 leaf * cm2 sapwood/m2 leaf *1.0e-4m2 !a_sapwood = a_leaf_tot * ( EDPftvarcon_inst%allom_latosa_int(FT) + cCohort%dbh* EDPftvarcon_inst%allom_latosa_slp(FT) ) *1.e-4_r8 ! applying Calvo-Alvarado allometry here since using realistic sapwood area in the rest of the model causes trees to die From e6679a850c03ae92849d08472fd60a5415520d53 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 14 Nov 2018 16:07:42 -0800 Subject: [PATCH 31/53] Re-arranging calls to initialize hydro cohorts --- biogeochem/EDCohortDynamicsMod.F90 | 33 +- biogeochem/EDPhysiologyMod.F90 | 5 +- biogeophys/FatesPlantHydraulicsMod.F90 | 488 ++++++++++++++----------- 3 files changed, 311 insertions(+), 215 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index f2fdf22d14..a24d75a773 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -98,6 +98,13 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, dbh, bleaf, bfine ! ! !DESCRIPTION: ! create new cohort + ! There are 4 places this is called + ! 1) Initializing new cohorts at the beginning of a cold-start simulation + ! 2) Initializing new recruits during dynamics + ! 3) Initializing new cohorts at the beginning of a inventory read + ! 4) Initializing new cohorts during restart + ! + ! It is assumed that in the first 3, this is called with a reasonable amount of starter information. ! ! !USES: ! @@ -126,6 +133,7 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, dbh, bleaf, bfine type(ed_cohort_type), pointer :: new_cohort ! Pointer to New Cohort structure. type(ed_cohort_type), pointer :: storesmallcohort type(ed_cohort_type), pointer :: storebigcohort + type(ed_cohort_hydr_type), pointer :: ccohort_hydr integer :: tnull,snull ! are the tallest and shortest cohorts allocate !---------------------------------------------------------------------- @@ -242,12 +250,31 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, dbh, bleaf, bfine new_cohort%isnew = .true. if( hlm_use_planthydro.eq.itrue ) then - call InitHydrCohort(CurrentSite,new_cohort) -! call updateSizeDepTreeHydProps(CurrentSite,new_cohort, bc_in) -! call initTreeHydStates(CurrentSite,new_cohort, bc_in) + + ccohort_hydr => ccohort%co_hydr + nlevsoi_hydr = currentSite%si_hydr%nlevsoi_hyd + + ! This allocates array spaces + call InitHydrCohort(currentSite,new_cohort) + + ! This calculates node heights + call UpdateTreeHydrNodes(ccohort_hydr,ft,new_cohort%hite,nlevsoi_hydr) + + ! This calculates volumes, lengths and max conductances + call UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) + + ! Since this is a newly initialized plant, we set the previous compartment-size + ! equal to the ones we just calculated. + call SavePreviousCompartmentVolumes(ccohort_hydr) + + ! This comes up with starter suctions and then water contents + ! based on the soil values + call initTreeHydStates(currentSite,new_cohort, bc_in) + if(recruitstatus==1)then new_cohort%co_hydr%is_newly_recruited = .true. endif + endif call insert_cohort(new_cohort, patchptr%tallest, patchptr%shortest, tnull, snull, & diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 50b91c3513..89e3257537 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1002,13 +1002,12 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) endif if (temp_cohort%n > 0.0_r8 )then - if ( debug ) write(fates_log(),*) 'EDPhysiologyMod.F90 call create_cohort ' + call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, temp_cohort%dbh, & b_leaf, b_fineroot, b_sapwood, b_dead, b_store, & temp_cohort%laimemory, cohortstatus,recruitstatus, temp_cohort%canopy_trim, currentPatch%NCL_p, & currentSite%spread, bc_in) - - + ! keep track of how many individuals were recruited for passing to history currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + temp_cohort%n diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 17523e7947..41ec79b178 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -83,7 +83,7 @@ module FatesPlantHydraulicsMod ! CIME Globals use shr_log_mod , only : errMsg => shr_log_errMsg use shr_infnan_mod , only : isnan => shr_infnan_isnan - + implicit none @@ -115,6 +115,12 @@ module FatesPlantHydraulicsMod character(len=*), parameter, private :: sourcefile = & __FILE__ + + + ! We use this parameter as the value for which we set un-initialized values + real(r8), parameter :: un_initialized = -9.9e32_r8 + + ! ! !PUBLIC MEMBER FUNCTIONS: public :: AccumulateMortalityWaterStorage @@ -366,257 +372,319 @@ subroutine UpdateTreeHydrNodes(ccohort_hydr,pft,plant_height,nlevsoi_hyd) return end subroutine UpdateTreeHydrNodes - ! ===================================================================================== - + subroutine SavePreviousCompartmentVolumes(ccohort_hydr) + + type(ed_cohort_hydr_type),intent(inout) :: ccohort_hydr + + + ! Saving the current compartment volumes into an "initial" save-space + ! allows us to see how the compartments change size when plants + ! change size and effect water contents + + ccohort_hydr%v_ag_init(:) = ccohort_hydr%v_ag(:) + ccohort_hydr%v_troot_init(:) = ccohort_hydr%v_troot(:) + ccohort_hydr%v_aroot_layer_init(:) = ccohort_hydr%v_aroot_layer(:) + + + return + end subroutine SavePreviousCompartmentVolumes + + ! ===================================================================================== + subroutine updateSizeDepTreeHydProps(currentSite,ccohort,bc_in) - ! + ! DESCRIPTION: Updates absorbing root length (total and its vertical distribution) ! as well as the consequential change in the size of the 'representative' rhizosphere ! shell radii, volumes, and compartment volumes of plant tissues - ! + ! !USES: use FatesConstantsMod , only : pi_const use shr_sys_mod , only : shr_sys_abort - ! - ! !ARGUMENTS: + + ! ARGUMENTS: type(ed_site_type) , intent(in) :: currentSite ! Site stuff type(ed_cohort_type) , intent(inout) :: ccohort ! current cohort pointer type(bc_in_type) , intent(in) :: bc_in ! Boundary Conditions - ! !LOCAL VARIABLES: - - - type(ed_patch_type), pointer :: cPatch - integer :: i,j,k,ft ! indices - real(r8) :: b_tot_carb ! total individual biomass in carbon units [kgC/indiv] - real(r8) :: b_bg_carb ! belowground biomass (coarse + fine roots) in carbon units [kgC/indiv] - real(r8) :: roota, rootb ! parameters for root distribution [m-1] - real(r8) :: latosa ! leaf:sapwood area ratio [m2/cm2] - ! TRANSPORTING ROOT QUANTITIES - real(r8) :: b_troot_carb ! transporting root biomass in carbon units [kgC/indiv] - real(r8) :: b_troot_biom ! transporting root biomass in dry wt units [kg/indiv] - real(r8) :: v_troot ! transporting root volume [m3/indiv] - real(r8) :: rootfr - ! CANOPY or LEAF QUANTITIES - real(r8) :: sla ! specific leaf area [cm2/g] - real(r8) :: depth_canopy ! crown (canopy) depth [m] - real(r8) :: dz_canopy ! vertical canopy discretization [m] - real(r8) :: a_sapwood_target ! sapwood cross-section area at reference height, at target biomass [m2] - real(r8) :: bsw_target ! sapwood carbon, at target [kgC] - real(r8) :: a_leaf_tot ! total leaf area [m2/indiv] - real(r8) :: b_canopy_carb ! total leaf (canopy) biomass in carbon units [kgC/indiv] - real(r8) :: b_canopy_biom ! total leaf (canopy) biomass in dry wt units [kg/indiv] - real(r8) :: v_canopy ! total leaf (canopy) volume [m3/indiv] - real(r8) :: denleaf ! leaf dry mass per unit fresh leaf volume [kg/m3] - ! STEM OR SAPWOOD QUANTITIES - real(r8) :: a_sapwood ! sapwood area [m2] - real(r8) :: v_sapwood ! sapwood volume [m3] - real(r8) :: z_stem ! tree height, minus any crown depth [m] - real(r8) :: dz_stem ! vertical stem discretization [m] - real(r8) :: b_woody_carb ! total woody biomass in carbon units [kgC/indiv] - real(r8) :: b_woody_bg_carb ! belowground woody biomass in carbon units [kgC/indiv] - real(r8) :: b_stem_carb ! aboveground stem biomass in carbon units [kgC/indiv] - real(r8) :: b_stem_biom ! aboveground stem biomass in dry wt units [kg/indiv] - real(r8) :: v_stem ! aboveground stem volume [m3/indiv] - !HYDRAULIC MAXIMUM CONDUCTANCES and assoc vars - real(r8) :: p=1._r8/3._r8 ! Savage et al. (2010) xylem taper exponent [-] - real(r8) :: rint_jansenchoat=22._r8 ! conduit radius at branch location where kmax measured, tropical mean [um] - real(r8) :: rint_petiole=10._r8 ! petiole conduit radius (assumed invariant, sensu Savage et al. 2010) [um] - real(r8) :: kmax_node_petiole ! maximum hydraulic conductivity at petiole [kg m-1 s-1 MPa-1] - real(r8) :: kmax_node1_nodekplus1(n_hypool_ag) ! cumulative kmax, petiole to node k+1, conduit taper effects excluded [kg s-1 MPa-1] - real(r8) :: kmax_node1_lowerk(n_hypool_ag) ! cumulative kmax, petiole to upper boundary of node k, conduit taper effects excluded [kg s-1 MPa-1] - real(r8) :: chi_node1_nodekplus1(n_hypool_ag)! ratio of cumulative kmax with taper effects included to that without [-] - real(r8) :: chi_node1_lowerk(n_hypool_ag) ! ratio of cumulative kmax with taper effects included to that without [-] - real(r8) :: kmax_treeag_tot ! total stem (petiole to transporting root node) hydraulic conductance [kg s-1 MPa-1] - real(r8) :: kmax_tot ! total tree (leaf to root tip) hydraulic conductance [kg s-1 MPa-1] - real(r8) :: dz_node1_nodekplus1 ! cumulative distance between canopy node and node k + 1 [m] - real(r8) :: dz_node1_lowerk ! cumulative distance between canopy node and upper boundary of node k [m] - real(r8) :: leaf_c ! Current amount of leaf carbon in the plant [kg] - real(r8) :: fnrt_c ! Current amount of fine-root carbon in the plant [kg] - real(r8) :: sapw_c ! Current amount of sapwood carbon in the plant [kg] - real(r8) :: struct_c ! Current amount of structural carbon in the plant [kg] - integer :: nlevsoi_hyd ! Number of soil hydraulic layers - integer :: nlevsoil ! Number of total soil layers + ! Locals + integer :: nlevsoil_hyd ! Number of total soil layers type(ed_cohort_hydr_type), pointer :: ccohort_hydr - !----------------------------------------------------------------------- - - - nlevsoi_hyd = currentSite%si_hydr%nlevsoi_hyd - nlevsoil = bc_in%nlevsoil - ccohort => cc_p - ccohort_hydr => cc_p%co_hydr - cPatch => ccohort%patchptr + nlevsoi_hyd = currentSite%si_hydr%nlevsoi_hyd + ccohort_hydr => ccohort%co_hydr ft = ccohort%pft + ! Save the current vegetation compartment volumes into + ! a save space so that it can be compared with the updated quantity. + + call SavePreviousCompartmentVolumes(ccohort_hydr) + ! This updates all of the z_node positions call UpdateTreeHydrNodes(ccohort_hydr,ft,ccohort%hite,nlevsoi_hyd) + + ! This updates plant compartment volumes, lengths and + ! maximum conductances. Make sure for already + ! initialized vegetation, that SavePreviousCompartment + ! volumes, and UpdateTreeHydrNodes is called prior to this. + + call UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) + + + end subroutine updateSizeDepTreeHydProps - ! SAVE INITIAL VOLUMES - ccohort_hydr%v_ag_init(:) = ccohort_hydr%v_ag(:) - ccohort_hydr%v_troot_init(:) = ccohort_hydr%v_troot(:) - ccohort_hydr%v_aroot_layer_init(:) = ccohort_hydr%v_aroot_layer(:) + ! ===================================================================================== + subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) - ! Pre-process biomass pools + ! ----------------------------------------------------------------------------------- + ! This subroutine calculates three attributes of a plant: + ! 1) the volumes of storage compartments in the plants + ! 2) the lenghts of the organs + ! 3) the conductances + ! These and are not dependent on the hydraulic state of the + ! plant, it is more about the structural characteristics and how much biomass + ! is present in the different tissues. + ! + ! Inputs, plant geometries, plant carbon pools, z_node values + ! + ! ----------------------------------------------------------------------------------- - leaf_c = ccohort%prt%GetState(leaf_organ, all_carbon_elements) - sapw_c = ccohort%prt%GetState(sapw_organ, all_carbon_elements) - fnrt_c = ccohort%prt%GetState(fnrt_organ, all_carbon_elements) - struct_c = ccohort%prt%GetState(struct_organ, all_carbon_elements) + ! Arguments + type(ed_cohort_type),intent(inout) :: ccohort + integer,intent(in) :: nlevsoi_hyd ! number of soil hydro layers + type(bc_in_type) , intent(in) :: bc_in ! Boundary Conditions - !roota = 4.372_r8 ! TESTING: deep (see Zeng 2001 Table 1) - !rootb = 0.978_r8 ! TESTING: deep (see Zeng 2001 Table 1) - !roota = 8.992_r8 ! TESTING: shallow (see Zeng 2001 Table 1) - !rootb = 8.992_r8 ! TESTING: shallow (see Zeng 2001 Table 1) + - if(leaf_c > 0._r8) then + type(ed_cohort_hydr_type), intent(inout) :: ccohort_hydr ! Plant hydraulics structure + integer :: pft ! Plant functional type index + real(r8) :: leaf_c ! Current amount of leaf carbon in the plant [kg] + real(r8) :: fnrt_c ! Current amount of fine-root carbon in the plant [kg] + real(r8) :: sapw_c ! Current amount of sapwood carbon in the plant [kg] + real(r8) :: struct_c ! Current amount of structural carbon in the plant [kg] + real(r8) :: b_canopy_carb ! total leaf (canopy) biomass in carbon units [kgC/indiv] + real(r8) :: b_canopy_biom ! total leaf (canopy) biomass in dry wt units [kg/indiv] + real(r8) :: b_woody_carb ! total woody biomass in carbon units [kgC/indiv] + real(r8) :: b_woody_bg_carb ! belowground woody biomass in carbon units [kgC/indiv] + real(r8) :: b_stem_carb ! aboveground stem biomass in carbon units [kgC/indiv] + real(r8) :: b_stem_biom ! aboveground stem biomass in dry wt units [kg/indiv] + real(r8) :: v_stem ! aboveground stem volume [m3/indiv] + real(r8) :: sla ! specific leaf area [cm2/g] + real(r8) :: v_canopy ! total leaf (canopy) volume [m3/indiv] + real(r8) :: denleaf ! leaf dry mass per unit fresh leaf volume [kg/m3] + real(r8) :: a_sapwood ! sapwood area [m2] + real(r8) :: v_sapwood ! sapwood volume [m3] + real(r8) :: b_troot_carb ! transporting root biomass in carbon units [kgC/indiv] + real(r8) :: b_troot_biom ! transporting root biomass in dry wt units [kg/indiv] + real(r8) :: v_troot ! transporting root volume [m3/indiv] + real(r8) :: rootfr ! mass fraction of roots in each layer [kg/kg] + real(r8) :: crown_depth ! Depth of the plant's crown [m] + real(r8) :: kmax_node1_nodekplus1(n_hypool_ag) ! cumulative kmax, petiole to node k+1, + ! conduit taper effects excluded [kg s-1 MPa-1] + real(r8) :: kmax_node1_lowerk(n_hypool_ag) ! cumulative kmax, petiole to upper boundary of node k, + ! conduit taper effects excluded [kg s-1 MPa-1] + real(r8) :: chi_node1_nodekplus1(n_hypool_ag) ! ratio of cumulative kmax with taper effects + ! included to that without [-] + real(r8) :: chi_node1_lowerk(n_hypool_ag) ! ratio of cumulative kmax with taper effects + ! included to that without [-] + real(r8) :: dz_node1_nodekplus1 ! cumulative distance between canopy + ! node and node k + 1 [m] + real(r8) :: dz_node1_lowerk ! cumulative distance between canopy + ! node and upper boundary of node k [m] + real(r8) :: kmax_treeag_tot ! total stem (petiole to transporting root node) + ! hydraulic conductance [kg s-1 MPa-1] + real(r8) :: kmax_tot ! total tree (leaf to root tip) + ! hydraulic conductance [kg s-1 MPa-1] + + leaf_c = ccohort%prt%GetState(leaf_organ, all_carbon_elements) + sapw_c = ccohort%prt%GetState(sapw_organ, all_carbon_elements) + fnrt_c = ccohort%prt%GetState(fnrt_organ, all_carbon_elements) + struct_c = ccohort%prt%GetState(struct_organ, all_carbon_elements) + + !roota = 4.372_r8 ! TESTING: deep (see Zeng 2001 Table 1) + !rootb = 0.978_r8 ! TESTING: deep (see Zeng 2001 Table 1) + !roota = 8.992_r8 ! TESTING: shallow (see Zeng 2001 Table 1) + !rootb = 8.992_r8 ! TESTING: shallow (see Zeng 2001 Table 1) + + if(leaf_c > 0._r8) then - b_woody_carb = sapw_c + struct_c - b_woody_bg_carb = (1.0_r8-EDPftvarcon_inst%allom_agb_frac(ft)) * b_woody_carb - b_tot_carb = sapw_c + struct_c + leaf_c + fnrt_c - b_canopy_carb = leaf_c - b_bg_carb = (1.0_r8-EDPftvarcon_inst%allom_agb_frac(ft)) * b_tot_carb - b_canopy_biom = b_canopy_carb * C2B - ! NOTE: SLATOP currently does not use any vertical scaling functions - ! but that may not be so forever. ie sla = slatop (RGK-082017) - sla = EDPftvarcon_inst%slatop(ft) * cm2_per_m2 ! m2/gC * cm2/m2 -> cm2/gC + ! ------------------------------------------------------------------------------ + ! Part 1. Set the volumes of the leaf, stem and root compartments + ! and lenghts of the roots + ! ------------------------------------------------------------------------------ - denleaf = -2.3231_r8*sla/C2B + 781.899_r8 ! empirical regression data from leaves at Caxiuana (~ 8 spp) - v_canopy = b_canopy_biom / denleaf - ccohort_hydr%v_ag(1:n_hypool_leaf) = v_canopy / real(n_hypool_leaf,r8) + b_woody_carb = sapw_c + struct_c + b_woody_bg_carb = (1.0_r8-EDPftvarcon_inst%allom_agb_frac(ft)) * b_woody_carb + b_tot_carb = sapw_c + struct_c + leaf_c + fnrt_c + b_canopy_carb = leaf_c + b_bg_carb = (1.0_r8-EDPftvarcon_inst%allom_agb_frac(ft)) * b_tot_carb + b_canopy_biom = b_canopy_carb * C2B + + ! NOTE: SLATOP currently does not use any vertical scaling functions + ! but that may not be so forever. ie sla = slatop (RGK-082017) + ! m2/gC * cm2/m2 -> cm2/gC + sla = EDPftvarcon_inst%slatop(ft) * cm2_per_m2 + + ! empirical regression data from leaves at Caxiuana (~ 8 spp) + denleaf = -2.3231_r8*sla/C2B + 781.899_r8 + v_canopy = b_canopy_biom / denleaf + + ccohort_hydr%v_ag(1:n_hypool_leaf) = v_canopy / real(n_hypool_leaf,r8) - b_stem_carb = b_tot_carb - b_bg_carb - b_canopy_carb - b_stem_biom = b_stem_carb * C2B ! kg DM - v_stem = b_stem_biom / (EDPftvarcon_inst%wood_density(ft)*1.e3_r8) !BOC...may be needed for testing/comparison w/ v_sapwood - a_leaf_tot = b_canopy_carb * sla * 1.e3_r8 / 1.e4_r8 ! m2 leaf = kg leaf DM * cm2/g * 1000g/1kg * 1m2/10000cm2 + b_stem_carb = b_tot_carb - b_bg_carb - b_canopy_carb + b_stem_biom = b_stem_carb * C2B ! kg DM + + !BOC...may be needed for testing/comparison w/ v_sapwood + v_stem = b_stem_biom / (EDPftvarcon_inst%wood_density(ft)*1.e3_r8) - call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim,a_sapwood_target,bsw_target) + ! m2 leaf = kg leaf DM * cm2/g * 1000g/1kg * 1m2/10000cm2 + a_leaf_tot = b_canopy_carb * sla * 1.e3_r8 / 1.e4_r8 + + call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim,a_sapwood_target,bsw_target) - a_sapwood = a_sapwood_target + a_sapwood = a_sapwood_target + + ! or .... + ! a_sapwood = a_sapwood_target * ccohort%bsw / bsw_target + + ! a_sapwood = a_leaf_tot / EDPftvarcon_inst%allom_latosa_int(ft)*1.e-4_r8 + ! m2 sapwood = m2 leaf * cm2 sapwood/m2 leaf *1.0e-4m2 + ! or ... + !a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * ccohort%hite ) * 1.e-4_r8 + + v_sapwood = a_sapwood * z_stem + ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem - ! or .... - ! a_sapwood = a_sapwood_target * ccohort%bsw / bsw_target - ! a_sapwood = a_leaf_tot / EDPftvarcon_inst%allom_latosa_int(ft)*1.e-4_r8 - ! m2 sapwood = m2 leaf * cm2 sapwood/m2 leaf *1.0e-4m2 - ! or ... - !a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * ccohort%hite ) * 1.e-4_r8 - - v_sapwood = a_sapwood * z_stem - ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem + !Determine belowground biomass as a function of total (sapwood, heartwood, leaf, fine root) biomass + !then subtract out the fine root biomass to get coarse (transporting) root biomass + + b_troot_carb = b_woody_bg_carb + b_troot_biom = b_troot_carb * C2B + v_troot = b_troot_biom / (EDPftvarcon_inst%wood_density(ft)*1.e3_r8) + !! BOC not sure if/how we should multiply this by the sapwood fraction + ccohort_hydr%v_troot(:) = v_troot / n_hypool_troot + ! Estimate absorbing root total length (all layers) + ! ------------------------------------------------------------------------------ + ccohort_hydr%l_aroot_tot = fnrt_c*C2B*EDPftvarcon_inst%hydr_srl(ft) - !Determine belowground biomass as a function of total (sapwood, heartwood, leaf, fine root) biomass - !then subtract out the fine root biomass to get coarse (transporting) root biomass + ! Estimate absorbing root volume (all layers) + ! ------------------------------------------------------------------------------ + ccohort_hydr%v_aroot_tot = pi_const*(EDPftvarcon_inst%hydr_rs2(ft)**2._r8)*ccohort_hydr%l_aroot_tot - b_troot_carb = b_woody_bg_carb - b_troot_biom = b_troot_carb * C2B - v_troot = b_troot_biom / (EDPftvarcon_inst%wood_density(ft)*1.e3_r8) - ccohort_hydr%v_troot(:) = v_troot / n_hypool_troot !! BOC not sure if/how we should multiply this by the sapwood fraction + + ! Partition the total absorbing root lengths and volumes into the active soil layers + ! ------------------------------------------------------------------------------ + if(nlevsoi_hyd == 1) then + ccohort_hydr%l_aroot_layer(nlevsoi_hyd) = ccohort_hydr%l_aroot_tot + ccohort_hydr%v_aroot_layer(nlevsoi_hyd) = ccohort_hydr%v_aroot_tot + else + do j=1,nlevsoi_hyd + if(j == 1) then + rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) + else + rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) - & + zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j-1)) + end if + ccohort_hydr%l_aroot_layer(j) = rootfr*ccohort_hydr%l_aroot_tot + ccohort_hydr%v_aroot_layer(j) = rootfr*ccohort_hydr%v_aroot_tot + end do + end if + - + ! ------------------------------------------------------------------------------ + ! Part II. Set maximum (size-dependent) hydraulic conductances + ! ------------------------------------------------------------------------------ - - ccohort_hydr%l_aroot_tot = fnrt_c*C2B*EDPftvarcon_inst%hydr_srl(ft) - !ccohort_hydr%v_aroot_tot = fnrt_c/EDecophyscon%ccontent(ft)/EDecophyscon%rootdens(ft) - ccohort_hydr%v_aroot_tot = pi_const*(EDPftvarcon_inst%hydr_rs2(ft)**2._r8)*ccohort_hydr%l_aroot_tot - !ccohort_hydr%l_aroot_tot = ccohort_hydr%v_aroot_tot/(pi_const*EDecophyscon%rs2(ft)**2) - if(nlevsoi_hyd == 1) then - ccohort_hydr%l_aroot_layer(nlevsoi_hyd) = ccohort_hydr%l_aroot_tot - ccohort_hydr%v_aroot_layer(nlevsoi_hyd) = ccohort_hydr%v_aroot_tot - else - ! ccohort_hydr%l_aroot_layer(:) = cPatch%rootfr_ft(ft,:)*ccohort_hydr%l_aroot_tot - ! ccohort_hydr%v_aroot_layer(:) = cPatch%rootfr_ft(ft,:)*ccohort_hydr%v_aroot_tot - do j=1,nlevsoi_hyd - if(j == 1) then - rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) - else - rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) - & + ! first estimate cumulative (petiole to node k) conductances + ! without taper as well as the chi taper function + + do k=n_hypool_leaf,n_hypool_ag + dz_node1_lowerk = ccohort_hydr%z_node_ag(n_hypool_leaf) & + - ccohort_hydr%z_lower_ag(k) + if(k < n_hypool_ag) then + dz_node1_nodekplus1 = ccohort_hydr%z_node_ag(n_hypool_leaf) & + - ccohort_hydr%z_node_ag(k+1) + else + dz_node1_nodekplus1 = ccohort_hydr%z_node_ag(n_hypool_leaf) & + - ccohort_hydr%z_node_troot(1) + end if + kmax_node1_nodekplus1(k) = EDPftvarcon_inst%hydr_kmax_node(ft,2) * a_sapwood / dz_node1_nodekplus1 + kmax_node1_lowerk(k) = EDPftvarcon_inst%hydr_kmax_node(ft,2) * a_sapwood / dz_node1_lowerk + chi_node1_nodekplus1(k) = xylemtaper(p, dz_node1_nodekplus1) + chi_node1_lowerk(k) = xylemtaper(p, dz_node1_lowerk) + if(.not.do_kbound_upstream) then + call CrownDepth(ccohort%hite,crown_depth) + if(crown_depth == 0._r8) then + write(fates_log(),*) 'do_kbound_upstream requires a nonzero canopy depth ' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if + enddo + + + ! then calculate the conductances at node boundaries as the difference of cumulative conductances + do k=n_hypool_leaf,n_hypool_ag + if(k == n_hypool_leaf) then + ccohort_hydr%kmax_bound(k) = kmax_node1_nodekplus1(k) * chi_node1_nodekplus1(k) + ccohort_hydr%kmax_lower(k) = kmax_node1_lowerk(k) * chi_node1_lowerk(k) + else + ccohort_hydr%kmax_bound(k) = ( 1._r8/(kmax_node1_nodekplus1(k) *chi_node1_nodekplus1(k) ) - & + 1._r8/(kmax_node1_nodekplus1(k-1)*chi_node1_nodekplus1(k-1)) ) ** (-1._r8) + ccohort_hydr%kmax_lower(k) = ( 1._r8/(kmax_node1_lowerk(k) *chi_node1_lowerk(k) ) - & + 1._r8/(kmax_node1_nodekplus1(k-1)*chi_node1_nodekplus1(k-1)) ) ** (-1._r8) + end if + if(k < n_hypool_ag) then + ccohort_hydr%kmax_upper(k+1) = ( 1._r8/(kmax_node1_nodekplus1(k) *chi_node1_nodekplus1(k) ) - & + 1._r8/(kmax_node1_lowerk(k) *chi_node1_lowerk(k) ) ) ** (-1._r8) + else if(k == n_hypool_ag) then + ccohort_hydr%kmax_upper_troot = ( 1._r8/(kmax_node1_nodekplus1(k) *chi_node1_nodekplus1(k) ) - & + 1._r8/(kmax_node1_lowerk(k) *chi_node1_lowerk(k) ) ) ** (-1._r8) + end if + + !!!!!!!!!! FOR TESTING ONLY + !ccohort_hydr%kmax_bound(:) = 0.02_r8 ! Diurnal lwp variation in coldstart: -0.1 MPa + ! Diurnal lwp variation in large-tree (50cmDBH) coldstart: less than -0.01 MPa + !ccohort_hydr%kmax_bound(:) = 0.0016_r8 ! Diurnal lwp variation in coldstart: -0.8 - 1.0 MPa + ! Diurnal lwp variation in large-tree (50cmDBH) coldstart: -1.5 - 2.0 MPa [seemingly unstable] + !ccohort_hydr%kmax_bound(:) = 0.0008_r8 ! Diurnal lwp variation in coldstart: -1.5 - 2.0 MPa + ! Diurnal lwp variation in large-tree (50cmDBH) coldstart: -2.0 - 3.0 MPa [seemingly unstable] + !ccohort_hydr%kmax_bound(:) = 0.0005_r8 ! Diurnal lwp variation in coldstart: -2.0 - 3.0 MPa and one -5 MPa outlier + ! Diurnal lwp variation in large-tree (50cmDBH) coldstart: -3.0 - 4.0 MPa and one -10 MPa outlier [Unstable] + !!!!!!!!!! + + enddo + + ! finally, estimate the remaining tree conductance belowground as a residual + kmax_treeag_tot = sum(1._r8/ccohort_hydr%kmax_bound(n_hypool_leaf:n_hypool_ag))**(-1._r8) + kmax_tot = EDPftvarcon_inst%hydr_rfrac_stem(ft) * kmax_treeag_tot + ccohort_hydr%kmax_treebg_tot = ( 1._r8/kmax_tot - 1._r8/kmax_treeag_tot ) ** (-1._r8) + + if(nlevsoi_hyd == 1) then + ccohort_hydr%kmax_treebg_layer(:) = ccohort_hydr%kmax_treebg_tot * cPatch%rootfr_ft(ft,:) + else + do j=1,nlevsoi_hyd + if(j == 1) then + rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) + else + rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) - & zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j-1)) - end if - ccohort_hydr%l_aroot_layer(j) = rootfr*ccohort_hydr%l_aroot_tot - ccohort_hydr%v_aroot_layer(j) = rootfr*ccohort_hydr%v_aroot_tot - end do - end if - + end if + ccohort_hydr%kmax_treebg_layer(j) = rootfr*ccohort_hydr%kmax_treebg_tot + end do + end if + end if !check for bleaf + + end subroutine UpdateTreeHydrLenVolCond - ! MAXIMUM (SIZE-DEPENDENT) HYDRAULIC CONDUCTANCES - ! first estimate cumulative (petiole to node k) conductances without taper as well as the chi taper function - do k=n_hypool_leaf,n_hypool_ag - dz_node1_lowerk = ccohort_hydr%z_node_ag(n_hypool_leaf) - ccohort_hydr%z_lower_ag(k) - if(k < n_hypool_ag) then - dz_node1_nodekplus1 = ccohort_hydr%z_node_ag(n_hypool_leaf) - ccohort_hydr%z_node_ag(k+1) - else - dz_node1_nodekplus1 = ccohort_hydr%z_node_ag(n_hypool_leaf) - ccohort_hydr%z_node_troot(1) - end if - kmax_node1_nodekplus1(k) = EDPftvarcon_inst%hydr_kmax_node(ft,2) * a_sapwood / dz_node1_nodekplus1 - kmax_node1_lowerk(k) = EDPftvarcon_inst%hydr_kmax_node(ft,2) * a_sapwood / dz_node1_lowerk - chi_node1_nodekplus1(k) = xylemtaper(p, dz_node1_nodekplus1) - chi_node1_lowerk(k) = xylemtaper(p, dz_node1_lowerk) - if(.not.do_kbound_upstream) then - call CrownDepth(ccohort%hite,crown_depth) - if(crown_depth == 0._r8) then - write(fates_log(),*) 'do_kbound_upstream requires a nonzero canopy depth ' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - end if - enddo - ! then calculate the conductances at node boundaries as the difference of cumulative conductances - do k=n_hypool_leaf,n_hypool_ag - if(k == n_hypool_leaf) then - ccohort_hydr%kmax_bound(k) = kmax_node1_nodekplus1(k) * chi_node1_nodekplus1(k) - ccohort_hydr%kmax_lower(k) = kmax_node1_lowerk(k) * chi_node1_lowerk(k) - else - ccohort_hydr%kmax_bound(k) = ( 1._r8/(kmax_node1_nodekplus1(k) *chi_node1_nodekplus1(k) ) - & - 1._r8/(kmax_node1_nodekplus1(k-1)*chi_node1_nodekplus1(k-1)) ) ** (-1._r8) - ccohort_hydr%kmax_lower(k) = ( 1._r8/(kmax_node1_lowerk(k) *chi_node1_lowerk(k) ) - & - 1._r8/(kmax_node1_nodekplus1(k-1)*chi_node1_nodekplus1(k-1)) ) ** (-1._r8) - end if - if(k < n_hypool_ag) then - ccohort_hydr%kmax_upper(k+1) = ( 1._r8/(kmax_node1_nodekplus1(k) *chi_node1_nodekplus1(k) ) - & - 1._r8/(kmax_node1_lowerk(k) *chi_node1_lowerk(k) ) ) ** (-1._r8) - else if(k == n_hypool_ag) then - ccohort_hydr%kmax_upper_troot = ( 1._r8/(kmax_node1_nodekplus1(k) *chi_node1_nodekplus1(k) ) - & - 1._r8/(kmax_node1_lowerk(k) *chi_node1_lowerk(k) ) ) ** (-1._r8) - end if - !!!!!!!!!! FOR TESTING ONLY - !ccohort_hydr%kmax_bound(:) = 0.02_r8 ! Diurnal lwp variation in coldstart: -0.1 MPa - ! Diurnal lwp variation in large-tree (50cmDBH) coldstart: less than -0.01 MPa - !ccohort_hydr%kmax_bound(:) = 0.0016_r8 ! Diurnal lwp variation in coldstart: -0.8 - 1.0 MPa - ! Diurnal lwp variation in large-tree (50cmDBH) coldstart: -1.5 - 2.0 MPa [seemingly unstable] - !ccohort_hydr%kmax_bound(:) = 0.0008_r8 ! Diurnal lwp variation in coldstart: -1.5 - 2.0 MPa - ! Diurnal lwp variation in large-tree (50cmDBH) coldstart: -2.0 - 3.0 MPa [seemingly unstable] - !ccohort_hydr%kmax_bound(:) = 0.0005_r8 ! Diurnal lwp variation in coldstart: -2.0 - 3.0 MPa and one -5 MPa outlier - ! Diurnal lwp variation in large-tree (50cmDBH) coldstart: -3.0 - 4.0 MPa and one -10 MPa outlier [Unstable] - !!!!!!!!!! - enddo - ! finally, estimate the remaining tree conductance belowground as a residual - kmax_treeag_tot = sum(1._r8/ccohort_hydr%kmax_bound(n_hypool_leaf:n_hypool_ag))**(-1._r8) - kmax_tot = EDPftvarcon_inst%hydr_rfrac_stem(ft) * kmax_treeag_tot - ccohort_hydr%kmax_treebg_tot = ( 1._r8/kmax_tot - 1._r8/kmax_treeag_tot ) ** (-1._r8) - if(nlevsoi_hyd == 1) then - ccohort_hydr%kmax_treebg_layer(:) = ccohort_hydr%kmax_treebg_tot * cPatch%rootfr_ft(ft,:) - else - do j=1,nlevsoi_hyd - if(j == 1) then - rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) - else - rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) - & - zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j-1)) - end if - ccohort_hydr%kmax_treebg_layer(j) = rootfr*ccohort_hydr%kmax_treebg_tot - end do - end if - end if !check for bleaf - end subroutine updateSizeDepTreeHydProps ! ===================================================================================== subroutine updateSizeDepTreeHydStates(currentSite,cc_p) @@ -953,6 +1021,7 @@ end subroutine FuseCohortHydraulics ! ===================================================================================== ! Initialization Routines ! ===================================================================================== + subroutine InitHydrCohort(currentSite,currentCohort) ! Arguments @@ -964,8 +1033,9 @@ subroutine InitHydrCohort(currentSite,currentCohort) allocate(ccohort_hydr) currentCohort%co_hydr => ccohort_hydr call ccohort_hydr%AllocateHydrCohortArrays(currentSite%si_hydr%nlevsoi_hyd) - ccohort_hydr%is_newly_recruited = .false. + ccohort_hydr%is_newly_recruited = .false. + end subroutine InitHydrCohort ! ===================================================================================== From 44d639db4deff42702efde7e3813987f4981c1b3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Wed, 14 Nov 2018 18:51:08 -0800 Subject: [PATCH 32/53] Debugging new hydro restarts --- biogeochem/EDCohortDynamicsMod.F90 | 19 ++-- biogeochem/FatesAllometryMod.F90 | 4 +- biogeophys/FatesPlantHydraulicsMod.F90 | 151 ++++++++++++++++++++----- main/FatesRestartInterfaceMod.F90 | 147 +++++++++--------------- 4 files changed, 190 insertions(+), 131 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index a24d75a773..6845fddd88 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -132,8 +132,8 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, dbh, bleaf, bfine ! !LOCAL VARIABLES: type(ed_cohort_type), pointer :: new_cohort ! Pointer to New Cohort structure. type(ed_cohort_type), pointer :: storesmallcohort - type(ed_cohort_type), pointer :: storebigcohort - type(ed_cohort_hydr_type), pointer :: ccohort_hydr + type(ed_cohort_type), pointer :: storebigcohort + integer :: nlevsoi_hyd ! number of hydraulically active soil layers integer :: tnull,snull ! are the tallest and shortest cohorts allocate !---------------------------------------------------------------------- @@ -251,22 +251,21 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, dbh, bleaf, bfine if( hlm_use_planthydro.eq.itrue ) then - ccohort_hydr => ccohort%co_hydr - nlevsoi_hydr = currentSite%si_hydr%nlevsoi_hyd - + nlevsoi_hyd = currentSite%si_hydr%nlevsoi_hyd + ! This allocates array spaces call InitHydrCohort(currentSite,new_cohort) ! This calculates node heights - call UpdateTreeHydrNodes(ccohort_hydr,ft,new_cohort%hite,nlevsoi_hydr) + call UpdateTreeHydrNodes(new_cohort%co_hydr,new_cohort%pft,new_cohort%hite,nlevsoi_hyd) ! This calculates volumes, lengths and max conductances - call UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) - + call UpdateTreeHydrLenVolCond(new_cohort,nlevsoi_hyd,bc_in) + ! Since this is a newly initialized plant, we set the previous compartment-size ! equal to the ones we just calculated. - call SavePreviousCompartmentVolumes(ccohort_hydr) - + call SavePreviousCompartmentVolumes(new_cohort%co_hydr) + ! This comes up with starter suctions and then water contents ! based on the soil values call initTreeHydStates(currentSite,new_cohort, bc_in) diff --git a/biogeochem/FatesAllometryMod.F90 b/biogeochem/FatesAllometryMod.F90 index d1a0eb8fa9..45df34aebc 100644 --- a/biogeochem/FatesAllometryMod.F90 +++ b/biogeochem/FatesAllometryMod.F90 @@ -1847,7 +1847,7 @@ end subroutine h2d_martcano ! ===================================================================================== - subroutine CrownDepth(hite,crown_depth) + subroutine CrownDepth(height,crown_depth) ! ----------------------------------------------------------------------------------- ! This routine returns the depth of a plant's crown. Which is the length @@ -1864,7 +1864,7 @@ subroutine CrownDepth(hite,crown_depth) ! crown depth from Poorter, Bongers & Bongers ! crown_depth = exp(-1.169_r8)*cCohort%hite**1.098_r8 - crown_depth = min(cCohort%hite,0.1_r8) + crown_depth = min(height,0.1_r8) return end subroutine CrownDepth diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 41ec79b178..cc1d65d992 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -36,7 +36,8 @@ module FatesPlantHydraulicsMod use FatesConstantsMod, only : denh2o => dens_fresh_liquid_water use FatesConstantsMod, only : grav => grav_earth use FatesConstantsMod, only : ifalse, itrue - + use FatesConstantsMod, only : pi_const + use EDParamsMod , only : hydr_kmax_rsurf use EDTypesMod , only : ed_site_type @@ -139,6 +140,10 @@ module FatesPlantHydraulicsMod public :: initTreeHydStates public :: updateSizeDepRhizHydProps public :: updateSizeDepRhizHydStates + public :: RestartHydrStates + public :: SavePreviousCompartmentVolumes + public :: UpdateTreeHydrNodes + public :: UpdateTreeHydrLenVolCond !------------------------------------------------------------------------------ ! 01/18/16: Created by Brad Christoffersen @@ -175,9 +180,79 @@ subroutine hydraulics_drive( nsites, sites, bc_in,bc_out,dtime ) end select end subroutine Hydraulics_Drive - + ! ===================================================================================== + subroutine RestartHydrStates(sites,nsites,bc_in,bc_out) + + ! It is assumed that the following state variables have been read in by + ! the restart machinery. + ! + ! co_hydr%th_ag + ! co_hydr%th_troot + ! co_hydr%th_aroot + ! si_hydr%r_node_shell + ! si_hydr%v_shell + ! si_hydr%h2osoi_liqvol_shell + ! si_hydr%l_aroot_layer + ! + ! The goal of this subroutine is to call + ! the correct sequence of hydraulics initializations to repopulate + ! information that relies on these key states, as well as other vegetation + ! states such as carbon pools and plant geometry. + + type(ed_site_type) , intent(inout), target :: sites(nsites) + integer , intent(in) :: nsites + type(bc_in_type) , intent(in) :: bc_in(nsites) + type(bc_out_type) , intent(inout) :: bc_out(nsites) + + ! locals + ! ---------------------------------------------------------------------------------- + ! LL pointers + type(ed_patch_type),pointer :: cpatch ! current patch + type(ed_cohort_type),pointer :: ccohort ! current cohort + integer :: s ! site loop counter + + do s = 1,nsites + + cpatch => sites(s)%oldest_patch + do while(associated(cpatch)) + + ccohort => cpatch%shortest + do while(associated(ccohort)) + + ! This calculates node heights + call UpdateTreeHydrNodes(ccohort%co_hydr,ccohort%pft,ccohort%hite, & + sites(s)%si_hydr%nlevsoi_hyd,bc_in(s)) + + ! This calculates volumes, lengths and max conductances + call UpdateTreeHydrLenVolCond(ccohort,sites(s)%si_hydr%nlevsoi_hyd,bc_in(s)) + + ! Since this is a newly initialized plant, we set the previous compartment-size + ! equal to the ones we just calculated. + call SavePreviousCompartmentVolumes(ccohort%co_hydr) + + ccohort%co_hydr%errh2o_growturn_aroot(:) = 0.0_r8 + ccohort%co_hydr%errh2o_growturn_ag(:) = 0.0_r8 + ccohort%co_hydr%errh2o_growturn_troot(:) = 0.0_r8 + + ccohort => ccohort%taller + enddo + + cpatch => cpatch%younger + end do + + call updateSizeDepRhizHydProps(sites(s), bc_in(s) ) + + end do + + call UpdateH2OVeg(nsites,sites,bc_out(s)) + + return + end subroutine RestartHydrStates + + ! ==================================================================================== + subroutine initTreeHydStates(site_p, cc_p, bc_in) ! REQUIRED INPUTS: @@ -274,7 +349,7 @@ end subroutine initTreeHydStates ! ===================================================================================== - subroutine UpdateTreeHydrNodes(ccohort_hydr,pft,plant_height,nlevsoi_hyd) + subroutine UpdateTreeHydrNodes(ccohort_hydr,ft,plant_height,nlevsoi_hyd,bc_in) ! -------------------------------------------------------------------------------- ! This subroutine calculates the nodal heights critical to hydraulics in the plant @@ -294,9 +369,11 @@ subroutine UpdateTreeHydrNodes(ccohort_hydr,pft,plant_height,nlevsoi_hyd) ! Arguments type(ed_cohort_hydr_type), intent(inout) :: ccohort_hydr - integer,intent(in) :: pft ! plant functional type index + integer,intent(in) :: ft ! plant functional type index real(r8), intent(in) :: plant_height ! [m] integer,intent(in) :: nlevsoi_hyd ! number of soil hydro layers + type(bc_in_type) , intent(in) :: bc_in ! Boundary Conditions + ! Locals @@ -305,6 +382,7 @@ subroutine UpdateTreeHydrNodes(ccohort_hydr,pft,plant_height,nlevsoi_hyd) real(r8) :: crown_depth ! crown depth for the plant [m] real(r8) :: dz_canopy ! discrete crown depth intervals [m] real(r8) :: z_stem ! the height of the plants stem below crown [m] + real(r8) :: dz_stem ! vertical stem discretization [m] real(r8) :: dcumul_rf ! cumulative root distribution discretization [-] real(r8) :: cumul_rf ! cumulative root distribution where depth is determined [-] real(r8) :: z_cumul_rf ! depth at which cumul_rf occurs [m] @@ -313,7 +391,10 @@ subroutine UpdateTreeHydrNodes(ccohort_hydr,pft,plant_height,nlevsoi_hyd) ! Crown Nodes ! in special case where n_hypool_leaf = 1, the node height of the canopy ! water pool is 1/2 the distance from the bottom of the canopy to the top of the tree - + + roota = EDPftvarcon_inst%roota_par(ft) + rootb = EDPftvarcon_inst%rootb_par(ft) + call CrownDepth(plant_height,crown_depth) dz_canopy = crown_depth / real(n_hypool_leaf,r8) @@ -401,7 +482,6 @@ subroutine updateSizeDepTreeHydProps(currentSite,ccohort,bc_in) ! shell radii, volumes, and compartment volumes of plant tissues ! !USES: - use FatesConstantsMod , only : pi_const use shr_sys_mod , only : shr_sys_abort ! ARGUMENTS: @@ -410,8 +490,9 @@ subroutine updateSizeDepTreeHydProps(currentSite,ccohort,bc_in) type(bc_in_type) , intent(in) :: bc_in ! Boundary Conditions ! Locals - integer :: nlevsoil_hyd ! Number of total soil layers + integer :: nlevsoi_hyd ! Number of total soil layers type(ed_cohort_hydr_type), pointer :: ccohort_hydr + integer :: ft nlevsoi_hyd = currentSite%si_hydr%nlevsoi_hyd ccohort_hydr => ccohort%co_hydr @@ -423,21 +504,21 @@ subroutine updateSizeDepTreeHydProps(currentSite,ccohort,bc_in) call SavePreviousCompartmentVolumes(ccohort_hydr) ! This updates all of the z_node positions - call UpdateTreeHydrNodes(ccohort_hydr,ft,ccohort%hite,nlevsoi_hyd) + call UpdateTreeHydrNodes(ccohort_hydr,ft,ccohort%hite,nlevsoi_hyd,bc_in) ! This updates plant compartment volumes, lengths and ! maximum conductances. Make sure for already ! initialized vegetation, that SavePreviousCompartment ! volumes, and UpdateTreeHydrNodes is called prior to this. - call UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) + call UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hyd,bc_in) end subroutine updateSizeDepTreeHydProps ! ===================================================================================== - subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) + subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hyd,bc_in) ! ----------------------------------------------------------------------------------- ! This subroutine calculates three attributes of a plant: @@ -456,11 +537,12 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) type(ed_cohort_type),intent(inout) :: ccohort integer,intent(in) :: nlevsoi_hyd ! number of soil hydro layers type(bc_in_type) , intent(in) :: bc_in ! Boundary Conditions - - - type(ed_cohort_hydr_type), intent(inout) :: ccohort_hydr ! Plant hydraulics structure - integer :: pft ! Plant functional type index + type(ed_cohort_hydr_type),pointer :: ccohort_hydr ! Plant hydraulics structure + integer :: j,k + integer :: ft ! Plant functional type index + real(r8) :: roota ! root profile parameter a zeng2001_crootfr + real(r8) :: rootb ! root profile parameter b zeng2001_crootfr real(r8) :: leaf_c ! Current amount of leaf carbon in the plant [kg] real(r8) :: fnrt_c ! Current amount of fine-root carbon in the plant [kg] real(r8) :: sapw_c ! Current amount of sapwood carbon in the plant [kg] @@ -471,11 +553,17 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) real(r8) :: b_woody_bg_carb ! belowground woody biomass in carbon units [kgC/indiv] real(r8) :: b_stem_carb ! aboveground stem biomass in carbon units [kgC/indiv] real(r8) :: b_stem_biom ! aboveground stem biomass in dry wt units [kg/indiv] + real(r8) :: b_bg_carb ! belowground biomass (coarse + fine roots) in carbon units [kgC/indiv] + real(r8) :: b_tot_carb ! total individual biomass in carbon units [kgC/indiv] real(r8) :: v_stem ! aboveground stem volume [m3/indiv] + real(r8) :: z_stem ! the height of the plants stem below crown [m] real(r8) :: sla ! specific leaf area [cm2/g] real(r8) :: v_canopy ! total leaf (canopy) volume [m3/indiv] real(r8) :: denleaf ! leaf dry mass per unit fresh leaf volume [kg/m3] real(r8) :: a_sapwood ! sapwood area [m2] + real(r8) :: a_sapwood_target ! sapwood cross-section area at reference height, at target biomass [m2] + real(r8) :: bsw_target ! sapwood carbon, at target [kgC] + real(r8) :: a_leaf_tot ! total leaf area [m2/indiv] real(r8) :: v_sapwood ! sapwood volume [m3] real(r8) :: b_troot_carb ! transporting root biomass in carbon units [kgC/indiv] real(r8) :: b_troot_biom ! transporting root biomass in dry wt units [kg/indiv] @@ -499,11 +587,20 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) real(r8) :: kmax_tot ! total tree (leaf to root tip) ! hydraulic conductance [kg s-1 MPa-1] + real(r8),parameter :: taper_exponent = 1._r8/3._r8 ! Savage et al. (2010) xylem taper exponent [-] + + + ccohort_hydr => ccohort%co_hydr + ft = ccohort%pft + leaf_c = ccohort%prt%GetState(leaf_organ, all_carbon_elements) sapw_c = ccohort%prt%GetState(sapw_organ, all_carbon_elements) fnrt_c = ccohort%prt%GetState(fnrt_organ, all_carbon_elements) struct_c = ccohort%prt%GetState(struct_organ, all_carbon_elements) + roota = EDPftvarcon_inst%roota_par(ft) + rootb = EDPftvarcon_inst%rootb_par(ft) + !roota = 4.372_r8 ! TESTING: deep (see Zeng 2001 Table 1) !rootb = 0.978_r8 ! TESTING: deep (see Zeng 2001 Table 1) !roota = 8.992_r8 ! TESTING: shallow (see Zeng 2001 Table 1) @@ -556,7 +653,9 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) ! m2 sapwood = m2 leaf * cm2 sapwood/m2 leaf *1.0e-4m2 ! or ... !a_sapwood = a_leaf_tot / ( 0.001_r8 + 0.025_r8 * ccohort%hite ) * 1.e-4_r8 - + + call CrownDepth(ccohort%hite,crown_depth) + z_stem = ccohort%hite - crown_depth v_sapwood = a_sapwood * z_stem ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem @@ -619,10 +718,9 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) end if kmax_node1_nodekplus1(k) = EDPftvarcon_inst%hydr_kmax_node(ft,2) * a_sapwood / dz_node1_nodekplus1 kmax_node1_lowerk(k) = EDPftvarcon_inst%hydr_kmax_node(ft,2) * a_sapwood / dz_node1_lowerk - chi_node1_nodekplus1(k) = xylemtaper(p, dz_node1_nodekplus1) - chi_node1_lowerk(k) = xylemtaper(p, dz_node1_lowerk) + chi_node1_nodekplus1(k) = xylemtaper(taper_exponent, dz_node1_nodekplus1) + chi_node1_lowerk(k) = xylemtaper(taper_exponent, dz_node1_lowerk) if(.not.do_kbound_upstream) then - call CrownDepth(ccohort%hite,crown_depth) if(crown_depth == 0._r8) then write(fates_log(),*) 'do_kbound_upstream requires a nonzero canopy depth ' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -669,7 +767,7 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hydr,bc_in) ccohort_hydr%kmax_treebg_tot = ( 1._r8/kmax_tot - 1._r8/kmax_treeag_tot ) ** (-1._r8) if(nlevsoi_hyd == 1) then - ccohort_hydr%kmax_treebg_layer(:) = ccohort_hydr%kmax_treebg_tot * cPatch%rootfr_ft(ft,:) + ccohort_hydr%kmax_treebg_layer(:) = ccohort_hydr%kmax_treebg_tot * ccohort%patchptr%rootfr_ft(ft,:) else do j=1,nlevsoi_hyd if(j == 1) then @@ -687,7 +785,7 @@ end subroutine UpdateTreeHydrLenVolCond ! ===================================================================================== - subroutine updateSizeDepTreeHydStates(currentSite,cc_p) + subroutine updateSizeDepTreeHydStates(currentSite,ccohort) ! ! !DESCRIPTION: ! @@ -696,11 +794,10 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) use EDTypesMod , only : dump_cohort ! !ARGUMENTS: - type(ed_site_type) , intent(in) :: currentSite ! Site stuff - type(ed_cohort_type) , intent(inout), target :: cc_p ! current cohort pointer + type(ed_site_type) , intent(in) :: currentSite ! Site stuff + type(ed_cohort_type) , intent(inout) :: ccohort ! ! !LOCAL VARIABLES: - type(ed_cohort_type), pointer :: cCohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr integer :: j,k,FT ! indices integer :: err_code = 0 @@ -708,11 +805,10 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) real(r8) :: th_troot_uncorr(n_hypool_troot) ! uncorrected transporting root water content[m3 m-3] real(r8) :: th_aroot_uncorr(currentSite%si_hydr%nlevsoi_hyd) ! uncorrected absorbing root water content[m3 m-3] real(r8), parameter :: small_theta_num = 1.e-7_r8 ! avoids theta values equalling thr or ths [m3 m-3] - integer :: nstep !number of time steps + integer :: nstep !number of time steps !----------------------------------------------------------------------- - cCohort => cc_p - ccohort_hydr => cCohort%co_hydr + ccohort_hydr => ccohort%co_hydr FT = cCohort%pft ! MAYBE ADD A NAN CATCH? If updateSizeDepTreeHydProps() was not called twice prior to the first @@ -1360,7 +1456,6 @@ subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) ! the same. ! ! !USES: - use FatesConstantsMod , only : pi_const use EDTypesMod , only : AREA ! !ARGUMENTS: @@ -4879,7 +4974,7 @@ subroutine shellGeom(l_aroot, rs1, area, dz, r_out_shell, r_node_shell, v_shell) ! the same. ! ! !USES: - use FatesConstantsMod, only : pi_const + ! ! !ARGUMENTS: real(r8) , intent(in) :: l_aroot diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 5e59e55137..ed56123425 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -140,9 +140,6 @@ module FatesRestartInterfaceMod integer, private :: ir_prt_base ! Base index for all PRT variables ! Hydraulic indices - integer, private :: ir_hydro_v_ag_covec - integer, private :: ir_hydro_v_troot_covec - integer, private :: ir_hydro_v_aroot_layer_covec integer, private :: ir_hydro_th_ag_covec integer, private :: ir_hydro_th_troot_covec integer, private :: ir_hydro_th_aroot_covec @@ -860,22 +857,6 @@ subroutine define_restart_vars(this, initialize_variables) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - - call this%RegisterCohortVector(symbol_base='fates_hydro_v_ag', vtype=cohort_r8, & - long_name_base='maximum storage volume of hydraulic compartments (above ground)', & - units='m3', veclength=n_hypool_ag, flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_ag_covec) - - call this%RegisterCohortVector(symbol_base='fates_hydro_v_troot', vtype=cohort_r8, & - long_name_base='maximum storage volume of transporting root compartments', & - units='m3', veclength=n_hypool_troot, flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_troot_covec) - - call this%RegisterCohortVector(symbol_base='fates_hydro_v_aroot_layer', vtype=cohort_r8, & - long_name_base='maximum storage volume of absorbing roots hydraulic compartments by layer', & - units='m3', veclength=nlevsoi_hyd_max, flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_aroot_layer_covec) - call this%RegisterCohortVector(symbol_base='fates_hydro_th_ag', vtype=cohort_r8, & long_name_base='water in aboveground compartments', & units='kg/plant', veclength=n_hypool_ag, flushval = flushzero, & @@ -1461,14 +1442,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) if(hlm_use_planthydro==itrue)then - ! Load the storage compartment volumes - call this%SetCohortRealVector(ccohort%co_hydr%v_ag,n_hypool_ag, & - ir_hydro_v_ag_covec,io_idx_co) - call this%SetCohortRealVector(ccohort%co_hydr%v_troot,n_hypool_troot, & - ir_hydro_v_troot_covec,io_idx_co) - call this%SetCohortRealVector(ccohort%co_hydr%v_aroot_layer,sites(s)%si_hydr%nlevsoi_hyd, & - ir_hydro_v_aroot_layer_covec,io_idx_co) - ! Load the water contents call this%SetCohortRealVector(ccohort%co_hydr%th_ag,n_hypool_ag, & ir_hydro_th_ag_covec,io_idx_co) @@ -1707,22 +1680,18 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in) ! local variables type(ed_patch_type) , pointer :: newp - type(ed_cohort_type), allocatable :: temp_cohort + type(ed_cohort_type), pointer :: new_cohort + type(ed_cohort_type), pointer :: prev_cohort real(r8) :: cwd_ag_local(ncwd) real(r8) :: cwd_bg_local(ncwd) real(r8) :: leaf_litter_local(maxpft) real(r8) :: root_litter_local(maxpft) real(r8) :: patch_age integer :: cohortstatus - integer :: s ! site index + integer :: s ! site index integer :: idx_pa ! local patch index integer :: io_idx_si ! global site index in IO vector integer :: io_idx_co_1st ! global cohort index in IO vector - real(r8) :: b_dead ! dummy structural biomass (kgC) - real(r8) :: b_store ! dummy storage carbon (kgC) - real(r8) :: b_leaf ! leaf biomass dummy var (kgC) - real(r8) :: b_fineroot ! fineroot dummy var (kgC) - real(r8) :: b_sapwood ! sapwood dummy var (kgC) real(r8) :: site_spread ! site sprea dummy var (0-1) integer :: fto integer :: ft @@ -1753,7 +1722,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in) call init_site_vars( sites(s) ) call zero_site( sites(s) ) - + ! ! set a few items that are necessary on restart for ED but not on the ! restart file @@ -1788,45 +1757,48 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in) ! give this patch a unique patch number newp%patchno = idx_pa - - do fto = 1, rio_ncohort_pa( io_idx_co_1st ) - allocate(temp_cohort) - - temp_cohort%n = 700.0_r8 - - temp_cohort%laimemory = 0.0_r8 - temp_cohort%canopy_trim = 1.0_r8 - temp_cohort%canopy_layer = 1.0_r8 - temp_cohort%canopy_layer_yesterday = 1.0_r8 - temp_cohort%pft = 1 ! Give it a nominal PFT value for allocation + ! Iterate over the number of cohorts + ! the file says are associated with this patch + ! we are just allocating space here, so we do + ! a simple list filling routine + + newp%tallest => null() + newp%shortest => null() + prev_cohort => null() - cohortstatus = 2 ! status of 2 means leaves are out (dummy var) + do fto = 1, rio_ncohort_pa( io_idx_co_1st ) - temp_cohort%hite = 1.25_r8 - ! Solve for diameter from height - call h2d_allom(temp_cohort%hite,temp_cohort%pft,temp_cohort%dbh) + allocate(new_cohort) + call nan_cohort(new_cohort) + new_cohort%patchptr => newp - if (debug) then - write(fates_log(),*) 'EDRestVectorMod.F90::createPatchCohortStructure call create_cohort ' + ! If this is the first in the list, it is tallest + if (.not.associated(newp%tallest)) then + newp%tallest => new_cohort + endif + + ! Every cohort's taller is the one that came before + ! (unless it is first) + if(associated(prev_cohort)) then + new_cohort%taller => prev_cohort + prev_cohort%shorter => new_cohort end if - - b_dead = 0.0_r8 - b_store = 0.0_r8 - b_leaf = 0.0_r8 - b_fineroot = 0.0_r8 - b_sapwood = 0.0_r8 - site_spread = 0.5_r8 - - ! Hydraulics - if turned on, the hydraulics arrays are being allocated in create_cohort as well. - - call create_cohort(sites(s),newp, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, temp_cohort%dbh, & - b_leaf, b_fineroot, b_sapwood, b_dead, b_store, & - temp_cohort%laimemory, cohortstatus,recruitstatus, temp_cohort%canopy_trim, newp%NCL_p, & - site_spread, bc_in(s)) - deallocate(temp_cohort) + ! Ever cohort added takes over as shortest + newp%shortest => new_cohort + + ! Initialize the PRT environment (allocate/choose hypothesis only) + call InitPRTCohort(new_cohort) + + ! Allocate hydraulics arrays + if( hlm_use_planthydro.eq.itrue ) then + call InitHydrCohort(sites(s),new_cohort) + end if + + ! Update the previous + prev_cohort => new_cohort enddo ! ends loop over fto @@ -2083,27 +2055,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) end do - if(hlm_use_planthydro==itrue)then - - ! Load the storage compartment volumes - call this%GetCohortRealVector(ccohort%co_hydr%v_ag,n_hypool_ag, & - ir_hydro_v_ag_covec,io_idx_co) - call this%GetCohortRealVector(ccohort%co_hydr%v_troot,n_hypool_troot, & - ir_hydro_v_troot_covec,io_idx_co) - call this%GetCohortRealVector(ccohort%co_hydr%v_aroot_layer,sites(s)%si_hydr%nlevsoi_hyd, & - ir_hydro_v_aroot_layer_covec,io_idx_co) - - ! Load the water contents - call this%GetCohortRealVector(ccohort%co_hydr%th_ag,n_hypool_ag, & - ir_hydro_th_ag_covec,io_idx_co) - call this%GetCohortRealVector(ccohort%co_hydr%th_troot,n_hypool_troot, & - ir_hydro_th_troot_covec,io_idx_co) - call this%GetCohortRealVector(ccohort%co_hydr%th_aroot,sites(s)%si_hydr%nlevsoi_hyd, & - ir_hydro_th_aroot_covec,io_idx_co) - end if - - - ccohort%canopy_layer = rio_canopy_layer_co(io_idx_co) ccohort%canopy_layer_yesterday = rio_canopy_layer_yesterday_co(io_idx_co) ccohort%canopy_trim = rio_canopy_trim_co(io_idx_co) @@ -2135,6 +2086,19 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ccohort%pft = rio_pft_co(io_idx_co) ccohort%status_coh = rio_status_co(io_idx_co) ccohort%isnew = ( rio_isnew_co(io_idx_co) .eq. new_cohort ) + + ! Initialize Plant Hydraulics + + if(hlm_use_planthydro==itrue)then + + ! Load the water contents + call this%GetCohortRealVector(ccohort%co_hydr%th_ag,n_hypool_ag, & + ir_hydro_th_ag_covec,io_idx_co) + call this%GetCohortRealVector(ccohort%co_hydr%th_troot,n_hypool_troot, & + ir_hydro_th_troot_covec,io_idx_co) + call this%GetCohortRealVector(ccohort%co_hydr%th_aroot,sites(s)%si_hydr%nlevsoi_hyd, & + ir_hydro_th_aroot_covec,io_idx_co) + end if io_idx_co = io_idx_co + 1 @@ -2295,7 +2259,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) sites(s)%resources_management%trunk_product_site = rio_trunk_product_si(io_idx_si) end do - + if ( debug ) then write(fates_log(),*) 'CVTL total cohorts ',totalCohorts end if @@ -2305,8 +2269,10 @@ end subroutine get_restart_vectors ! ==================================================================================== + + - subroutine update_3dpatch_radiation(this, nc, nsites, sites, bc_out) + subroutine update_3dpatch_radiation(this, nsites, sites, bc_out) ! ------------------------------------------------------------------------- ! This subroutine populates output boundary conditions related to radiation @@ -2320,7 +2286,6 @@ subroutine update_3dpatch_radiation(this, nc, nsites, sites, bc_out) ! !ARGUMENTS: class(fates_restart_interface_type) , intent(inout) :: this - integer , intent(in) :: nc integer , intent(in) :: nsites type(ed_site_type) , intent(inout), target :: sites(nsites) type(bc_out_type) , intent(inout) :: bc_out(nsites) From 6abcbe6c32f0a8af3edb48d30e401e2e38657105 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Thu, 15 Nov 2018 10:58:34 -0700 Subject: [PATCH 33/53] update the leaf lai for hydro after fuse cohorts --- biogeochem/EDCohortDynamicsMod.F90 | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index ca98d6b1d8..c20a91841b 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -733,6 +733,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) real(r8) :: newn real(r8) :: diff real(r8) :: dynamic_fusion_tolerance + real(r8) :: leaf_c ! leaf carbon [kg] integer :: largersc, smallersc, sc_i ! indices for tracking the growth flux caused by fusion real(r8) :: larger_n, smaller_n @@ -851,11 +852,7 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) currentCohort%size_class,currentCohort%size_by_pft_class) - if(hlm_use_planthydro.eq.itrue) then - call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread, & - currentCohort%pft,currentCohort%c_area) - currentCohort%treelai = tree_lai(currentCohort%bl, currentCohort%status_coh, & - currentCohort%pft, currentCohort%c_area, currentCohort%n ) + if(hlm_use_planthydro.eq.itrue) then call FuseCohortHydraulics(currentSite,currentCohort,nextc,bc_in,newn) endif @@ -987,7 +984,18 @@ subroutine fuse_cohorts(currentSite, currentPatch, bc_in) endif ! At this point, nothing should be pointing to current Cohort - if (hlm_use_planthydro.eq.itrue) call DeallocateHydrCohort(nextc) + ! 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, all_carbon_elements) + currentCohort%treelai = tree_lai(leaf_c, & + currentCohort%pft, currentCohort%c_area, currentCohort%n, & + currentCohort%canopy_layer, currentPatch%canopy_layer_tlai ) + call updateSizeDepTreeHydProps(currentSite,currentCohort, bc_in) + call DeallocateHydrCohort(nextc) + endif ! Deallocate the cohort's PRT structure call nextc%prt%DeallocatePRTVartypes() From 9f262a6a3e8c255f45262a141a11319e7e4635e0 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Thu, 15 Nov 2018 11:00:20 -0700 Subject: [PATCH 34/53] track the error for hydro dynamics --- biogeophys/FatesPlantHydraulicsMod.F90 | 16 ++++++++++------ main/FatesHistoryInterfaceMod.F90 | 13 ++++++++++--- main/FatesHydraulicsMemMod.F90 | 6 +++++- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index ab3cb386bb..8fe891f126 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -813,7 +813,6 @@ subroutine FuseCohortHydraulics(currentSite,currentCohort, nextCohort, bc_in, ne ccohort_hydr%flc_aroot(j), site_hydr, bc_in) end do call flc_gs_from_psi(currentCohort, ccohort_hydr%psi_ag(1)) - call updateSizeDepTreeHydProps(currentSite,currentCohort, bc_in) !hydraulics quantities that are functions of hite & biomasses ccohort_hydr%qtop_dt = (currentCohort%n*ccohort_hydr%qtop_dt + & nextCohort%n*ncohort_hydr%qtop_dt)/newn ccohort_hydr%dqtopdth_dthdt = (currentCohort%n*ccohort_hydr%dqtopdth_dthdt + & @@ -1129,7 +1128,8 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) ! growturn_err is a term to accomodate error in growth or turnover. need to be improved for future(CX) bc_out(s)%plant_stored_h2o_si = csite_hydr%h2oveg + csite_hydr%h2oveg_dead - & csite_hydr%h2oveg_growturn_err - & - csite_hydr%h2oveg_pheno_err + csite_hydr%h2oveg_pheno_err-& + csite_hydr%h2oveg_hydro_err end do @@ -1926,6 +1926,7 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) real(r8) :: refill_rate ! rate of xylem refilling [fraction per unit time; s-1] real(r8) :: roota, rootb ! parameters for root distribution [m-1] real(r8) :: rootfr ! root fraction at different soil layers + real(r8) :: prev_h2oveg ! previous time step plant water storage (kg/m2) type(ed_site_hydr_type), pointer :: site_hydr type(ed_cohort_hydr_type), pointer :: ccohort_hydr integer :: err_code = 0 @@ -1958,6 +1959,7 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) dth_layershell_col(:,:) = 0._r8 site_hydr%dwat_veg = 0._r8 site_hydr%errh2o_hyd = 0._r8 + prev_h2oveg = site_hydr%h2oveg ncoh_col = 0 ! Calculate the mean site level transpiration flux @@ -2601,7 +2603,6 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) !qflx_rootsoi(c,j) = -(sum(dth_layershell_col(j,:))*bc_in(s)%dz_sisl(j)*denh2o/dtime) bc_out(s)%qflx_soil2root_sisl(j) = & -(sum(dth_layershell_col(j,:)*site_hydr%v_shell(j,:)) * & - !site_hydr%l_aroot_layer(j)/bc_in(s)%dz_sisl(j)/AREA*denh2o/dtime)- & !BOC(10/02/2018)...error - should be plus site_hydr%l_aroot_layer(j)/bc_in(s)%dz_sisl(j)/AREA*denh2o/dtime)+ & site_hydr%recruit_w_uptake(j) @@ -2635,12 +2636,15 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) totalrootuptake = sum(bc_out(s)%qflx_soil2root_sisl(:))*dtime - total_e = bc_out(s)%plant_stored_h2o_si - site_hydr%h2oveg - & - site_hydr%h2oveg_dead + totalrootuptake - totalqtop_dt + total_e = prev_h2oveg - site_hydr%h2oveg - & + + totalrootuptake - totalqtop_dt + + site_hydr%h2oveg_hydro_err = site_hydr%h2oveg_hydro_err + site_hydr%errh2o_hyd bc_out(s)%plant_stored_h2o_si = site_hydr%h2oveg + site_hydr%h2oveg_dead - & site_hydr%h2oveg_growturn_err - & - site_hydr%h2oveg_pheno_err + site_hydr%h2oveg_pheno_err-& + site_hydr%h2oveg_hydro_err enddo !site diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 0645ddaf8f..adc7000c01 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -156,7 +156,8 @@ module FatesHistoryInterfaceMod integer, private :: ih_h2oveg_recruit_si integer, private :: ih_h2oveg_growturn_err_si integer, private :: ih_h2oveg_pheno_err_si - + integer, private :: ih_h2oveg_hydro_err_si + ! Indices to (site x scpf) variables integer, private :: ih_nplant_si_scpf integer, private :: ih_gpp_si_scpf @@ -1521,7 +1522,8 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_h2oveg_dead_si => this%hvars(ih_h2oveg_dead_si)%r81d, & hio_h2oveg_recruit_si => this%hvars(ih_h2oveg_recruit_si)%r81d, & hio_h2oveg_growturn_err_si => this%hvars(ih_h2oveg_growturn_err_si)%r81d, & - hio_h2oveg_pheno_err_si => this%hvars(ih_h2oveg_pheno_err_si)%r81d) + hio_h2oveg_pheno_err_si => this%hvars(ih_h2oveg_pheno_err_si)%r81d,& + hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d) ! --------------------------------------------------------------------------------- @@ -2236,6 +2238,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_h2oveg_recruit_si(io_si) = sites(s)%si_hydr%h2oveg_recruit hio_h2oveg_growturn_err_si(io_si) = sites(s)%si_hydr%h2oveg_growturn_err hio_h2oveg_pheno_err_si(io_si) = sites(s)%si_hydr%h2oveg_pheno_err + hio_h2oveg_hydro_err_si(io_si) = sites(s)%si_hydr%h2oveg_hydro_err endif enddo ! site loop @@ -4628,7 +4631,11 @@ subroutine define_history_vars(this, initialize_variables) long='cumulative net borrowed (+) from plant_stored_h2o due to leaf emergence', use_default='inactive', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_h2oveg_pheno_err_si ) - + + call this%set_history_var(vname='H2OVEG_HYDRO_ERR', units = 'kg/m2', & + long='cumulative net borrowed (+) from plant_stored_h2o due to plant hydrodynamics', use_default='inactive', & + avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & + upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_h2oveg_hydro_err_si ) end if ! Must be last thing before return diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index a1d2fbfd71..eb233c66d1 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -151,7 +151,10 @@ module FatesHydraulicsMemMod ! Draw from or add to this pool when ! insufficient plant water available to ! support production of new leaves. - + real(r8) :: h2oveg_hydro_err ! error water pool (kg/m2) for hydrodynamics + ! Draw from or add to this pool when + ! insufficient plant water available to + ! support transpiration ! Hold Until Van Genuchten is implemented ! col inverse of air-entry pressure [MPa-1] (for van Genuchten SWC only) @@ -366,6 +369,7 @@ subroutine InitHydrSite(this) this%h2oveg_dead = 0.0_r8 this%h2oveg_growturn_err = 0.0_r8 this%h2oveg_pheno_err = 0.0_r8 + this%h2oveg_hydro_err = 0.0_r8 end associate From b529e5c6b88f57148a1a4d8aafe92d45ccff1455 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Thu, 15 Nov 2018 11:19:49 -0700 Subject: [PATCH 35/53] avoid the calls to update plant water when no recruitment happens in hydro --- biogeophys/FatesPlantHydraulicsMod.F90 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 8fe891f126..413046798f 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -1138,7 +1138,7 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) end subroutine UpdateH2OVeg !===================================================================================== - subroutine RecruitWUptake(nsites,sites,bc_in,dtime) + subroutine RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) ! ---------------------------------------------------------------------------------- ! This subroutine is called to caluate the water requirement for newly recruited cohorts @@ -1153,6 +1153,7 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime) type(ed_site_type), intent(inout), target :: sites(nsites) type(bc_in_type), intent(in) :: bc_in(nsites) real(r8), intent(in) :: dtime !time (seconds) + logical, intent(out) :: recruitflag !flag to check if there is newly recruited cohorts ! Locals type(ed_cohort_type), pointer :: currentCohort @@ -1165,7 +1166,8 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime) real(r8) :: rootb !root distriubiton parameter b real(r8) :: rootfr !fraction of root in different soil layer real(r8) :: recruitw !water for newly recruited cohorts (kg water/m2/s) - + + recruitflag = .false. do s = 1,nsites csite_hydr => sites(s)%si_hydr csite_hydr%recruit_w_uptake = 0.0_r8 @@ -1178,6 +1180,7 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime) !----------------------------------------------------------- ! recruitment water uptake if(ccohort_hydr%is_newly_recruited) then + recruitflag = .true. roota = EDPftvarcon_inst%roota_par(ft) rootb = EDPftvarcon_inst%rootb_par(ft) recruitw = (sum(ccohort_hydr%th_ag(:)*ccohort_hydr%v_ag(:)) + & @@ -1927,6 +1930,8 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) real(r8) :: roota, rootb ! parameters for root distribution [m-1] real(r8) :: rootfr ! root fraction at different soil layers real(r8) :: prev_h2oveg ! previous time step plant water storage (kg/m2) + logical :: recruitflag ! flag to check if there is newly recruited cohorts + type(ed_site_hydr_type), pointer :: site_hydr type(ed_cohort_hydr_type), pointer :: ccohort_hydr integer :: err_code = 0 @@ -1946,10 +1951,10 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) !nstep = get_nstep() !For newly recruited cohorts, add the water uptake demand to csite_hydr%recruit_w_uptake - call RecruitWUptake(nsites,sites,bc_in,dtime) + call RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) !update water storage in veg after incorporating newly recuited cohorts - call UpdateH2OVeg(nsites,sites,bc_out) + if(recruitflag) call UpdateH2OVeg(nsites,sites,bc_out) do s = 1, nsites From 258acb621804222950ea6d70554bc85757b0a656 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Thu, 15 Nov 2018 11:29:15 -0700 Subject: [PATCH 36/53] add a debug flag to turn on and off warning for mass error checking --- biogeophys/FatesPlantHydraulicsMod.F90 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 413046798f..748ecd3752 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -112,6 +112,8 @@ module FatesPlantHydraulicsMod ! hydraulic properties and states be ! updated every day when trees grow or ! when recruitment happens? + logical,parameter :: debug = .false. !flag to report warning in hydro + character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -3081,7 +3083,9 @@ subroutine Hydraulics_1DSolve(cc_p, ft, z_node, v_node, ths_node, thr_node, kmax we_tot_outer = dw_tot_outer + (qtop_dt + dqtopdth_dthdt) ! kg/timestep we_area_outer = we_tot_outer/(cCohort%c_area / cCohort%n) ! kg/m2 ground/individual if(abs(we_tot_outer*cCohort%n)/AREA>1.0e-7_r8) then - write(fates_log(),*)'WARNING: plant hydraulics water balance error exceeds 1.0e-7 and is ajusted for error' + if(debug) then + write(fates_log(),*)'WARNING: plant hydraulics water balance error exceeds 1.0e-7 and is ajusted for error' + endif !dump the error water to the bin with largest water storage max_l = maxloc(th_node(:)*v_node(:),dim=1) th_node(max_l) = th_node(max_l)- & From cfbdb864e29d90ad76b2a5b5539f83d4167e7350 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Thu, 15 Nov 2018 15:54:36 -0700 Subject: [PATCH 37/53] cleaned the codes on updating veg water storage and error terms --- biogeophys/FatesPlantHydraulicsMod.F90 | 50 +++++++------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 748ecd3752..f8567bc785 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -557,6 +557,7 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) ! !USES: use FatesUtilsMod , only : check_var_real use EDTypesMod , only : dump_cohort + use EDTypesMod , only : AREA ! !ARGUMENTS: type(ed_site_type) , intent(in) :: currentSite ! Site stuff @@ -565,6 +566,7 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) ! !LOCAL VARIABLES: type(ed_cohort_type), pointer :: cCohort type(ed_cohort_hydr_type), pointer :: ccohort_hydr + type(ed_site_hydr_type),pointer :: csite_hydr integer :: j,k,FT ! indices integer :: err_code = 0 real(r8) :: th_ag_uncorr( n_hypool_ag) ! uncorrected aboveground water content[m3 m-3] @@ -609,18 +611,12 @@ subroutine updateSizeDepTreeHydStates(currentSite,cc_p) ! + means water created; - means water destroyed ccohort_hydr%errh2o_growturn_ag(:) = ccohort_hydr%th_ag(:) - th_ag_uncorr(:) ccohort_hydr%errh2o_growturn_troot(:) = ccohort_hydr%th_troot(:) - th_troot_uncorr(:) - !for debug only - !nstep = get_nstep() - !if(nstep == 49) then - !write(fates_log(),*)'ccohort_hydr%errh2o_growturn_aroot(:) = ', ccohort_hydr%errh2o_growturn_aroot(:) - !write(fates_log(),*)'ccohort_hydr%th_aroot(:) = ', ccohort_hydr%th_aroot(:) - !write(fates_log(),*)'th_aroot_uncorr(:) = ', th_aroot_uncorr(:) - !write(fates_log(),*)'ccohort_hydr%v_aroot_layer_init(:) = ', ccohort_hydr%v_aroot_layer_init(:) - !write(fates_log(),*)'ccohort_hydr%v_aroot_layer(:) = ', ccohort_hydr%v_aroot_layer(:) - !call dump_cohort(cCohort) - !call endrun(msg=errMsg(sourcefile, __LINE__)) - !end if - + csite_hydr =>currentSite%si_hydr + csite_hydr%h2oveg_growturn_err = csite_hydr%h2oveg_growturn_err + & + (sum(ccohort_hydr%errh2o_growturn_ag(:)*ccohort_hydr%v_ag(:)) + & + sum(ccohort_hydr%errh2o_growturn_troot(:)*ccohort_hydr%v_troot(:)) + & + sum(ccohort_hydr%errh2o_growturn_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & + denh2o*cCohort%n/AREA ! UPDATES OF WATER POTENTIALS ARE DONE PRIOR TO RICHARDS' SOLUTION WITHIN FATESPLANTHYDRAULICSMOD.F90 @@ -1085,20 +1081,8 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) csite_hydr => sites(s)%si_hydr csite_hydr%h2oveg = 0.0_r8 - currentPatch => sites(s)%oldest_patch - do while(associated(currentPatch)) - - balive_patch = 0._r8 - currentCohort=>currentPatch%tallest - do while(associated(currentCohort)) - balive_patch = balive_patch + & - (currentCohort%prt%GetState(fnrt_organ, all_carbon_elements) + & - currentCohort%prt%GetState(sapw_organ, all_carbon_elements) + & - currentCohort%prt%GetState(leaf_organ, all_carbon_elements)) * currentCohort%n - - currentCohort => currentCohort%shorter - enddo !cohort - + currentPatch => sites(s)%oldest_patch + do while(associated(currentPatch)) currentCohort=>currentPatch%tallest do while(associated(currentCohort)) ccohort_hydr => currentCohort%co_hydr @@ -1109,12 +1093,6 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & denh2o*currentCohort%n - - csite_hydr%h2oveg_growturn_err = csite_hydr%h2oveg_growturn_err + & - (sum(ccohort_hydr%errh2o_growturn_ag(:)*ccohort_hydr%v_ag(:)) + & - sum(ccohort_hydr%errh2o_growturn_troot(:)*ccohort_hydr%v_troot(:)) + & - sum(ccohort_hydr%errh2o_growturn_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & - denh2o*currentCohort%n endif currentCohort => currentCohort%shorter @@ -1123,7 +1101,6 @@ subroutine UpdateH2OVeg(nsites,sites,bc_out) enddo !end patch loop csite_hydr%h2oveg = csite_hydr%h2oveg / AREA - csite_hydr%h2oveg_growturn_err = csite_hydr%h2oveg_growturn_err / AREA ! Note that h2oveg_dead is incremented wherever we have litter fluxes ! and it will be reduced via an evaporation term @@ -2634,7 +2611,7 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) ccohort=>cpatch%tallest do while(associated(ccohort)) ccohort_hydr => ccohort%co_hydr - totalrootuptake = totalrootuptake + ccohort_hydr%rootuptake* ccohort%n/AREA + !totalrootuptake = totalrootuptake + ccohort_hydr%rootuptake* ccohort%n/AREA totalqtop_dt= totalqtop_dt+ ccohort_hydr%qtop_dt* ccohort%n/AREA ccohort => ccohort%shorter enddo !cohort @@ -2643,10 +2620,9 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) totalrootuptake = sum(bc_out(s)%qflx_soil2root_sisl(:))*dtime - total_e = prev_h2oveg - site_hydr%h2oveg - & - + totalrootuptake - totalqtop_dt + total_e = site_hydr%h2oveg-(prev_h2oveg + totalrootuptake - totalqtop_dt) - site_hydr%h2oveg_hydro_err = site_hydr%h2oveg_hydro_err + site_hydr%errh2o_hyd + site_hydr%h2oveg_hydro_err = site_hydr%h2oveg_hydro_err + total_e bc_out(s)%plant_stored_h2o_si = site_hydr%h2oveg + site_hydr%h2oveg_dead - & site_hydr%h2oveg_growturn_err - & From 015533ccb9f7624cfb5afd363c69e47307676dc3 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Thu, 15 Nov 2018 21:56:20 -0800 Subject: [PATCH 38/53] fates hydro restart refactors - syntax updates --- biogeochem/EDCohortDynamicsMod.F90 | 6 +++++- biogeophys/FatesPlantHydraulicsMod.F90 | 26 ++++++++++++++------------ main/FatesRestartInterfaceMod.F90 | 6 +++++- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/biogeochem/EDCohortDynamicsMod.F90 b/biogeochem/EDCohortDynamicsMod.F90 index 6845fddd88..57ea9dca09 100644 --- a/biogeochem/EDCohortDynamicsMod.F90 +++ b/biogeochem/EDCohortDynamicsMod.F90 @@ -31,6 +31,9 @@ module EDCohortDynamicsMod use FatesPlantHydraulicsMod, only : InitHydrCohort use FatesPlantHydraulicsMod, only : DeallocateHydrCohort use FatesPlantHydraulicsMod, only : AccumulateMortalityWaterStorage + use FatesPlantHydraulicsMod, only : UpdateTreeHydrNodes + use FatesPlantHydraulicsMod, only : UpdateTreeHydrLenVolCond + use FatesPlantHydraulicsMod, only : SavePreviousCompartmentVolumes use FatesSizeAgeTypeIndicesMod, only : sizetype_class_index use FatesAllometryMod , only : bleaf use FatesAllometryMod , only : bfineroot @@ -257,7 +260,8 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, dbh, bleaf, bfine call InitHydrCohort(currentSite,new_cohort) ! This calculates node heights - call UpdateTreeHydrNodes(new_cohort%co_hydr,new_cohort%pft,new_cohort%hite,nlevsoi_hyd) + call UpdateTreeHydrNodes(new_cohort%co_hydr,new_cohort%pft, & + new_cohort%hite,nlevsoi_hyd,bc_in) ! This calculates volumes, lengths and max conductances call UpdateTreeHydrLenVolCond(new_cohort,nlevsoi_hyd,bc_in) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index cc1d65d992..c4212432af 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -37,6 +37,8 @@ module FatesPlantHydraulicsMod use FatesConstantsMod, only : grav => grav_earth use FatesConstantsMod, only : ifalse, itrue use FatesConstantsMod, only : pi_const + use FatesConstantsMod, only : cm2_per_m2 + use FatesConstantsMod, only : g_per_kg use EDParamsMod , only : hydr_kmax_rsurf @@ -50,6 +52,7 @@ module FatesPlantHydraulicsMod use FatesInterfaceMod , only : hlm_use_planthydro use FatesAllometryMod, only : bsap_allom + use FatesAllometryMod, only : CrownDepth use FatesHydraulicsMemMod, only: ed_site_hydr_type use FatesHydraulicsMemMod, only: ed_cohort_hydr_type @@ -77,8 +80,6 @@ module FatesPlantHydraulicsMod use clm_time_manager , only : get_step_size, get_nstep - use FatesConstantsMod, only: cm2_per_m2 - use EDPftvarcon, only : EDPftvarcon_inst ! CIME Globals @@ -448,8 +449,6 @@ subroutine UpdateTreeHydrNodes(ccohort_hydr,ft,plant_height,nlevsoi_hyd,bc_in) ccohort_hydr%z_node_troot(:) = ccohort_hydr%z_node_aroot(nlevsoi_hyd) end if - - return end subroutine UpdateTreeHydrNodes @@ -468,7 +467,6 @@ subroutine SavePreviousCompartmentVolumes(ccohort_hydr) ccohort_hydr%v_troot_init(:) = ccohort_hydr%v_troot(:) ccohort_hydr%v_aroot_layer_init(:) = ccohort_hydr%v_aroot_layer(:) - return end subroutine SavePreviousCompartmentVolumes @@ -636,11 +634,12 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hyd,bc_in) b_stem_carb = b_tot_carb - b_bg_carb - b_canopy_carb b_stem_biom = b_stem_carb * C2B ! kg DM - !BOC...may be needed for testing/comparison w/ v_sapwood - v_stem = b_stem_biom / (EDPftvarcon_inst%wood_density(ft)*1.e3_r8) + !BOC...may be needed for testing/comparison w/ v_sapwood + ! kg / ( g cm-3 * cm3/m3 * kg/g ) -> m3 + v_stem = b_stem_biom / (EDPftvarcon_inst%wood_density(ft)*1.e3_r8 ) ! m2 leaf = kg leaf DM * cm2/g * 1000g/1kg * 1m2/10000cm2 - a_leaf_tot = b_canopy_carb * sla * 1.e3_r8 / 1.e4_r8 + a_leaf_tot = b_canopy_carb * sla * g_per_kg / cm2_per_m2 call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim,a_sapwood_target,bsw_target) @@ -660,8 +659,9 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hyd,bc_in) ccohort_hydr%v_ag(n_hypool_leaf+1:n_hypool_ag) = v_sapwood / n_hypool_stem - !Determine belowground biomass as a function of total (sapwood, heartwood, leaf, fine root) biomass - !then subtract out the fine root biomass to get coarse (transporting) root biomass + ! Determine belowground biomass as a function of total (sapwood, heartwood, + ! leaf, fine root) biomass then subtract out the fine root biomass to get + ! coarse (transporting) root biomass b_troot_carb = b_woody_bg_carb b_troot_biom = b_troot_carb * C2B @@ -677,7 +677,8 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hyd,bc_in) ! Estimate absorbing root volume (all layers) ! ------------------------------------------------------------------------------ - ccohort_hydr%v_aroot_tot = pi_const*(EDPftvarcon_inst%hydr_rs2(ft)**2._r8)*ccohort_hydr%l_aroot_tot + ccohort_hydr%v_aroot_tot = pi_const * (EDPftvarcon_inst%hydr_rs2(ft)**2._r8) * & + ccohort_hydr%l_aroot_tot ! Partition the total absorbing root lengths and volumes into the active soil layers @@ -767,7 +768,8 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hyd,bc_in) ccohort_hydr%kmax_treebg_tot = ( 1._r8/kmax_tot - 1._r8/kmax_treeag_tot ) ** (-1._r8) if(nlevsoi_hyd == 1) then - ccohort_hydr%kmax_treebg_layer(:) = ccohort_hydr%kmax_treebg_tot * ccohort%patchptr%rootfr_ft(ft,:) + ccohort_hydr%kmax_treebg_layer(:) = ccohort_hydr%kmax_treebg_tot * & + ccohort%patchptr%rootfr_ft(ft,:) else do j=1,nlevsoi_hyd if(j == 1) then diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index ed56123425..673c994122 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -22,7 +22,10 @@ module FatesRestartInterfaceMod use FatesHydraulicsMemMod, only : n_hypool_troot use FatesHydraulicsMemMod, only : nlevsoi_hyd_max use PRTGenericMod, only : prt_global - + use EDCohortDynamicsMod, only : nan_cohort + use EDCohortDynamicsMod, only : zero_cohort + use EDCohortDynamicsMod, only : InitPRTCohort + use FatesPlantHydraulicsMod, only : InitHydrCohort ! CIME GLOBALS use shr_log_mod , only : errMsg => shr_log_errMsg @@ -1772,6 +1775,7 @@ subroutine create_patchcohort_structure(this, nc, nsites, sites, bc_in) allocate(new_cohort) call nan_cohort(new_cohort) + call zero_cohort(new_cohort) new_cohort%patchptr => newp ! If this is the first in the list, it is tallest From 6481b735adf70d733c291c9706b0031e358700cc Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Fri, 16 Nov 2018 11:47:36 -0800 Subject: [PATCH 39/53] Added some zero-ing initializations to hydraulics during restarts --- biogeophys/FatesPlantHydraulicsMod.F90 | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index f43e20d67a..6d4ad18eea 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -245,11 +245,18 @@ subroutine RestartHydrStates(sites,nsites,bc_in,bc_out) cpatch => cpatch%younger end do + sites(s)%si_hydr%h2oveg = 0.0_r8 + sites(s)%si_hydr%h2oveg_recruit = 0.0_r8 + sites(s)%si_hydr%h2oveg_dead = 0.0_r8 + sites(s)%si_hydr%h2oveg_growturn_err = 0.0_r8 + sites(s)%si_hydr%h2oveg_pheno_err = 0.0_r8 + sites(s)%si_hydr%h2oveg_hydro_err = 0.0_r8 + call updateSizeDepRhizHydProps(sites(s), bc_in(s) ) end do - call UpdateH2OVeg(nsites,sites,bc_out(s)) + call UpdateH2OVeg(nsites,sites,bc_out) return end subroutine RestartHydrStates @@ -563,7 +570,6 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hyd,bc_in) real(r8) :: a_sapwood ! sapwood area [m2] real(r8) :: a_sapwood_target ! sapwood cross-section area at reference height, at target biomass [m2] real(r8) :: bsw_target ! sapwood carbon, at target [kgC] - real(r8) :: a_leaf_tot ! total leaf area [m2/indiv] real(r8) :: v_sapwood ! sapwood volume [m3] real(r8) :: b_troot_carb ! transporting root biomass in carbon units [kgC/indiv] real(r8) :: b_troot_biom ! transporting root biomass in dry wt units [kg/indiv] @@ -639,12 +645,11 @@ subroutine UpdateTreeHydrLenVolCond(ccohort,nlevsoi_hyd,bc_in) ! kg / ( g cm-3 * cm3/m3 * kg/g ) -> m3 v_stem = b_stem_biom / (EDPftvarcon_inst%wood_density(ft)*1.e3_r8 ) - ! calculate the leaf area based on the leaf profile - a_leaf_tot = cCohort%treelai * cCohort%c_area/cCohort%n + ! calculate the sapwood cross-sectional area call bsap_allom(ccohort%dbh,ccohort%pft,ccohort%canopy_trim,a_sapwood_target,bsw_target) - a_sapwood = a_sapwood_target + ! Alternative ways to calculate sapwood cross section ! or .... ! a_sapwood = a_sapwood_target * ccohort%bsw / bsw_target @@ -1476,7 +1481,7 @@ subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) csite_hydr%l_aroot_layer(:) = 0._r8 cPatch => currentSite%youngest_patch do while(associated(cPatch)) - cCohort => cPatch%tallest + cCohort => cPatch%tallest do while(associated(cCohort)) ccohort_hydr => cCohort%co_hydr csite_hydr%l_aroot_layer(:) = csite_hydr%l_aroot_layer(:) + ccohort_hydr%l_aroot_layer(:)*cCohort%n From 50e8141bbe2ce030f4d9b3c15ab8f3a8b9a2f2fe Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 19 Nov 2018 14:43:10 -0800 Subject: [PATCH 40/53] Corrected hydro-restart initialization procedure --- biogeophys/FatesPlantHydraulicsMod.F90 | 120 ++++++++++++++++++++----- main/FatesRestartInterfaceMod.F90 | 116 ++++++++++++++++++++++-- 2 files changed, 207 insertions(+), 29 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 6d4ad18eea..68e342752c 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -145,6 +145,7 @@ module FatesPlantHydraulicsMod public :: updateSizeDepRhizHydStates public :: RestartHydrStates public :: SavePreviousCompartmentVolumes + public :: SavePreviousRhizVolumes public :: UpdateTreeHydrNodes public :: UpdateTreeHydrLenVolCond @@ -212,9 +213,10 @@ subroutine RestartHydrStates(sites,nsites,bc_in,bc_out) ! locals ! ---------------------------------------------------------------------------------- ! LL pointers - type(ed_patch_type),pointer :: cpatch ! current patch - type(ed_cohort_type),pointer :: ccohort ! current cohort - integer :: s ! site loop counter + type(ed_patch_type),pointer :: cpatch ! current patch + type(ed_cohort_type),pointer :: ccohort ! current cohort + type(ed_cohort_hydr_type),pointer :: ccohort_hydr + integer :: s ! site loop counter do s = 1,nsites @@ -224,8 +226,10 @@ subroutine RestartHydrStates(sites,nsites,bc_in,bc_out) ccohort => cpatch%shortest do while(associated(ccohort)) + ccohort_hydr => ccohort%co_hydr + ! This calculates node heights - call UpdateTreeHydrNodes(ccohort%co_hydr,ccohort%pft,ccohort%hite, & + call UpdateTreeHydrNodes(ccohort_hydr,ccohort%pft,ccohort%hite, & sites(s)%si_hydr%nlevsoi_hyd,bc_in(s)) ! This calculates volumes, lengths and max conductances @@ -233,26 +237,42 @@ subroutine RestartHydrStates(sites,nsites,bc_in,bc_out) ! Since this is a newly initialized plant, we set the previous compartment-size ! equal to the ones we just calculated. - call SavePreviousCompartmentVolumes(ccohort%co_hydr) - - ccohort%co_hydr%errh2o_growturn_aroot(:) = 0.0_r8 - ccohort%co_hydr%errh2o_growturn_ag(:) = 0.0_r8 - ccohort%co_hydr%errh2o_growturn_troot(:) = 0.0_r8 + call SavePreviousCompartmentVolumes(ccohort_hydr) + + ! Set some generic initial values + ccohort_hydr%refill_days = 3.0_r8 + ccohort_hydr%lwp_mem(:) = 0.0_r8 + ccohort_hydr%lwp_stable = 0.0_r8 + ccohort_hydr%lwp_is_unstable = .false. + ccohort_hydr%flc_ag(:) = 1.0_r8 + ccohort_hydr%flc_troot(:) = 1.0_r8 + ccohort_hydr%flc_aroot(:) = 1.0_r8 + ccohort_hydr%flc_min_ag(:) = 1.0_r8 + ccohort_hydr%flc_min_troot(:) = 1.0_r8 + ccohort_hydr%flc_min_aroot(:) = 1.0_r8 + ccohort_hydr%refill_thresh = -0.01_r8 + ccohort_hydr%refill_days = 3.0_r8 ccohort => ccohort%taller enddo cpatch => cpatch%younger end do + + sites(s)%si_hydr%l_aroot_layer_init(:) = -9.9e10_r8 + sites(s)%si_hydr%r_node_shell_init(:,:) = -9.9e10_r8 + sites(s)%si_hydr%v_shell_init(:,:) = -9.9e10_r8 + - sites(s)%si_hydr%h2oveg = 0.0_r8 - sites(s)%si_hydr%h2oveg_recruit = 0.0_r8 - sites(s)%si_hydr%h2oveg_dead = 0.0_r8 - sites(s)%si_hydr%h2oveg_growturn_err = 0.0_r8 - sites(s)%si_hydr%h2oveg_pheno_err = 0.0_r8 - sites(s)%si_hydr%h2oveg_hydro_err = 0.0_r8 - call updateSizeDepRhizHydProps(sites(s), bc_in(s) ) + ! Update static quantities related to the rhizosphere + call UpdateSizeDepRhizVolLenCon(sites(s), bc_in(s)) + + ! We update the "initial" values of the rhizosphere after + ! the previous call to make sure that the conductances are updated + ! Now we set the prevous to the current so that the water states + ! are not perturbed + call SavePreviousRhizVolumes(sites(s), bc_in(s)) end do @@ -1435,7 +1455,28 @@ end subroutine RecruitWUptake ! ===================================================================================== - subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) + subroutine SavePreviousRhizVolumes(currentSite, bc_in) + + ! !ARGUMENTS: + type(ed_site_type) , intent(inout), target :: currentSite + type(bc_in_type) , intent(in) :: bc_in + type(ed_site_hydr_type), pointer :: csite_hydr + integer :: nlevsoi_hyd + + csite_hydr => currentSite%si_hydr + nlevsoi_hyd = csite_hydr%nlevsoi_hyd + + csite_hydr%l_aroot_layer_init(:) = csite_hydr%l_aroot_layer(:) + csite_hydr%r_node_shell_init(:,:) = csite_hydr%r_node_shell(:,:) + csite_hydr%v_shell_init(:,:) = csite_hydr%v_shell(:,:) + + return + end subroutine SavePreviousRhizVolumes + + ! ====================================================================================== + + subroutine UpdateSizeDepRhizVolLenCon(currentSite, bc_in) + ! ! !DESCRIPTION: Updates size of 'representative' rhizosphere -- node radii, volumes. ! As fine root biomass (and thus absorbing root length) increases, this characteristic @@ -1469,14 +1510,10 @@ subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) integer :: nlevsoi_hyd !----------------------------------------------------------------------- - + csite_hydr => currentSite%si_hydr nlevsoi_hyd = csite_hydr%nlevsoi_hyd - csite_hydr%l_aroot_layer_init(:) = csite_hydr%l_aroot_layer(:) - csite_hydr%r_node_shell_init(:,:) = csite_hydr%r_node_shell(:,:) - csite_hydr%v_shell_init(:,:) = csite_hydr%v_shell(:,:) - ! update cohort-level root length density and accumulate it across cohorts and patches to the column level csite_hydr%l_aroot_layer(:) = 0._r8 cPatch => currentSite%youngest_patch @@ -1523,8 +1560,10 @@ subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) csite_hydr%kmax_lower_shell(j,k) = kmax_root_surf_total else + kmax_soil_total = 2._r8*pi_const*csite_hydr%l_aroot_layer(j) / & log(csite_hydr%r_node_shell(j,k)/csite_hydr%rs1(j))*hksat_s + !csite_hydr%kmax_upper_shell(j,k) = 2._r8*pi_const*csite_hydr%l_aroot_layer(j) / & ! log(csite_hydr%r_node_shell(j,k)/csite_hydr%rs1(j))*hksat_s !csite_hydr%kmax_bound_shell(j,k) = 2._r8*pi_const*csite_hydr%l_aroot_layer(j) / & @@ -1570,6 +1609,43 @@ subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) end if !has l_aroot_layer changed? enddo ! loop over soil layers + + + return + end subroutine UpdateSizeDepRhizVolLenCon + + + ! ===================================================================================== + + + subroutine updateSizeDepRhizHydProps(currentSite, bc_in ) + ! + ! !DESCRIPTION: Updates size of 'representative' rhizosphere -- node radii, volumes. + ! As fine root biomass (and thus absorbing root length) increases, this characteristic + ! rhizosphere shrinks even though the total volume of soil tapped by fine roots remains + ! the same. + ! + ! !USES: + + use EDTypesMod , only : AREA + + ! !ARGUMENTS: + type(ed_site_type) , intent(inout), target :: currentSite + type(bc_in_type) , intent(in) :: bc_in + + + ! Save current volumes, lenghts and nodes to an "initial" + ! used to calculate effects in states later on. + + call SavePreviousRhizVolumes(currentSite, bc_in) + + ! Update the properties of the vegetation-soil hydraulic environment + ! these are independent on the water state + + call UpdateSizeDepRhizVolLenCon(currentSite, bc_in) + + + return end subroutine updateSizeDepRhizHydProps ! ================================================================================= diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 673c994122..3412e07ae5 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -150,7 +150,14 @@ module FatesRestartInterfaceMod integer, private :: ir_hydro_r_node_shell_si integer, private :: ir_hydro_v_shell_si integer, private :: ir_hydro_liqvol_shell_si - + integer, private :: ir_hydro_err_growturn_aroot_covec + integer, private :: ir_hydro_err_growturn_ag_covec + integer, private :: ir_hydro_err_growturn_troot_covec + integer, private :: ir_hydro_recruit_si + integer, private :: ir_hydro_dead_si + integer, private :: ir_hydro_growturn_err_si + integer, private :: ir_hydro_pheno_err_si + integer, private :: ir_hydro_hydro_err_si ! The number of variable dim/kind types we have defined (static) integer, parameter :: fates_restart_num_dimensions = 2 !(cohort,column) @@ -875,6 +882,22 @@ subroutine define_restart_vars(this, initialize_variables) units='kg/plant', veclength=nlevsoi_hyd_max, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_th_aroot_covec) + call this%RegisterCohortVector(symbol_base='fates_hydro_err_aroot', vtype=cohort_r8, & + long_name_base='error in plant-hydro balance in absorbing roots', & + units='kg/plant', veclength=nlevsoi_hyd_max, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_err_growturn_aroot_covec) + + call this%RegisterCohortVector(symbol_base='fates_hydro_err_ag', vtype=cohort_r8, & + long_name_base='error in plant-hydro balance above ground', & + units='kg/plant', veclength=n_hypool_ag, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_err_growturn_ag_covec) + + call this%RegisterCohortVector(symbol_base='fates_hydro_err_troot', vtype=cohort_r8, & + long_name_base='error in plant-hydro balance above ground', & + units='kg/plant', veclength=n_hypool_troot, flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_err_growturn_troot_covec) + + ! Site-level absorbing root maximum volume call this%set_restart_var(vname='fates_hydro_l_aroot_layer', vtype=cohort_r8, & long_name='Total length (across cohorts) of absorbing roots by soil layer', & @@ -898,6 +921,36 @@ subroutine define_restart_vars(this, initialize_variables) long_name='Volumetric water content of rhizosphere compartments (layerxshell)', & units='m3/m3', flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_liqvol_shell_si ) + + ! Site-level water bound in new recruits + call this%set_restart_var(vname='fates_hydro_recruit_h2o', vtype=site_r8, & + long_name='Site level water mass used for new recruits', & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_recruit_si ) + + ! Site-level water bound in dead plants + call this%set_restart_var(vname='fates_hydro_dead_h2o', vtype=site_r8, & + long_name='Site level water bound in dead plants', & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_dead_si ) + + ! Site-level water balance error due to growth/turnover + call this%set_restart_var(vname='fates_hydro_growturn_err', vtype=site_r8, & + long_name='Site level error for hydraulics due to growth/turnover', & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_growturn_err_si ) + + ! Site-level water balance error due to phenology? + call this%set_restart_var(vname='fates_hydro_pheno_err', vtype=site_r8, & + long_name='Site level error for hydraulics due to phenology', & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_pheno_err_si ) + + ! Site-level water balance error in vegetation + call this%set_restart_var(vname='fates_hydro_hydro_err', vtype=site_r8, & + long_name='Site level error for hydrodynamics', & + units='kg', flushval = flushzero, & + hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_hydro_err_si ) end if @@ -1346,7 +1399,13 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_hydro_l_aroot_layer_si => this%rvars(ir_hydro_l_aroot_layer_si)%r81d, & rio_hydro_r_node_shell_si => this%rvars(ir_hydro_r_node_shell_si)%r81d, & rio_hydro_v_shell_si => this%rvars(ir_hydro_v_shell_si)%r81d, & - rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d ) + rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d, & + rio_hydro_recruit_si => this%rvars(ir_hydro_recruit_si)%r81d, & + rio_hydro_dead_si => this%rvars(ir_hydro_dead_si)%r81d, & + rio_hydro_growturn_err_si => this%rvars(ir_hydro_growturn_err_si)%r81d, & + rio_hydro_pheno_err_si => this%rvars(ir_hydro_pheno_err_si)%r81d, & + rio_hydro_hydro_err_si => this%rvars(ir_hydro_hydro_err_si)%r81d) + totalCohorts = 0 @@ -1452,6 +1511,20 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ir_hydro_th_troot_covec,io_idx_co) call this%SetCohortRealVector(ccohort%co_hydr%th_aroot,sites(s)%si_hydr%nlevsoi_hyd, & ir_hydro_th_aroot_covec,io_idx_co) + + ! Load the error terms + call this%setCohortRealVector(ccohort%co_hydr%errh2o_growturn_aroot, & + sites(s)%si_hydr%nlevsoi_hyd, & + ir_hydro_err_growturn_aroot_covec,io_idx_co) + + call this%setCohortRealVector(ccohort%co_hydr%errh2o_growturn_troot, & + n_hypool_troot, & + ir_hydro_err_growturn_troot_covec,io_idx_co) + + call this%setCohortRealVector(ccohort%co_hydr%errh2o_growturn_ag, & + n_hypool_ag, & + ir_hydro_err_growturn_ag_covec,io_idx_co) + end if rio_canopy_layer_co(io_idx_co) = ccohort%canopy_layer @@ -1611,6 +1684,12 @@ subroutine set_restart_vectors(this,nc,nsites,sites) if(hlm_use_planthydro==itrue)then + rio_hydro_recruit_si(io_idx_si) = sites(s)%si_hydr%h2oveg_recruit + rio_hydro_dead_si(io_idx_si) = sites(s)%si_hydr%h2oveg_dead + rio_hydro_growturn_err_si(io_idx_si) = sites(s)%si_hydr%h2oveg_growturn_err + rio_hydro_pheno_err_si(io_idx_si) = sites(s)%si_hydr%h2oveg_pheno_err + rio_hydro_hydro_err_si(io_idx_si) = sites(s)%si_hydr%h2oveg_hydro_err + ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell do i = 1, sites(s)%si_hydr%nlevsoi_hyd @@ -1630,6 +1709,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) end do rio_hydro_l_aroot_layer_si(io_idx_si_lyr) = sites(s)%si_hydr%l_aroot_layer(i) + io_idx_si_lyr = io_idx_si_lyr + 1 end do end if @@ -1979,7 +2059,12 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_hydro_l_aroot_layer_si => this%rvars(ir_hydro_l_aroot_layer_si)%r81d, & rio_hydro_r_node_shell_si => this%rvars(ir_hydro_r_node_shell_si)%r81d, & rio_hydro_v_shell_si => this%rvars(ir_hydro_v_shell_si)%r81d, & - rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d ) + rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d, & + rio_hydro_recruit_si => this%rvars(ir_hydro_recruit_si)%r81d, & + rio_hydro_dead_si => this%rvars(ir_hydro_dead_si)%r81d, & + rio_hydro_growturn_err_si => this%rvars(ir_hydro_growturn_err_si)%r81d, & + rio_hydro_pheno_err_si => this%rvars(ir_hydro_pheno_err_si)%r81d, & + rio_hydro_hydro_err_si => this%rvars(ir_hydro_hydro_err_si)%r81d) totalcohorts = 0 @@ -2097,11 +2182,23 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! Load the water contents call this%GetCohortRealVector(ccohort%co_hydr%th_ag,n_hypool_ag, & - ir_hydro_th_ag_covec,io_idx_co) + ir_hydro_th_ag_covec,io_idx_co) call this%GetCohortRealVector(ccohort%co_hydr%th_troot,n_hypool_troot, & - ir_hydro_th_troot_covec,io_idx_co) + ir_hydro_th_troot_covec,io_idx_co) call this%GetCohortRealVector(ccohort%co_hydr%th_aroot,sites(s)%si_hydr%nlevsoi_hyd, & - ir_hydro_th_aroot_covec,io_idx_co) + ir_hydro_th_aroot_covec,io_idx_co) + + call this%GetCohortRealVector(ccohort%co_hydr%errh2o_growturn_aroot, & + sites(s)%si_hydr%nlevsoi_hyd, & + ir_hydro_err_growturn_aroot_covec,io_idx_co) + + call this%GetCohortRealVector(ccohort%co_hydr%errh2o_growturn_troot, & + n_hypool_troot, & + ir_hydro_err_growturn_troot_covec,io_idx_co) + + call this%GetCohortRealVector(ccohort%co_hydr%errh2o_growturn_ag, & + n_hypool_ag, & + ir_hydro_err_growturn_ag_covec,io_idx_co) end if io_idx_co = io_idx_co + 1 @@ -2209,6 +2306,12 @@ subroutine get_restart_vectors(this, nc, nsites, sites) if(hlm_use_planthydro==itrue)then + sites(s)%si_hydr%h2oveg_recruit = rio_hydro_recruit_si(io_idx_si) + sites(s)%si_hydr%h2oveg_dead = rio_hydro_dead_si(io_idx_si) + sites(s)%si_hydr%h2oveg_growturn_err = rio_hydro_growturn_err_si(io_idx_si) + sites(s)%si_hydr%h2oveg_pheno_err = rio_hydro_pheno_err_si(io_idx_si) + sites(s)%si_hydr%h2oveg_hydro_err = rio_hydro_hydro_err_si(io_idx_si) + ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell do i = 1, sites(s)%si_hydr%nlevsoi_hyd @@ -2234,7 +2337,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) end do end if - sites(s)%old_stock = rio_old_stock_si(io_idx_si) sites(s)%status = rio_cd_status_si(io_idx_si) From 757d93b31d9fbbc2fff868942bc64c81f905b801 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Mon, 19 Nov 2018 15:25:26 -0800 Subject: [PATCH 41/53] Removed length, node and volumes from shell restarts as they are auto calculated --- biogeophys/FatesPlantHydraulicsMod.F90 | 7 ++- main/FatesRestartInterfaceMod.F90 | 61 -------------------------- 2 files changed, 3 insertions(+), 65 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 68e342752c..8db569c78e 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -259,10 +259,9 @@ subroutine RestartHydrStates(sites,nsites,bc_in,bc_out) cpatch => cpatch%younger end do - sites(s)%si_hydr%l_aroot_layer_init(:) = -9.9e10_r8 - sites(s)%si_hydr%r_node_shell_init(:,:) = -9.9e10_r8 - sites(s)%si_hydr%v_shell_init(:,:) = -9.9e10_r8 - + sites(s)%si_hydr%l_aroot_layer_init(:) = un_initialized + sites(s)%si_hydr%r_node_shell_init(:,:) = un_initialized + sites(s)%si_hydr%v_shell_init(:,:) = un_initialized ! Update static quantities related to the rhizosphere diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index 3412e07ae5..fa851b32fc 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -146,9 +146,6 @@ module FatesRestartInterfaceMod integer, private :: ir_hydro_th_ag_covec integer, private :: ir_hydro_th_troot_covec integer, private :: ir_hydro_th_aroot_covec - integer, private :: ir_hydro_l_aroot_layer_si - integer, private :: ir_hydro_r_node_shell_si - integer, private :: ir_hydro_v_shell_si integer, private :: ir_hydro_liqvol_shell_si integer, private :: ir_hydro_err_growturn_aroot_covec integer, private :: ir_hydro_err_growturn_ag_covec @@ -897,25 +894,6 @@ subroutine define_restart_vars(this, initialize_variables) units='kg/plant', veclength=n_hypool_troot, flushval = flushzero, & hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_err_growturn_troot_covec) - - ! Site-level absorbing root maximum volume - call this%set_restart_var(vname='fates_hydro_l_aroot_layer', vtype=cohort_r8, & - long_name='Total length (across cohorts) of absorbing roots by soil layer', & - units='m', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_l_aroot_layer_si ) - - ! Site-level Nodal Radius of rhizosphere compartments - call this%set_restart_var(vname='fates_hydro_r_node_shell', vtype=cohort_r8, & - long_name='Nodal Radius of rhizosphere compartments (layerxshell)', & - units='m', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_r_node_shell_si ) - - ! Site-level volume of rhizosphere compartments - call this%set_restart_var(vname='fates_hydro_v_shell', vtype=cohort_r8, & - long_name='Volume of rhizosphere compartments (layerxshell)', & - units='m3', flushval = flushzero, & - hlms='CLM:ALM', initialize=initialize_variables, ivar=ivar, index = ir_hydro_v_shell_si ) - ! Site-level volumentric liquid water content (shell x layer) call this%set_restart_var(vname='fates_hydro_liqvol_shell', vtype=cohort_r8, & long_name='Volumetric water content of rhizosphere compartments (layerxshell)', & @@ -1309,7 +1287,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) integer :: io_idx_pa_cwd ! each cwd class within each patch (pa_cwd) integer :: io_idx_pa_ib ! each SW band (vis/ir) per patch (pa_ib) integer :: io_idx_si_wmem ! each water memory class within each site - integer :: io_idx_si_lyr ! site - layer x index integer :: io_idx_si_lyr_shell ! site - layer x shell index ! Some counters (for checking mostly) @@ -1396,9 +1373,6 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_age_pa => this%rvars(ir_age_pa)%r81d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & - rio_hydro_l_aroot_layer_si => this%rvars(ir_hydro_l_aroot_layer_si)%r81d, & - rio_hydro_r_node_shell_si => this%rvars(ir_hydro_r_node_shell_si)%r81d, & - rio_hydro_v_shell_si => this%rvars(ir_hydro_v_shell_si)%r81d, & rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d, & rio_hydro_recruit_si => this%rvars(ir_hydro_recruit_si)%r81d, & rio_hydro_dead_si => this%rvars(ir_hydro_dead_si)%r81d, & @@ -1432,11 +1406,8 @@ subroutine set_restart_vectors(this,nc,nsites,sites) io_idx_si_wmem = io_idx_co_1st ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell - io_idx_si_lyr = io_idx_co_1st io_idx_si_lyr_shell = io_idx_co_1st - - ! write seed_bank info(site-level, but PFT-resolved) do i = 1,numpft rio_seed_bank_sift(io_idx_co_1st+i-1) = sites(s)%seed_bank(i) @@ -1692,25 +1663,12 @@ subroutine set_restart_vectors(this,nc,nsites,sites) ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell do i = 1, sites(s)%si_hydr%nlevsoi_hyd - ! Loop shells do k = 1, nshell - - rio_hydro_r_node_shell_si(io_idx_si_lyr_shell) = & - sites(s)%si_hydr%r_node_shell(i,k) - - rio_hydro_v_shell_si(io_idx_si_lyr_shell) = & - sites(s)%si_hydr%v_shell(i,k) - rio_hydro_liqvol_shell_si(io_idx_si_lyr_shell) = & sites(s)%si_hydr%h2osoi_liqvol_shell(i,k) - io_idx_si_lyr_shell = io_idx_si_lyr_shell + 1 end do - - rio_hydro_l_aroot_layer_si(io_idx_si_lyr) = sites(s)%si_hydr%l_aroot_layer(i) - - io_idx_si_lyr = io_idx_si_lyr + 1 end do end if @@ -1976,7 +1934,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) integer :: io_idx_pa_cwd ! each cwd class within each patch (pa_cwd) integer :: io_idx_pa_ib ! each SW radiation band per patch (pa_ib) integer :: io_idx_si_wmem ! each water memory class within each site - integer :: io_idx_si_lyr ! site - layer x index integer :: io_idx_si_lyr_shell ! site - layer x shell index ! Some counters (for checking mostly) @@ -2056,9 +2013,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_age_pa => this%rvars(ir_age_pa)%r81d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & - rio_hydro_l_aroot_layer_si => this%rvars(ir_hydro_l_aroot_layer_si)%r81d, & - rio_hydro_r_node_shell_si => this%rvars(ir_hydro_r_node_shell_si)%r81d, & - rio_hydro_v_shell_si => this%rvars(ir_hydro_v_shell_si)%r81d, & rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d, & rio_hydro_recruit_si => this%rvars(ir_hydro_recruit_si)%r81d, & rio_hydro_dead_si => this%rvars(ir_hydro_dead_si)%r81d, & @@ -2080,7 +2034,6 @@ subroutine get_restart_vectors(this, nc, nsites, sites) io_idx_si_wmem = io_idx_co_1st ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell - io_idx_si_lyr = io_idx_co_1st io_idx_si_lyr_shell = io_idx_co_1st @@ -2314,26 +2267,12 @@ subroutine get_restart_vectors(this, nc, nsites, sites) ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell do i = 1, sites(s)%si_hydr%nlevsoi_hyd - ! Loop shells do k = 1, nshell - - sites(s)%si_hydr%r_node_shell(i,k) = & - rio_hydro_r_node_shell_si(io_idx_si_lyr_shell) - - sites(s)%si_hydr%v_shell(i,k) = & - rio_hydro_v_shell_si(io_idx_si_lyr_shell) - sites(s)%si_hydr%h2osoi_liqvol_shell(i,k) = & rio_hydro_liqvol_shell_si(io_idx_si_lyr_shell) - io_idx_si_lyr_shell = io_idx_si_lyr_shell + 1 end do - - sites(s)%si_hydr%l_aroot_layer(i) = & - rio_hydro_l_aroot_layer_si(io_idx_si_lyr) - - io_idx_si_lyr = io_idx_si_lyr + 1 end do end if From 9d70ddd84e2b03d3c1cf69f721fe27bc8ea2fd03 Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 20 Nov 2018 13:50:38 -0800 Subject: [PATCH 42/53] Added debug protection to an abundant water balance error write statement --- biogeophys/FatesPlantHydraulicsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 8db569c78e..78046c1aa8 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -3361,7 +3361,7 @@ subroutine Hydraulics_1DSolve(cc_p, ft, z_node, v_node, ths_node, thr_node, kmax ccohort_hydr%iterh2 = real(iterh2) ! WATER BALANCE ERROR-HANDLING - if (abs(we_local) > thresh) then + if ( (abs(we_local) > thresh) .and. debug) then write(fates_log(),*)'WARNING: plant hydraulics water balance error exceeds threshold of ',& thresh else if (abs(we_local) > thresh_break) then From a25024575d6c3aa15fdd57810df0b7c82a75d796 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Tue, 20 Nov 2018 12:32:05 -0700 Subject: [PATCH 43/53] Add the recruitment water constrain based on water availability in the soil --- biogeochem/EDPhysiologyMod.F90 | 42 +++++++++--- biogeophys/FatesPlantHydraulicsMod.F90 | 92 ++++++++++++++++++++++++++ main/FatesHydraulicsMemMod.F90 | 6 +- 3 files changed, 128 insertions(+), 12 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index 89e3257537..a73fc317ff 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -39,6 +39,11 @@ module EDPhysiologyMod use EDParamsMod , only : fates_mortality_disturbance_fraction use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage + use FatesPlantHydraulicsMod , only : updateSizeDepTreeHydProps + use FatesPlantHydraulicsMod , only : initTreeHydStates + use FatesPlantHydraulicsMod , only : InitHydrCohort + use FatesPlantHydraulicsMod , only : ConstrainRecruitNumber + use FatesConstantsMod , only : itrue,ifalse use FatesConstantsMod , only : calloc_abs_error @@ -993,23 +998,38 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) else ! prescribed recruitment rates. number per sq. meter per year temp_cohort%n = currentPatch%area * EDPftvarcon_inst%prescribed_recruitment(ft) * hlm_freq_day - ! modify the carbon balance accumulators to take into account the different way of defining recruitment - ! add prescribed rates as an input C flux, and the recruitment that would have otherwise occured as an output flux - ! (since the carbon associated with them effectively vanishes) - currentSite%flux_in = currentSite%flux_in + temp_cohort%n * & - (b_store + b_leaf + b_fineroot + b_sapwood + b_dead) - currentSite%flux_out = currentSite%flux_out + currentPatch%area * currentPatch%seed_germination(ft)*hlm_freq_day endif if (temp_cohort%n > 0.0_r8 )then - - call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, temp_cohort%dbh, & + if ( DEBUG ) write(fates_log(),*) 'EDPhysiologyMod.F90 call create_cohort ' + if( hlm_use_planthydro.eq.itrue ) then + call InitHydrCohort(CurrentSite,temp_cohort) + call carea_allom(temp_cohort%dbh,temp_cohort%n,currentSite%spread, & + ft,temp_cohort%c_area) + temp_cohort%treelai = tree_lai(temp_cohort%bl, & + cohortstatus, ft, & + temp_cohort%c_area, temp_cohort%n ) + call updateSizeDepTreeHydProps(CurrentSite,temp_cohort, bc_in) + call initTreeHydStates(CurrentSite,temp_cohort, bc_in) + call ConstrainRecruitNumber(currentSite,temp_cohort, bc_in) + endif + if(temp_cohort%n > 0.0_r8) then + call create_cohort(currentSite,currentPatch, temp_cohort%pft, temp_cohort%n, temp_cohort%hite, temp_cohort%dbh, & b_leaf, b_fineroot, b_sapwood, b_dead, b_store, & temp_cohort%laimemory, cohortstatus,recruitstatus, temp_cohort%canopy_trim, currentPatch%NCL_p, & currentSite%spread, bc_in) - - ! keep track of how many individuals were recruited for passing to history - currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + temp_cohort%n + ! keep track of how many individuals were recruited for passing to history + currentSite%recruitment_rate(ft) = currentSite%recruitment_rate(ft) + temp_cohort%n + ! modify the carbon balance accumulators to take into account the different way of defining recruitment + ! add prescribed rates as an input C flux, and the recruitment that would have otherwise occured as an output flux + ! (since the carbon associated with them effectively vanishes) + ! check the water for hydraulics + if (hlm_use_ed_prescribed_phys .ne. ifalse .and. EDPftvarcon_inst%prescribed_recruitment(ft) .ge. 0. ) then + currentSite%flux_in = currentSite%flux_in + temp_cohort%n * & + (b_store + b_leaf + b_fineroot + b_sapwood + b_dead) + currentSite%flux_out = currentSite%flux_out + currentPatch%area * currentPatch%seed_germination(ft)*hlm_freq_day + endif + endif endif enddo !pft loop diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index 78046c1aa8..fd83b8206f 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -73,6 +73,8 @@ module FatesPlantHydraulicsMod use FatesHydraulicsMemMod, only: C2B use FatesHydraulicsMemMod, only: InitHydraulicsDerived use FatesHydraulicsMemMod, only: nlevsoi_hyd_max + use FatesHydraulicsMemMod, only: cohort_recruit_water_layer + use FatesHydraulicsMemMod, only: recruit_water_avail_layer use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : leaf_organ, fnrt_organ, sapw_organ @@ -148,6 +150,7 @@ module FatesPlantHydraulicsMod public :: SavePreviousRhizVolumes public :: UpdateTreeHydrNodes public :: UpdateTreeHydrLenVolCond + public :: ConstrainRecruitNumber !------------------------------------------------------------------------------ ! 01/18/16: Created by Brad Christoffersen @@ -1451,6 +1454,95 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) end do ! site loop end subroutine RecruitWUptake + + !===================================================================================== + subroutine ConstrainRecruitNumber(csite,ccohort, bc_in) + + ! --------------------------------------------------------------------------- + ! This subroutine constrains the number of plants so that there is enought water + ! for newly recruited individuals from the soil + ! --------------------------------------------------------------------------- + use EDTypesMod, only : AREA + + ! Arguments + type(ed_site_type), intent(inout), target :: csite + type(ed_cohort_type) , intent(inout), target :: ccohort + type(bc_in_type) , intent(in) :: bc_in + + ! Locals + type(ed_cohort_hydr_type), pointer :: ccohort_hydr + type(ed_site_hydr_type), pointer :: csite_hydr + real(r8) :: tmp1 + real(r8) :: watres_local !minum water content + real(r8) :: total_water !total water in rhizosphere at a specific layer (m^3) + real(r8) :: total_water_min !total minimum water in rhizosphere at a specific layer (m^3) + real(r8) :: roota !root distriubiton parameter a + real(r8) :: rootb !root distriubiton parameter b + real(r8) :: rootfr !fraction of root in different soil layer + real(r8) :: recruitw !water for newly recruited cohorts (kg water/m2/individual) + real(r8) :: n, nmin !number of individuals in cohorts + integer :: s, j, ft + + + csite_hydr => csite%si_hydr + ccohort_hydr =>ccohort%co_hydr + recruitw = (sum(ccohort_hydr%th_ag(:)*ccohort_hydr%v_ag(:)) + & + sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & + sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & + denh2o + + do j=1,csite_hydr%nlevsoi_hyd + if(j == 1) then + rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) + else + rootfr = zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j)) - & + zeng2001_crootfr(roota, rootb, bc_in%zi_sisl(j-1)) + end if + cohort_recruit_water_layer(j) = recruitw*rootfr + end do + + do j=1,csite_hydr%nlevsoi_hyd + select case (iswc) + case (van_genuchten) + write(fates_log(),*) & + 'Van Genuchten plant hydraulics is inoperable until further notice' + call endrun(msg=errMsg(sourcefile, __LINE__)) + case (campbell) + call swcCampbell_satfrac_from_psi(bc_in%smpmin_si*denh2o*grav*1.e-9_r8, & + (-1._r8)*bc_in%sucsat_sisl(j)*denh2o*grav*1.e-9_r8, & + bc_in%bsw_sisl(j), & + tmp1) + call swcCampbell_th_from_satfrac(tmp1, & + bc_in%watsat_sisl(j), & + watres_local) + + + case default + end select + total_water = sum(csite_hydr%v_shell(j,:)*csite_hydr%h2osoi_liqvol_shell(j,:)) * & + ccohort_hydr%l_aroot_layer(j)/& + bc_in %dz_sisl(j) + total_water_min = sum(csite_hydr%v_shell(j,:)*watres_local) * & + ccohort_hydr%l_aroot_layer(j)/& + bc_in %dz_sisl(j) + !assumes that only 50% is available for recruit water.... + recruit_water_avail_layer(j)=0.5_r8*min(0.0_r8,total_water-total_water_min) + + end do + + nmin = 1.0e+36 + do j=1,csite_hydr%nlevsoi_hyd + if(recruit_water_avail_layer(j)>0.0_r8) then + n = recruit_water_avail_layer(j)/cohort_recruit_water_layer(j) + else + n = 0.0_r8 + endif + nmin = min(n, nmin) + end do + ccohort%n = min (ccohort%n, nmin) + + end subroutine ConstrainRecruitNumber + ! ===================================================================================== diff --git a/main/FatesHydraulicsMemMod.F90 b/main/FatesHydraulicsMemMod.F90 index 06545b3f10..fad1790e03 100644 --- a/main/FatesHydraulicsMemMod.F90 +++ b/main/FatesHydraulicsMemMod.F90 @@ -69,7 +69,11 @@ module FatesHydraulicsMemMod ! P-V curve: correction for nonzero psi0x real(r8), dimension(n_porous_media) :: cap_corr - + + !temporatory variables + real(r8) :: cohort_recruit_water_layer(nlevsoi_hyd_max) ! the recruit water requirement for a + ! single individual at different layer (kg H2o/m2) + real(r8) :: recruit_water_avail_layer(nlevsoi_hyd_max) ! the recruit water avaibility from soil (kg H2o/m2) type ed_site_hydr_type From 8b6371f3b6258336713c3f124399ddb5e9067c63 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Wed, 21 Nov 2018 00:12:59 -0700 Subject: [PATCH 44/53] update the recruit water constrain for hydro --- biogeochem/EDPhysiologyMod.F90 | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index a73fc317ff..b170c5a6ee 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -1006,9 +1006,18 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) call InitHydrCohort(CurrentSite,temp_cohort) call carea_allom(temp_cohort%dbh,temp_cohort%n,currentSite%spread, & ft,temp_cohort%c_area) - temp_cohort%treelai = tree_lai(temp_cohort%bl, & - cohortstatus, ft, & - temp_cohort%c_area, temp_cohort%n ) + if(associated(currentPatch%shortest)) then + temp_cohort%canopy_layer = currentPatch%shortest%canopy_layer + else + temp_cohort%canopy_layer = 1 + endif + temp_cohort%pft = ft + temp_cohort%bsw = b_sapwood + temp_cohort%br = b_fineroot + temp_cohort%bl = b_leaf + temp_cohort%treelai = tree_lai(temp_cohort%bl, ft,& + temp_cohort%c_area,temp_cohort%n, & + temp_cohort%canopy_layer,currentPatch%canopy_layer_tlai) call updateSizeDepTreeHydProps(CurrentSite,temp_cohort, bc_in) call initTreeHydStates(CurrentSite,temp_cohort, bc_in) call ConstrainRecruitNumber(currentSite,temp_cohort, bc_in) From 8e03126517879df3f79e88f672ef0b76ea168501 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Wed, 21 Nov 2018 00:14:06 -0700 Subject: [PATCH 45/53] update the recruit water constrain within plant hydro --- biogeophys/FatesPlantHydraulicsMod.F90 | 37 ++++++++++++++++++-------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index fd83b8206f..f5d6568859 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -1409,12 +1409,16 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) real(r8) :: rootb !root distriubiton parameter b real(r8) :: rootfr !fraction of root in different soil layer real(r8) :: recruitw !water for newly recruited cohorts (kg water/m2/s) + real(r8) :: recruitw_total ! total water for newly recruited cohorts (kg water/m2/s) + real(r8) :: err !mass error of water for newly recruited cohorts (kg water/m2/s) + real(r8) :: sumrw_uptake !sum of water take for newly recruited cohorts (kg water/m2/s) recruitflag = .false. do s = 1,nsites csite_hydr => sites(s)%si_hydr csite_hydr%recruit_w_uptake = 0.0_r8 - currentPatch => sites(s)%oldest_patch + currentPatch => sites(s)%oldest_patch + recruitw_total = 0.0_r8 do while(associated(currentPatch)) currentCohort=>currentPatch%tallest do while(associated(currentCohort)) @@ -1430,6 +1434,7 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) sum(ccohort_hydr%th_troot(:)*ccohort_hydr%v_troot(:)) + & sum(ccohort_hydr%th_aroot(:)*ccohort_hydr%v_aroot_layer(:)))* & denh2o*currentCohort%n/AREA/dtime + recruitw_total = recruitw_total + recruitw if( csite_hydr%nlevsoi_hyd == 1) then csite_hydr%recruit_w_uptake(1) = csite_hydr%recruit_w_uptake(1)+ & recruitw @@ -1451,6 +1456,15 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) end do !cohort loop currentPatch => currentPatch%younger end do !patch + !balance check + sumrw_uptake = sum(csite_hydr%recruit_w_uptake) + err = recruitw_total - sumrw_uptake + if(abs(err)>1.0_r8e-10)then + do j=1,csite_hydr%nlevsoi_hyd + csite_hydr%recruit_w_uptake(j) = csite_hydr%recruit_w_uptake(j) + & + err*csite_hydr%recruit_w_uptake(j)/sumrw_uptake + enddo + endif end do ! site loop end subroutine RecruitWUptake @@ -1483,7 +1497,9 @@ subroutine ConstrainRecruitNumber(csite,ccohort, bc_in) real(r8) :: n, nmin !number of individuals in cohorts integer :: s, j, ft - + roota = EDPftvarcon_inst%roota_par(ccohort%pft) + rootb = EDPftvarcon_inst%rootb_par(ccohort%pft) + csite_hydr => csite%si_hydr ccohort_hydr =>ccohort%co_hydr recruitw = (sum(ccohort_hydr%th_ag(:)*ccohort_hydr%v_ag(:)) + & @@ -1520,24 +1536,22 @@ subroutine ConstrainRecruitNumber(csite,ccohort, bc_in) case default end select total_water = sum(csite_hydr%v_shell(j,:)*csite_hydr%h2osoi_liqvol_shell(j,:)) * & - ccohort_hydr%l_aroot_layer(j)/& + csite_hydr%l_aroot_layer(j)/& bc_in %dz_sisl(j) total_water_min = sum(csite_hydr%v_shell(j,:)*watres_local) * & - ccohort_hydr%l_aroot_layer(j)/& + csite_hydr%l_aroot_layer(j)/& bc_in %dz_sisl(j) !assumes that only 50% is available for recruit water.... - recruit_water_avail_layer(j)=0.5_r8*min(0.0_r8,total_water-total_water_min) + recruit_water_avail_layer(j)=0.5_r8*max(0.0_r8,total_water-total_water_min) end do nmin = 1.0e+36 do j=1,csite_hydr%nlevsoi_hyd - if(recruit_water_avail_layer(j)>0.0_r8) then + if(cohort_recruit_water_layer(j)>0.0_r8) then n = recruit_water_avail_layer(j)/cohort_recruit_water_layer(j) - else - n = 0.0_r8 + nmin = min(n, nmin) endif - nmin = min(n, nmin) end do ccohort%n = min (ccohort%n, nmin) @@ -3025,8 +3039,9 @@ subroutine hydraulics_bc ( nsites, sites,bc_in,bc_out,dtime ) enddo !cohort cpatch => cpatch%younger enddo !patch - - totalrootuptake = sum(bc_out(s)%qflx_soil2root_sisl(:))*dtime + !remove the recruitment water uptake as it has been added to prev_h2oveg + totalrootuptake = sum(bc_out(s)%qflx_soil2root_sisl(:)- & + site_hydr%recruit_w_uptake(:))*dtime total_e = site_hydr%h2oveg-(prev_h2oveg + totalrootuptake - totalqtop_dt) From 22b84c5d0680a163e738fb7ccf0c5503867f3529 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Wed, 21 Nov 2018 00:44:36 -0700 Subject: [PATCH 46/53] update the hydro codes to avoid positive water potentials --- biogeophys/FatesPlantHydraulicsMod.F90 | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/biogeophys/FatesPlantHydraulicsMod.F90 b/biogeophys/FatesPlantHydraulicsMod.F90 index f5d6568859..f32177a4de 100644 --- a/biogeophys/FatesPlantHydraulicsMod.F90 +++ b/biogeophys/FatesPlantHydraulicsMod.F90 @@ -338,6 +338,7 @@ subroutine initTreeHydStates(site_p, cc_p, bc_in) do k=1, n_hypool_troot dz = ccohort_hydr%z_node_troot(k) - ccohort_hydr%z_node_aroot(1) ccohort_hydr%psi_troot(k) = ccohort_hydr%psi_aroot(1) - 1.e-6_r8*denh2o*grav*dz + if (ccohort_hydr%psi_troot(k)>0.0_r8) ccohort_hydr%psi_troot(k) = -0.01_r8 call th_from_psi(ft, 3, ccohort_hydr%psi_troot(k), ccohort_hydr%th_troot(k), csite%si_hydr, bc_in) end do @@ -349,6 +350,7 @@ subroutine initTreeHydStates(site_p, cc_p, bc_in) do k=n_hypool_ag-1, 1, -1 dz = ccohort_hydr%z_node_ag(k) - ccohort_hydr%z_node_ag(k+1) ccohort_hydr%psi_ag(k) = ccohort_hydr%psi_ag(k+1) - 1.e-6_r8*denh2o*grav*dz + if(ccohort_hydr%psi_ag(k)>0.0_r8) ccohort_hydr%psi_ag(k)= -0.01_r8 call th_from_psi(ft, porous_media(k), ccohort_hydr%psi_ag(k), ccohort_hydr%th_ag(k), csite%si_hydr, bc_in) end do @@ -1459,7 +1461,7 @@ subroutine RecruitWUptake(nsites,sites,bc_in,dtime,recruitflag) !balance check sumrw_uptake = sum(csite_hydr%recruit_w_uptake) err = recruitw_total - sumrw_uptake - if(abs(err)>1.0_r8e-10)then + if(abs(err)>1.0e-10_r8)then do j=1,csite_hydr%nlevsoi_hyd csite_hydr%recruit_w_uptake(j) = csite_hydr%recruit_w_uptake(j) + & err*csite_hydr%recruit_w_uptake(j)/sumrw_uptake @@ -3881,14 +3883,20 @@ subroutine bisect_pv(ft, pm, lower, upper, xtol, ytol, psi_node, th_node) real(r8) :: y_new ! corresponding y value at x.new real(r8) :: f_new ! y difference between new y guess at x.new and target y real(r8) :: chg ! difference between x upper and lower bounds (approach 0 in bisection) + integer :: nitr ! number of iterations !---------------------------------------------------------------------- - + if(psi_node > 0.0_r8) then + write(fates_log(),*)'Error: psi_note become positive,& + psi_node=',psi_node + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif call psi_from_th(ft, pm, lower, y_lo) call psi_from_th(ft, pm, upper, y_hi) f_lo = y_lo - psi_node f_hi = y_hi - psi_node chg = upper - lower - do while(abs(chg) .gt. xtol) + nitr = 0 + do while(abs(chg) .gt. xtol .and. nitr < 100) x_new = 0.5_r8*(lower + upper) call psi_from_th(ft, pm, x_new, y_new) f_new = y_new - psi_node @@ -3898,8 +3906,13 @@ subroutine bisect_pv(ft, pm, lower, upper, xtol, ytol, psi_node, th_node) if((f_lo * f_new) .lt. 0._r8) upper = x_new if((f_hi * f_new) .lt. 0._r8) lower = x_new chg = upper - lower + nitr = nitr + 1 end do + if(nitr .eq. 100)then + write(fates_log(),*)'Warning: number of iteraction reaches 100 for bisect_pv' + endif + th_node = x_new end subroutine bisect_pv From 4a20a17939eec22b7ca361fe9e8d699b8d2481c4 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Sat, 24 Nov 2018 23:20:55 -0700 Subject: [PATCH 47/53] update the recruitment constraint for parteh --- biogeochem/EDPhysiologyMod.F90 | 36 ++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/biogeochem/EDPhysiologyMod.F90 b/biogeochem/EDPhysiologyMod.F90 index b170c5a6ee..d335afc4ae 100644 --- a/biogeochem/EDPhysiologyMod.F90 +++ b/biogeochem/EDPhysiologyMod.F90 @@ -13,12 +13,13 @@ module EDPhysiologyMod use FatesInterfaceMod, only : hlm_day_of_year use FatesInterfaceMod, only : numpft use FatesInterfaceMod, only : hlm_use_planthydro + use FatesInterfaceMod, only : hlm_parteh_mode use FatesConstantsMod, only : r8 => fates_r8 use FatesConstantsMod, only : nearzero use EDPftvarcon , only : EDPftvarcon_inst use FatesInterfaceMod, only : bc_in_type use EDCohortDynamicsMod , only : zero_cohort - use EDCohortDynamicsMod , only : create_cohort, sort_cohorts + use EDCohortDynamicsMod , only : create_cohort, sort_cohorts,InitPRTCohort use FatesAllometryMod , only : tree_lai use FatesAllometryMod , only : tree_sai use FatesAllometryMod , only : decay_coeff_kn @@ -43,6 +44,7 @@ module EDPhysiologyMod use FatesPlantHydraulicsMod , only : initTreeHydStates use FatesPlantHydraulicsMod , only : InitHydrCohort use FatesPlantHydraulicsMod , only : ConstrainRecruitNumber + use FatesPlantHydraulicsMod , only : DeallocateHydrCohort use FatesConstantsMod , only : itrue,ifalse use FatesConstantsMod , only : calloc_abs_error @@ -59,7 +61,8 @@ module EDPhysiologyMod use FatesAllometryMod , only : carea_allom use FatesAllometryMod , only : CheckIntegratedAllometries use FatesAllometryMod , only : StructureResetOfDH - + + use PRTGenericMod, only : prt_carbon_allom_hyp use PRTGenericMod, only : leaf_organ use PRTGenericMod, only : all_carbon_elements use PRTGenericMod, only : carbon12_element @@ -955,6 +958,10 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) allocate(temp_cohort) ! create temporary cohort call zero_cohort(temp_cohort) + if( hlm_use_planthydro.eq.itrue ) then + call InitHydrCohort(CurrentSite,temp_cohort) + endif + call InitPRTCohort(temp_cohort) do ft = 1,numpft @@ -1002,8 +1009,8 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) if (temp_cohort%n > 0.0_r8 )then if ( DEBUG ) write(fates_log(),*) 'EDPhysiologyMod.F90 call create_cohort ' + !constrain the number of individual based on rhyzosphere water availability if( hlm_use_planthydro.eq.itrue ) then - call InitHydrCohort(CurrentSite,temp_cohort) call carea_allom(temp_cohort%dbh,temp_cohort%n,currentSite%spread, & ft,temp_cohort%c_area) if(associated(currentPatch%shortest)) then @@ -1012,10 +1019,18 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) temp_cohort%canopy_layer = 1 endif temp_cohort%pft = ft - temp_cohort%bsw = b_sapwood - temp_cohort%br = b_fineroot - temp_cohort%bl = b_leaf - temp_cohort%treelai = tree_lai(temp_cohort%bl, ft,& + select case(hlm_parteh_mode) + case (prt_carbon_allom_hyp) + + call SetState(temp_cohort%prt,leaf_organ, carbon12_element, b_leaf) + call SetState(temp_cohort%prt,fnrt_organ, carbon12_element, b_fineroot) + call SetState(temp_cohort%prt,sapw_organ, carbon12_element, b_sapwood) + call SetState(temp_cohort%prt,store_organ, carbon12_element, b_store) + call SetState(temp_cohort%prt,struct_organ, carbon12_element, b_dead) + call SetState(temp_cohort%prt,repro_organ , carbon12_element, 0.0_r8) + + end select + temp_cohort%treelai = tree_lai(b_leaf, ft,& temp_cohort%c_area,temp_cohort%n, & temp_cohort%canopy_layer,currentPatch%canopy_layer_tlai) call updateSizeDepTreeHydProps(CurrentSite,temp_cohort, bc_in) @@ -1038,11 +1053,16 @@ subroutine recruitment( currentSite, currentPatch, bc_in ) (b_store + b_leaf + b_fineroot + b_sapwood + b_dead) currentSite%flux_out = currentSite%flux_out + currentPatch%area * currentPatch%seed_germination(ft)*hlm_freq_day endif + endif endif enddo !pft loop - + !deallocate the temporatory cohort + if (hlm_use_planthydro.eq.itrue) call DeallocateHydrCohort(temp_cohort) + !Deallocate the cohort's PRT structure + call temp_cohort%prt%DeallocatePRTVartypes() + deallocate(temp_cohort%prt) deallocate(temp_cohort) ! delete temporary cohort end subroutine recruitment From be3ae7a649f3020e1bbff56773798e6063973b94 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Sat, 24 Nov 2018 23:23:06 -0700 Subject: [PATCH 48/53] add a new default parameter file for hydro --- .../fates_params_hydro_default.cdl | 1072 +++++++++++++++++ 1 file changed, 1072 insertions(+) create mode 100644 parameter_files/fates_params_hydro_default.cdl diff --git a/parameter_files/fates_params_hydro_default.cdl b/parameter_files/fates_params_hydro_default.cdl new file mode 100644 index 0000000000..2ae35a917c --- /dev/null +++ b/parameter_files/fates_params_hydro_default.cdl @@ -0,0 +1,1072 @@ +netcdf fates_params.2trop { +dimensions: + fates_NCWD = 4 ; + fates_history_age_bins = 7 ; + fates_history_height_bins = 6 ; + fates_history_size_bins = 13 ; + fates_hydr_organs = 4 ; + fates_prt_organs = 6 ; + fates_litterclass = 6 ; + fates_pft = 2 ; + fates_scalar = 1 ; + fates_string_length = 60 ; + fates_variants = 2 ; +variables: + float 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" ; + float fates_history_ageclass_bin_edges(fates_history_age_bins) ; + fates_history_ageclass_bin_edges:units = "yr" ; + fates_history_ageclass_bin_edges:long_name = "Lower edges for age class bins used in age-resolved patch history output" ; + float fates_FBD(fates_litterclass) ; + fates_FBD:units = "NA" ; + fates_FBD:long_name = "spitfire parameter related to fuel bulk density, see SFMain.F90" ; + float fates_SAV(fates_litterclass) ; + fates_SAV:units = "NA" ; + fates_SAV:long_name = "spitfire parameter related to surface area to volume ratio, see SFMain.F90" ; + float fates_alpha_FMC(fates_litterclass) ; + fates_alpha_FMC:units = "NA" ; + fates_alpha_FMC:long_name = "spitfire parameter related to fuel moisture content, Equation 6 Thonicke et al 2010" ; + float 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" ; + float fates_low_moisture_Coeff(fates_litterclass) ; + fates_low_moisture_Coeff:units = "NA" ; + fates_low_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + float fates_low_moisture_Slope(fates_litterclass) ; + fates_low_moisture_Slope:units = "NA" ; + fates_low_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + float fates_max_decomp(fates_litterclass) ; + fates_max_decomp:units = "kgC/m2/yr ?" ; + fates_max_decomp:long_name = "maximum rate of litter & CWD transfer from non-decomposing class into decomposing class" ; + float fates_mid_moisture(fates_litterclass) ; + fates_mid_moisture:units = "NA" ; + fates_mid_moisture:long_name = "spitfire litter moisture threshold to be considered medium dry" ; + float fates_mid_moisture_Coeff(fates_litterclass) ; + fates_mid_moisture_Coeff:units = "NA" ; + fates_mid_moisture_Coeff:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + float fates_mid_moisture_Slope(fates_litterclass) ; + fates_mid_moisture_Slope:units = "NA" ; + fates_mid_moisture_Slope:long_name = "spitfire parameter, equation B1 Thonicke et al 2010" ; + float fates_min_moisture(fates_litterclass) ; + fates_min_moisture:units = "NA" ; + fates_min_moisture:long_name = "spitfire litter moisture threshold to be considered very dry" ; + float 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" ; + float fates_hydr_epsil_node(fates_hydr_organs, fates_pft) ; + fates_hydr_epsil_node:units = "MPa" ; + fates_hydr_epsil_node:long_name = "bulk elastic modulus" ; + float fates_hydr_fcap_node(fates_hydr_organs, fates_pft) ; + fates_hydr_fcap_node:units = "unitless" ; + fates_hydr_fcap_node:long_name = "fraction of (1-resid_node) that is capillary in source" ; + float fates_hydr_kmax_node(fates_hydr_organs, fates_pft) ; + fates_hydr_kmax_node:units = "kgMPa/m/s" ; + fates_hydr_kmax_node:long_name = "maximum xylem conductivity per unit conducting xylem area" ; + float 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" ; + float 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" ; + float fates_hydr_pitlp_node(fates_hydr_organs, fates_pft) ; + fates_hydr_pitlp_node:units = "MPa" ; + fates_hydr_pitlp_node:long_name = "turgor loss point" ; + float fates_hydr_resid_node(fates_hydr_organs, fates_pft) ; + fates_hydr_resid_node:units = "fraction" ; + fates_hydr_resid_node:long_name = "residual fraction" ; + float 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" ; + float 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" ; + char fates_pftname(fates_pft, fates_string_length) ; + fates_pftname:units = "unitless - string" ; + fates_pftname:long_name = "Description of plant type" ; + char fates_prt_organ_name(fates_prt_organs, fates_string_length) ; + fates_prt_organ_name:units = "unitless - string" ; + fates_prt_organ_name:long_name = "Plant organ name (order must match PRTGenericMod.F90)" ; + float fates_rootprof_beta(fates_variants, fates_pft) ; + fates_rootprof_beta:units = "unitless" ; + fates_rootprof_beta:long_name = "Rooting beta parameter, for C and N vertical discretization (NOT USED BY DEFAULT)" ; + float 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" ; + float fates_allom_agb1(fates_pft) ; + fates_allom_agb1:units = "variable" ; + fates_allom_agb1:long_name = "Parameter 1 for agb allometry" ; + float fates_allom_agb2(fates_pft) ; + fates_allom_agb2:units = "variable" ; + fates_allom_agb2:long_name = "Parameter 2 for agb allometry" ; + float fates_allom_agb3(fates_pft) ; + fates_allom_agb3:units = "variable" ; + fates_allom_agb3:long_name = "Parameter 3 for agb allometry" ; + float fates_allom_agb4(fates_pft) ; + fates_allom_agb4:units = "variable" ; + fates_allom_agb4:long_name = "Parameter 4 for agb allometry" ; + float fates_allom_agb_frac(fates_pft) ; + fates_allom_agb_frac:units = "fraction" ; + fates_allom_agb_frac:long_name = "Fraction of woody biomass that is above ground" ; + float fates_allom_amode(fates_pft) ; + fates_allom_amode:units = "index" ; + fates_allom_amode:long_name = "AGB allometry function index" ; + float 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" ; + float fates_allom_cmode(fates_pft) ; + fates_allom_cmode:units = "index" ; + fates_allom_cmode:long_name = "coarse root biomass allometry function index" ; + float fates_allom_d2bl1(fates_pft) ; + fates_allom_d2bl1:units = "variable" ; + fates_allom_d2bl1:long_name = "Parameter 1 for d2bl allometry" ; + float fates_allom_d2bl2(fates_pft) ; + fates_allom_d2bl2:units = "variable" ; + fates_allom_d2bl2:long_name = "Parameter 2 for d2bl allometry" ; + float fates_allom_d2bl3(fates_pft) ; + fates_allom_d2bl3:units = "unitless" ; + fates_allom_d2bl3:long_name = "Parameter 3 for d2bl allometry" ; + float fates_allom_d2ca_coefficient_max(fates_pft) ; + fates_allom_d2ca_coefficient_max:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_max:long_name = "max (savanna) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + float fates_allom_d2ca_coefficient_min(fates_pft) ; + fates_allom_d2ca_coefficient_min:units = "m2 cm^(-1/beta)" ; + fates_allom_d2ca_coefficient_min:long_name = "min (forest) dbh to area multiplier factor where: area = n*d2ca_coeff*dbh^beta" ; + float fates_allom_d2h1(fates_pft) ; + fates_allom_d2h1:units = "variable" ; + fates_allom_d2h1:long_name = "Parameter 1 for d2h allometry (intercept, or c)" ; + float fates_allom_d2h2(fates_pft) ; + fates_allom_d2h2:units = "variable" ; + fates_allom_d2h2:long_name = "Parameter 2 for d2h allometry (slope, or m)" ; + float fates_allom_d2h3(fates_pft) ; + fates_allom_d2h3:units = "variable" ; + fates_allom_d2h3:long_name = "Parameter 3 for d2h allometry (optional)" ; + float fates_allom_dbh_maxheight(fates_pft) ; + fates_allom_dbh_maxheight:units = "cm" ; + fates_allom_dbh_maxheight:long_name = "the diameter (if any) corresponding to maximum height, diameters may increase beyond this" ; + float fates_allom_fmode(fates_pft) ; + fates_allom_fmode:units = "index" ; + fates_allom_fmode:long_name = "fine root biomass allometry function index" ; + float fates_allom_hmode(fates_pft) ; + fates_allom_hmode:units = "index" ; + fates_allom_hmode:long_name = "height allometry function index" ; + float fates_allom_l2fr(fates_pft) ; + fates_allom_l2fr:units = "gC/gC" ; + fates_allom_l2fr:long_name = "Allocation parameter: fine root C per leaf C" ; + float fates_allom_la_per_sa_int(fates_pft) ; + fates_allom_la_per_sa_int:units = "m2/cm2" ; + fates_allom_la_per_sa_int:long_name = "Leaf area per sapwood area, intercept" ; + float fates_allom_la_per_sa_slp(fates_pft) ; + fates_allom_la_per_sa_slp:units = "m2/cm2/m" ; + fates_allom_la_per_sa_slp:long_name = "Leaf area per sapwood area rate of change with height, slope (optional)" ; + float fates_allom_lmode(fates_pft) ; + fates_allom_lmode:units = "index" ; + fates_allom_lmode:long_name = "leaf biomass allometry function index" ; + float 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" ; + float fates_allom_smode(fates_pft) ; + fates_allom_smode:units = "index" ; + fates_allom_smode:long_name = "sapwood allometry function index" ; + float fates_allom_stmode(fates_pft) ; + fates_allom_stmode:units = "index" ; + fates_allom_stmode:long_name = "storage allometry function index" ; + float fates_branch_turnover(fates_pft) ; + fates_branch_turnover:units = "yr-1" ; + fates_branch_turnover:long_name = "turnover time of branches" ; + + float 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" ; + + float 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" ; + + float 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" ; + + float 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" ; + + float 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" ; + + float 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" ; + + float fates_turnover_retrans_mode(fates_pft) ; + fates_turnover_retrans_mode:units = "index" ; + fates_turnover_retrans_mode:long_name = "retranslocation method for leaf/fineroot turnover" ; + + float 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" ; + + float 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" ; + + float 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 " ; + + float fates_c2b(fates_pft) ; + fates_c2b:units = "ratio" ; + fates_c2b:long_name = "Carbon to biomass multiplier of bulk structural tissues" ; + float fates_displar(fates_pft) ; + fates_displar:units = "unitless" ; + fates_displar:long_name = "Ratio of displacement height to canopy top height" ; + float fates_fire_alpha_SH(fates_pft) ; + fates_fire_alpha_SH:units = "NA" ; + fates_fire_alpha_SH:long_name = "spitfire parameter, alpha scorch height, Equation 16 Thonicke et al 2010" ; + float 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" ; + float 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" ; + float 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" ; + float fates_fr_fcel(fates_pft) ; + fates_fr_fcel:units = "fraction" ; + fates_fr_fcel:long_name = "Fine root litter cellulose fraction" ; + float fates_fr_flab(fates_pft) ; + fates_fr_flab:units = "fraction" ; + fates_fr_flab:long_name = "Fine root litter labile fraction" ; + float fates_fr_flig(fates_pft) ; + fates_fr_flig:units = "fraction" ; + fates_fr_flig:long_name = "Fine root litter lignin fraction" ; + float fates_grperc(fates_pft) ; + fates_grperc:units = "unitless" ; + fates_grperc:long_name = "Growth respiration factor" ; + float 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" ; + float 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" ; + float fates_hydr_p_taper(fates_pft) ; + fates_hydr_p_taper:units = "unitless" ; + fates_hydr_p_taper:long_name = "xylem taper exponent" ; + float 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" ; + float fates_hydr_rs2(fates_pft) ; + fates_hydr_rs2:units = "m" ; + fates_hydr_rs2:long_name = "absorbing root radius" ; + float fates_hydr_srl(fates_pft) ; + fates_hydr_srl:units = "m g-1" ; + fates_hydr_srl:long_name = "specific root length" ; + float fates_leaf_BB_slope(fates_pft) ; + fates_leaf_BB_slope:units = "unitless" ; + fates_leaf_BB_slope:long_name = "stomatal slope parameter, as per Ball-Berry" ; + float fates_leaf_c3psn(fates_pft) ; + fates_leaf_c3psn:units = "flag" ; + fates_leaf_c3psn:long_name = "Photosynthetic pathway (1=c3, 0=c4)" ; + float 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" ; + float fates_leaf_diameter(fates_pft) ; + fates_leaf_diameter:units = "m" ; + fates_leaf_diameter:long_name = "Characteristic leaf dimension" ; + float fates_leaf_jmaxha(fates_pft) ; + fates_leaf_jmaxha:units = "J/mol" ; + fates_leaf_jmaxha:long_name = "activation energy for jmax" ; + float fates_leaf_jmaxhd(fates_pft) ; + fates_leaf_jmaxhd:units = "J/mol" ; + fates_leaf_jmaxhd:long_name = "deactivation energy for jmax" ; + float fates_leaf_jmaxse(fates_pft) ; + fates_leaf_jmaxse:units = "J/mol/K" ; + fates_leaf_jmaxse:long_name = "entropy term for jmax" ; + float fates_leaf_long(fates_pft) ; + fates_leaf_long:units = "yr" ; + fates_leaf_long:long_name = "Leaf longevity (ie turnover timescale)" ; + float 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" ; + float fates_leaf_slatop(fates_pft) ; + fates_leaf_slatop:units = "m^2/gC" ; + fates_leaf_slatop:long_name = "Specific Leaf Area (SLA) at top of canopy, projected area basis" ; + float 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" ; + float fates_leaf_tpuha(fates_pft) ; + fates_leaf_tpuha:units = "J/mol" ; + fates_leaf_tpuha:long_name = "activation energy for tpu" ; + float fates_leaf_tpuhd(fates_pft) ; + fates_leaf_tpuhd:units = "J/mol" ; + fates_leaf_tpuhd:long_name = "deactivation energy for tpu" ; + float fates_leaf_tpuse(fates_pft) ; + fates_leaf_tpuse:units = "J/mol/K" ; + fates_leaf_tpuse:long_name = "entropy term for tpu" ; + float fates_leaf_vcmax25top(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" ; + float fates_leaf_vcmaxha(fates_pft) ; + fates_leaf_vcmaxha:units = "J/mol" ; + fates_leaf_vcmaxha:long_name = "activation energy for vcmax" ; + float fates_leaf_vcmaxhd(fates_pft) ; + fates_leaf_vcmaxhd:units = "J/mol" ; + fates_leaf_vcmaxhd:long_name = "deactivation energy for vcmax" ; + float fates_leaf_vcmaxse(fates_pft) ; + fates_leaf_vcmaxse:units = "J/mol/K" ; + fates_leaf_vcmaxse:long_name = "entropy term for vcmax" ; + float fates_leaf_xl(fates_pft) ; + fates_leaf_xl:units = "unitless" ; + fates_leaf_xl:long_name = "Leaf/stem orientation index" ; + float fates_lf_fcel(fates_pft) ; + fates_lf_fcel:units = "fraction" ; + fates_lf_fcel:long_name = "Leaf litter cellulose fraction" ; + float fates_lf_flab(fates_pft) ; + fates_lf_flab:units = "fraction" ; + fates_lf_flab:long_name = "Leaf litter labile fraction" ; + float fates_lf_flig(fates_pft) ; + fates_lf_flig:units = "fraction" ; + fates_lf_flig:long_name = "Leaf litter lignin fraction" ; + float 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" ; + float fates_maintresp_reduction_intercept(fates_pft) ; + fates_maintresp_reduction_intercept:units = "unitless (0-1)" ; + fates_maintresp_reduction_intercept:long_name = "intercept of MR reduction as f(carbon storage), 0=no throttling, 1=max throttling" ; + float fates_mort_bmort(fates_pft) ; + fates_mort_bmort:units = "1/yr" ; + fates_mort_bmort:long_name = "background mortality rate" ; + float fates_mort_freezetol(fates_pft) ; + fates_mort_freezetol:units = "NA" ; + fates_mort_freezetol:long_name = "minimum temperature tolerance (NOT USED)" ; + float fates_mort_hf_sm_threshold(fates_pft) ; + fates_mort_hf_sm_threshold:units = "unitless" ; + fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + float fates_mort_scalar_coldstress(fates_pft) ; + fates_mort_scalar_coldstress:units = "1/yr" ; + fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; + float fates_mort_scalar_cstarvation(fates_pft) ; + fates_mort_scalar_cstarvation:units = "1/yr" ; + fates_mort_scalar_cstarvation:long_name = "maximum mortality rate from carbon starvation" ; + float 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" ; + float fates_pft_used(fates_pft) ; + fates_pft_used:units = "0 = off (dont use), 1 = on (use)" ; + fates_pft_used:long_name = "Switch to turn on and off PFTs (also see fates_initd for cold-start)" ; + float fates_phen_evergreen(fates_pft) ; + fates_phen_evergreen:units = "logical flag" ; + fates_phen_evergreen:long_name = "Binary flag for evergreen leaf habit" ; + float 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" ; + float 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" ; + float 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" ; + float 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" ; + float fates_prescribed_npp_canopy(fates_pft) ; + fates_prescribed_npp_canopy:units = "gC / m^2 / yr" ; + fates_prescribed_npp_canopy:long_name = "NPP per unit crown area of canopy trees for prescribed physiology mode" ; + float fates_prescribed_npp_understory(fates_pft) ; + fates_prescribed_npp_understory:units = "gC / m^2 / yr" ; + fates_prescribed_npp_understory:long_name = "NPP per unit crown area of understory trees for prescribed physiology mode" ; + float fates_prescribed_recruitment(fates_pft) ; + fates_prescribed_recruitment:units = "n/yr" ; + fates_prescribed_recruitment:long_name = "recruitment rate for prescribed physiology mode" ; + float 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" ; + float 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" ; + float fates_rholnir(fates_pft) ; + fates_rholnir:units = "fraction" ; + fates_rholnir:long_name = "Leaf reflectance: near-IR" ; + float fates_rholvis(fates_pft) ; + fates_rholvis:units = "fraction" ; + fates_rholvis:long_name = "Leaf reflectance: visible" ; + float fates_rhosnir(fates_pft) ; + fates_rhosnir:units = "fraction" ; + fates_rhosnir:long_name = "Stem reflectance: near-IR" ; + float fates_rhosvis(fates_pft) ; + fates_rhosvis:units = "fraction" ; + fates_rhosvis:long_name = "Stem reflectance: visible" ; + float fates_root_long(fates_pft) ; + fates_root_long:units = "yr" ; + fates_root_long:long_name = "root longevity (alternatively, turnover time)" ; + float fates_roota_par(fates_pft) ; + fates_roota_par:units = "1/m" ; + fates_roota_par:long_name = "CLM rooting distribution parameter" ; + float fates_rootb_par(fates_pft) ; + fates_rootb_par:units = "1/m" ; + fates_rootb_par:long_name = "CLM rooting distribution parameter" ; + float fates_seed_alloc(fates_pft) ; + fates_seed_alloc:units = "fraction" ; + fates_seed_alloc:long_name = "fraction of available carbon balance allocated to seeds" ; + float 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)" ; + float 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" ; + float fates_seed_decay_turnover(fates_pft) ; + fates_seed_decay_turnover:units = "1/yr" ; + fates_seed_decay_turnover:long_name = "turnover time for seeds with respect to germination" ; + float fates_seed_germination_timescale(fates_pft) ; + fates_seed_germination_timescale:units = "1/yr" ; + fates_seed_germination_timescale:long_name = "turnover time for seeds with respect to decay" ; + float fates_seed_rain(fates_pft) ; + fates_seed_rain:units = "KgC/m2/yr" ; + fates_seed_rain:long_name = "External seed rain from outside site (non-mass conserving)" ; + float fates_smpsc(fates_pft) ; + fates_smpsc:units = "mm" ; + fates_smpsc:long_name = "Soil water potential at full stomatal closure" ; + float fates_smpso(fates_pft) ; + fates_smpso:units = "mm" ; + fates_smpso:long_name = "Soil water potential at full stomatal opening" ; + float fates_taulnir(fates_pft) ; + fates_taulnir:units = "fraction" ; + fates_taulnir:long_name = "Leaf transmittance: near-IR" ; + float fates_taulvis(fates_pft) ; + fates_taulvis:units = "fraction" ; + fates_taulvis:long_name = "Leaf transmittance: visible" ; + float fates_tausnir(fates_pft) ; + fates_tausnir:units = "fraction" ; + fates_tausnir:long_name = "Stem transmittance: near-IR" ; + float fates_tausvis(fates_pft) ; + fates_tausvis:units = "fraction" ; + fates_tausvis:long_name = "Stem transmittance: visible" ; + float fates_trim_inc(fates_pft) ; + fates_trim_inc:units = "m2/m2" ; + fates_trim_inc:long_name = "Arbitrary incremental change in trimming function." ; + float 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" ; + float fates_wood_density(fates_pft) ; + fates_wood_density:units = "g/cm3" ; + fates_wood_density:long_name = "mean density of woody tissue in plant" ; + float fates_woody(fates_pft) ; + fates_woody:units = "logical flag" ; + fates_woody:long_name = "Binary woody lifeform flag" ; + float fates_z0mr(fates_pft) ; + fates_z0mr:units = "unitless" ; + fates_z0mr:long_name = "Ratio of momentum roughness length to canopy top height" ; + float fates_base_mr_20(fates_scalar) ; + fates_base_mr_20:units = "gC/gN/s" ; + fates_base_mr_20:long_name = "Base maintenance respiration rate for plant tissues, using Ryan 1991" ; + float fates_bbopt_c3(fates_scalar) ; + fates_bbopt_c3:units = "umol H2O/m**2/s" ; + fates_bbopt_c3:long_name = "Ball-Berry minimum unstressed leaf conductance for C3" ; + float fates_bbopt_c4(fates_scalar) ; + fates_bbopt_c4:units = "umol H2O/m**2/s" ; + fates_bbopt_c4:long_name = "Ball-Berry minimum unstressed leaf conductance for C4" ; + float fates_canopy_closure_thresh(fates_scalar) ; + 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" ; + float fates_cohort_fusion_tol(fates_scalar) ; + fates_cohort_fusion_tol:units = "unitless" ; + fates_cohort_fusion_tol:long_name = "minimum fraction in difference in dbh between cohorts" ; + float fates_comp_excln(fates_scalar) ; + fates_comp_excln:units = "none" ; + fates_comp_excln:long_name = "weighting factor (exponent on dbh) for canopy layer exclusion and promotion" ; + float fates_cwd_fcel(fates_scalar) ; + fates_cwd_fcel:units = "unitless" ; + fates_cwd_fcel:long_name = "Cellulose fraction for CWD" ; + float fates_cwd_flig(fates_scalar) ; + fates_cwd_flig:units = "unitless" ; + fates_cwd_flig:long_name = "Lignin fraction of coarse woody debris" ; + float fates_fire_nignitions(fates_scalar) ; + fates_fire_nignitions:units = "/m2 (?)" ; + fates_fire_nignitions:long_name = "number of daily ignitions (nfires = nignitions*FDI*area_scaling)" ; + float fates_hydr_kmax_rsurf(fates_scalar) ; + fates_hydr_kmax_rsurf:units = "kg water/m2 root area/Mpa/s" ; + fates_hydr_kmax_rsurf:long_name = "maximum conducitivity for unit root surface" ; + float fates_hydr_psi0(fates_scalar) ; + fates_hydr_psi0:units = "MPa" ; + fates_hydr_psi0:long_name = "sapwood water potential at saturation" ; + float fates_hydr_psicap(fates_scalar) ; + fates_hydr_psicap:units = "MPa" ; + fates_hydr_psicap:long_name = "sapwood water potential at which capillary reserves exhausted" ; + float fates_init_litter(fates_scalar) ; + fates_init_litter:units = "NA" ; + fates_init_litter:long_name = "Initialization value for litter pool in cold-start (NOT USED)" ; + float fates_logging_coll_under_frac(fates_scalar) ; + 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" ; + float fates_logging_collateral_frac(fates_scalar) ; + fates_logging_collateral_frac:units = "fraction" ; + fates_logging_collateral_frac:long_name = "Fraction of large stems in upperstory that die from logging collateral damage" ; + float fates_logging_dbhmax_infra(fates_scalar) ; + 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." ; + float fates_logging_dbhmin(fates_scalar) ; + fates_logging_dbhmin:units = "cm" ; + fates_logging_dbhmin:long_name = "Minimum dbh at which logging is applied" ; + float fates_logging_direct_frac(fates_scalar) ; + fates_logging_direct_frac:units = "fraction" ; + fates_logging_direct_frac:long_name = "Fraction of stems logged directly per event" ; + float fates_logging_event_code(fates_scalar) ; + fates_logging_event_code:units = "unitless" ; + fates_logging_event_code:long_name = "Integer code that options how logging events are structured" ; + float fates_logging_mechanical_frac(fates_scalar) ; + fates_logging_mechanical_frac:units = "fraction" ; + fates_logging_mechanical_frac:long_name = "Fraction of stems killed due infrastructure an other mechanical means" ; + float fates_mort_disturb_frac(fates_scalar) ; + 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)" ; + float fates_mort_understorey_death(fates_scalar) ; + fates_mort_understorey_death:units = "fraction" ; + fates_mort_understorey_death:long_name = "fraction of plants in understorey cohort impacted by overstorey tree-fall" ; + float fates_patch_fusion_tol(fates_scalar) ; + fates_patch_fusion_tol:units = "unitless" ; + fates_patch_fusion_tol:long_name = "minimum fraction in difference in profiles between patches" ; + float fates_phen_a(fates_scalar) ; + fates_phen_a:units = "none" ; + fates_phen_a:long_name = "GDD accumulation function, intercept parameter: gdd_thesh = a + b exp(c*ncd)" ; + float fates_phen_b(fates_scalar) ; + fates_phen_b:units = "none" ; + fates_phen_b:long_name = "GDD accumulation function, multiplier parameter: gdd_thesh = a + b exp(c*ncd)" ; + float fates_phen_c(fates_scalar) ; + fates_phen_c:units = "none" ; + fates_phen_c:long_name = "GDD accumulation function, exponent parameter: gdd_thesh = a + b exp(c*ncd)" ; + float fates_phen_chiltemp(fates_scalar) ; + fates_phen_chiltemp:units = "degrees C" ; + fates_phen_chiltemp:long_name = "chilling day counting threshold" ; + float fates_phen_coldtemp(fates_scalar) ; + fates_phen_coldtemp:units = "degrees C" ; + fates_phen_coldtemp:long_name = "temperature exceedance to flag a cold-day for temperature leaf drop" ; + float fates_phen_doff_time(fates_scalar) ; + fates_phen_doff_time:units = "days" ; + fates_phen_doff_time:long_name = "day threshold compared against days since leaves became off-allometry" ; + float fates_phen_drought_threshold(fates_scalar) ; + fates_phen_drought_threshold:units = "m3/m3" ; + fates_phen_drought_threshold:long_name = "liquid volume in soil layer, threashold for drought phenology" ; + float fates_phen_mindayson(fates_scalar) ; + fates_phen_mindayson:units = "days" ; + fates_phen_mindayson:long_name = "day threshold compared against days since leaves became on-allometry" ; + float fates_phen_ncolddayslim(fates_scalar) ; + fates_phen_ncolddayslim:units = "days" ; + fates_phen_ncolddayslim:long_name = "day threshold exceedance for temperature leaf-drop" ; + float fates_durat_slope ; + fates_durat_slope:units = "NA" ; + fates_durat_slope:long_name = "spitfire parameter, fire max duration slope, Equation 14 Thonicke et al 2010" ; + float fates_fdi_a ; + fates_fdi_a:units = "NA" ; + fates_fdi_a:long_name = "spitfire parameter (unknown) " ; + float fates_fdi_alpha ; + fates_fdi_alpha:units = "NA" ; + fates_fdi_alpha:long_name = "spitfire parameter, EQ 7 Venevsky et al. GCB 2002,(modified EQ 8 Thonicke et al. 2010) " ; + float fates_fdi_b ; + fates_fdi_b:units = "NA" ; + fates_fdi_b:long_name = "spitfire parameter (unknown) " ; + float fates_fire_wind_max ; + fates_fire_wind_max:units = "m/min" ; + fates_fire_wind_max:long_name = "maximum wind speed expected by the fire model" ; + float fates_fuel_energy ; + fates_fuel_energy:units = "kJ/kg" ; + fates_fuel_energy:long_name = "pitfire parameter, heat content of fuel" ; + float fates_max_durat ; + fates_max_durat:units = "minutes" ; + fates_max_durat:long_name = "spitfire parameter, fire maximum duration, Equation 14 Thonicke et al 2010" ; + float fates_miner_damp ; + fates_miner_damp:units = "NA" ; + fates_miner_damp:long_name = "spitfire parameter, mineral-dampening coefficient EQ A1 Thonicke et al 2010 " ; + float fates_miner_total ; + fates_miner_total:units = "fraction" ; + fates_miner_total:long_name = "spitfire parameter, total mineral content, Table A1 Thonicke et al 2010" ; + float fates_part_dens ; + fates_part_dens:units = "kg/m2" ; + fates_part_dens:long_name = "spitfire parameter, oven dry particle density, Table A1 Thonicke et al 2010" ; + +// global attributes: + :history = "This file was made from FatesPFTIndexSwapper.py \n", + " Input File = fates_params_13pfts.c180315.nc \n", + " Indices = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13] \n", + " Wed Feb 28 13:43:44 PST 2018 Values from Jennifer Holms 13pft test file fates_params.c170929_13pfts.nc were then manually converted over into positions 2-13, position 1 kept the tropical broadleaf evergreen. Wed Mar 7 15:53:33 PST 2018 (RGK) added fates_logging_dbhmax_infra, fates_maintresp_reduction_curvature, fates_maintresp_reduction_intercept, and fates_leaf_clumping_index. CHanged fates_clone_alloc to fates_seed_alloc_mature. Updated minimum grass sizes per J Shuman notes. Set grass AGB intercepts and latosa to zero. Updated clumping to have more substanteated starter values per suggestions by Shawn Serbin.\n", + " Thu Mar 15 13:48:11 PDT 2018 Added C4 plants via suggestions by @huitang_earth.\n", + " Mon Mar 19 19:05:44 EDT 2018 forced all plants to be evergreen till carbon-imbalances are fixed.\n", + " Mon Mar 19 19:05:44 EDT 2018 added entry for fates_history_height_bin_edges.\n", + " Thu Apr 12 14:18:46 PDT 2018 updated names on CN recruitment parameters. -- fates_params_14pft.c180412.nc -- \n", + " This file was made then modified wih FatesPFTIndexSwapper.py to reduce to 2 tropical pfts again. \n", + " Indices = [1, 1] \n", + " Wed Aug 29 12:14:41 PDT 2018: (RGK) Updated latosa to la_per_sa (inverts units, invert defaults also)\n" ; +data: + + fates_history_sizeclass_bin_edges = 0, 5, 10, 15, 20, 30, 40, 50, 60, 70, + 80, 90, 100 ; + + fates_history_ageclass_bin_edges = 0, 1, 2, 5, 10, 20, 50 ; + + fates_FBD = 4, 15.4, 16.8, 19.6, 999, 4 ; + + fates_SAV = 66, 13, 3.58, 0.98, 0.2, 66 ; + + fates_alpha_FMC = 0.0050769, 0.001, 0.0002754, 7.54e-05, 1.54e-05, 999 ; + + fates_history_height_bin_edges = 0, 0.1, 0.3, 1, 3, 10 ; + + fates_low_moisture_Coeff = 1.15, 1.12, 1.09, 0.98, 0.8, 1.15 ; + + fates_low_moisture_Slope = 0.62, 0.62, 0.72, 0.85, 0.8, 0.62 ; + + fates_max_decomp = 1, 0.52, 0.383, 0.383, 0.19, 999 ; + + fates_mid_moisture = 0.8, 0.72, 0.51, 0.38, 1, 0.8 ; + + fates_mid_moisture_Coeff = 3.2, 2.35, 1.47, 1.06, 0.8, 3.2 ; + + fates_mid_moisture_Slope = 3.2, 2.35, 1.47, 1.06, 0.8, 3.2 ; + + fates_min_moisture = 0.24, 0.18, 0.12, 0, 0, 0.24 ; + + fates_hydr_avuln_node = + 2, 2, + 2, 2, + 2, 2, + 2, 2 ; + + fates_hydr_epsil_node = + 12, 12, + 10, 10, + 10, 10, + 8, 8 ; + + fates_hydr_fcap_node = + 0, 0, + 0.08, 0.08, + 0.08, 0.08, + 0, 0 ; + + fates_hydr_kmax_node = + -999, -999, + 3, 3, + -999, -999, + -999, -999 ; + + fates_hydr_p50_node = + -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25, + -2.25, -2.25 ; + + fates_hydr_pinot_node = + -1.465984, -1.465984, + -1.228070, -1.228070, + -1.228070, -1.228070, + -1.043478, -1.043478 ; + + fates_hydr_pitlp_node = + -1.67, -1.67, + -1.4, -1.4, + -1.4, -1.4, + -1.2, -1.2 ; + + fates_hydr_resid_node = + 0.25, 0.25, + 0.325, 0.325, + 0.325, 0.325, + 0.15, 0.15 ; + + fates_hydr_thetas_node = + 0.65, 0.65, + 0.65, 0.65, + 0.65, 0.65, + 0.75, 0.75 ; + + fates_CWD_frac = 0.045, 0.075, 0.21, 0.67 ; + + fates_pftname = + "broadleaf_evergreen_tropical_tree ", + "broadleaf_evergreen_tropical_tree " ; + + fates_prt_organ_name = + "leaf ", + "fine root ", + "sapwood ", + "storage ", + "reproduction ", + "structure "; + + fates_rootprof_beta = + 0.976, 0.976, + _, _ ; + + fates_alloc_storage_cushion = 2, 2 ; + + fates_allom_agb1 = 0.06896, 0.06896 ; + + fates_allom_agb2 = 0.572, 0.572 ; + + fates_allom_agb3 = 1.94, 1.94 ; + + fates_allom_agb4 = 0.931, 0.931 ; + + fates_allom_agb_frac = 0.6, 0.6 ; + + fates_allom_amode = 1, 1 ; + + fates_allom_blca_expnt_diff = 0, 0 ; + + fates_allom_cmode = 1, 1 ; + + fates_allom_d2bl1 = 0.07, 0.07 ; + + fates_allom_d2bl2 = 1.3, 1.3 ; + + fates_allom_d2bl3 = 0.55, 0.55 ; + + fates_allom_d2ca_coefficient_max = 0.6568464, 0.6568464 ; + + fates_allom_d2ca_coefficient_min = 0.3381119, 0.3381119 ; + + fates_allom_d2h1 = 0.64, 0.64 ; + + fates_allom_d2h2 = 0.37, 0.37 ; + + fates_allom_d2h3 = -999.9, -999.9 ; + + fates_allom_dbh_maxheight = 150, 150 ; + + fates_allom_fmode = 1, 1 ; + + fates_allom_hmode = 1, 1 ; + + fates_allom_l2fr = 1, 1 ; + + fates_allom_la_per_sa_int = 0.8, 0.8 ; + + fates_allom_la_per_sa_slp = 0.0, 0.0 ; + + fates_allom_lmode = 1, 1 ; + + fates_allom_sai_scaler = 0.10, 0.10 ; + + fates_allom_smode = 1, 1 ; + + fates_allom_stmode = 1, 1 ; + + fates_branch_turnover = 50, 50 ; + + fates_prt_nitr_stoich_p1 = + 0.033, 0.033, + 0.024, 0.024, + 0.0000047, 0.0000047, + 0.0000047, 0.0000047, + 0.0, 0.0, + 0.0000047, 0.0000047; + + fates_prt_nitr_stoich_p2 = + _, _, + _, _, + _, _, + _, _, + _, _, + _, _; + + fates_prt_phos_stoich_p1 = + _, _, + _, _, + _, _, + _, _, + _, _, + _, _; + + fates_prt_phos_stoich_p2 = + _, _, + _, _, + _, _, + _, _, + _, _, + _, _; + + fates_prt_alloc_priority = + _, _, + _, _, + _, _, + _, _, + _, _, + _, _; + + fates_phenflush_fraction = + 0.5, 0.5; + + fates_turnover_retrans_mode = + 1, 1; + + fates_turnover_carb_retrans = + 0.00, 0.00, + 0.00, 0.00, + 0.00, 0.00, + 0.00, 0.00, + 0.00, 0.00, + 0.00, 0.00; + + fates_turnover_nitr_retrans = + _, _, + _, _, + _, _, + _, _, + _, _, + _, _; + + fates_turnover_phos_retrans = + _, _, + _, _, + _, _, + _, _, + _, _, + _, _; + + fates_c2b = 2, 2 ; + + fates_displar = 0.67, 0.67 ; + + fates_fire_alpha_SH = 0.2, 0.2 ; + + fates_fire_bark_scaler = 0.07, 0.07 ; + + fates_fire_crown_depth_frac = 0.5, 0.5 ; + + fates_fire_crown_kill = 0.775, 0.775 ; + + fates_fr_fcel = 0.5, 0.5 ; + + fates_fr_flab = 0.25, 0.25 ; + + fates_fr_flig = 0.25, 0.25 ; + + fates_grperc = 0.11, 0.11 ; + + fates_hydr_avuln_gs = 2.5, 2.5 ; + + fates_hydr_p50_gs = -1.5, -1.5 ; + + fates_hydr_p_taper = 0.333, 0.333 ; + + fates_hydr_rfrac_stem = 0.625, 0.625 ; + + fates_hydr_rs2 = 0.0001, 0.0001 ; + + fates_hydr_srl = 25, 25 ; + + fates_leaf_BB_slope = 8, 8 ; + + fates_leaf_c3psn = 1, 1 ; + + fates_leaf_clumping_index = 0.85, 0.85 ; + + fates_leaf_diameter = 0.04, 0.04 ; + + fates_leaf_jmaxha = 43540, 43540 ; + + fates_leaf_jmaxhd = 152040, 152040 ; + + fates_leaf_jmaxse = 495, 495 ; + + fates_leaf_long = 1.5, 1.5 ; + + fates_leaf_slamax = 0.0954, 0.0954 ; + + fates_leaf_slatop = 0.012, 0.012 ; + + fates_leaf_stor_priority = 0.8, 0.8 ; + + fates_leaf_tpuha = 53100, 53100 ; + + fates_leaf_tpuhd = 150650, 150650 ; + + fates_leaf_tpuse = 490, 490 ; + + fates_leaf_vcmax25top = 50, 50 ; + + fates_leaf_vcmaxha = 65330, 65330 ; + + fates_leaf_vcmaxhd = 149250, 149250 ; + + fates_leaf_vcmaxse = 485, 485 ; + + fates_leaf_xl = 0.1, 0.1 ; + + fates_lf_fcel = 0.5, 0.5 ; + + fates_lf_flab = 0.25, 0.25 ; + + fates_lf_flig = 0.25, 0.25 ; + + fates_maintresp_reduction_curvature = 0.01, 0.01 ; + + fates_maintresp_reduction_intercept = 1, 1 ; + + fates_mort_bmort = 0.014, 0.014 ; + + fates_mort_freezetol = 2.5, 2.5 ; + + fates_mort_hf_sm_threshold = 1e-06, 1e-06 ; + + fates_mort_scalar_coldstress = 3, 3 ; + + fates_mort_scalar_cstarvation = 0.6, 0.6 ; + + fates_mort_scalar_hydrfailure = 0.6, 0.6 ; + + fates_pft_used = 1, 1 ; + + fates_phen_evergreen = 1, 1 ; + + fates_phen_season_decid = 0, 0 ; + + fates_phen_stress_decid = 0, 0 ; + + fates_prescribed_mortality_canopy = 0.0194, 0.0194 ; + + fates_prescribed_mortality_understory = 0.025, 0.025 ; + + fates_prescribed_npp_canopy = 0.4, 0.4 ; + + fates_prescribed_npp_understory = 0.03125, 0.03125 ; + + fates_prescribed_recruitment = 0.02, 0.02 ; + + fates_recruit_hgt_min = 1.25, 1.25 ; + + fates_recruit_initd = 0.2, 0.2 ; + + fates_rholnir = 0.45, 0.45 ; + + fates_rholvis = 0.1, 0.1 ; + + fates_rhosnir = 0.39, 0.39 ; + + fates_rhosvis = 0.16, 0.16 ; + + fates_root_long = 1, 1 ; + + fates_roota_par = 7, 7 ; + + fates_rootb_par = 1, 1 ; + + fates_seed_alloc = 0.1, 0.1 ; + + fates_seed_alloc_mature = 0, 0 ; + + fates_seed_dbh_repro_threshold = 150, 150 ; + + fates_seed_decay_turnover = 0.51, 0.51 ; + + fates_seed_germination_timescale = 0.5, 0.5 ; + + fates_seed_rain = 0.28, 0.28 ; + + fates_smpsc = -255000, -255000 ; + + fates_smpso = -66000, -66000 ; + + fates_taulnir = 0.25, 0.25 ; + + fates_taulvis = 0.05, 0.05 ; + + fates_tausnir = 0.001, 0.001 ; + + fates_tausvis = 0.001, 0.001 ; + + fates_trim_inc = 0.03, 0.03 ; + + fates_trim_limit = 0.3, 0.3 ; + + fates_wood_density = 0.7, 0.7 ; + + fates_woody = 1, 1 ; + + fates_z0mr = 0.055, 0.055 ; + + fates_base_mr_20 = 2.52e-06 ; + + fates_bbopt_c3 = 10000 ; + + fates_bbopt_c4 = 40000 ; + + fates_canopy_closure_thresh = 0.8 ; + + fates_cohort_fusion_tol = 0.05 ; + + fates_comp_excln = 3 ; + + fates_cwd_fcel = 0.76 ; + + fates_cwd_flig = 0.24 ; + + fates_fire_nignitions = 15 ; + + fates_hydr_kmax_rsurf = 20; + + fates_hydr_psi0 = 0 ; + + fates_hydr_psicap = -0.6 ; + + fates_init_litter = 0.05 ; + + fates_logging_coll_under_frac = 0.55983 ; + + fates_logging_collateral_frac = 0.05 ; + + fates_logging_dbhmax_infra = 35 ; + + fates_logging_dbhmin = 50 ; + + fates_logging_direct_frac = 0.15 ; + + fates_logging_event_code = -30 ; + + fates_logging_mechanical_frac = 0.05 ; + + fates_mort_disturb_frac = 1 ; + + fates_mort_understorey_death = 0.55983 ; + + fates_patch_fusion_tol = 0.05 ; + + fates_phen_a = -68 ; + + fates_phen_b = 638 ; + + fates_phen_c = -0.001 ; + + fates_phen_chiltemp = 5 ; + + fates_phen_coldtemp = 7.5 ; + + fates_phen_doff_time = 100 ; + + fates_phen_drought_threshold = 0.15 ; + + fates_phen_mindayson = 30 ; + + fates_phen_ncolddayslim = 5 ; + + fates_durat_slope = -11.06 ; + + fates_fdi_a = 17.62 ; + + fates_fdi_alpha = 0.00037 ; + + fates_fdi_b = 243.12 ; + + fates_fire_wind_max = 45.718 ; + + fates_fuel_energy = 18000 ; + + fates_max_durat = 240 ; + + fates_miner_damp = 0.41739 ; + + fates_miner_total = 0.055 ; + + fates_part_dens = 513 ; +} From d2c8d8b9bd42dbc320343bb9c9b9c996a8efd4bd Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Sun, 25 Nov 2018 14:40:06 -0700 Subject: [PATCH 49/53] add the hydraulic failure mortality based on fractional loss of conductivity --- biogeochem/EDMortalityFunctionsMod.F90 | 29 +++++++++++++++++++++--- main/EDPftvarcon.F90 | 14 ++++++++++-- parameter_files/fates_params_14pfts.cdl | 8 ++++++- parameter_files/fates_params_default.cdl | 5 ++++ 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index b052d34773..24be3323ae 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -16,6 +16,7 @@ module EDMortalityFunctionsMod use FatesInterfaceMod , only : bc_in_type use FatesInterfaceMod , only : hlm_use_ed_prescribed_phys use FatesInterfaceMod , only : hlm_freq_day + use FatesInterfaceMod , only : hlm_use_planthydro use EDLoggingMortalityMod , only : LoggingMortality_frac use EDParamsMod , only : fates_mortality_disturbance_fraction use FatesInterfaceMod , only : bc_in_type @@ -62,8 +63,14 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort ) real(r8) :: leaf_c_target ! target leaf biomass kgC real(r8) :: store_c real(r8) :: hf_sm_threshold ! hydraulic failure soil moisture threshold + real(r8) :: hf_flc_threshold ! hydraulic failure fractional loss of conductivity threshold real(r8) :: temp_dep_fraction ! Temp. function (freezing mortality) real(r8) :: temp_in_C ! Daily averaged temperature in Celcius + real(r8) :: min_fmc_ag ! minimum fraction of maximum conductivity for aboveground + real(r8) :: min_fmc_tr ! minimum fraction of maximum conductivity for transporting root + real(r8) :: min_fmc_ar ! minimum fraction of maximum conductivity for absorbing root + real(r8) :: min_fmc ! minimum fraction of maximum conductivity for whole plant + real(r8) :: flc ! fractional loss of conductivity real(r8), parameter :: frost_mort_buffer = 5.0_r8 ! 5deg buffer for freezing mortality logical, parameter :: test_zero_mortality = .false. ! Developer test which ! may help to debug carbon imbalances @@ -77,12 +84,28 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort ) ! Proxy for hydraulic failure induced mortality. hf_sm_threshold = EDPftvarcon_inst%hf_sm_threshold(cohort_in%pft) - - if(cohort_in%patchptr%btran_ft(cohort_in%pft) <= hf_sm_threshold)then + hf_flc_threshold = EDPftvarcon_inst%hf_flc_threshold(cohort_in%pft) + if(hlm_use_planthydro.eq.itrue)then + min_fmc_ag = minval(cohort_in%co_hydr%flc_ag(:)) + min_fmc_tr = minval(cohort_in%co_hydr%flc_troot(:)) + min_fmc_ar = minval(cohort_in%co_hydr%flc_aroot(:)) + min_fmc = min(min_fmc_ag, min_fmc_tr) + min_fmc = min(min_fmc, min_fmc_ar) + flc = 1.0_r8-min_fmc + !note the flc is set as the fraction of max conductivity in hydro + if(flc >= hf_flc_threshold .and. hf_flc_threshold < 1.0_r8 )then + hmort = (flc-hf_flc_threshold)/(1.0_r8-hf_flc_threshold) * & + EDPftvarcon_inst%mort_scalar_hydrfailure(cohort_in%pft) + else + hmort = 0.0_r8 + endif + else + if(cohort_in%patchptr%btran_ft(cohort_in%pft) <= hf_sm_threshold)then hmort = EDPftvarcon_inst%mort_scalar_hydrfailure(cohort_in%pft) else hmort = 0.0_r8 - endif + endif + endif ! Carbon Starvation induced mortality. if ( cohort_in%dbh > 0._r8 ) then diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index a4966fcfad..33317bb371 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -86,6 +86,7 @@ module EDPftvarcon real(r8), allocatable :: mort_scalar_cstarvation(:) real(r8), allocatable :: mort_scalar_hydrfailure(:) real(r8), allocatable :: hf_sm_threshold(:) + real(r8), allocatable :: hf_flc_threshold(:) real(r8), allocatable :: vcmaxha(:) real(r8), allocatable :: jmaxha(:) real(r8), allocatable :: tpuha(:) @@ -652,7 +653,11 @@ subroutine Register_PFT(this, fates_params) name = 'fates_mort_hf_sm_threshold' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) - + + name = 'fates_mort_hf_flc_threshold' + call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & + dimension_names=dim_names, lower_bounds=dim_lower_bound) + name = 'fates_leaf_vcmaxha' call fates_params%RegisterParameter(name=name, dimension_shape=dimension_shape_1d, & dimension_names=dim_names, lower_bounds=dim_lower_bound) @@ -1083,7 +1088,11 @@ subroutine Receive_PFT(this, fates_params) name = 'fates_mort_hf_sm_threshold' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hf_sm_threshold) - + + name = 'fates_mort_flc_sm_threshold' + call fates_params%RetreiveParameterAllocate(name=name, & + data=this%hf_flc_threshold) + name = 'fates_leaf_vcmaxha' call fates_params%RetreiveParameterAllocate(name=name, & data=this%vcmaxha) @@ -1670,6 +1679,7 @@ subroutine FatesReportPFTParams(is_master) write(fates_log(),fmt0) 'mort_scalar_cstarvation = ',EDPftvarcon_inst%mort_scalar_cstarvation write(fates_log(),fmt0) 'mort_scalar_hydrfailure = ',EDPftvarcon_inst%mort_scalar_hydrfailure write(fates_log(),fmt0) 'hf_sm_threshold = ',EDPftvarcon_inst%hf_sm_threshold + write(fates_log(),fmt0) 'hf_flc_threshold = ',EDPftvarcon_inst%hf_flc_threshold write(fates_log(),fmt0) 'vcmaxha = ',EDPftvarcon_inst%vcmaxha write(fates_log(),fmt0) 'jmaxha = ',EDPftvarcon_inst%jmaxha write(fates_log(),fmt0) 'tpuha = ',EDPftvarcon_inst%tpuha diff --git a/parameter_files/fates_params_14pfts.cdl b/parameter_files/fates_params_14pfts.cdl index 39f1d6ee40..ebbf1b46ac 100644 --- a/parameter_files/fates_params_14pfts.cdl +++ b/parameter_files/fates_params_14pfts.cdl @@ -404,6 +404,9 @@ variables: float fates_mort_hf_sm_threshold(fates_pft) ; fates_mort_hf_sm_threshold:units = "unitless" ; fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + float fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; float fates_mort_scalar_coldstress(fates_pft) ; fates_mort_scalar_coldstress:units = "1/yr" ; fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; @@ -1039,7 +1042,10 @@ data: 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, 1e-06, 1e-06 ; - + + 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, 0.5, 0.5 ; + fates_mort_scalar_coldstress = 3, 3, 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, diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 9684fd2c27..88eef98ac0 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -344,6 +344,9 @@ variables: float fates_mort_hf_sm_threshold(fates_pft) ; fates_mort_hf_sm_threshold:units = "unitless" ; fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + float fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; float fates_mort_scalar_coldstress(fates_pft) ; fates_mort_scalar_coldstress:units = "1/yr" ; fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; @@ -909,6 +912,8 @@ data: fates_mort_freezetol = 2.5, 2.5 ; fates_mort_hf_sm_threshold = 1e-06, 1e-06 ; + + fates_mort_hf_sm_threshold = 0.5, 0.5 ; fates_mort_scalar_coldstress = 3, 3 ; From 8fcbadd6da763ef998ec83ffd417cdb3c2499a01 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Sun, 25 Nov 2018 14:49:59 -0700 Subject: [PATCH 50/53] update the parameter files for hydraulic failure mortality --- parameter_files/fates_params_default.cdl | 2 +- parameter_files/fates_params_hydro_default.cdl | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/parameter_files/fates_params_default.cdl b/parameter_files/fates_params_default.cdl index 88eef98ac0..20afac23ef 100644 --- a/parameter_files/fates_params_default.cdl +++ b/parameter_files/fates_params_default.cdl @@ -913,7 +913,7 @@ data: fates_mort_hf_sm_threshold = 1e-06, 1e-06 ; - fates_mort_hf_sm_threshold = 0.5, 0.5 ; + fates_mort_hf_flc_threshold = 0.5, 0.5 ; fates_mort_scalar_coldstress = 3, 3 ; diff --git a/parameter_files/fates_params_hydro_default.cdl b/parameter_files/fates_params_hydro_default.cdl index 2ae35a917c..e6e3adfbec 100644 --- a/parameter_files/fates_params_hydro_default.cdl +++ b/parameter_files/fates_params_hydro_default.cdl @@ -344,6 +344,9 @@ variables: float fates_mort_hf_sm_threshold(fates_pft) ; fates_mort_hf_sm_threshold:units = "unitless" ; fates_mort_hf_sm_threshold:long_name = "soil moisture (btran units) at which drought mortality begins for non-hydraulic model" ; + float fates_mort_hf_flc_threshold(fates_pft) ; + fates_mort_hf_flc_threshold:units = "fraction" ; + fates_mort_hf_flc_threshold:long_name = "plant fractional loss of conductivity at which drought mortality begins for hydraulic model" ; float fates_mort_scalar_coldstress(fates_pft) ; fates_mort_scalar_coldstress:units = "1/yr" ; fates_mort_scalar_coldstress:long_name = "maximum mortality rate from cold stress" ; @@ -909,6 +912,8 @@ data: fates_mort_freezetol = 2.5, 2.5 ; fates_mort_hf_sm_threshold = 1e-06, 1e-06 ; + + fates_mort_hf_flc_threshold = 0.5, 0.5 ; fates_mort_scalar_coldstress = 3, 3 ; From 78b28ab3064bb4464a2683d3c36c1298d57407ff Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Sun, 25 Nov 2018 14:58:41 -0700 Subject: [PATCH 51/53] correct a typo of hf_flc_threshold --- main/EDPftvarcon.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/EDPftvarcon.F90 b/main/EDPftvarcon.F90 index 33317bb371..33070b16ab 100644 --- a/main/EDPftvarcon.F90 +++ b/main/EDPftvarcon.F90 @@ -1089,7 +1089,7 @@ subroutine Receive_PFT(this, fates_params) call fates_params%RetreiveParameterAllocate(name=name, & data=this%hf_sm_threshold) - name = 'fates_mort_flc_sm_threshold' + name = 'fates_mort_hf_flc_threshold' call fates_params%RetreiveParameterAllocate(name=name, & data=this%hf_flc_threshold) From 30f776d2f5f4a1a0f07eaccd47a2f33063d75537 Mon Sep 17 00:00:00 2001 From: Chonggang Xu Date: Sun, 25 Nov 2018 15:08:01 -0700 Subject: [PATCH 52/53] moved a comment on hf mortality for easier readibility of codes --- biogeochem/EDMortalityFunctionsMod.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biogeochem/EDMortalityFunctionsMod.F90 b/biogeochem/EDMortalityFunctionsMod.F90 index 24be3323ae..130a269593 100644 --- a/biogeochem/EDMortalityFunctionsMod.F90 +++ b/biogeochem/EDMortalityFunctionsMod.F90 @@ -86,13 +86,13 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort ) hf_sm_threshold = EDPftvarcon_inst%hf_sm_threshold(cohort_in%pft) hf_flc_threshold = EDPftvarcon_inst%hf_flc_threshold(cohort_in%pft) if(hlm_use_planthydro.eq.itrue)then + !note the flc is set as the fraction of max conductivity in hydro min_fmc_ag = minval(cohort_in%co_hydr%flc_ag(:)) min_fmc_tr = minval(cohort_in%co_hydr%flc_troot(:)) min_fmc_ar = minval(cohort_in%co_hydr%flc_aroot(:)) min_fmc = min(min_fmc_ag, min_fmc_tr) min_fmc = min(min_fmc, min_fmc_ar) flc = 1.0_r8-min_fmc - !note the flc is set as the fraction of max conductivity in hydro if(flc >= hf_flc_threshold .and. hf_flc_threshold < 1.0_r8 )then hmort = (flc-hf_flc_threshold)/(1.0_r8-hf_flc_threshold) * & EDPftvarcon_inst%mort_scalar_hydrfailure(cohort_in%pft) From 657473e06d68e149d4998d7fe999d02f30db75fe Mon Sep 17 00:00:00 2001 From: Ryan Knox Date: Tue, 1 Jan 2019 22:43:51 -0700 Subject: [PATCH 53/53] Fixes for history and restarts, making sure that hydro diagostics are only accessed if turned on and allocated --- main/FatesHistoryInterfaceMod.F90 | 39 +++++++++++++------------ main/FatesRestartInterfaceMod.F90 | 48 ++++++++++++------------------- 2 files changed, 38 insertions(+), 49 deletions(-) diff --git a/main/FatesHistoryInterfaceMod.F90 b/main/FatesHistoryInterfaceMod.F90 index 81b4629769..760d180a51 100644 --- a/main/FatesHistoryInterfaceMod.F90 +++ b/main/FatesHistoryInterfaceMod.F90 @@ -1518,12 +1518,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_ddbh_canopy_si_scag => this%hvars(ih_ddbh_canopy_si_scag)%r82d, & hio_ddbh_understory_si_scag => this%hvars(ih_ddbh_understory_si_scag)%r82d, & hio_mortality_canopy_si_scag => this%hvars(ih_mortality_canopy_si_scag)%r82d, & - hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d, & - hio_h2oveg_dead_si => this%hvars(ih_h2oveg_dead_si)%r81d, & - hio_h2oveg_recruit_si => this%hvars(ih_h2oveg_recruit_si)%r81d, & - hio_h2oveg_growturn_err_si => this%hvars(ih_h2oveg_growturn_err_si)%r81d, & - hio_h2oveg_pheno_err_si => this%hvars(ih_h2oveg_pheno_err_si)%r81d,& - hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d) + hio_mortality_understory_si_scag => this%hvars(ih_mortality_understory_si_scag)%r82d) ! --------------------------------------------------------------------------------- @@ -1534,7 +1529,7 @@ subroutine update_history_dyn(this,nc,nsites,sites) ! If we don't have dynamics turned on, we just abort these diagnostics - !if (hlm_use_ed_st3.eq.itrue) return + if (hlm_use_ed_st3.eq.itrue) return ! --------------------------------------------------------------------------------- ! Loop through the FATES scale hierarchy and fill the history IO arrays @@ -1553,6 +1548,18 @@ subroutine update_history_dyn(this,nc,nsites,sites) hio_seed_bank_si(io_si) = sum(sites(s)%seed_bank) * g_per_kg hio_canopy_spread_si(io_si) = sites(s)%spread + + + ! If hydraulics are turned on, track the error terms + ! associated with dynamics + + if(hlm_use_planthydro.eq.itrue)then + this%hvars(ih_h2oveg_dead_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_dead + this%hvars(ih_h2oveg_recruit_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_recruit + this%hvars(ih_h2oveg_growturn_err_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_growturn_err + this%hvars(ih_h2oveg_pheno_err_si)%r81d(io_si) = sites(s)%si_hydr%h2oveg_pheno_err + end if + ipa = 0 cpatch => sites(s)%oldest_patch @@ -2237,14 +2244,6 @@ subroutine update_history_dyn(this,nc,nsites,sites) sites(s)%leaf_litter_diagnostic_input_carbonflux(:) = 0._r8 sites(s)%root_litter_diagnostic_input_carbonflux(:) = 0._r8 - if(hlm_use_planthydro==itrue)then - hio_h2oveg_dead_si(io_si) = sites(s)%si_hydr%h2oveg_dead - hio_h2oveg_recruit_si(io_si) = sites(s)%si_hydr%h2oveg_recruit - hio_h2oveg_growturn_err_si(io_si) = sites(s)%si_hydr%h2oveg_growturn_err - hio_h2oveg_pheno_err_si(io_si) = sites(s)%si_hydr%h2oveg_pheno_err - hio_h2oveg_hydro_err_si(io_si) = sites(s)%si_hydr%h2oveg_hydro_err - endif - enddo ! site loop end associate @@ -2780,7 +2779,8 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) hio_lflc_scpf => this%hvars(ih_lflc_scpf)%r82d, & hio_btran_scpf => this%hvars(ih_btran_scpf)%r82d, & hio_h2oveg_si => this%hvars(ih_h2oveg_si)%r81d, & - hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d ) + hio_nplant_si_scpf => this%hvars(ih_nplant_si_scpf)%r82d, & + hio_h2oveg_hydro_err_si => this%hvars(ih_h2oveg_hydro_err_si)%r81d ) ! Flush the relevant history variables call this%flush_hvars(nc,upfreq_in=4) @@ -2790,6 +2790,9 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) io_si = this%iovar_map(nc)%site_index(s) io_pa1 = this%iovar_map(nc)%patch1_index(s) + hio_h2oveg_si(io_si) = sites(s)%si_hydr%h2oveg + hio_h2oveg_hydro_err_si(io_si) = sites(s)%si_hydr%h2oveg_hydro_err + ncohort_scpf(:) = 0.0_r8 ! Counter for normalizing weighting ! factors for cohort mean propoerties ! This is actually used as a check @@ -3031,8 +3034,6 @@ subroutine update_history_hydraulics(this,nc,nsites,sites,dt_tstep) end do end if - hio_h2oveg_si(io_si) = sites(s)%si_hydr%h2oveg - enddo ! site loop end associate @@ -4639,7 +4640,7 @@ subroutine define_history_vars(this, initialize_variables) call this%set_history_var(vname='H2OVEG_HYDRO_ERR', units = 'kg/m2', & long='cumulative net borrowed (+) from plant_stored_h2o due to plant hydrodynamics', use_default='inactive', & avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, & - upfreq=1, ivar=ivar, initialize=initialize_variables, index = ih_h2oveg_hydro_err_si ) + upfreq=4, ivar=ivar, initialize=initialize_variables, index = ih_h2oveg_hydro_err_si ) end if ! Must be last thing before return diff --git a/main/FatesRestartInterfaceMod.F90 b/main/FatesRestartInterfaceMod.F90 index fa851b32fc..c108be8757 100644 --- a/main/FatesRestartInterfaceMod.F90 +++ b/main/FatesRestartInterfaceMod.F90 @@ -1372,13 +1372,7 @@ subroutine set_restart_vectors(this,nc,nsites,sites) rio_livegrass_pa => this%rvars(ir_livegrass_pa)%r81d, & rio_age_pa => this%rvars(ir_age_pa)%r81d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & - rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & - rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d, & - rio_hydro_recruit_si => this%rvars(ir_hydro_recruit_si)%r81d, & - rio_hydro_dead_si => this%rvars(ir_hydro_dead_si)%r81d, & - rio_hydro_growturn_err_si => this%rvars(ir_hydro_growturn_err_si)%r81d, & - rio_hydro_pheno_err_si => this%rvars(ir_hydro_pheno_err_si)%r81d, & - rio_hydro_hydro_err_si => this%rvars(ir_hydro_hydro_err_si)%r81d) + rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d) totalCohorts = 0 @@ -1655,17 +1649,20 @@ subroutine set_restart_vectors(this,nc,nsites,sites) if(hlm_use_planthydro==itrue)then - rio_hydro_recruit_si(io_idx_si) = sites(s)%si_hydr%h2oveg_recruit - rio_hydro_dead_si(io_idx_si) = sites(s)%si_hydr%h2oveg_dead - rio_hydro_growturn_err_si(io_idx_si) = sites(s)%si_hydr%h2oveg_growturn_err - rio_hydro_pheno_err_si(io_idx_si) = sites(s)%si_hydr%h2oveg_pheno_err - rio_hydro_hydro_err_si(io_idx_si) = sites(s)%si_hydr%h2oveg_hydro_err + ! No associate statements because there is no gaurantee these + ! are allocated + + this%rvars(ir_hydro_recruit_si)%r81d(io_idx_si) = sites(s)%si_hydr%h2oveg_recruit + this%rvars(ir_hydro_dead_si)%r81d(io_idx_si) = sites(s)%si_hydr%h2oveg_dead + this%rvars(ir_hydro_growturn_err_si)%r81d(io_idx_si) = sites(s)%si_hydr%h2oveg_growturn_err + this%rvars(ir_hydro_pheno_err_si)%r81d(io_idx_si) = sites(s)%si_hydr%h2oveg_pheno_err + this%rvars(ir_hydro_hydro_err_si)%r81d(io_idx_si) = sites(s)%si_hydr%h2oveg_hydro_err ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell do i = 1, sites(s)%si_hydr%nlevsoi_hyd ! Loop shells do k = 1, nshell - rio_hydro_liqvol_shell_si(io_idx_si_lyr_shell) = & + this%rvars(ir_hydro_liqvol_shell_si)%r81d(io_idx_si_lyr_shell) = & sites(s)%si_hydr%h2osoi_liqvol_shell(i,k) io_idx_si_lyr_shell = io_idx_si_lyr_shell + 1 end do @@ -2012,13 +2009,7 @@ subroutine get_restart_vectors(this, nc, nsites, sites) rio_livegrass_pa => this%rvars(ir_livegrass_pa)%r81d, & rio_age_pa => this%rvars(ir_age_pa)%r81d, & rio_area_pa => this%rvars(ir_area_pa)%r81d, & - rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d, & - rio_hydro_liqvol_shell_si => this%rvars(ir_hydro_liqvol_shell_si)%r81d, & - rio_hydro_recruit_si => this%rvars(ir_hydro_recruit_si)%r81d, & - rio_hydro_dead_si => this%rvars(ir_hydro_dead_si)%r81d, & - rio_hydro_growturn_err_si => this%rvars(ir_hydro_growturn_err_si)%r81d, & - rio_hydro_pheno_err_si => this%rvars(ir_hydro_pheno_err_si)%r81d, & - rio_hydro_hydro_err_si => this%rvars(ir_hydro_hydro_err_si)%r81d) + rio_watermem_siwm => this%rvars(ir_watermem_siwm)%r81d) totalcohorts = 0 @@ -2259,18 +2250,18 @@ subroutine get_restart_vectors(this, nc, nsites, sites) if(hlm_use_planthydro==itrue)then - sites(s)%si_hydr%h2oveg_recruit = rio_hydro_recruit_si(io_idx_si) - sites(s)%si_hydr%h2oveg_dead = rio_hydro_dead_si(io_idx_si) - sites(s)%si_hydr%h2oveg_growturn_err = rio_hydro_growturn_err_si(io_idx_si) - sites(s)%si_hydr%h2oveg_pheno_err = rio_hydro_pheno_err_si(io_idx_si) - sites(s)%si_hydr%h2oveg_hydro_err = rio_hydro_hydro_err_si(io_idx_si) + sites(s)%si_hydr%h2oveg_recruit = this%rvars(ir_hydro_recruit_si)%r81d(io_idx_si) + sites(s)%si_hydr%h2oveg_dead = this%rvars(ir_hydro_dead_si)%r81d(io_idx_si) + sites(s)%si_hydr%h2oveg_growturn_err = this%rvars(ir_hydro_growturn_err_si)%r81d(io_idx_si) + sites(s)%si_hydr%h2oveg_pheno_err = this%rvars(ir_hydro_pheno_err_si)%r81d(io_idx_si) + sites(s)%si_hydr%h2oveg_hydro_err = this%rvars(ir_hydro_hydro_err_si)%r81d(io_idx_si) ! Hydraulics counters lyr = hydraulic layer, shell = rhizosphere shell do i = 1, sites(s)%si_hydr%nlevsoi_hyd ! Loop shells do k = 1, nshell sites(s)%si_hydr%h2osoi_liqvol_shell(i,k) = & - rio_hydro_liqvol_shell_si(io_idx_si_lyr_shell) + this%rvars(ir_hydro_liqvol_shell_si)%r81d(io_idx_si_lyr_shell) io_idx_si_lyr_shell = io_idx_si_lyr_shell + 1 end do end do @@ -2312,12 +2303,9 @@ subroutine get_restart_vectors(this, nc, nsites, sites) end associate end subroutine get_restart_vectors - ! ==================================================================================== - - - subroutine update_3dpatch_radiation(this, nsites, sites, bc_out) + subroutine update_3dpatch_radiation(this, nsites, sites, bc_out) ! ------------------------------------------------------------------------- ! This subroutine populates output boundary conditions related to radiation