Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Land Use] C-based wood harvest #888

Merged
merged 27 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
420431f
Added C based logging in FATES. Passed validation.
sshu3 Mar 8, 2022
6725822
Updated minor corrections from fatesluc branch.
sshu3 Mar 10, 2022
d5bd304
Updated changes from parent branch "fatesluc".
sshu3 Mar 17, 2022
aaa1062
Merge branch 'fatesluc_cbasedhrv' into HEAD
sshu3 Mar 20, 2022
14c3002
Added historical outputs of secondary patches.
sshu3 Jun 16, 2022
67b9211
Pass NPP and AR to ELM for calculating NBP.
sshu3 Aug 2, 2022
ce81248
Removed hlm_harvest_bypass_criteria. Applied fix on global restart run.
sshu3 Sep 23, 2022
7827534
Merge branch 'master' into fatesluc_cbasedhrv_v2_merge
glemieux Sep 26, 2022
1fb5220
Remove "available_forest_c" and simplify the logic.
sshu3 Oct 26, 2022
ad337ea
Minor revisions on comments, temporary commit
sshu3 Oct 28, 2022
81ebf32
Minor revisions on comments and merged with master branch, temporary …
sshu3 Oct 28, 2022
91d4576
Patch up paralell disturbance and model phenology issue.
sshu3 Oct 31, 2022
bed5e40
Patch up some errors when merging with FATES API 24.
sshu3 Nov 1, 2022
422723e
Ignore small logging rate which would produce tiny secondary patch.
sshu3 Nov 4, 2022
fec6597
Clarify calculations and comments on the harvest debt.
sshu3 Nov 9, 2022
fe6b0ab
Merge branch 'fatesluc_nocomp' into fatesluc_cbasedhrv_v2
sshu3 Nov 10, 2022
b62fe84
Change back EDPatchDynamicsMod.F90 for sanity purpose.
sshu3 Nov 11, 2022
b35025e
Ignore small logging disturbance.
sshu3 Nov 24, 2022
68d96be
Merge tag 'sci.1.60.3_api.24.2.0' into fatesluc_cbasedhrv_v2
glemieux Dec 3, 2022
23ee93f
Create subroutine to encapsulate the calculation of harvest debt.
sshu3 Dec 20, 2022
f597756
Merge branch 'main' into fatesluc_cbasedhrv_v2
glemieux Jan 4, 2023
eb609b5
all_carbon to carbon12
rgknox Jan 6, 2023
56006f8
Merge pull request #3 from rgknox/fatesluc_cbasedhrv_v2-api25
sshu88 Jan 6, 2023
f1f855d
Update EDPatchDynamicsMod.F90
sshu88 Jan 18, 2023
e6772ad
Merge branch 'main' into fatesluc_cbasedhrv_v2
glemieux Jan 26, 2023
2504716
manually reinstate tveg history variable
glemieux Jan 26, 2023
d80ef20
add local variable initialization for get_harvest_debt
glemieux Jan 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions biogeochem/EDCanopyStructureMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1995,7 +1995,7 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out)

! Pass FATES Harvested C to bc_out.
call UpdateHarvestC(sites(s),bc_out(s))

end do

! This call to RecruitWaterStorage() makes an accounting of
Expand All @@ -2009,7 +2009,6 @@ subroutine update_hlm_dynamics(nsites,sites,fcolumn,bc_out)
call RecruitWaterStorage(nsites,sites,bc_out)
end if


end subroutine update_hlm_dynamics

! =====================================================================================
Expand Down
391 changes: 360 additions & 31 deletions biogeochem/EDLoggingMortalityMod.F90

Large diffs are not rendered by default.

17 changes: 11 additions & 6 deletions biogeochem/EDMortalityFunctionsMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,8 @@ end subroutine mortality_rates

! ============================================================================

subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary)
subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, &
harvestable_forest_c, harvest_tag)

!
! !DESCRIPTION:
Expand All @@ -234,14 +235,21 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr
! elsewhere).
!
! !USES:

use FatesInterfaceTypesMod, only : hlm_freq_day
!
! !ARGUMENTS
type(ed_site_type), intent(inout), target :: currentSite
type(ed_cohort_type),intent(inout), target :: currentCohort
type(bc_in_type), intent(in) :: bc_in
real(r8), intent(in) :: frac_site_primary

real(r8), intent(in) :: harvestable_forest_c(:) ! total carbon available for logging, kgC site-1
integer, intent(out) :: harvest_tag(:) ! tag to record the harvest status
! for the calculation of harvest debt in C-based
! harvest mode
! 0 - successful;
! 1 - unsuccessful since not enough carbon
! 2 - not applicable
!
! !LOCAL VARIABLES:
real(r8) :: cmort ! starvation mortality rate (fraction per year)
Expand Down Expand Up @@ -271,10 +279,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_pr
bc_in%hlm_harvest_units, &
currentCohort%patchptr%anthro_disturbance_label, &
currentCohort%patchptr%age_since_anthro_disturbance, &
frac_site_primary)



frac_site_primary, harvestable_forest_c, harvest_tag)

if (currentCohort%canopy_layer > 1)then
! Include understory logging mortality rates not associated with disturbance
Expand Down
41 changes: 37 additions & 4 deletions biogeochem/EDPatchDynamicsMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ module EDPatchDynamicsMod
use FatesInterfaceTypesMod , only : hlm_use_sp
use FatesInterfaceTypesMod , only : hlm_use_nocomp
use FatesInterfaceTypesMod , only : hlm_use_fixed_biogeog
use FatesInterfaceTypesMod , only : hlm_num_lu_harvest_cats
use FatesGlobals , only : endrun => fates_endrun
use FatesConstantsMod , only : r8 => fates_r8
use FatesConstantsMod , only : itrue, ifalse
Expand All @@ -58,6 +59,9 @@ module EDPatchDynamicsMod
use EDLoggingMortalityMod, only : logging_litter_fluxes
use EDLoggingMortalityMod, only : logging_time
use EDLoggingMortalityMod, only : get_harvest_rate_area
use EDLoggingMortalityMod, only : get_harvest_rate_carbon
use EDLoggingMortalityMod, only : get_harvestable_carbon
use EDLoggingMortalityMod, only : get_harvest_debt
use EDParamsMod , only : fates_mortality_disturbance_fraction
use FatesAllometryMod , only : carea_allom
use FatesAllometryMod , only : set_root_fraction
Expand All @@ -70,6 +74,7 @@ module EDPatchDynamicsMod
use FatesConstantsMod , only : n_anthro_disturbance_categories
use FatesConstantsMod , only : fates_unset_r8
use FatesConstantsMod , only : fates_unset_int
use FatesConstantsMod , only : hlm_harvest_carbon
use EDCohortDynamicsMod , only : InitPRTObject
use EDCohortDynamicsMod , only : InitPRTBoundaryConditions
use ChecksBalancesMod, only : SiteMassStock
Expand Down Expand Up @@ -187,9 +192,12 @@ subroutine disturbance_rates( site_in, bc_in)
real(r8) :: dist_rate_ldist_notharvested
integer :: threshold_sizeclass
integer :: i_dist
integer :: h_index
real(r8) :: frac_site_primary
real(r8) :: harvest_rate
real(r8) :: tempsum
real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats)
integer :: harvest_tag(hlm_num_lu_harvest_cats)

!----------------------------------------------------------------------------------------------
! Calculate Mortality Rates (these were previously calculated during growth derivatives)
Expand All @@ -198,6 +206,9 @@ subroutine disturbance_rates( site_in, bc_in)

! first calculate the fractino of the site that is primary land
call get_frac_site_primary(site_in, frac_site_primary)

! get available biomass for harvest for all patches
call get_harvestable_carbon(site_in, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c)

currentPatch => site_in%oldest_patch
do while (associated(currentPatch))
Expand Down Expand Up @@ -228,7 +239,9 @@ subroutine disturbance_rates( site_in, bc_in)
bc_in%hlm_harvest_units, &
currentPatch%anthro_disturbance_label, &
currentPatch%age_since_anthro_disturbance, &
frac_site_primary)
frac_site_primary, &
harvestable_forest_c, &
harvest_tag)

currentCohort%lmort_direct = lmort_direct
currentCohort%lmort_collateral = lmort_collateral
Expand All @@ -237,9 +250,12 @@ subroutine disturbance_rates( site_in, bc_in)

currentCohort => currentCohort%taller
end do

currentPatch => currentPatch%younger
end do

glemieux marked this conversation as resolved.
Show resolved Hide resolved
call get_harvest_debt(site_in, bc_in, harvest_tag)

! ---------------------------------------------------------------------------------------------
! Calculate Disturbance Rates based on the mortality rates just calculated
! ---------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -289,6 +305,11 @@ subroutine disturbance_rates( site_in, bc_in)
currentCohort%lmort_infra + &
currentCohort%l_degrad ) * &
currentCohort%c_area/currentPatch%area

if(currentPatch%disturbance_rates(dtype_ilog)>1.0) then
write(fates_log(),*) 'See luc mortalities:', currentCohort%lmort_direct, &
currentCohort%lmort_collateral, currentCohort%lmort_infra, currentCohort%l_degrad
end if

! Non-harvested part of the logging disturbance rate
dist_rate_ldist_notharvested = dist_rate_ldist_notharvested + currentCohort%l_degrad * &
Expand All @@ -299,13 +320,19 @@ subroutine disturbance_rates( site_in, bc_in)
enddo !currentCohort

! for non-closed-canopy areas subject to logging, add an additional increment of area disturbed
! equivalent to the fradction logged to account for transfer of interstitial ground area to new secondary lands
! equivalent to the fraction logged to account for transfer of interstitial ground area to new secondary lands
if ( logging_time .and. &
(currentPatch%area - currentPatch%total_canopy_area) .gt. fates_tiny ) then
! The canopy is NOT closed.

call get_harvest_rate_area (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, &
bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate)
if(bc_in%hlm_harvest_units == hlm_harvest_carbon) then
call get_harvest_rate_carbon (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, &
bc_in%hlm_harvest_rates, currentPatch%age_since_anthro_disturbance, harvestable_forest_c, &
harvest_rate, harvest_tag)
else
call get_harvest_rate_area (currentPatch%anthro_disturbance_label, bc_in%hlm_harvest_catnames, &
bc_in%hlm_harvest_rates, frac_site_primary, currentPatch%age_since_anthro_disturbance, harvest_rate)
end if

currentPatch%disturbance_rates(dtype_ilog) = currentPatch%disturbance_rates(dtype_ilog) + &
(currentPatch%area - currentPatch%total_canopy_area) * harvest_rate / currentPatch%area
Expand All @@ -315,6 +342,12 @@ subroutine disturbance_rates( site_in, bc_in)
(currentPatch%area - currentPatch%total_canopy_area) * harvest_rate / currentPatch%area
endif

! For nocomp mode, we need to prevent producing too small patches, which may produce small patches
if ((hlm_use_nocomp .eq. itrue) .and. &
(currentPatch%disturbance_rates(dtype_ilog)*currentPatch%area .lt. min_patch_area_forced)) then
currentPatch%disturbance_rates(dtype_ilog) = 0._r8
end if

! fraction of the logging disturbance rate that is non-harvested
if (currentPatch%disturbance_rates(dtype_ilog) .gt. nearzero) then
currentPatch%fract_ldist_not_harvested = dist_rate_ldist_notharvested / &
Expand Down
1 change: 0 additions & 1 deletion biogeochem/EDPhysiologyMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1753,7 +1753,6 @@ subroutine SeedIn( currentSite, bc_in )
! !USES:
use EDTypesMod, only : area
use EDTypesMod, only : homogenize_seed_pfts

!
! !ARGUMENTS
type(ed_site_type), intent(inout), target :: currentSite
Expand Down
1 change: 0 additions & 1 deletion biogeochem/FatesAllometryMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -2515,7 +2515,6 @@ subroutine ForceDBH( ipft, crowndamage, canopy_trim, d, h, bdead, bl )
end if

call h_allom(d,ipft,h)

if(counter>20)then
write(fates_log(),*) 'dbh counter: ',counter,' is woody: ',&
(prt_params%woody(ipft) == itrue)
Expand Down
2 changes: 2 additions & 0 deletions main/EDInitMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ subroutine zero_site( site_in )
site_in%fmort_cflux_ustory_damage(:,:) = 0._r8

! Resources management (logging/harvesting, etc)
site_in%resources_management%harvest_debt = 0.0_r8
site_in%resources_management%harvest_debt_sec = 0.0_r8
site_in%resources_management%trunk_product_site = 0.0_r8

! canopy spread
Expand Down
39 changes: 29 additions & 10 deletions main/EDMainMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ module EDMainMod
use FatesPlantHydraulicsMod , only : AccumulateMortalityWaterStorage
use FatesAllometryMod , only : h_allom,tree_sai,tree_lai
use EDLoggingMortalityMod , only : IsItLoggingTime
use EDLoggingMortalityMod , only : get_harvestable_carbon
use DamageMainMod , only : IsItDamageTime
use EDPatchDynamicsMod , only : get_frac_site_primary
use FatesGlobals , only : endrun => fates_endrun
Expand Down Expand Up @@ -322,6 +323,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
! FIX(SPM,032414) refactor so everything goes through interface
!
! !USES:
use FatesInterfaceTypesMod, only : hlm_num_lu_harvest_cats
use FatesInterfaceTypesMod, only : nlevdamage
use FatesAllometryMod , only : bleaf
use FatesAllometryMod , only : carea_allom
Expand Down Expand Up @@ -381,6 +383,9 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
real(r8) :: target_leaf_c
real(r8) :: frac_site_primary

real(r8) :: harvestable_forest_c(hlm_num_lu_harvest_cats)
integer :: harvest_tag(hlm_num_lu_harvest_cats)

real(r8) :: n_old
real(r8) :: n_recover
real(r8) :: sapw_c
Expand Down Expand Up @@ -414,6 +419,13 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )

call get_frac_site_primary(currentSite, frac_site_primary)

! Clear site GPP and AR passing to HLM
bc_out%gpp_site = 0._r8
bc_out%ar_site = 0._r8

! Patch level biomass are required for C-based harvest
call get_harvestable_carbon(currentSite, bc_in%site_area, bc_in%hlm_harvest_catnames, harvestable_forest_c)

! Set a pointer to this sites carbon12 mass balance
site_cmass => currentSite%mass_balance(element_pos(carbon12_element))

Expand Down Expand Up @@ -456,7 +468,6 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
do while(associated(currentCohort))

ft = currentCohort%pft

! Some cohorts are created and inserted to the list while
! the loop is going. These are pointed to the "taller" position
! of current, and then inherit properties of their donor (current)
Expand All @@ -465,8 +476,10 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )

if_not_newlyrecovered: if(.not.newly_recovered) then


! Calculate the mortality derivatives
call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary )
call Mortality_Derivative( currentSite, currentCohort, bc_in, frac_site_primary, &
harvestable_forest_c, harvest_tag )

! -----------------------------------------------------------------------------
! Apply Plant Allocation and Reactive Transport
Expand All @@ -477,6 +490,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
! decrement the available carbon pool to zero.
! -----------------------------------------------------------------------------


if (hlm_use_ed_prescribed_phys .eq. itrue) then
if (currentCohort%canopy_layer .eq. 1) then
currentCohort%npp_acc = EDPftvarcon_inst%prescribed_npp_canopy(ft) &
Expand All @@ -485,14 +499,14 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
currentCohort%npp_acc = EDPftvarcon_inst%prescribed_npp_understory(ft) &
* currentCohort%c_area / currentCohort%n / hlm_days_per_year
endif

! We don't explicitly define a respiration rate for prescribe phys
! but we do need to pass mass balance. So we say it is zero respiration
currentCohort%gpp_acc = currentCohort%npp_acc
currentCohort%resp_acc = 0._r8

end if

! -----------------------------------------------------------------------------
! Save NPP/GPP/R in these "hold" style variables. These variables
! persist after this routine is complete, and used in I/O diagnostics.
Expand All @@ -504,21 +518,26 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
! <x>_acc will be reset soon and will be accumulated on the next leaf
! photosynthesis step
! -----------------------------------------------------------------------------

currentCohort%npp_acc_hold = currentCohort%npp_acc * real(hlm_days_per_year,r8)
currentCohort%gpp_acc_hold = currentCohort%gpp_acc * real(hlm_days_per_year,r8)
currentCohort%resp_acc_hold = currentCohort%resp_acc * real(hlm_days_per_year,r8)


! Passing gpp_acc_hold to HLM
bc_out%gpp_site = bc_out%gpp_site + currentCohort%gpp_acc_hold * &
AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day
bc_out%ar_site = bc_out%ar_site + currentCohort%resp_acc_hold * &
AREA_INV * currentCohort%n / hlm_days_per_year / sec_per_day

! Conduct Maintenance Turnover (parteh)
if(debug) call currentCohort%prt%CheckMassConservation(ft,3)
if(any(currentSite%dstatus == [phen_dstat_moiston,phen_dstat_timeon])) then
is_drought = .false.
else
is_drought = .true.
end if

call PRTMaintTurnover(currentCohort%prt,ft,is_drought)

! -----------------------------------------------------------------------------------
! Call the routine that advances leaves in age.
! This will move a portion of the leaf mass in each
Expand All @@ -538,7 +557,7 @@ subroutine ed_integrate_state_variables(currentSite, bc_in, bc_out )
currentCohort%resp_excess = 0._r8

end if if_not_newlyrecovered

! If the current diameter of a plant is somehow less than what is consistent
! with what is allometrically consistent with the stuctural biomass, then
! correct the dbh to match.
Expand Down
9 changes: 8 additions & 1 deletion main/EDTypesMod.F90
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,9 @@ module EDTypesMod
type, public :: ed_resources_management_type

real(r8) :: trunk_product_site ! Actual trunk product at site level KgC/site
real(r8) :: harvest_debt ! the amount of kgC per site that did not successfully harvested
real(r8) :: harvest_debt_sec ! the amount of kgC per site from secondary patches that did
! not successfully harvested

!debug variables
real(r8) :: delta_litter_stock ! kgC/site = kgC/ha
Expand Down Expand Up @@ -781,7 +784,6 @@ module EDTypesMod
! in runs that are restarted, regardless of
! the conditions of restart


real(r8) :: water_memory(numWaterMem) ! last 10 days of soil moisture memory...


Expand Down Expand Up @@ -1166,6 +1168,10 @@ subroutine dump_cohort(ccohort)
write(fates_log(),*) 'co%dgmort = ', ccohort%dgmort
write(fates_log(),*) 'co%hmort = ', ccohort%hmort
write(fates_log(),*) 'co%frmort = ', ccohort%frmort
write(fates_log(),*) 'co%asmort = ', ccohort%asmort
write(fates_log(),*) 'co%lmort_direct = ', ccohort%lmort_direct
write(fates_log(),*) 'co%lmort_collateral = ', ccohort%lmort_collateral
write(fates_log(),*) 'co%lmort_infra = ', ccohort%lmort_infra
write(fates_log(),*) 'co%isnew = ', ccohort%isnew
write(fates_log(),*) 'co%dndt = ', ccohort%dndt
write(fates_log(),*) 'co%dhdt = ', ccohort%dhdt
Expand All @@ -1177,6 +1183,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 (associated(ccohort%co_hydr) ) then
call dump_cohort_hydr(ccohort)
endif
Expand Down
Loading