Skip to content

Commit 1b93458

Browse files
authored
Merge pull request #333 from ckoven/reduce_minbiomasstol
Updates to patch fusion logic
2 parents 5c40b26 + 8ddcec3 commit 1b93458

File tree

3 files changed

+98
-52
lines changed

3 files changed

+98
-52
lines changed

biogeochem/EDPatchDynamicsMod.F90

Lines changed: 87 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ module EDPatchDynamicsMod
77
use FatesInterfaceMod , only : hlm_freq_day
88
use EDPftvarcon , only : EDPftvarcon_inst
99
use EDCohortDynamicsMod , only : fuse_cohorts, sort_cohorts, insert_cohort
10-
use EDtypesMod , only : ncwd, n_dbh_bins, ntol, area, dbhmax
10+
use EDtypesMod , only : ncwd, n_dbh_bins, area, patchfusion_dbhbin_loweredges
11+
use EDtypesMod , only : force_patchfuse_min_biomass
1112
use EDTypesMod , only : maxPatchesPerSite
1213
use EDTypesMod , only : ed_site_type, ed_patch_type, ed_cohort_type
1314
use EDTypesMod , only : min_patch_area
@@ -118,7 +119,8 @@ subroutine disturbance_rates( site_in, bc_in)
118119

119120
call mortality_rates(currentCohort,bc_in,cmort,hmort,bmort,frmort)
120121
currentCohort%dmort = cmort+hmort+bmort+frmort
121-
call carea_allom(currentCohort%dbh,currentCohort%n,site_in%spread,currentCohort%pft,currentCohort%c_area)
122+
call carea_allom(currentCohort%dbh,currentCohort%n,site_in%spread,currentCohort%pft, &
123+
currentCohort%c_area)
122124

123125
! Initialize diagnostic mortality rates
124126
currentCohort%cmort = cmort
@@ -1321,6 +1323,8 @@ subroutine fuse_patches( csite, bc_in )
13211323
!
13221324
! !USES:
13231325
use EDParamsMod , only : ED_val_patch_fusion_tol
1326+
use EDTypesMod , only : patch_fusion_tolerance_relaxation_increment
1327+
use EDTypesMod , only : max_age_of_second_oldest_patch
13241328
!
13251329
! !ARGUMENTS:
13261330
type(ed_site_type), intent(inout), target :: csite
@@ -1332,14 +1336,12 @@ subroutine fuse_patches( csite, bc_in )
13321336
integer :: ft,z !counters for pft and height class
13331337
real(r8) :: norm !normalized difference between biomass profiles
13341338
real(r8) :: profiletol !tolerance of patch fusion routine. Starts off high and is reduced if there are too many patches.
1335-
integer :: maxpatch !maximum number of allowed patches. FIX-RF. These should be namelist variables.
13361339
integer :: nopatches !number of patches presently in gridcell
13371340
integer :: iterate !switch of patch reduction iteration scheme. 1 to keep going, 0 to stop
13381341
integer :: fuse_flag !do patches get fused (1) or not (0).
1342+
!
13391343
!---------------------------------------------------------------------
13401344

1341-
maxpatch = maxPatchesPerSite
1342-
13431345
currentSite => csite
13441346

13451347
profiletol = ED_val_patch_fusion_tol
@@ -1356,7 +1358,7 @@ subroutine fuse_patches( csite, bc_in )
13561358
iterate = 1
13571359

13581360
!---------------------------------------------------------------------!
1359-
! Keep doing this until nopatches >= maxpatch !
1361+
! Keep doing this until nopatches >= maxPatchesPerSite !
13601362
!---------------------------------------------------------------------!
13611363

13621364
do while(iterate == 1)
@@ -1382,36 +1384,80 @@ subroutine fuse_patches( csite, bc_in )
13821384
endif
13831385

13841386
if(associated(tpp).and.associated(currentPatch))then
1385-
fuse_flag = 1 !the default is to fuse the patches
1387+
1388+
!--------------------------------------------------------------------------------------------
1389+
! The default is to fuse the patches, unless some criteria is met which keeps them separated.
1390+
! there are multiple criteria which all need to be met to keep them distinct:
1391+
! (a) one of them is younger than the max age at which we force fusion;
1392+
! (b) there is more than a threshold (tiny) amount of biomass in at least one of the patches;
1393+
! (c) for at least one pft x size class, where there is biomass in that class in at least one patch,
1394+
! and the normalized difference between the patches exceeds a threshold.
1395+
!--------------------------------------------------------------------------------------------
1396+
1397+
fuse_flag = 1
13861398
if(currentPatch%patchno /= tpp%patchno) then !these should be the same patch
13871399

1388-
!---------------------------------------------------------------------!
1389-
! Calculate the difference criteria for each pft and dbh class !
1390-
!---------------------------------------------------------------------!
1391-
do ft = 1,numpft ! loop over pfts
1392-
do z = 1,n_dbh_bins ! loop over hgt bins
1393-
!is there biomass in this category?
1394-
if(currentPatch%pft_agb_profile(ft,z) > 0.0_r8.or.tpp%pft_agb_profile(ft,z) > 0.0_r8)then
1395-
norm = abs(currentPatch%pft_agb_profile(ft,z) - tpp%pft_agb_profile(ft,z))/(0.5_r8*&
1396-
&(currentPatch%pft_agb_profile(ft,z) + tpp%pft_agb_profile(ft,z)))
1397-
!---------------------------------------------------------------------!
1398-
! Look for differences in profile biomass, above the minimum biomass !
1399-
!---------------------------------------------------------------------!
1400-
1401-
if(norm > profiletol)then
1402-
!looking for differences between profile density.
1403-
if(currentPatch%pft_agb_profile(ft,z) > NTOL.or.tpp%pft_agb_profile(ft,z) > NTOL)then
1404-
fuse_flag = 0 !do not fuse - keep apart.
1405-
endif
1406-
endif ! profile tol
1407-
endif ! NTOL
1408-
enddo !ht bins
1409-
enddo ! PFT
1410-
1411-
!---------------------------------------------------------------------!
1412-
! Call the patch fusion routine if there is a meaningful difference !
1413-
! any of the pft x height categories !
1414-
!---------------------------------------------------------------------!
1400+
!-----------------------------------------------------------------------------------
1401+
! check to see if both patches are older than the age at which we force them to fuse
1402+
!-----------------------------------------------------------------------------------
1403+
1404+
if ( tpp%age .le. max_age_of_second_oldest_patch .or. &
1405+
currentPatch%age .le. max_age_of_second_oldest_patch ) then
1406+
1407+
1408+
!---------------------------------------------------------------------------------------------------------
1409+
! the next bit of logic forces fusion of two patches which both have tiny biomass densities. without this,
1410+
! fates gives a bunch of really young patches which all have almost no biomass and so don't need to be
1411+
! distinguished from each other. but if force_patchfuse_min_biomass is too big, it takes too long for the
1412+
! youngest patch to build up enough biomass to be its own distinct entity, which leads to large oscillations
1413+
! in the patch dynamics and dependent variables.
1414+
!---------------------------------------------------------------------------------------------------------
1415+
1416+
if(sum(currentPatch%pft_agb_profile(:,:)) > force_patchfuse_min_biomass .or. &
1417+
sum(tpp%pft_agb_profile(:,:)) > force_patchfuse_min_biomass ) then
1418+
1419+
!---------------------------------------------------------------------!
1420+
! Calculate the difference criteria for each pft and dbh class !
1421+
!---------------------------------------------------------------------!
1422+
1423+
do ft = 1,numpft ! loop over pfts
1424+
do z = 1,n_dbh_bins ! loop over hgt bins
1425+
1426+
!----------------------------------
1427+
!is there biomass in this category?
1428+
!----------------------------------
1429+
1430+
if(currentPatch%pft_agb_profile(ft,z) > 0.0_r8 .or. &
1431+
tpp%pft_agb_profile(ft,z) > 0.0_r8)then
1432+
1433+
!-------------------------------------------------------------------------------------
1434+
! what is the relative difference in biomass i nthis category between the two patches?
1435+
!-------------------------------------------------------------------------------------
1436+
1437+
norm = abs(currentPatch%pft_agb_profile(ft,z) - &
1438+
tpp%pft_agb_profile(ft,z))/(0.5_r8 * &
1439+
&(currentPatch%pft_agb_profile(ft,z) + tpp%pft_agb_profile(ft,z)))
1440+
1441+
!---------------------------------------------------------------------!
1442+
! Look for differences in profile biomass, above the minimum biomass !
1443+
!---------------------------------------------------------------------!
1444+
1445+
if(norm > profiletol)then
1446+
1447+
fuse_flag = 0 !do not fuse - keep apart.
1448+
1449+
endif ! profile tol
1450+
endif ! biomass(ft,z) .gt. 0
1451+
enddo !ht bins
1452+
enddo ! PFT
1453+
endif ! sum(biomass(:,:) .gt. force_patchfuse_min_biomass
1454+
endif ! maxage
1455+
1456+
!-------------------------------------------------------------------------!
1457+
! Call the patch fusion routine if there is not a meaningful difference !
1458+
! any of the pft x height categories !
1459+
! or both are older than forced fusion age !
1460+
!-------------------------------------------------------------------------!
14151461

14161462
if(fuse_flag == 1)then
14171463
tmpptr => currentPatch%older
@@ -1445,9 +1491,9 @@ subroutine fuse_patches( csite, bc_in )
14451491
currentPatch => currentPatch%older
14461492
enddo
14471493

1448-
if(nopatches > maxpatch)then
1494+
if(nopatches > maxPatchesPerSite)then
14491495
iterate = 1
1450-
profiletol = profiletol * 1.1_r8
1496+
profiletol = profiletol * patch_fusion_tolerance_relaxation_increment
14511497

14521498
!---------------------------------------------------------------------!
14531499
! Making profile tolerance larger means that more fusion will happen !
@@ -1456,7 +1502,7 @@ subroutine fuse_patches( csite, bc_in )
14561502
iterate = 0
14571503
endif
14581504

1459-
enddo !do while nopatches>maxpatch
1505+
enddo !do while nopatches>maxPatchesPerSite
14601506

14611507
end subroutine fuse_patches
14621508

@@ -1765,20 +1811,15 @@ subroutine patch_pft_size_profile(cp_pnt)
17651811

17661812
currentPatch => cp_pnt
17671813

1768-
delta_dbh = (DBHMAX/N_DBH_BINS)
1769-
17701814
currentPatch%pft_agb_profile(:,:) = 0.0_r8
17711815

17721816
do j = 1,N_DBH_BINS
1773-
if (j == 1) then
1774-
mind(j) = 0.0_r8
1775-
maxd(j) = delta_dbh
1776-
else if (j == N_DBH_BINS) then
1777-
mind(j) = (j-1) * delta_dbh
1817+
if (j == N_DBH_BINS) then
1818+
mind(j) = patchfusion_dbhbin_loweredges(j)
17781819
maxd(j) = gigantictrees
17791820
else
1780-
mind(j) = (j-1) * delta_dbh
1781-
maxd(j) = (j)*delta_dbh
1821+
mind(j) = patchfusion_dbhbin_loweredges(j)
1822+
maxd(j) = patchfusion_dbhbin_loweredges(j+1)
17821823
endif
17831824
enddo
17841825

main/EDTypesMod.F90

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,18 @@ module EDTypesMod
8181
real(r8), parameter :: fire_threshold = 50.0_r8 ! threshold for fires that spread or go out. KWm-2 (Pyne 1986)
8282

8383
! PATCH FUSION
84-
real(r8), parameter :: NTOL = 0.05_r8 ! min plant density for hgt bin to be used in height profile comparisons
84+
real(r8), parameter :: force_patchfuse_min_biomass = 0.005_r8 ! min biomass (kg / m2 patch area) below which to force-fuse patches
85+
integer , parameter :: N_DBH_BINS = 6 ! no. of dbh bins used when comparing patches
86+
real(r8), parameter :: patchfusion_dbhbin_loweredges(N_DBH_BINS) = &
87+
(/0._r8, 5._r8, 20._r8, 50._r8, 100._r8, 150._r8/) ! array of bin lower edges for comparing patches
88+
real(r8), parameter :: patch_fusion_tolerance_relaxation_increment = 1.1_r8 ! amount by which to increment patch fusion threshold
89+
real(r8), parameter :: max_age_of_second_oldest_patch = 200._r8 ! age in years above which to combine all patches
90+
91+
! COHORT FUSION
8592
real(r8), parameter :: HITEMAX = 30.0_r8 ! max dbh value used in hgt profile comparison
86-
real(r8), parameter :: DBHMAX = 150.0_r8 ! max dbh value used in hgt profile comparison
8793
integer , parameter :: N_HITE_BINS = 60 ! no. of hite bins used to distribute LAI
88-
integer , parameter :: N_DBH_BINS = 5 ! no. of dbh bins used when comparing patches
89-
9094

95+
! COHORT TERMINATION
9196
real(r8), parameter :: min_npm2 = 1.0E-8_r8 ! minimum cohort number density per m2 before termination
9297
real(r8), parameter :: min_patch_area = 0.001_r8 ! smallest allowable patch area before termination
9398
real(r8), parameter :: min_nppatch = 1.0E-11_r8 ! minimum number of cohorts per patch (min_npm2*min_patch_area)

main/FatesHistoryInterfaceMod.F90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2615,12 +2615,12 @@ subroutine define_history_vars(this, initialize_variables)
26152615
! Site level counting variables
26162616
call this%set_history_var(vname='ED_NPATCHES', units='none', &
26172617
long='Total number of ED patches per site', use_default='active', &
2618-
avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=1.0_r8, upfreq=1, &
2618+
avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, &
26192619
ivar=ivar, initialize=initialize_variables, index = ih_npatches_si)
26202620

26212621
call this%set_history_var(vname='ED_NCOHORTS', units='none', &
26222622
long='Total number of ED cohorts per site', use_default='active', &
2623-
avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=1.0_r8, upfreq=1, &
2623+
avgflag='A', vtype=site_r8, hlms='CLM:ALM', flushval=0.0_r8, upfreq=1, &
26242624
ivar=ivar, initialize=initialize_variables, index = ih_ncohorts_si)
26252625

26262626
! Patch variables

0 commit comments

Comments
 (0)