Skip to content

Commit

Permalink
Refactoring: move cohort type to its own file. Functionalize in prepa…
Browse files Browse the repository at this point in the history
…ration for OOP
  • Loading branch information
marcadella committed Jan 9, 2025
1 parent 08591f8 commit a03df9f
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 328 deletions.
5 changes: 3 additions & 2 deletions src/Makevars
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ FT_OBJS = params_core.mod.o sofunutils.mod.o grid_siterun.mod.o params_siml_pmod
forcing_siterun_pmodel.mod.o forcing_siterun_biomee.mod.o interface_biosphere_pmodel.mod.o interface_biosphere_biomee.mod.o \
tile_pmodel.mod.o plant_pmodel.mod.o soiltemp_sitch.mod.o waterbal_splash.mod.o vegdynamics_pmodel.mod.o gpp_pmodel.mod.o \
gpp_biomee.mod.o photosynth_pmodel.mod.o biosphere_pmodel.mod.o biosphere_biomee.mod.o vegetation_biomee.mod.o soil_biomee.mod.o \
datatypes_biomee.mod.o luluc.mod.o pmodel.mod.o biomee.mod.o
datatypes_biomee.mod.o luluc.mod.o cohort_biomee.mod.o pmodel.mod.o biomee.mod.o

all: $(SHLIB)

Expand Down Expand Up @@ -36,7 +36,8 @@ biosphere_biomee.mod.o: interface_biosphere_biomee.mod.o datatypes_biomee.mod.o
soiltemp_sitch.mod.o sofunutils.mod.o
soil_biomee.mod.o: datatypes_biomee.mod.o sofunutils.mod.o
vegetation_biomee.mod.o: datatypes_biomee.mod.o soil_biomee.mod.o gpp_biomee.mod.o
datatypes_biomee.mod.o: interface_biosphere_biomee.mod.o params_core.mod.o classdefs.mod.o
datatypes_biomee.mod.o: interface_biosphere_biomee.mod.o params_core.mod.o classdefs.mod.o cohort_biomee.mod.o
cohort_biomee.mod.o: interface_biosphere_biomee.mod.o params_core.mod.o classdefs.mod.o
sofunutils.mod.o: params_core.mod.o
params_siml_biomee.mod.o: params_core.mod.o
params_siml_pmodel.mod.o: params_core.mod.o
Expand Down
111 changes: 29 additions & 82 deletions src/classdefs.mod.f90
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ module md_classdefs
implicit none

private
public carbon, nitrogen, orgpool, orgcp, orgcpRec, orgsub, orgmv, &

! Public types
public carbon, nitrogen, orgpool, common_fluxes

! Public functions
public orgcp, orgcpRec, orgsub, orgmv, &
orgmvRec, orginit, cmv, cmvRec, ccp, ccpRec, csub, cinit, nmv, &
nmvRec, ncp, ncpRec, nsub, ninit, orgfrac, cfrac, nfrac, orgplus, &
cplus, nplus, orgminus, cminus, nminus, cton, ntoc
cplus, nplus, orgminus, cminus, nminus, cton, ntoc, update_fluxes

! ! Minimum precision
! real, parameter :: epsilon = 1.0e-5

! additional checks
logical, parameter :: check_sanity = .false.

! Carbon, so far contains only c12 (to be extended for c13)
type carbon
Expand All @@ -39,10 +42,32 @@ module md_classdefs
type(nitrogen) :: n
end type orgpool

type :: common_fluxes
! Note: the unit depends on the context
real :: Trsp = 0.0
real :: GPP = 0.0
real :: NPP = 0.0
real :: Resp = 0.0
real :: Nup = 0.0
real :: fixedN = 0.0
end type common_fluxes

contains
!=========================LOW-LEVEL================================

subroutine update_fluxes(fluxes, delta)
! Add delta quantities to partial fluxes (accounting)
type(common_fluxes), intent(inout) :: fluxes
type(common_fluxes), intent(in) :: delta

fluxes%Trsp = fluxes%Trsp + delta%Trsp
fluxes%GPP = fluxes%GPP + delta%GPP
fluxes%NPP = fluxes%NPP + delta%NPP
fluxes%Resp = fluxes%Resp + delta%Resp
fluxes%Nup = fluxes%Nup + delta%Nup
fluxes%fixedN = fluxes%fixedN + delta%fixedN

end subroutine update_fluxes

!--------------------------ORGANIC---------------------------------

Expand All @@ -54,7 +79,6 @@ subroutine orgcp( amount, to, scale )
type(orgpool), intent(in) :: amount
type(orgpool), intent(inout) :: to
real, optional, intent(in) :: scale
!real, optional, intent(in) :: d13C

if ( present( scale ) ) then
call ccp( amount%c,to%c, scale )
Expand All @@ -64,14 +88,6 @@ subroutine orgcp( amount, to, scale )
call ncp( amount%n,to%n )
end if

! if (present(d13C)) then
! to%c%c12 = amount%c%c12 + to%c%c12
! to%n%n14 = amount%n%n14 + to%n%n14
! else
! to%c%c12 = amount%c%c12 + to%c%c12
! to%n%n14 = amount%n%n14 + to%n%n14
! end if

end subroutine orgcp


Expand Down Expand Up @@ -104,22 +120,6 @@ subroutine orgsub( amount, from )
type(orgpool), intent(in) :: amount
type(orgpool), intent(inout) :: from

! print*, 'ORGSUB'
! print*,'amount ', amount
! print*,'from ', from

! if (check_sanity) then
! if ( amount%c%c12>from%c%c12+epsilon) then
! stop 'in ORGSUB: attempting to remove C amount > from-pool'
! else if ( amount%n%n14>from%n%n14+epsilon) then
! stop 'in ORGSUB: attempting to remove N amount > from-pool'
! else if (from%c%c12<0.0) then
! stop 'in ORGSUB: C in from-pool negative'
! else if (from%n%n14<0.0) then
! stop 'in ORGSUB: N in from-pool negative'
! end if
! end if

call csub( amount%c,from%c)
call nsub( amount%n,from%n)

Expand Down Expand Up @@ -250,22 +250,13 @@ subroutine ccp( amount, to, scale )
type(carbon), intent(in) :: amount
type(carbon), intent(inout) :: to
real, optional, intent(in) :: scale
!real, optional, intent(in) :: d13C

if ( present( scale ) ) then
to%c12 = to%c12 + amount%c12 * scale
else
to%c12 = to%c12 + amount%c12
end if

! if (present(d13C)) then
! to%c%c12 = amount%c%c12 + to%c%c12
! to%n%n14 = amount%n%n14 + to%n%n14
! else
! to%c%c12 = amount%c%c12 + to%c%c12
! to%n%n14 = amount%n%n14 + to%n%n14
! end if

end subroutine ccp


Expand All @@ -277,19 +268,10 @@ subroutine ccpRec( amount, to, outc)
type(carbon), intent(in) :: amount
type(carbon), intent(inout) :: to
real, intent(inout) :: outc
! real, optional, intent(in) :: d13C

to%c12 = amount%c12 + to%c12
outc = outc + amount%c12

! if (present(d13C)) then
! to%c%c12 = amount%c%c12 + to%c%c12
! to%n%n14 = amount%n%n14 + to%n%n14
! else
! to%c%c12 = amount%c%c12 + to%c%c12
! to%n%n14 = amount%n%n14 + to%n%n14
! end if

end subroutine ccpRec


Expand All @@ -300,16 +282,6 @@ subroutine csub( amount, from )
!----------------------------------------------------------------
type(carbon), intent(in) :: amount
type(carbon), intent(inout) :: from


!if (check_sanity) then
! if ( amount%c12 > from%c12+epsilon) then
! write(0,*) 'amount', amount%c12
! write(0,*) 'from ', from%c12
! write(0,*) 'in CSUB: attempting to remove amount > from-pool'
! stop
! end if
!end if

from%c12 = from%c12 - amount%c12

Expand Down Expand Up @@ -418,13 +390,6 @@ subroutine nsub( amount, from )
!----------------------------------------------------------------
type(nitrogen), intent(in) :: amount
type(nitrogen), intent(inout) :: from


! if (check_sanity) then
! if ( amount%n14>from%n14+epsilon) then
! stop 'in NSUB: attempting to remove amount > from-pool'
! end if
! end if

from%n14 = from%n14 - amount%n14

Expand Down Expand Up @@ -734,15 +699,6 @@ function cton( pool, default ) result( out_cton )
out_cton = pool%c%c12 / pool%n%n14
end if
else

! if (check_sanity) then
! if (pool%n%n14==0.) then
! stop 'in CTON: N is zero'
! end if
! if (pool%n%n14<0.0 .or. pool%c%c12<0.0) then
! stop 'in CTON: C and/or N is negative'
! end if
! end if

out_cton = pool%c%c12 / pool%n%n14

Expand Down Expand Up @@ -770,15 +726,6 @@ function ntoc( pool, default ) result( out_ntoc )
out_ntoc = pool%n%n14 / pool%c%c12
end if
else

! if (check_sanity) then
! if (pool%c%c12==0.) then
! stop 'in NTOC: C is zero'
! end if
! if (pool%n%n14<0.0 .or. pool%c%c12<0.0) then
! stop 'in NTOC: C and/or N is negative'
! end if
! end if

out_ntoc = pool%n%n14 / pool%c%c12

Expand Down
160 changes: 160 additions & 0 deletions src/cohort_biomee.mod.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
module md_cohort
!////////////////////////////////////////////////////////////////
! Module containing BiomeE state variable and parameter
! definitions.
! Code adopted from BiomeE https://doi.org/10.5281/zenodo.7125963.
!----------------------------------------------------------------
use md_interface_biomee, only: myinterface, spec_data_type, MAX_LEVELS
use md_params_core, only: pi
use md_classdefs

! define data types and constants
implicit none
!=============== Public types ===========================================================
public :: cohort_type

!=============== Public subroutines =====================================================
public :: rootarea, W_supply, NSNmax

integer, public, parameter :: LEAF_OFF = 0
integer, public, parameter :: LEAF_ON = 1
integer, public, parameter :: PT_C3 = 0 ! physiology types
integer, public, parameter :: PT_C4 = 1 ! physiology types

!=============== Cohort level data type =============================================================
type :: cohort_type

!===== Metadata
integer :: ccID = -1 ! cohort ID
integer :: layer = 1 ! the layer of this cohort (numbered from top, top layer=1)
real :: layerfrac = 0.0 ! fraction of layer area occupied by this cohort
integer :: firstlayer = 0 ! 0 = never been in the first layer; 1 = at least one year in first layer

!===== Population structure
real :: nindivs = 1.0 ! density of vegetation, tree/m2
real :: age = 0.0 ! age of cohort, years
real :: topyear = 0.0 ! the years that a cohort is in top layer
real :: dbh = 0.0 ! diameter at breast height, m
real :: height = 0.0 ! vegetation height, m
real :: crownarea = 1.0 ! crown area, m2 tree-1
real :: leafarea = 0.0 ! total area of leaves, m2 tree-1

!===== Biological prognostic variables
integer :: species = 1 ! vegetation species
real :: gdd = 0.0 ! growing degree-day (phenology)
integer :: status = LEAF_OFF ! growth status of plant
real :: leaf_age = 0.0 ! leaf age (years)

!===== Organic pools
type(orgpool) :: pleaf ! leaf biomass, kg tree-1
type(orgpool) :: proot ! root biomass, kg tree-1
type(orgpool) :: psapw ! sapwood biomass, kg tree-1
type(orgpool) :: pwood ! heartwood (non-living) biomass, kg tree-1
type(orgpool) :: pseed ! biomass put aside for future progeny, kg tree-1
type(orgpool) :: plabl ! labile pool, temporary storage of N and C, kg tree-1

!===== Fast step fluxes, kg timestep-1 tree-1
type(common_fluxes) :: fast_fluxes

real :: resl = 0.0 ! leaf respiration, kg C timestep-1 tree-1
real :: resr = 0.0 ! root respiration, kg C timestep-1 tree-1

!===== Daily fluxes, kg day-1 tree-1
type(common_fluxes) :: daily_fluxes

!===== Annual fluxes, kg yr-1 tree-1
type(common_fluxes) :: annual_fluxes
real :: NPPleaf = 0.0 ! C allocated to leaf, kg C yr-1 tree-1
real :: NPProot = 0.0 ! C allocated to root, kg C yr-1 tree-1
real :: NPPwood = 0.0 ! C allocated to wood, kg C yr-1 tree-1

!===== Annual fluxes due to tree death, kg m-2 yr-1
real :: n_deadtrees = 0.0 ! plant to soil N flux due to mortality (kg N m-2 yr-1)
real :: c_deadtrees = 0.0 ! plant to soil C flux due to mortality (kg C m-2 yr-1)
real :: m_turnover = 0.0 ! C turnover due to mortality and tissue turnover (kg C m-2 yr-1)
real :: deathrate = 0.0 ! Deathrate (0 to 1)

!===== Nitrogen model related variables
real :: bl_max = 0.0 ! Max. leaf biomass, kg C tree-1
real :: br_max = 0.0 ! Max. fine root biomass, kg C tree-1

!===== Water uptake-related variables
real :: WupL(MAX_LEVELS) = 0.0 ! normalized vertical distribution of uptake

!===== Photosynthesis variables
real :: An_op = 0.0 ! mol C/(m2 of leaf per year)
real :: An_cl = 0.0 ! mol C/(m2 of leaf per year)
real :: C_growth = 0.0 ! Carbon gain since last growth, kg C day-1 tree-1
real :: N_growth = 0.0 ! Nitrogen used for plant tissue growth, kg N day-1 tree-1
real :: resg = 0.0 ! growth respiration, kg C day-1 tree-1

!===== Memory variables used for computing deltas
real :: DBH_ys = 0.0 ! DBH at the begining of a year (growing season)
real :: BA_ys = 0.0 ! Basal area at the beginning og a year

end type cohort_type

contains
function NSNmax(cohort) result(res)
real :: res
type(cohort_type) :: cohort

! Local variable
type(spec_data_type) :: sp

sp = myinterface%params_species(cohort%species)

res = sp%fNSNmax * &
(cohort%bl_max / (sp%CNleaf0 * sp%leafLS) + cohort%br_max / sp%CNroot0)
end function NSNmax

function W_supply(cohort) result(res)
! potential water uptake rate per unit time per tree
real :: res
type(cohort_type) :: cohort

res = sum(cohort%WupL(:))
end function W_supply

function rootareaL(cohort, level) result(res)
! Root length per layer, m of root/m
real :: res
integer :: level
type(cohort_type) :: cohort

res = rootarea(cohort) * myinterface%params_species(cohort%species)%root_frac(level)
end function rootareaL

function rootarea(cohort) result(res)
! total fine root area per tree
real :: res
type(cohort_type) :: cohort

res = cohort%proot%c%c12 * myinterface%params_species(cohort%species)%SRA
end function rootarea

function lai(cohort) result(res)
! Leaf area index: surface of leaves per m2 of crown
real :: res
type(cohort_type) :: cohort

res = cohort%leafarea / cohort%crownarea !(cohort%crownarea *(1.0-sp%internal_gap_frac))
end function lai

function basal_area(cohort) result(res)
! Tree basal area, m2 tree-1
real :: res
type(cohort_type) :: cohort

res = pi/4 * cohort%dbh * cohort%dbh
end function basal_area

function volume(cohort) result(res)
! Tree basal volume, m3 tree-1
real :: res
type(cohort_type) :: cohort

res = (cohort%psapw%c%c12 + cohort%pwood%c%c12) / myinterface%params_species(cohort%species)%rho_wood
end function volume

end module md_cohort
Loading

0 comments on commit a03df9f

Please sign in to comment.