Skip to content

Commit 9cfdf01

Browse files
Merge branch 'evasinha/lnd/add_sugarcane_based_on_ECOSMOS' (PR #7681)
This feature adds new parameterizations to represent the sugarcane crop in ELM. The implementation is based on sugarcane implementation in the Agricultural version of the Integrated Biosphere Simulator (Agro-IBIS) model (Cuadra et al., 2012 and Colmanetti et al., 2024). It is important to note that sugarcane is modeled as a perennial crop, and this requires modifying the crop and percrop parameters in the parameter file, along with accompanying changes in ELM. The model was calibrated using the methodology used in Sinha et al. 2022. [non BFB] for Crops since the parameter file is updated.
2 parents 31de276 + b4b19c9 commit 9cfdf01

File tree

10 files changed

+180
-42
lines changed

10 files changed

+180
-42
lines changed

components/elm/bld/namelist_files/namelist_defaults.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case).
123123
for the CLM2 data in the CESM distribution -->
124124
<!-- Plant function types (relative to {csmdata}) -->
125125
<paramfile use_cn=".false." use_fates=".false." >lnd/clm2/paramdata/clm_params_c180301.nc</paramfile>
126-
<paramfile use_crop=".true." >lnd/clm2/paramdata/clm_params_c220224.nc</paramfile>
126+
<paramfile use_crop=".true." >lnd/clm2/paramdata/clm_params_c251006.nc</paramfile>
127127
<paramfile nu_com="ECA" use_fates=".true." use_crop=".false." >lnd/clm2/paramdata/clm_params.cbgc.c07292018.nc</paramfile>
128128
<paramfile nu_com="ECA" use_cn=".true." use_crop=".false." >lnd/clm2/paramdata/clm_params.cbgc.c07292018.nc</paramfile>
129129
<paramfile use_crop=".false." use_cn=".true." >lnd/clm2/paramdata/clm_params_c211124.nc</paramfile>

components/elm/src/biogeochem/AllocationMod.F90

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ module AllocationMod
108108
real(r8) :: dayscrecover !number of days to recover negative cpool
109109
real(r8), allocatable :: arepr(:) !reproduction allocation coefficient
110110
real(r8), allocatable :: aroot(:) !root allocation coefficient
111+
real(r8), allocatable :: aerial(:) !aboveground allocation coefficient
111112

112113
!$acc declare create(bdnr )
113114
!$acc declare create(dayscrecover )
@@ -247,6 +248,7 @@ subroutine AllocationInit ( bounds, elm_fates)
247248
if ( crop_prog )then
248249
allocate(arepr(bounds%begp:bounds%endp)); arepr(bounds%begp : bounds%endp) = nan
249250
allocate(aroot(bounds%begp:bounds%endp)); aroot(bounds%begp : bounds%endp) = nan
251+
allocate(aerial(bounds%begp:bounds%endp)); aerial(bounds%begp : bounds%endp) = nan
250252
end if
251253

252254
! Allocate scratch space for ECA and FATES/ECA
@@ -476,7 +478,7 @@ subroutine TotalNPDemand(num_soilp,filter_soilp, photosyns_vars, &
476478
canopystate_vars, crop_vars, cnstate_vars, dt)
477479
!! Assess the total plant N demand and P demand
478480
use pftvarcon , only: npcropmin, declfact, bfact, aleaff, arootf, astemf, noveg
479-
use pftvarcon , only: iscft, percrop, nwcereal, nwcerealirrig
481+
use pftvarcon , only: iscft, percrop, nwcereal, nwcerealirrig, nsugarcane, nsugarcaneirrig
480482
use pftvarcon , only: arooti, fleafi, allconsl, allconss, grperc, grpnow, nsoybean
481483
use elm_varpar , only: nlevdecomp
482484
use elm_varcon , only: nitrif_n2o_loss_frac, secspday
@@ -504,7 +506,21 @@ subroutine TotalNPDemand(num_soilp,filter_soilp, photosyns_vars, &
504506
integer, parameter :: cphase_gf = 3 !Crop phenology phase grain fill
505507
integer, parameter :: max_lai = 1 !Maximum allowed lai
506508
integer :: ivt, fp, p
507-
!-----------------------------------------------------------------------
509+
510+
! LOCAL VARAIBLES for sugarcane allocation based on Colmanetti et al., 2024 10.1016/j.eja.2023.127061
511+
real(r8), parameter :: rootd = 0.3_r8 ! root decline parameter
512+
real(r8), parameter :: sf1 = 0.02_r8 ! parameters for linear carbon allocation to the stalk
513+
real(r8), parameter :: ipf1 = 1.0_r8 ! parameters for linear carbon allocation to the stalk
514+
real(r8), parameter :: ecf2 = 0.065_r8 ! parameters for logarithmic carbon allocation to the stalk
515+
real(r8), parameter :: ipf2 = 10.0_r8 ! parameters for logarithmic carbon allocation to the stalk
516+
real(r8), parameter :: sf3 = 0.006_r8 ! parameters for linear carbon allocation to the stalk-sucrose
517+
real(r8), parameter :: ipf3 = 5.0_r8 ! parameters for linear carbon allocation to the stalk-sucrose
518+
real(r8), parameter :: ecf4 = 0.017_r8 ! parameters for logarithmic carbon allocation to the stalk-sucrose
519+
real(r8), parameter :: ipf4 = 10.0_r8 ! parameters for logarithmic carbon allocation to the stalk-sucrose
520+
real(r8) :: rmat, af1, af2, af3, af4, sipf3, sipf4
521+
522+
!-----------------------------------------------------------------------
523+
508524
associate( &
509525
woody => veg_vp%woody , & ! Input: [real(r8) (:) ] woody lifeform flag (0 = non-woody, 1 = tree, 2 = shrub)
510526
froot_leaf => veg_vp%froot_leaf , & ! Input: [real(r8) (:) ] allocation parameter: new fine root C per new leaf C (gC/gC)
@@ -548,6 +564,8 @@ subroutine TotalNPDemand(num_soilp,filter_soilp, photosyns_vars, &
548564
huileaf => cnstate_vars%huileaf_patch , & ! Input: [real(r8) (:) ] heat unit index needed from planting to leaf emergence
549565
huigrain => cnstate_vars%huigrain_patch , & ! Input: [real(r8) (:) ] same to reach vegetative maturity
550566
croplive => crop_vars%croplive_patch , & ! Input: [logical (:) ] flag, true if planted, not harvested
567+
nyrs_crop_active => crop_vars%nyrs_crop_active_patch , & ! Input: [integer (:) ] number of years this crop patch has been active
568+
onset_gdd => cnstate_vars%onset_gdd_patch , & ! Output: [real(r8) (:) ] onset growing degree days
551569
peaklai => cnstate_vars%peaklai_patch , & ! Input: [integer (:) ] 1: max allowed lai; 0: not at max
552570
!lgsf => cnstate_vars%lgsf_patch , & ! Input: [real(r8) (:) ] long growing season factor [0-1]
553571
aleafi => cnstate_vars%aleafi_patch , & ! Output: [real(r8) (:) ] saved allocation coefficient from phase 2
@@ -879,15 +897,60 @@ subroutine TotalNPDemand(num_soilp,filter_soilp, photosyns_vars, &
879897
g1 = 0.25_r8
880898

881899
else if (croplive(p) .and. percrop(ivt) == 1.0_r8) then
882-
arepr(p) = 0._r8
883-
aroot(p) = max(0._r8, min(1._r8, arooti(ivt) - &
884-
(arooti(ivt) - arootf(ivt)) * &
885-
min(1._r8, hui(p)/gddmaturity(p))))
886-
fleaf = fleafi(ivt) * (exp(-bfact(ivt)) - &
887-
exp(-bfact(ivt)*hui(p)/gddmaturity(p))) / & ! replacing huigrain with gddmaturity since huigrain does not exist for perennial crops
888-
(exp(-bfact(ivt))-1) ! fraction alloc to leaf (from J Norman alloc curve)
889-
aleaf(p) = max(1.e-5_r8, (1._r8 - aroot(p)) * fleaf)
890-
astem(p) = 1._r8 - arepr(p) - aleaf(p) - aroot(p)
900+
if (ivt==nsugarcane .or. ivt==nsugarcaneirrig) then
901+
902+
rmat = 100.0_r8 * (onset_gdd(p)/gddmaturity(p))
903+
904+
! Aerial(p) ranges from 0 to 1 and is the allocation
905+
! coefficient for aboveground carbon components, including
906+
! stems and leaves
907+
908+
! Aboveground sugarcane plant growth decreases by 0.6 in the
909+
! year when sugarcane is planted and by 1 in the following years
910+
if (nyrs_crop_active(p) == 0) then ! Year 1
911+
aerial(p) = (1.0_r8 - arootf(ivt)) * min(1.0_r8, (1 - exp(-(rootd * 0.6 * rmat))))
912+
else
913+
aerial(p) = (1.0_r8 - arootf(ivt)) * min(1.0_r8, (1 - exp(-(rootd * rmat))))
914+
end if
915+
916+
aroot(p) = 1.0_r8 - aerial(p)
917+
918+
! Carbon allocation to stems is nearly linear at the start of
919+
! the sugarcane growth cycle and then follows a logarithmic
920+
! pattern until the cycle's end
921+
! af1 - fraction of the aboveground carbon initially allocated to the stem
922+
! af2 - fraction of the aboveground carbon allocated to the
923+
! stem over most of the plant's lifespan
924+
af1 = max(0._r8, (rmat * sf1) - (ipf1 * sf1))
925+
af2 = max(0._r8, (1.0_r8 - exp(-((rmat * ecf2) - (ipf2 * ecf2)))) )
926+
927+
! Allocation coeff for aboveground carbon is split between stem and leaves
928+
astem(p) = min( (1.0_r8 - aleaff(ivt) - arootf(ivt)), (aerial(p) * max(af1, af2)) )
929+
aleaf(p) = max(1.e-5_r8, (aerial(p) - astem(p)))
930+
931+
932+
sipf3 = ipf1 + (100.0_r8 - ipf1) * (ipf3 / 100.0_r8)
933+
sipf4 = ipf2 + (100.0_r8 - ipf2) * (ipf4 / 100.0_r8)
934+
935+
af3 = max(0._r8, (rmat * sf3) - (sipf3 * sf3))
936+
af4 = max(0._r8, (1.0_r8 - exp(-((rmat * ecf4) - (sipf4 * ecf4)))) )
937+
938+
! Carbon allocated to the stem is then divided between
939+
! stem sucrose or reporductive part and stem structural components
940+
arepr(p) = astem(p) * max(0._r8, af3, af4)
941+
astem(p) = astem(p) - arepr(p)
942+
943+
else ! if perennial but not sugarcane
944+
arepr(p) = 0._r8
945+
aroot(p) = max(0._r8, min(1._r8, arooti(ivt) - &
946+
(arooti(ivt) - arootf(ivt)) * &
947+
min(1._r8, hui(p)/gddmaturity(p))))
948+
fleaf = fleafi(ivt) * (exp(-bfact(ivt)) - &
949+
exp(-bfact(ivt)*hui(p)/gddmaturity(p))) / & ! replacing huigrain with gddmaturity since huigrain does not exist for perennial crops
950+
(exp(-bfact(ivt))-1) ! fraction alloc to leaf (from J Norman alloc curve)
951+
aleaf(p) = max(1.e-5_r8, (1._r8 - aroot(p)) * fleaf)
952+
astem(p) = 1._r8 - arepr(p) - aleaf(p) - aroot(p)
953+
end if
891954

892955
f1 = aroot(p) / aleaf(p)
893956
f3 = astem(p) / aleaf(p)

components/elm/src/biogeochem/CNEcosystemDynBetrMod.F90

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ module CNEcosystemDynBetrMod
5959
!-----------------------------------------------------------------------
6060
subroutine CNEcosystemDynBetr(bounds, &
6161
num_soilc, filter_soilc, &
62-
num_soilp, filter_soilp, num_pcropp, filter_pcropp, doalb, &
62+
num_soilp, filter_soilp, num_pcropp, filter_pcropp, &
63+
num_ppercropp, filter_ppercropp, doalb, &
6364
cnstate_vars, carbonflux_vars, carbonstate_vars, &
6465
c13_carbonflux_vars, c13_carbonstate_vars, &
6566
c14_carbonflux_vars, c14_carbonstate_vars, &
@@ -118,6 +119,8 @@ subroutine CNEcosystemDynBetr(bounds, &
118119
integer , intent(in) :: filter_soilp(:) ! filter for soil patches
119120
integer , intent(in) :: num_pcropp ! number of prog. crop patches in filter
120121
integer , intent(in) :: filter_pcropp(:) ! filter for prognostic crop patches
122+
integer , intent(in) :: num_ppercropp ! number of prog perennial crop patches in filter
123+
integer , intent(in) :: filter_ppercropp(:) ! filter for prognostic perennial crop patches
121124
logical , intent(in) :: doalb ! true = surface albedo calculation time step
122125
type(cnstate_type) , intent(inout) :: cnstate_vars
123126
type(carbonflux_type) , intent(inout) :: carbonflux_vars
@@ -189,7 +192,8 @@ subroutine CNEcosystemDynBetr(bounds, &
189192

190193
call t_startf('MaintenanceResp')
191194
if (crop_prog) then
192-
call NitrogenFert(bounds, num_soilc,filter_soilc, num_pcropp, filter_pcropp )
195+
call NitrogenFert(bounds, num_soilc,filter_soilc, num_pcropp, filter_pcropp, &
196+
num_ppercropp, filter_ppercropp )
193197

194198
end if
195199
call MaintenanceResp(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, &

components/elm/src/biogeochem/CropType.F90

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ subroutine UpdateAccVars(this, bounds, temperature_vars)
727727
end subroutine UpdateAccVars
728728

729729
!-----------------------------------------------------------------------
730-
subroutine CropIncrementYear (this, num_pcropp, filter_pcropp)
730+
subroutine CropIncrementYear (this, num_pcropp, filter_pcropp, num_ppercropp, filter_ppercropp)
731731
!
732732
! !DESCRIPTION:
733733
! Increment the crop year, if appropriate
@@ -741,6 +741,8 @@ subroutine CropIncrementYear (this, num_pcropp, filter_pcropp)
741741
class(crop_type) :: this
742742
integer , intent(in) :: num_pcropp ! number of prog. crop patches in filter
743743
integer , intent(in) :: filter_pcropp(:) ! filter for prognostic crop patches
744+
integer , intent(in) :: num_ppercropp ! number of prog perennial crop patches in filter
745+
integer , intent(in) :: filter_ppercropp(:) ! filter for prognostic perennial crop patches
744746
!
745747
! !LOCAL VARIABLES:
746748
integer kyr ! current year
@@ -762,6 +764,12 @@ subroutine CropIncrementYear (this, num_pcropp, filter_pcropp)
762764

763765
this%nyrs_crop_active_patch(p) = this%nyrs_crop_active_patch(p) + 1
764766
end do
767+
768+
do fp = 1, num_ppercropp
769+
p = filter_ppercropp(fp)
770+
771+
this%nyrs_crop_active_patch(p) = this%nyrs_crop_active_patch(p) + 1
772+
end do
765773
end if
766774

767775
end subroutine CropIncrementYear

components/elm/src/biogeochem/EcosystemDynMod.F90

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ subroutine EcosystemDynNoLeaching1(bounds, &
287287
num_soilc, filter_soilc, &
288288
num_soilp, filter_soilp, &
289289
num_pcropp, filter_pcropp, &
290+
num_ppercropp, filter_ppercropp, &
290291
cnstate_vars, atm2lnd_vars, &
291292
canopystate_vars, soilstate_vars, crop_vars, &
292293
ch4_vars, photosyns_vars, &
@@ -328,6 +329,8 @@ subroutine EcosystemDynNoLeaching1(bounds, &
328329
integer , intent(in) :: filter_soilp(:) ! filter for soil patches
329330
integer , intent(in) :: num_pcropp ! number of prog. crop patches in filter
330331
integer , intent(in) :: filter_pcropp(:) ! filter for prognostic crop patches
332+
integer , intent(in) :: num_ppercropp ! number of prog perennial crop patches in filter
333+
integer , intent(in) :: filter_ppercropp(:) ! filter for prognostic perennial crop patches
331334
type(cnstate_type) , intent(inout) :: cnstate_vars
332335
type(atm2lnd_type) , intent(in) :: atm2lnd_vars
333336
type(canopystate_type) , intent(in) :: canopystate_vars
@@ -405,7 +408,8 @@ subroutine EcosystemDynNoLeaching1(bounds, &
405408
event = 'MaintenanceResp'
406409
call t_start_lnd(event)
407410
if (crop_prog) then
408-
call NitrogenFert(bounds, num_soilc,filter_soilc, num_pcropp, filter_pcropp )
411+
call NitrogenFert(bounds, num_soilc,filter_soilc, num_pcropp, filter_pcropp, &
412+
num_ppercropp, filter_ppercropp)
409413
call PhosphorusFert(bounds, num_soilc, filter_soilc )
410414

411415
call CNSoyfix(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, &

components/elm/src/biogeochem/NitrogenDynamicsMod.F90

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,8 @@ subroutine NitrogenLeaching(num_soilc, filter_soilc, dt )
387387
end subroutine NitrogenLeaching
388388

389389
!-----------------------------------------------------------------------
390-
subroutine NitrogenFert(bounds, num_soilc, filter_soilc, num_pcropp, filter_pcropp)
390+
subroutine NitrogenFert(bounds, num_soilc, filter_soilc, &
391+
num_pcropp, filter_pcropp, num_ppercropp, filter_ppercropp)
391392
!
392393
! !DESCRIPTION:
393394
! On the radiation time step, update the nitrogen fertilizer for crops
@@ -403,6 +404,8 @@ subroutine NitrogenFert(bounds, num_soilc, filter_soilc, num_pcropp, filter_pcro
403404
integer , intent(in) :: filter_soilc(:) ! filter for soil columns
404405
integer , intent(in) :: num_pcropp ! number of prog. crop patches in filter
405406
integer , intent(in) :: filter_pcropp(:) ! filter for prognostic crop patches
407+
integer , intent(in) :: num_ppercropp ! number of prog perennial crop patches in filter
408+
integer , intent(in) :: filter_ppercropp(:) ! filter for prognostic perennial crop patches
406409
!
407410
! !LOCAL VARIABLES:
408411
integer :: c,fc,p,fp ! indices
@@ -444,6 +447,10 @@ subroutine NitrogenFert(bounds, num_soilc, filter_soilc, num_pcropp, filter_pcro
444447
p = filter_pcropp(fp)
445448
totalfert(p) = synthfert(p) + manure(p)
446449
end do
450+
do fp = 1, num_ppercropp
451+
p = filter_ppercropp(fp)
452+
totalfert(p) = synthfert(p) + manure(p)
453+
end do
447454
end if
448455

449456
! if fan_to_bgc_crop == .true., FAN fills in the fert_to_sminn and totalfert for

0 commit comments

Comments
 (0)