-
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
Size- and age- dependent mortality #599
Changes from 6 commits
7223c9b
18bcd44
7b34903
cfb431c
17a60ef
0789867
d8e7935
7a5bebe
9e5ab32
b01c136
e45153c
fb52c50
ab6fc20
dd28a9b
63c2958
774b105
c83725a
aef198f
9345e67
50f6efe
cbc4c17
54e8dfb
fc733f9
eed4545
22eb568
337ec13
dd4d196
f4afdf2
cec41c7
ee90e0f
10809b9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -42,28 +42,34 @@ module EDMortalityFunctionsMod | |||
|
||||
|
||||
|
||||
subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort ) | ||||
subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort,smort,asmort ) | ||||
|
||||
! ============================================================================ | ||||
! Calculate mortality rates from carbon storage, hydraulic cavitation, | ||||
! background and freezing | ||||
! background and freezing and size dependent senescence | ||||
! ============================================================================ | ||||
|
||||
use FatesConstantsMod, only : tfrz => t_water_freeze_k_1atm | ||||
|
||||
use FatesInterfaceMod , only : hlm_hio_ignore_val | ||||
|
||||
type (ed_cohort_type), intent(in) :: cohort_in | ||||
type (bc_in_type), intent(in) :: bc_in | ||||
real(r8),intent(out) :: bmort ! background mortality : Fraction per year | ||||
real(r8),intent(out) :: cmort ! carbon starvation mortality | ||||
real(r8),intent(out) :: hmort ! hydraulic failure mortality | ||||
real(r8),intent(out) :: frmort ! freezing stress mortality | ||||
real(r8),intent(out) :: smort ! size dependent senescence term | ||||
real(r8),intent(out) :: asmort ! age dependent senescence term | ||||
|
||||
real(r8) :: frac ! relativised stored carbohydrate | ||||
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) :: mort_ip_size_senescence ! inflection point for increase in mortality with dbh | ||||
real(r8) :: mort_r_size_senescence ! rate of mortality increase with dbh in senesence term | ||||
real(r8) :: mort_ip_age_senescence ! inflection point for increase in mortality with age | ||||
real(r8) :: mort_r_age_senescence ! rate of mortality increase with age in senescence term | ||||
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 | ||||
|
@@ -75,12 +81,41 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort ) | |||
logical, parameter :: test_zero_mortality = .false. ! Developer test which | ||||
! may help to debug carbon imbalances | ||||
! and the like | ||||
|
||||
! Size Dependent Senescence | ||||
! rate (r) and inflection point (ip) define the increase in mortality rate with dbh | ||||
mort_r_size_senescence = EDPftvarcon_inst%mort_r_size_senescence(cohort_in%pft) | ||||
mort_ip_size_senescence = EDPftvarcon_inst%mort_ip_size_senescence(cohort_in%pft) | ||||
|
||||
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. I'm worried that a user will set mort_r_size_senescence to 0 and think that will turn off size dependent senescence. I think that value generates an smort of 0.5. Will check how this is read in. 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. Lets add some metadata to the parameter value entry that explains _ turns this off, and what valid ranges are. There is also this subroutine here, a good place to check if fates parameters are in acceptable ranges (if for instance 0 is an unexpected/invalid, you can have fates gracefully complain and fail): Line 2071 in d8e7935
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. Sounds good. I'll add some metadata to the parameter value entry and some checks in FatesCheckParams. |
||||
! if param values have been set then calculate smort | ||||
if (mort_ip_size_senescence < 10000.0_r8 ) then | ||||
smort = 1.0_r8 / ( 1.0_r8 + exp( -1.0_r8 * mort_r_size_senescence * & | ||||
(cohort_in%dbh - mort_ip_size_senescence) ) ) | ||||
else | ||||
smort = 0.0_r8 | ||||
end if | ||||
|
||||
! if user has set cohort age fusion param to not be _ we calculate age | ||||
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. What is _ in this sentence? Also why doesn't this use 'cohort_age_tracking'? 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. I've changed it to match the comment above for size mortality. The size and age dependent mortality parameters are _ by default in the parameter file. The user has to set them in order to turn on either mortality term. Cohort age tracking is turned on separately with the cohort_age_tracking parameter. This was in case anyone in the future wanted to track cohort age independently of having size or age mortality turned on. 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. check_initialized is defined in PRTGenericMod.F90, but that check is designed to work in step with un_initialized. See here: https://github.com/NGEET/fates/blob/master/parteh/PRTGenericMod.F90#L43 It only works in situations where we are defining uninitialized values with "un_initialized". In this case, the parameter values that have "_" from the file, are not the same as un_initialized. I remember we thought it was 9.9E36, but there was some confusion if we were importing that value correctly... I had thought that "spval" from CLM/ELM would give us this value. We have an "ignore" value for history, but that value is not necessarily the "no data" value we get from netcdf: https://github.com/NGEET/fates/blob/master/main/FatesInterfaceMod.F90#L94 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 ok, thank you. I misunderstood the un_initialized value. Would it make most sense then for me to define a local arbitrary large number to compare these parameters against, in order to check whether or not they have been set by the user in the parameter file? 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. I think the fill values we were printing out when they made there way to FATES were 1E36 right? If so, I think this is is where it is defined... https://github.com/ESCOMP/CTSM/blob/master/src/main/ncdio_pio.F90.in#L146 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. If I print a parameter that is "_" in the parameter file I get 9.9692099...E+036. 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. I think it is defined in ./cime/src/externals/pio2/src/flib/pio_types.F90 L234-235 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. I've made a new variable called 'fates_check_param_set' defined in FatesConstantsMod to check whether the mortality parameters have been set. This might not be the way to go so happy to change it if there is a better way of doing things. But it seems to be working. 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. @rgknox I think the discussion from yesterday is here. |
||||
! dependent mortality | ||||
if (mort_ip_age_senescence < 10000.0_r8) then | ||||
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. Is it true that we only want to calculate an aging mortality rate if we are tracking aging and cohort_age_tracking is true? Should we be using that logical here? 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. Yes, ageing mortality can only be calculated if cohort age tracking is on. I changed the logic so that cohort age tracking could be on without having ageing mortality. So now the 'cohort_age_tracking' parameter in the param file turns on cohort age tracking. And both size and age dependent mortality get turned on by setting the ip_age/size_senescence parameters. I can put in some flags so that the ip_age_senescence parameter can't be turned on without cohort_age_tracking being on. |
||||
! Age Dependent Senescence | ||||
! rate and inflection point define the change in mortality with age | ||||
mort_r_age_senescence = EDPftvarcon_inst%mort_r_age_senescence(cohort_in%pft) | ||||
mort_ip_age_senescence = EDPftvarcon_inst%mort_ip_age_senescence(cohort_in%pft) | ||||
asmort = 1.0_r8 / (1.0_r8 + exp(-1.0_r8 * mort_r_age_senescence * & | ||||
(cohort_in%coage - mort_ip_age_senescence ) ) ) | ||||
else | ||||
asmort = 0.0_r8 | ||||
end if | ||||
|
||||
if (hlm_use_ed_prescribed_phys .eq. ifalse) then | ||||
|
||||
|
||||
if (hlm_use_ed_prescribed_phys .eq. ifalse) then | ||||
|
||||
! 'Background' mortality (can vary as a function of | ||||
! density as in ED1.0 and ED2.0, but doesn't here for tractability) | ||||
bmort = EDPftvarcon_inst%bmort(cohort_in%pft) | ||||
|
||||
bmort = EDPftvarcon_inst%bmort(cohort_in%pft) | ||||
|
||||
! Proxy for hydraulic failure induced mortality. | ||||
hf_sm_threshold = EDPftvarcon_inst%hf_sm_threshold(cohort_in%pft) | ||||
|
@@ -141,9 +176,10 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort ) | |||
|
||||
!mortality_rates = bmort + hmort + cmort | ||||
|
||||
else ! i.e. hlm_use_ed_prescribed_phys is true | ||||
else ! i.e. hlm_use_ed_prescribed_phys is true | ||||
|
||||
if ( cohort_in%canopy_layer .eq. 1) then | ||||
bmort = EDPftvarcon_inst%prescribed_mortality_canopy(cohort_in%pft) | ||||
bmort = EDPftvarcon_inst%prescribed_mortality_canopy(cohort_in%pft) | ||||
else | ||||
bmort = EDPftvarcon_inst%prescribed_mortality_understory(cohort_in%pft) | ||||
endif | ||||
|
@@ -157,6 +193,8 @@ subroutine mortality_rates( cohort_in,bc_in,cmort,hmort,bmort,frmort ) | |||
hmort = 0.0_r8 | ||||
frmort = 0.0_r8 | ||||
bmort = 0.0_r8 | ||||
smort = 0.0_r8 | ||||
asmort = 0.0_r8 | ||||
end if | ||||
|
||||
return | ||||
|
@@ -174,6 +212,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in) | |||
! | ||||
! !USES: | ||||
|
||||
use FatesInterfaceMod, only : hlm_freq_day | ||||
! | ||||
! !ARGUMENTS | ||||
type(ed_site_type), intent(inout), target :: currentSite | ||||
|
@@ -185,6 +224,8 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in) | |||
real(r8) :: bmort ! background mortality rate (fraction per year) | ||||
real(r8) :: hmort ! hydraulic failure mortality rate (fraction per year) | ||||
real(r8) :: frmort ! freezing mortality rate (fraction per year) | ||||
real(r8) :: smort ! size dependent senescence mortality rate (fraction per year) | ||||
real(r8) :: asmort ! age dependent senescence mortality rate (fraction per year) | ||||
real(r8) :: dndt_logging ! Mortality rate (per day) associated with the a logging event | ||||
integer :: ipft ! local copy of the pft index | ||||
!---------------------------------------------------------------------- | ||||
|
@@ -193,7 +234,7 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in) | |||
|
||||
! Mortality for trees in the understorey. | ||||
!if trees are in the canopy, then their death is 'disturbance'. This probably needs a different terminology | ||||
call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort) | ||||
call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort,smort, asmort) | ||||
call LoggingMortality_frac(ipft, currentCohort%dbh, currentCohort%canopy_layer, & | ||||
currentCohort%lmort_direct, & | ||||
currentCohort%lmort_collateral, & | ||||
|
@@ -206,14 +247,36 @@ subroutine Mortality_Derivative( currentSite, currentCohort, bc_in) | |||
if (currentCohort%canopy_layer > 1)then | ||||
! Include understory logging mortality rates not associated with disturbance | ||||
dndt_logging = (currentCohort%lmort_direct + & | ||||
currentCohort%lmort_collateral + & | ||||
currentCohort%lmort_infra)/hlm_freq_day | ||||
currentCohort%dndt = -1.0_r8 * (cmort+hmort+bmort+frmort+dndt_logging) * currentCohort%n | ||||
currentCohort%lmort_collateral + & | ||||
currentCohort%lmort_infra)/hlm_freq_day | ||||
|
||||
! this caps bmort so that daily mortality cannot exceed 0.995 | ||||
if ((cmort+hmort+bmort+frmort+smort+asmort + dndt_logging)*hlm_freq_day & | ||||
> 1.0_r8)then | ||||
bmort = (1.0_r8 - ((cmort+hmort+asmort+frmort+smort+dndt_logging)*hlm_freq_day)) & | ||||
/hlm_freq_day | ||||
endif | ||||
|
||||
currentCohort%dndt = -1.0_r8 * & | ||||
(cmort+hmort+bmort+frmort+smort+asmort + dndt_logging) & | ||||
* currentCohort%n | ||||
else | ||||
|
||||
! cap on bmort for canopy layers - bmort is adjusted so that total mortality | ||||
! including disturbance fraction does not exceed 0.995 | ||||
if(((cmort+hmort+bmort+frmort+smort+asmort)*hlm_freq_day) > & | ||||
1.0_r8 - fates_mortality_disturbance_fraction)then | ||||
bmort = (1.0_r8 - fates_mortality_disturbance_fraction - & | ||||
((cmort+hmort+asmort+frmort+smort)*hlm_freq_day))/hlm_freq_day | ||||
endif | ||||
|
||||
|
||||
! Mortality from logging in the canopy is ONLY disturbance generating, don't | ||||
! update number densities via non-disturbance inducing death | ||||
currentCohort%dndt = -(1.0_r8 - fates_mortality_disturbance_fraction) & | ||||
* (cmort+hmort+bmort+frmort) * currentCohort%n | ||||
currentCohort%dndt= -(1.0_r8-fates_mortality_disturbance_fraction) & | ||||
* (cmort+hmort+bmort+frmort+smort+asmort+dndt_logging) * & | ||||
currentCohort%n | ||||
|
||||
endif | ||||
|
||||
return | ||||
|
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.
and size and age dependent senescence maybe?
Also, is it me, or is 'senescence' really, really, hard to spell?
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.
Added 'age' in there. And yes! It is a terrible word to have to type repeatedly.
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.
Ha ha. Glad it isn't just my brain senescing, or whatever.