-
Notifications
You must be signed in to change notification settings - Fork 92
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
Use HLM-provided land-use time series data to drive FATES harvest #663
Changes from 36 commits
e9faf6a
12e9e1c
14e34f4
f0dc220
22adbed
d292629
40a3c0a
8ffedd9
30af2ac
c1e8b35
597f404
0b6ab98
6320c5c
4517c20
42e3c2e
7847c61
29dabcc
6b574f9
3afe8ed
2bf49b8
a9bb15e
3d32b1a
0cd417e
1749dc4
4f9a485
a317ef5
c2332b9
b78f410
2905a9b
5e6fa21
cbc4ca0
bb04f89
dafd55f
7afdb04
3807a36
d08dfd4
8d9f189
568648f
abd57ec
8872a91
4f087cf
ffaa76e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,7 @@ module EDLoggingMortalityMod | |
use EDParamsMod , only : logging_export_frac | ||
use EDParamsMod , only : logging_event_code | ||
use EDParamsMod , only : logging_dbhmin | ||
use EDParamsMod , only : logging_dbhmax | ||
use EDParamsMod , only : logging_collateral_frac | ||
use EDParamsMod , only : logging_direct_frac | ||
use EDParamsMod , only : logging_mechanical_frac | ||
|
@@ -44,6 +45,8 @@ module EDLoggingMortalityMod | |
use FatesInterfaceTypesMod , only : hlm_model_day | ||
use FatesInterfaceTypesMod , only : hlm_day_of_year | ||
use FatesInterfaceTypesMod , only : hlm_days_per_year | ||
use FatesInterfaceTypesMod , only : hlm_use_lu_harvest | ||
use FatesInterfaceTypesMod , only : hlm_num_lu_harvest_cats | ||
use FatesInterfaceTypesMod , only : hlm_use_logging | ||
use FatesInterfaceTypesMod , only : hlm_use_planthydro | ||
use FatesConstantsMod , only : itrue,ifalse | ||
|
@@ -55,6 +58,12 @@ module EDLoggingMortalityMod | |
use PRTGenericMod , only : sapw_organ, struct_organ, leaf_organ | ||
use PRTGenericMod , only : fnrt_organ, store_organ, repro_organ | ||
use FatesAllometryMod , only : set_root_fraction | ||
use FatesConstantsMod , only : primaryforest, secondaryforest, secondary_age_threshold | ||
use FatesConstantsMod , only : fates_tiny | ||
use FatesConstantsMod , only : months_per_year | ||
use FatesConstantsMod , only : hlm_harvest_area_fraction | ||
use FatesConstantsMod , only : hlm_harvest_carbon | ||
use FatesConstantsMod, only : fates_check_param_set | ||
|
||
implicit none | ||
private | ||
|
@@ -80,6 +89,7 @@ module EDLoggingMortalityMod | |
public :: logging_litter_fluxes | ||
public :: logging_time | ||
public :: IsItLoggingTime | ||
public :: get_harvest_rate_area | ||
|
||
contains | ||
|
||
|
@@ -104,10 +114,17 @@ subroutine IsItLoggingTime(is_master,currentSite) | |
logging_time = .false. | ||
icode = int(logging_event_code) | ||
|
||
! this is true for either hlm harvest or fates logging | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How is it true for both those cases? Is it set elsewhere? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To clarify, hlm_use_logging is set to true if hlm harvest is active or if fates logging is active (based on namelist inputs). This is so that just one variable is used to determine whether today is a logging/harvest day or not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes. I think I understood this more as I went through the code... |
||
if(hlm_use_logging.eq.ifalse) return | ||
|
||
! all of these are valid for hlm harvest | ||
! so adjust annual harvest inputs accordingly in LoggingMortality_frac | ||
! note that the specific event will allow only one hlm harvest, regardless of input | ||
! code 3, every day, may not work properly because of the exclusive mortality selection | ||
! even less fequent low harvest rates may be excluded - may need to give harvest priority | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are they valid in the sense that logging happens in addition to the harvesting? This maybe needs elaborating. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This means that they can each be set as an input value, and they should run. |
||
if(icode .eq. 1) then | ||
! Logging is turned off | ||
! Logging is turned off - not sure why we need another switch | ||
logging_time = .false. | ||
|
||
else if(icode .eq. 2) then | ||
|
@@ -168,41 +185,92 @@ end subroutine IsItLoggingTime | |
! ====================================================================================== | ||
|
||
subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & | ||
lmort_collateral,lmort_infra, l_degrad ) | ||
lmort_collateral,lmort_infra, l_degrad, & | ||
hlm_harvest_rates, hlm_harvest_catnames, & | ||
hlm_harvest_units, & | ||
patch_anthro_disturbance_label, secondary_age, & | ||
frac_site_primary) | ||
|
||
! Arguments | ||
integer, intent(in) :: pft_i ! pft index | ||
real(r8), intent(in) :: dbh ! diameter at breast height (cm) | ||
integer, intent(in) :: canopy_layer ! canopy layer of this cohort | ||
real(r8), intent(in) :: hlm_harvest_rates(:) ! annual harvest rate per hlm category | ||
character(len=64), intent(in) :: hlm_harvest_catnames(:) ! names of hlm harvest categories | ||
integer, intent(in) :: hlm_harvest_units ! unit type of hlm harvest rates: [area vs. mass] | ||
integer, intent(in) :: patch_anthro_disturbance_label ! patch level anthro_disturbance_label | ||
real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance | ||
real(r8), intent(out) :: lmort_direct ! direct (harvestable) mortality fraction | ||
real(r8), intent(out) :: lmort_collateral ! collateral damage mortality fraction | ||
real(r8), intent(out) :: lmort_infra ! infrastructure mortality fraction | ||
real(r8), intent(out) :: l_degrad ! fraction of trees that are not killed | ||
! but suffer from forest degradation (i.e. they | ||
! are moved to newly-anthro-disturbed secondary | ||
! forest patch) | ||
real(r8), intent(in) :: frac_site_primary | ||
|
||
! Local variables | ||
real(r8) :: harvest_rate ! the final harvest rate to apply to this cohort today | ||
|
||
! Parameters | ||
real(r8), parameter :: adjustment = 1.0 ! adjustment for mortality rates | ||
|
||
! todo: probably lower the dbhmin default value to 30 cm | ||
! todo: change the default logging_event_code to 1 september (-244) | ||
! todo: change the default logging_direct_frac to 1.0 for cmip inputs | ||
! todo: check outputs against the LUH2 carbon data | ||
! todo: eventually set up distinct harvest practices, each with a set of input paramaeters | ||
! todo: implement harvested carbon inputs | ||
|
||
if (logging_time) then | ||
ckoven marked this conversation as resolved.
Show resolved
Hide resolved
|
||
! Pass logging rates to cohort level | ||
|
||
if (hlm_use_lu_harvest == ifalse) then | ||
! 0=use fates logging parameters directly when logging_time == .true. | ||
! this means harvest the whole cohort area | ||
harvest_rate = 1._r8 | ||
|
||
else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_area_fraction) then | ||
! We are harvesting based on areal fraction, not carbon/biomass terms. | ||
! 1=use area fraction from hlm | ||
ckoven marked this conversation as resolved.
Show resolved
Hide resolved
|
||
! combine forest and non-forest fracs and then apply: | ||
! primary and secondary area fractions to the logging rates, which are fates parameters | ||
|
||
! Definitions of the underlying harvest land category variables | ||
! these are hardcoded to match the LUH input data via landuse.timseries file (see dynHarvestMod) | ||
! these are fractions of vegetated area harvested, split into five land category variables | ||
! HARVEST_VH1 = harvest from primary forest | ||
! HARVEST_VH2 = harvest from primary non-forest | ||
! HARVEST_SH1 = harvest from secondary mature forest | ||
! HARVEST_SH2 = harvest from secondary young forest | ||
! HARVEST_SH3 = harvest from secondary non-forest (assume this is young for biomass) | ||
|
||
! Get the area-based harvest rates based on info passed to FATES from the boundary condition | ||
call get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_catnames, & | ||
hlm_harvest_rates, frac_site_primary, secondary_age, harvest_rate) | ||
|
||
else if (hlm_use_lu_harvest == itrue .and. hlm_harvest_units == hlm_harvest_carbon) then | ||
! 2=use carbon from hlm | ||
! not implemented yet | ||
write(fates_log(),*) 'HLM harvest carbon data not implemented yet. Exiting.' | ||
call endrun(msg=errMsg(sourcefile, __LINE__)) | ||
endif | ||
|
||
! transfer of area to secondary land is based on overall area affected, not just logged crown area | ||
! l_degrad accounts for the affected area between logged crowns | ||
if(EDPftvarcon_inst%woody(pft_i) == 1)then ! only set logging rates for trees | ||
|
||
! Pass logging rates to cohort level | ||
|
||
if (dbh >= logging_dbhmin ) then | ||
lmort_direct = logging_direct_frac * adjustment | ||
l_degrad = 0._r8 | ||
|
||
if (dbh >= logging_dbhmin .and. .not. & | ||
((logging_dbhmax < fates_check_param_set) .and. (dbh < logging_dbhmax )) ) then | ||
lmort_direct = harvest_rate * logging_direct_frac | ||
l_degrad = harvest_rate * (1._r8 - logging_direct_frac) ! fraction passed to 'degraded' forest. | ||
else | ||
lmort_direct = 0.0_r8 | ||
l_degrad = logging_direct_frac * adjustment | ||
lmort_direct = 0.0_r8 | ||
l_degrad = harvest_rate | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean that if trees are not large enough to log, the cohort is still degraded/moved to secondary patch? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, never mind I see, background degradation rate regardless of logging. |
||
end if | ||
|
||
if (dbh >= logging_dbhmax_infra) then | ||
lmort_infra = 0.0_r8 | ||
l_degrad = l_degrad + logging_mechanical_frac * adjustment | ||
l_degrad = l_degrad + harvest_rate * logging_mechanical_frac | ||
else | ||
lmort_infra = logging_mechanical_frac * adjustment | ||
lmort_infra = harvest_rate * logging_mechanical_frac | ||
end if | ||
!damage rates for size class < & > threshold_size need to be specified seperately | ||
|
||
|
@@ -213,16 +281,16 @@ subroutine LoggingMortality_frac( pft_i, dbh, canopy_layer, lmort_direct, & | |
! for collateral damage, even understory collateral damage. | ||
|
||
if (canopy_layer .eq. 1) then | ||
lmort_collateral = logging_collateral_frac * adjustment | ||
lmort_collateral = harvest_rate * logging_collateral_frac | ||
else | ||
lmort_collateral = 0._r8 | ||
lmort_collateral = 0._r8 | ||
endif | ||
|
||
else | ||
else ! non-woody plants in the canopy still become moved to secondary patch at same rate | ||
lmort_direct = 0.0_r8 | ||
lmort_collateral = 0.0_r8 | ||
lmort_infra = 0.0_r8 | ||
l_degrad = 0.0_r8 | ||
lmort_infra = harvest_rate * logging_mechanical_frac | ||
l_degrad = harvest_rate | ||
end if | ||
else | ||
lmort_direct = 0.0_r8 | ||
|
@@ -235,6 +303,90 @@ end subroutine LoggingMortality_frac | |
|
||
! ============================================================================ | ||
|
||
subroutine get_harvest_rate_area (patch_anthro_disturbance_label, hlm_harvest_catnames, hlm_harvest_rates, & | ||
frac_site_primary, secondary_age, harvest_rate) | ||
|
||
|
||
! ------------------------------------------------------------------------------------------- | ||
! | ||
! DESCRIPTION: | ||
! get the area-based harvest rates based on info passed to FATES from the bioundary conditions in. | ||
! assumes logging_time == true | ||
|
||
! Arguments | ||
real(r8), intent(in) :: hlm_harvest_rates(:) ! annual harvest rate per hlm category | ||
character(len=64), intent(in) :: hlm_harvest_catnames(:) ! names of hlm harvest categories | ||
integer, intent(in) :: patch_anthro_disturbance_label ! patch level anthro_disturbance_label | ||
real(r8), intent(in) :: secondary_age ! patch level age_since_anthro_disturbance | ||
real(r8), intent(in) :: frac_site_primary | ||
real(r8), intent(out) :: harvest_rate | ||
|
||
! Local Variables | ||
integer :: h_index ! for looping over harvest categories | ||
integer :: icode ! Integer equivalent of the event code (parameter file only allows reals) | ||
|
||
! Loop around harvest categories to determine the annual hlm harvest rate for the current cohort based on patch history info | ||
harvest_rate = 0._r8 | ||
do h_index = 1,hlm_num_lu_harvest_cats | ||
if (patch_anthro_disturbance_label .eq. primaryforest) then | ||
if(hlm_harvest_catnames(h_index) .eq. "HARVEST_VH1" .or. & | ||
hlm_harvest_catnames(h_index) .eq. "HARVEST_VH2") then | ||
harvest_rate = harvest_rate + hlm_harvest_rates(h_index) | ||
endif | ||
else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & | ||
secondary_age >= secondary_age_threshold) then | ||
if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH1") then | ||
harvest_rate = harvest_rate + hlm_harvest_rates(h_index) | ||
endif | ||
else if (patch_anthro_disturbance_label .eq. secondaryforest .and. & | ||
secondary_age < secondary_age_threshold) then | ||
if(hlm_harvest_catnames(h_index) .eq. "HARVEST_SH2" .or. & | ||
hlm_harvest_catnames(h_index) .eq. "HARVEST_SH3") then | ||
harvest_rate = harvest_rate + hlm_harvest_rates(h_index) | ||
endif | ||
endif | ||
end do | ||
|
||
! Normalize by site-level primary or secondary forest fraction | ||
! since harvest_rate is specified as a fraction of the gridcell | ||
! also need to put a cap so as not to harvest more primary or secondary area than there is in a gridcell | ||
if (patch_anthro_disturbance_label .eq. primaryforest) then | ||
if (frac_site_primary .gt. fates_tiny) then | ||
harvest_rate = min((harvest_rate / frac_site_primary),frac_site_primary) | ||
else | ||
harvest_rate = 0._r8 | ||
endif | ||
else | ||
if ((1._r8-frac_site_primary) .gt. fates_tiny) then | ||
harvest_rate = min((harvest_rate / (1._r8-frac_site_primary)),& | ||
(1._r8-frac_site_primary)) | ||
else | ||
harvest_rate = 0._r8 | ||
endif | ||
endif | ||
|
||
! calculate today's harvest rate | ||
! whether to harvest today has already been determined by IsItLoggingTime | ||
! for icode == 2, icode < 0, and icode > 10000 apply the annual rate one time (no calc) | ||
! Bad logging event flag is caught in IsItLoggingTime, so don't check it here | ||
icode = int(logging_event_code) | ||
if(icode .eq. 1) then | ||
! Logging is turned off - not sure why we need another switch | ||
ckoven marked this conversation as resolved.
Show resolved
Hide resolved
|
||
harvest_rate = 0._r8 | ||
else if(icode .eq. 3) then | ||
! Logging event every day - this may not work due to the mortality exclusivity | ||
harvest_rate = harvest_rate / hlm_days_per_year | ||
else if(icode .eq. 4) then | ||
! logging event once a month | ||
if(hlm_current_day.eq.1 ) then | ||
harvest_rate = harvest_rate / months_per_year | ||
end if | ||
end if | ||
|
||
end subroutine get_harvest_rate_area | ||
|
||
! ============================================================================ | ||
|
||
subroutine logging_litter_fluxes(currentSite, currentPatch, newPatch, patch_site_areadis) | ||
|
||
! ------------------------------------------------------------------------------------------- | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An idea for down the road, in the US Forest Service most harvesting/logging is done with a specific age class outcome as an object. The classes are: even-age (one age class, total range of ages present <20% of the rotation age), two-aged (two age classes), and uneven-aged (three or more distinct age classes), all of which have their own harvest practices associated with them. This may be useful designation in the future as more logging/harvest features are added.