Skip to content

Commit 315e0d6

Browse files
authored
Merge pull request #1424 from rgknox/nclmax-3-sortfixes
promotion/demotion refactor and nclmax = 3
2 parents 1afb393 + 59c46cb commit 315e0d6

File tree

6 files changed

+502
-1007
lines changed

6 files changed

+502
-1007
lines changed

biogeochem/EDCanopyStructureMod.F90

Lines changed: 416 additions & 977 deletions
Large diffs are not rendered by default.

biogeochem/EDCohortDynamicsMod.F90

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -340,12 +340,13 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_
340340
terminate = itrue
341341
termination_type = i_term_mort_type_numdens
342342
if ( debug ) then
343-
write(fates_log(),*) 'terminating cohorts 0',currentCohort%n/currentPatch%area,currentCohort%dbh,currentCohort%pft,call_index
343+
write(fates_log(),*) 'terminating cohorts 0',currentCohort%n/currentPatch%area, &
344+
currentCohort%dbh,currentCohort%pft,call_index
344345
endif
345346
endif
346347

347348
! The rest of these are only allowed if we are not dealing with a recruit (level 2)
348-
if (.not.currentCohort%isnew .and. level == 2) then
349+
if_level_2: if (.not.currentCohort%isnew .and. level == 2) then
349350

350351
! Not enough n or dbh
351352
if (currentCohort%n/currentPatch%area <= min_npm2 .or. & !
@@ -354,18 +355,13 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_
354355
terminate = itrue
355356
termination_type = i_term_mort_type_numdens
356357
if ( debug ) then
357-
write(fates_log(),*) 'terminating cohorts 1',currentCohort%n/currentPatch%area,currentCohort%dbh,currentCohort%pft,call_index
358+
write(fates_log(),*) 'terminating cohorts 1', &
359+
currentCohort%n/currentPatch%area,currentCohort%dbh, &
360+
currentCohort%pft,call_index
358361
endif
359362
endif
360363

361-
! Outside the maximum canopy layer
362-
if (currentCohort%canopy_layer > nclmax ) then
363-
terminate = itrue
364-
termination_type = i_term_mort_type_canlev
365-
if ( debug ) then
366-
write(fates_log(),*) 'terminating cohorts 2', currentCohort%canopy_layer,currentCohort%pft,call_index
367-
endif
368-
endif
364+
369365

370366
! live biomass pools are terminally depleted
371367
if ( ( sapw_c+leaf_c+fnrt_c ) < 1e-10_r8 .or. &
@@ -387,8 +383,18 @@ subroutine terminate_cohorts( currentSite, currentPatch, level , call_index, bc_
387383
struct_c,sapw_c,leaf_c,fnrt_c,store_c,currentCohort%pft,call_index
388384
endif
389385

390-
endif
391-
endif ! if (.not.currentCohort%isnew .and. level == 2) then
386+
endif
387+
388+
end if if_level_2
389+
390+
! Outside the maximum canopy layer
391+
if (currentCohort%canopy_layer > nclmax .and. level == 3) then
392+
terminate = itrue
393+
termination_type = i_term_mort_type_canlev
394+
if ( debug ) then
395+
write(fates_log(),*) 'terminating cohorts 2', currentCohort%canopy_layer,currentCohort%pft,call_index
396+
endif
397+
endif
392398

393399
if (terminate == itrue) then
394400
call terminate_cohort(currentSite, currentPatch, currentCohort, bc_in, termination_type)

biogeochem/FatesPatchMod.F90

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ module FatesPatchMod
2121
use PRTGenericMod, only : struct_organ, leaf_organ, sapw_organ
2222
use PRTParametersMod, only : prt_params
2323
use FatesConstantsMod, only : nocomp_bareground
24-
use EDParamsMod, only : nlevleaf, nclmax, maxpft
24+
use EDParamsMod, only : nlevleaf, nclmax, maxpft,max_cohort_per_patch
2525
use FatesConstantsMod, only : n_dbh_bins, n_dist_types
2626
use FatesConstantsMod, only : t_water_freeze_k_1atm
2727
use FatesRunningMeanMod, only : ema_24hr, fixed_24hr, ema_lpa, ema_longterm
@@ -41,14 +41,35 @@ module FatesPatchMod
4141
! for error message writing
4242
character(len=*), parameter :: sourcefile = __FILE__
4343

44+
type :: fates_cohort_vec_type
45+
46+
! This is a scratch array for cohort pointers
47+
! this is useful if you want to loop over a sparse subset
48+
! of fates cohorts over and over again, allowing
49+
! you to iterate them in a do loop
50+
51+
type(fates_cohort_type), pointer :: p => null()
52+
53+
! This is the area of the cohort (less than or equal to cohort%carea)
54+
! that will be promoted or demoted, ie promoted/demoted crown area
55+
! units [m2/site] or [m2/ha] (same as the patch area and crown area)
56+
! We track it here because we construct the cohort list for specific
57+
! canopy layers
58+
59+
real(r8) :: pd_area
60+
61+
end type fates_cohort_vec_type
62+
63+
4464
type, public :: fates_patch_type
4565

4666
! POINTERS
4767
type (fates_cohort_type), pointer :: tallest => null() ! pointer to patch's tallest cohort
4868
type (fates_cohort_type), pointer :: shortest => null() ! pointer to patch's shortest cohort
4969
type (fates_patch_type), pointer :: older => null() ! pointer to next older patch
5070
type (fates_patch_type), pointer :: younger => null() ! pointer to next younger patch
51-
71+
type (fates_cohort_vec_type), pointer :: co_scr(:) ! Scratch vector of cohort properties
72+
5273
!---------------------------------------------------------------------------
5374

5475
! INDICES
@@ -279,7 +300,8 @@ subroutine Init(this, num_swb, num_levsoil)
279300
allocate(this%sabs_dir(num_swb))
280301
allocate(this%sabs_dif(num_swb))
281302
allocate(this%fragmentation_scaler(num_levsoil))
282-
303+
allocate(this%co_scr(max_cohort_per_patch))
304+
283305
! initialize all values to nan
284306
call this%NanValues()
285307

@@ -898,6 +920,7 @@ subroutine FreeMemory(this, regeneration_model, numpft)
898920
this%sabs_dir, &
899921
this%sabs_dif, &
900922
this%fragmentation_scaler, &
923+
this%co_scr, &
901924
stat=istat, errmsg=smsg)
902925

903926
! These arrays are allocated via a call from EDCanopyStructureMod
@@ -1161,19 +1184,29 @@ end subroutine CountCohorts
11611184

11621185
!===========================================================================
11631186

1164-
subroutine SortCohorts(this)
1187+
subroutine SortCohorts(this,check_order)
11651188
!
11661189
! DESCRIPTION: sort cohorts in patch's linked list
11671190
! uses insertion sort to build a new list
11681191
!
11691192

11701193
! ARGUMENTS:
11711194
class(fates_patch_type), intent(inout), target :: this ! patch
1195+
1196+
logical, optional, intent(in) :: check_order
11721197

11731198
! LOCALS:
11741199
type(fates_cohort_type), pointer :: currentCohort
11751200
type(fates_cohort_type), pointer :: nextCohort
1201+
1202+
logical :: check_order_present
11761203

1204+
if (present(check_order)) then
1205+
check_order_present = check_order
1206+
else
1207+
check_order_present = .false.
1208+
end if
1209+
11771210
! check for inconsistent list state
11781211
if (.not. associated(this%shortest) .and. .not. associated(this%tallest)) then
11791212
! empty list
@@ -1186,6 +1219,23 @@ subroutine SortCohorts(this)
11861219

11871220
! hold on to current linked list so we don't lose it
11881221
currentCohort => this%shortest
1222+
1223+
if(check_order_present)then
1224+
do while (associated(currentCohort))
1225+
if( associated(currentCohort%taller)) then
1226+
if(currentCohort%height > currentCohort%taller%height)then
1227+
write(fates_log(),*) 'Cohort sort checking has failed,'
1228+
write(fates_log(),*) 'they are not in height order:'
1229+
write(fates_log(),*) 'current: ',currentCohort%height
1230+
write(fates_log(),*) 'taller: ',currentCohort%taller%height
1231+
call endrun(msg=errMsg(sourcefile, __LINE__))
1232+
end if
1233+
end if
1234+
currentCohort => currentCohort%taller
1235+
end do
1236+
return
1237+
end if
1238+
11891239

11901240
! reset the current list: we'll build it incrementally
11911241
this%shortest => null()

main/EDParamsMod.F90

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ module EDParamsMod
4444
!moving average of par at the seedling layer used to
4545
!calculate seedling to sapling transition rates
4646
real(r8),protected, public :: fates_mortality_disturbance_fraction ! the fraction of canopy mortality that results in disturbance
47-
real(r8),protected, public :: ED_val_comp_excln ! weighting factor for canopy layer exclusion and promotion
47+
real(r8),protected, public :: comp_excln_exp ! weighting factor (exponent) for canopy layer exclusion and promotion
4848
real(r8),protected, public :: ED_val_vai_top_bin_width ! width in VAI units of uppermost leaf+stem layer scattering element
4949
real(r8),protected, public :: ED_val_vai_width_increase_factor ! factor by which each leaf+stem scattering element increases in VAI width
5050
real(r8),protected, public :: ED_val_nignitions ! number of annual ignitions per square km
@@ -81,10 +81,10 @@ module EDParamsMod
8181

8282
real(r8), parameter, public :: soil_tfrz_thresh = -2.0_r8 ! Soil temperature threshold below which hydraulic failure mortality is off (non-hydro only) in degrees C
8383

84-
integer, parameter, public :: nclmax = 2 ! Maximum number of canopy layers (used only for scratch arrays)
85-
! We would make this even higher, but making this
86-
! a little lower keeps the size down on some output arrays
87-
! For large arrays at patch level we use dynamic allocation
84+
integer, parameter, public :: nclmax = 3 ! Maximum number of canopy layers allowed
85+
! We would make this even higher, but making this
86+
! a little lower keeps the size down on some output arrays
87+
! For large arrays at patch level we use dynamic allocation
8888

8989
! parameters that govern the VAI (LAI+SAI) bins used in radiative transfer code
9090
integer, parameter, public :: nlevleaf = 30 ! number of leaf+stem layers in each canopy layer
@@ -303,7 +303,7 @@ subroutine FatesParamsInit()
303303
sdlng2sap_par_timescale = nan
304304
photo_temp_acclim_thome_time = nan
305305
fates_mortality_disturbance_fraction = nan
306-
ED_val_comp_excln = nan
306+
comp_excln_exp = nan
307307
ED_val_vai_top_bin_width = nan
308308
ED_val_vai_width_increase_factor = nan
309309
ED_val_nignitions = nan
@@ -610,7 +610,7 @@ subroutine FatesReceiveParams(fates_params)
610610
data=fates_mortality_disturbance_fraction)
611611

612612
call fates_params%RetrieveParameter(name=ED_name_comp_excln, &
613-
data=ED_val_comp_excln)
613+
data=comp_excln_exp)
614614

615615
call fates_params%RetrieveParameter(name=ED_name_vai_top_bin_width, &
616616
data=ED_val_vai_top_bin_width)
@@ -825,7 +825,7 @@ subroutine FatesReportParams(is_master)
825825
write(fates_log(),fmt0) 'photo_temp_acclim_thome_time (years) = ',photo_temp_acclim_thome_time
826826
write(fates_log(),fmti) 'hydr_htftype_node = ',hydr_htftype_node
827827
write(fates_log(),fmt0) 'fates_mortality_disturbance_fraction = ',fates_mortality_disturbance_fraction
828-
write(fates_log(),fmt0) 'ED_val_comp_excln = ',ED_val_comp_excln
828+
write(fates_log(),fmt0) 'comp_excln_exp = ',comp_excln_exp
829829
write(fates_log(),fmt0) 'ED_val_vai_top_bin_width = ',ED_val_vai_top_bin_width
830830
write(fates_log(),fmt0) 'ED_val_vai_width_increase_factor = ',ED_val_vai_width_increase_factor
831831
write(fates_log(),fmt0) 'ED_val_nignitions = ',ED_val_nignitions

main/FatesHistoryInterfaceMod.F90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ module FatesHistoryInterfaceMod
5555
use FatesInterfaceTypesMod , only : hlm_freq_day
5656
use FatesInterfaceTypesMod , only : hlm_parteh_mode
5757
use FatesInterfaceTypesMod , only : hlm_use_sp
58-
use EDParamsMod , only : ED_val_comp_excln
58+
use EDParamsMod , only : comp_excln_exp
5959
use EDParamsMod , only : ED_val_phen_coldtemp
6060
use EDParamsMod , only : nlevleaf
6161
use EDParamsMod , only : ED_val_history_height_bin_edges
@@ -2693,7 +2693,7 @@ subroutine update_history_dyn_sitelevel(this,nc,nsites,sites)
26932693
hio_ncl_si(io_si) = hio_ncl_si(io_si) + cpatch%ncl_p * cpatch%area * AREA_INV
26942694

26952695
! only valid when "strict ppa" enabled
2696-
if ( ED_val_comp_excln .lt. 0._r8 ) then
2696+
if ( comp_excln_exp .lt. 0._r8 ) then
26972697
hio_zstar_si(io_si) = hio_zstar_si(io_si) &
26982698
+ cpatch%zstar * cpatch%area * AREA_INV
26992699
end if
@@ -4861,7 +4861,7 @@ subroutine update_history_dyn_subsite_ageclass(this,nc,nsites,sites)
48614861
end do
48624862

48634863
! only valid when "strict ppa" enabled
4864-
if ( ED_val_comp_excln .lt. 0._r8 ) then
4864+
if ( comp_excln_exp .lt. 0._r8 ) then
48654865
hio_zstar_si_age(io_si,cpatch%age_class) = hio_zstar_si_age(io_si,cpatch%age_class) &
48664866
+ cpatch%zstar * patch_area_div_site_area
48674867
end if
@@ -7347,7 +7347,7 @@ subroutine define_history_vars(this, initialize_variables)
73477347
upfreq=group_dyna_complx, ivar=ivar, initialize=initialize_variables, &
73487348
index=ih_npatches_si_age)
73497349

7350-
if ( ED_val_comp_excln .lt. 0._r8 ) then ! only valid when "strict ppa" enabled
7350+
if ( comp_excln_exp .lt. 0._r8 ) then ! only valid when "strict ppa" enabled
73517351
tempstring = 'active'
73527352
else
73537353
tempstring = 'inactive'

testing/unit_testing/sort_cohorts_test/test_SortCohorts.pf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module test_SortCohorts
2424
class(TestSortCohorts), intent(inout) :: this ! test object
2525
type(fates_patch_type) :: patch ! patch object
2626

27-
! sort cohorts - should pass
27+
! sort cohorts - should pass - the argument
2828
call patch%SortCohorts()
2929

3030
end subroutine EmptyList_SortCohorts_Passes

0 commit comments

Comments
 (0)