Skip to content

Commit 3f5aa1b

Browse files
authored
Merge pull request #402 from kovenock/kovenock_slaprofile
SLA Profile with Canopy Depth
2 parents 91785e3 + 3aa3791 commit 3f5aa1b

11 files changed

+382
-156
lines changed

biogeochem/EDCanopyStructureMod.F90

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,8 +1016,10 @@ subroutine canopy_summarization( nsites, sites, bc_in )
10161016

10171017
call carea_allom(currentCohort%dbh,currentCohort%n,sites(s)%spread,&
10181018
currentCohort%pft,currentCohort%c_area)
1019-
currentCohort%treelai = tree_lai(currentCohort%bl, currentCohort%status_coh, &
1020-
currentCohort%pft, currentCohort%c_area, currentCohort%n )
1019+
1020+
currentCohort%treelai = tree_lai(currentCohort%bl, &
1021+
currentCohort%pft, currentCohort%c_area, currentCohort%n, &
1022+
currentCohort%canopy_layer, currentPatch%canopy_layer_tlai )
10211023

10221024
canopy_leaf_area = canopy_leaf_area + currentCohort%treelai *currentCohort%c_area
10231025

@@ -1087,7 +1089,7 @@ subroutine leaf_area_profile( currentSite , snow_depth_si, frac_sno_eff_si)
10871089
!
10881090
! The following patch level diagnostics are updated here:
10891091
!
1090-
! currentPatch%canopy_layer_tai(cl) ! TAI of each canopy layer
1092+
! currentPatch%canopy_layer_tlai(cl) ! total leaf area index of canopy layer
10911093
! currentPatch%ncan(cl,ft) ! number of vegetation layers needed
10921094
! ! in this patch's pft/canopy-layer
10931095
! currentPatch%nrad(cl,ft) ! same as ncan, but does not include
@@ -1157,7 +1159,7 @@ subroutine leaf_area_profile( currentSite , snow_depth_si, frac_sno_eff_si)
11571159
! calculate tree lai and sai.
11581160
! --------------------------------------------------------------------------------
11591161

1160-
currentPatch%canopy_layer_tai(:) = 0._r8
1162+
currentPatch%canopy_layer_tlai(:) = 0._r8
11611163
currentPatch%ncan(:,:) = 0
11621164
currentPatch%nrad(:,:) = 0
11631165
patch_lai = 0._r8
@@ -1176,38 +1178,38 @@ subroutine leaf_area_profile( currentSite , snow_depth_si, frac_sno_eff_si)
11761178

11771179
if (currentPatch%total_canopy_area > nearzero ) then
11781180

1179-
currentCohort => currentPatch%shortest
1181+
1182+
currentCohort => currentPatch%tallest
11801183
do while(associated(currentCohort))
11811184

11821185
ft = currentCohort%pft
11831186
cl = currentCohort%canopy_layer
11841187

1185-
currentCohort%treelai = tree_lai(currentCohort%bl, currentCohort%status_coh, currentCohort%pft, &
1186-
currentCohort%c_area, currentCohort%n )
1187-
currentCohort%treesai = tree_sai(currentCohort%dbh, currentCohort%pft, currentCohort%canopy_trim, &
1188-
currentCohort%c_area, currentCohort%n)
1188+
! Calculate LAI of layers above
1189+
! Note that the canopy_layer_lai is also calculated in this loop
1190+
! but since we go top down in terms of plant size, we should be okay
1191+
1192+
currentCohort%treelai = tree_lai(currentCohort%bl, currentCohort%pft, currentCohort%c_area, &
1193+
currentCohort%n, currentCohort%canopy_layer, &
1194+
currentPatch%canopy_layer_tlai )
1195+
1196+
currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, &
1197+
currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, &
1198+
currentPatch%canopy_layer_tlai, currentCohort%treelai )
11891199

11901200
currentCohort%lai = currentCohort%treelai *currentCohort%c_area/currentPatch%total_canopy_area
11911201
currentCohort%sai = currentCohort%treesai *currentCohort%c_area/currentPatch%total_canopy_area
11921202

11931203
! Number of actual vegetation layers in this cohort's crown
1194-
currentCohort%NV = ceiling((currentCohort%treelai+currentCohort%treesai)/dinc_ed)
1204+
currentCohort%nv = ceiling((currentCohort%treelai+currentCohort%treesai)/dinc_ed)
11951205

11961206
currentPatch%ncan(cl,ft) = max(currentPatch%ncan(cl,ft),currentCohort%NV)
11971207

11981208
patch_lai = patch_lai + currentCohort%lai
11991209

1200-
! currentPatch%canopy_layer_tai(cl) = currentPatch%canopy_layer_tai(cl) + &
1201-
! currentCohort%lai + currentCohort%sai
1210+
currentPatch%canopy_layer_tlai(cl) = currentPatch%canopy_layer_tlai(cl) + currentCohort%lai
12021211

1203-
do cl = 1,nclmax-1
1204-
if(currentCohort%canopy_layer == cl)then
1205-
currentPatch%canopy_layer_tai(cl) = currentPatch%canopy_layer_tai(cl) + &
1206-
currentCohort%lai + currentCohort%sai
1207-
endif
1208-
enddo
1209-
1210-
currentCohort => currentCohort%taller
1212+
currentCohort => currentCohort%shorter
12111213

12121214
enddo !currentCohort
12131215

@@ -1384,7 +1386,7 @@ subroutine leaf_area_profile( currentSite , snow_depth_si, frac_sno_eff_si)
13841386

13851387
if(iv==currentCohort%NV) then
13861388
remainder = (currentCohort%treelai + currentCohort%treesai) - &
1387-
(dinc_ed*dble(currentCohort%NV-1.0_r8))
1389+
(dinc_ed*dble(currentCohort%nv-1.0_r8))
13881390
if(remainder > dinc_ed )then
13891391
write(fates_log(), *)'ED: issue with remainder', &
13901392
currentCohort%treelai,currentCohort%treesai,dinc_ed, &
@@ -1484,7 +1486,7 @@ subroutine leaf_area_profile( currentSite , snow_depth_si, frac_sno_eff_si)
14841486
enddo !currentCohort
14851487
call endrun(msg=errMsg(sourcefile, __LINE__))
14861488
end if
1487-
end do
1489+
end do
14881490

14891491
do ft = 1,numpft
14901492
do iv = 1,currentPatch%ncan(cl,ft)

biogeochem/EDCohortDynamicsMod.F90

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ module EDCohortDynamicsMod
2121
use EDTypesMod , only : min_npm2, min_nppatch
2222
use EDTypesMod , only : min_n_safemath
2323
use EDTypesMod , only : nlevleaf
24-
use EDTypesMod , only : dinc_ed
2524
use FatesInterfaceMod , only : hlm_use_planthydro
2625
use FatesPlantHydraulicsMod, only : FuseCohortHydraulics
2726
use FatesPlantHydraulicsMod, only : CopyCohortHydraulics
@@ -152,11 +151,16 @@ subroutine create_cohort(currentSite, patchptr, pft, nn, hite, dbh, bleaf, bfine
152151
! Assign canopy extent and depth
153152
call carea_allom(new_cohort%dbh,new_cohort%n,spread,new_cohort%pft,new_cohort%c_area)
154153

155-
new_cohort%treelai = tree_lai(new_cohort%bl, new_cohort%status_coh, new_cohort%pft, &
156-
new_cohort%c_area, new_cohort%n)
154+
new_cohort%treelai = tree_lai(new_cohort%bl, new_cohort%pft, new_cohort%c_area, &
155+
new_cohort%n, new_cohort%canopy_layer, &
156+
patchptr%canopy_layer_tlai )
157+
158+
new_cohort%treesai = tree_sai(new_cohort%pft, new_cohort%dbh, new_cohort%canopy_trim, &
159+
new_cohort%c_area, new_cohort%n, new_cohort%canopy_layer, &
160+
patchptr%canopy_layer_tlai, new_cohort%treelai )
161+
157162
new_cohort%lai = new_cohort%treelai * new_cohort%c_area/patchptr%area
158-
new_cohort%treesai = tree_sai(new_cohort%dbh, new_cohort%pft, new_cohort%canopy_trim, &
159-
new_cohort%c_area, new_cohort%n)
163+
160164

161165
! Put cohort at the right place in the linked list
162166
storebigcohort => patchptr%tallest

biogeochem/EDPatchDynamicsMod.F90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,7 +1267,7 @@ subroutine zero_patch(cp_p)
12671267
currentPatch%age = nan
12681268
currentPatch%age_class = 1
12691269
currentPatch%area = nan
1270-
currentPatch%canopy_layer_tai(:) = nan
1270+
currentPatch%canopy_layer_tlai(:) = nan
12711271
currentPatch%total_canopy_area = nan
12721272

12731273
currentPatch%tlai_profile(:,:,:) = nan
@@ -1347,7 +1347,7 @@ subroutine zero_patch(cp_p)
13471347
currentPatch%burnt_frac_litter(:) = 0.0_r8
13481348
currentPatch%btran_ft(:) = 0.0_r8
13491349

1350-
currentPatch%canopy_layer_tai(:) = 0.0_r8
1350+
currentPatch%canopy_layer_tlai(:) = 0.0_r8
13511351

13521352
currentPatch%seeds_in(:) = 0.0_r8
13531353
currentPatch%seed_decay(:) = 0.0_r8

biogeochem/EDPhysiologyMod.F90

Lines changed: 84 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module EDPhysiologyMod
2020
use EDCohortDynamicsMod , only : create_cohort, sort_cohorts
2121
use FatesAllometryMod , only : tree_lai
2222
use FatesAllometryMod , only : tree_sai
23+
use FatesAllometryMod , only : decay_coeff_kn
2324

2425
use EDTypesMod , only : numWaterMem
2526
use EDTypesMod , only : dl_sf, dinc_ed
@@ -162,40 +163,59 @@ subroutine trim_canopy( currentSite )
162163
! Canopy trimming / leaf optimisation. Removes leaves in negative annual carbon balance.
163164
!
164165
! !USES:
165-
!
166-
!
166+
167167
! !ARGUMENTS
168168
type (ed_site_type),intent(inout), target :: currentSite
169169
!
170170
! !LOCAL VARIABLES:
171171
type (ed_cohort_type) , pointer :: currentCohort
172172
type (ed_patch_type) , pointer :: currentPatch
173173

174-
integer :: z ! leaf layer
175-
integer :: ipft ! pft index
176-
integer :: trimmed ! was this layer trimmed in this year? If not expand the canopy.
177-
real(r8) :: tar_bl ! target leaf biomass (leaves flushed, trimmed)
178-
real(r8) :: tar_bfr ! target fine-root biomass (leaves flushed, trimmed)
179-
real(r8) :: bfr_per_bleaf ! ratio of fine root per leaf biomass
174+
integer :: z ! leaf layer
175+
integer :: ipft ! pft index
176+
logical :: trimmed ! was this layer trimmed in this year? If not expand the canopy.
177+
real(r8) :: tar_bl ! target leaf biomass (leaves flushed, trimmed)
178+
real(r8) :: tar_bfr ! target fine-root biomass (leaves flushed, trimmed)
179+
real(r8) :: bfr_per_bleaf ! ratio of fine root per leaf biomass
180+
real(r8) :: sla_levleaf ! sla at leaf level z
181+
real(r8) :: nscaler_levleaf ! nscaler value at leaf level z
182+
integer :: cl ! canopy layer index
183+
real(r8) :: kn ! nitrogen decay coefficient
184+
real(r8) :: sla_max ! Observational constraint on how large sla (m2/gC) can become
185+
186+
real(r8) :: leaf_inc ! LAI-only portion of the vegetation increment of dinc_ed
187+
real(r8) :: lai_canopy_above ! the LAI in the canopy layers above the layer of interest
188+
real(r8) :: lai_layers_above ! the LAI in the leaf layers, within the current canopy,
189+
! above the leaf layer of interest
190+
real(r8) :: lai_current ! the LAI in the current leaf layer
191+
real(r8) :: cumulative_lai ! the cumulative LAI, top down, to the leaf layer of interest
180192

181193
!----------------------------------------------------------------------
182194

183195
currentPatch => currentSite%youngest_patch
184-
185196
do while(associated(currentPatch))
197+
186198
currentCohort => currentPatch%tallest
187199
do while (associated(currentCohort))
188-
trimmed = 0
200+
201+
trimmed = .false.
189202
ipft = currentCohort%pft
190203
call carea_allom(currentCohort%dbh,currentCohort%n,currentSite%spread,currentCohort%pft,currentCohort%c_area)
191-
currentCohort%treelai = tree_lai(currentCohort%bl, currentCohort%status_coh, currentCohort%pft, &
192-
currentCohort%c_area, currentCohort%n )
193-
currentCohort%treesai = tree_sai(currentCohort%dbh, currentCohort%pft, currentCohort%canopy_trim, &
194-
currentCohort%c_area, currentCohort%n)
195-
currentCohort%nv = ceiling((currentCohort%treelai+currentCohort%treesai)/dinc_ed)
204+
currentCohort%treelai = tree_lai(currentCohort%bl, currentCohort%pft, currentCohort%c_area, &
205+
currentCohort%n, currentCohort%canopy_layer, &
206+
currentPatch%canopy_layer_tlai )
207+
208+
currentCohort%treesai = tree_sai(currentCohort%pft, currentCohort%dbh, currentCohort%canopy_trim, &
209+
currentCohort%c_area, currentCohort%n, currentCohort%canopy_layer, &
210+
currentPatch%canopy_layer_tlai, currentCohort%treelai )
211+
212+
currentCohort%nv = ceiling((currentCohort%treelai+currentCohort%treesai)/dinc_ed)
213+
196214
if (currentCohort%nv > nlevleaf)then
197-
write(fates_log(),*) 'nv > nlevleaf',currentCohort%nv,currentCohort%treelai,currentCohort%treesai, &
198-
currentCohort%c_area,currentCohort%n,currentCohort%bl
215+
write(fates_log(),*) 'nv > nlevleaf',currentCohort%nv, &
216+
currentCohort%treelai,currentCohort%treesai, &
217+
currentCohort%c_area,currentCohort%n,currentCohort%bl
218+
call endrun(msg=errMsg(sourcefile, __LINE__))
199219
endif
200220

201221
call bleaf(currentcohort%dbh,ipft,currentcohort%canopy_trim,tar_bl)
@@ -206,35 +226,68 @@ subroutine trim_canopy( currentSite )
206226
bfr_per_bleaf = tar_bfr/tar_bl
207227
endif
208228

229+
! Identify current canopy layer (cl)
230+
cl = currentCohort%canopy_layer
231+
232+
! PFT-level maximum SLA value, even if under a thick canopy (same units as slatop)
233+
sla_max = EDPftvarcon_inst%slamax(ipft)
234+
209235
!Leaf cost vs netuptake for each leaf layer.
210-
do z = 1,nlevleaf
211-
if (currentCohort%year_net_uptake(z) /= 999._r8)then !there was activity this year in this leaf layer.
236+
do z = 1, currentCohort%nv
237+
238+
! Calculate the cumulative total vegetation area index (no snow occlusion, stems and leaves)
239+
240+
leaf_inc = dinc_ed * &
241+
currentCohort%treelai/(currentCohort%treelai+currentCohort%treesai)
242+
243+
! Now calculate the cumulative top-down lai of the current layer's midpoint
244+
lai_canopy_above = sum(currentPatch%canopy_layer_tlai(1:cl-1))
245+
lai_layers_above = leaf_inc * (z-1)
246+
lai_current = min(leaf_inc, currentCohort%treelai - lai_layers_above)
247+
cumulative_lai = lai_canopy_above + lai_layers_above + 0.5*lai_current
248+
249+
if (currentCohort%year_net_uptake(z) /= 999._r8)then !there was activity this year in this leaf layer.
250+
251+
252+
! Calculate sla_levleaf following the sla profile with overlying leaf area
253+
! Scale for leaf nitrogen profile
254+
kn = decay_coeff_kn(ipft)
255+
! Nscaler value at leaf level z
256+
nscaler_levleaf = exp(-kn * cumulative_lai)
257+
! Sla value at leaf level z after nitrogen profile scaling (m2/gC)
258+
sla_levleaf = EDPftvarcon_inst%slatop(ipft)/nscaler_levleaf
259+
260+
if(sla_levleaf > sla_max)then
261+
sla_levleaf = sla_max
262+
end if
263+
212264
!Leaf Cost kgC/m2/year-1
213265
!decidous costs.
214266
if (EDPftvarcon_inst%season_decid(ipft) == 1.or. &
215267
EDPftvarcon_inst%stress_decid(ipft) == 1)then
216268

217-
218-
currentCohort%leaf_cost = 1._r8/(EDPftvarcon_inst%slatop(ipft)*1000.0_r8)
269+
! Leaf cost at leaf level z accounting for sla profile (kgC/m2)
270+
currentCohort%leaf_cost = 1._r8/(sla_levleaf*1000.0_r8)
219271

220272
if ( int(EDPftvarcon_inst%allom_fmode(ipft)) .eq. 1 ) then
221273
! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment
222274
! to the leaf increment; otherwise do not.
223275
currentCohort%leaf_cost = currentCohort%leaf_cost + &
224-
1.0_r8/(EDPftvarcon_inst%slatop(ipft)*1000.0_r8) * &
276+
1.0_r8/(sla_levleaf*1000.0_r8) * &
225277
bfr_per_bleaf / EDPftvarcon_inst%root_long(ipft)
226278
endif
227279

228280
currentCohort%leaf_cost = currentCohort%leaf_cost * &
229281
(EDPftvarcon_inst%grperc(ipft) + 1._r8)
230282
else !evergreen costs
231-
currentCohort%leaf_cost = 1.0_r8/(EDPftvarcon_inst%slatop(ipft)* &
283+
! Leaf cost at leaf level z accounting for sla profile
284+
currentCohort%leaf_cost = 1.0_r8/(sla_levleaf* &
232285
EDPftvarcon_inst%leaf_long(ipft)*1000.0_r8) !convert from sla in m2g-1 to m2kg-1
233286
if ( int(EDPftvarcon_inst%allom_fmode(ipft)) .eq. 1 ) then
234287
! if using trimmed leaf for fine root biomass allometry, add the cost of the root increment
235288
! to the leaf increment; otherwise do not.
236289
currentCohort%leaf_cost = currentCohort%leaf_cost + &
237-
1.0_r8/(EDPftvarcon_inst%slatop(ipft)*1000.0_r8) * &
290+
1.0_r8/(sla_levleaf*1000.0_r8) * &
238291
bfr_per_bleaf / EDPftvarcon_inst%root_long(ipft)
239292
endif
240293
currentCohort%leaf_cost = currentCohort%leaf_cost * &
@@ -256,15 +309,15 @@ subroutine trim_canopy( currentSite )
256309
currentCohort%laimemory = currentCohort%laimemory * &
257310
(1.0_r8 - EDPftvarcon_inst%trim_inc(ipft))
258311
endif
259-
trimmed = 1
312+
trimmed = .true.
260313
endif
261314
endif
262315
endif
263316
endif !leaf activity?
264317
enddo !z
265318

266319
currentCohort%year_net_uptake(:) = 999.0_r8
267-
if (trimmed == 0.and.currentCohort%canopy_trim < 1.0_r8)then
320+
if ( (.not.trimmed) .and.currentCohort%canopy_trim < 1.0_r8)then
268321
currentCohort%canopy_trim = currentCohort%canopy_trim + EDPftvarcon_inst%trim_inc(ipft)
269322
endif
270323

@@ -2416,4 +2469,9 @@ subroutine flux_into_litter_pools(nsites, sites, bc_in, bc_out)
24162469

24172470
end subroutine flux_into_litter_pools
24182471

2472+
! ===================================================================================
2473+
2474+
2475+
2476+
24192477
end module EDPhysiologyMod

0 commit comments

Comments
 (0)