Forked from
4C / FORESEE
206 commits behind the upstream repository.
-
Petra Lasch-Born authoredPetra Lasch-Born authored
stand_regen.f 18.87 KiB
!*****************************************************************!
!* *!
!* 4C (FORESEE) Simulation Model *!
!* *!
!* *!
!* subroutine for regeneration *!
!* including the SR: *!
!* - gener_seed *!
!* - seed_ini *!
!* - simseed *!
!* - growth_seed *!
!* - mort_seed *!
!* *!
!* Copyright (C) 1996-2018 *!
!* Potsdam Institute for Climate Impact Reserach (PIK) *!
!* Authors and contributors see AUTHOR file *!
!* This file is part of 4C and is licensed under BSD-2-Clause *!
!* See LICENSE file or under: *!
!* http://www.https://opensource.org/licenses/BSD-2-Clause *!
!* Contact: *!
!* https://gitlab.pik-potsdam.de/foresee/4C *!
!* *!
!*****************************************************************!
SUBROUTINE stand_regen
USE data_simul
USE data_stand
IMPLICIT NONE
flag_standup = 2
CALL mort_seed
CALL gener_seed
END SUBROUTINE stand_regen
SUBROUTINE gener_seed
USE data_stand
USE data_species
USE data_simul
use data_out
USE data_plant
USE data_soil
IMPLICIT NONE
real :: seedla ! leaf area of all seedling cohorts
real :: laiseed ! lai ----"------
integer :: nseed ! number of generated seeds
real :: redseed
integer :: i
integer, dimension(5) :: agemin, seedpot
real, dimension(5,3) :: latg
real :: help,help1, help2
real :: pequal
integer :: hlayer
integer :: flag_reg_help
TYPE(coh_obj), POINTER :: p
DATA latg /1.,0.3,0.1,1.,0.1,1.,0.9,0.5,1.,0.5,1.,1.,0.9,1.,0.9/
if (flag_trace) write (unit_trace, '(I4,I10,A)') iday, time_cur, ' gener_seed'
flag_reg_help = 0
agemin = 0
seedpot = 0
seedla = 0.
help1 = 0.
! calculation of leafarea of all seedling cohorts
SELECT CASE (flag_reg)
! according to FORGRA (Vincent Kint)
CASE (30)
call random_number(pequal)
DO i= 1, nspecies
nseed = 0
p =>pt%first
DO WHILE (ASSOCIATED(p))
if(p%coh%species.eq.i) then
if (i.eq.1) then
agemin(i) = 50 + (30* pequal)
call random_number(pequal)
seedpot(i) = 810*pequal
else if(i.eq.3) then
agemin(i) = 15 + (45* pequal)
call random_number(pequal)
seedpot(i) = 1000*pequal
else if(i.eq.4) then
agemin(i) = 15 +(35* pequal)
call random_number(pequal)
seedpot(i) = 1125*pequal
else if(i.eq.5) then
agemin(i) = 10 +(10* pequal)
call random_number(pequal)
seedpot(i) = 8750*pequal
end if
if(p%coh%x_age.ge. agemin(i).and.p%coh%diam.gt.0.) then
nseed = nseed + seedpot(i)*(p%coh%ntreem + p%coh%ntreea)
end if
end if
p => p%next
END DO ! cohort
help2 = irelpool_ll
if(help2.lt.0) help2 =0
if(help2.eq. 0.) then
redseed = 0.
else if( help2.gt.0. .and. help2.le.latg(i,1)) then
redseed = help2*latg(i,1)/0.4
else if ( help2.gt.latg(i,1).and. help2.le.latg(i,2)) then
redseed = help2*latg(i,2)/0.6
else if ( help2.gt.latg(i,2).and. help2.le.latg(i,3)) then
redseed = help2*latg(i,3)/0.8
else if(help2.gt.latg(i,3)) then
redseed = help2* latg(i,3)
end if
nseed = nseed * redseed
! for birch 1 year old saplings are used
if (i.eq.5) then
numplant(i) = nseed
flag_reg = 14
if(nseed.ne.0) call planting
flag_reg= 0
else
call seed_multi(nseed,i)
end if
END DO ! species
CASE(1,2,3)
p =>pt%first
DO WHILE (ASSOCIATED(p))
if(p%coh%height.lt.thr_height) then
seedla = seedla + p%coh%t_leaf*p%coh%ntreea
help1 = help1 + p%coh%x_fol*p%coh%ntreea
end if
p => p%next
END DO
! calculation LAI of lowest_layer
laiseed=seedla/kpatchsize
DO i=1,nspecies
IF (spar(i)%regflag.eq.1) THEN
CALL simseed(i,nseed)
IF(laiseed.lt.1) THEN
! reduction of seedling number nseed depending on light module and free space in the lowest_layer
SELECT CASE (flag_light)
CASE(1)
IF(flag_reg.ne.3) THEN
CALL seed_ini(nseed,i)
ELSE
CALL seed_multi(nseed,i)
END IF
CASE (2)
if (anz_coh.eq. 0) then
if(time.eq.1) then
hlayer = 0
else
hlayer = 1
end if
else
hlayer = lowest_layer -1
end if
help = vstruct(hlayer)%Irel
if (help.lt.0.05) help = 0
IF(help.eq.0) THEN
nseed = 0
ELSE
nseed = nseed*help
IF(flag_reg.ne.3) THEN
CALL seed_ini(nseed,i)
ELSE
CALL seed_multi(nseed,i)
END IF
END IF
CASE(3)
redseed= bgpool_ll
nseed = nseed*redseed
IF(flag_reg.ne.3) THEN
CALL seed_ini(nseed,i)
ELSE
CALL seed_multi(nseed,i)
END IF
CASE(4)
if(i.gt.5) then
redseed= irelpool_ll
else
! according to FORGRA, not for all species (i=1,5)
help2 = irelpool_ll
if(help2.lt. 0.01) then
redseed = 0.
else if( help2.gt.0.01 .and. help2.le.latg(i,1)) then
redseed = help2*latg(i,1)/0.4
else if ( help2.gt.latg(i,1).and. help2.le.latg(i,2)) then
redseed = help2*latg(i,2)/0.6
else if ( help2.gt.latg(i,2).and. help2.le.latg(i,3)) then
redseed = help2*latg(i,3)/0.8
else if(help2.gt.latg(i,3)) then
redseed = help2* latg(i,3)
end if
end if
nseed = redseed * nseed
IF(flag_reg.ne.3) THEN
CALL seed_ini(nseed,i)
ELSE
if (i.eq.5) then
numplant(i) = nseed
flag_reg_help = flag_reg
flag_reg = 14
if(nseed.ne.0) call planting
flag_reg = flag_reg_help
else
CALL seed_multi(nseed,i)
end if
END IF
END SELECT
ELSE
nseed = 0.
END IF
ELSE
nseed=0.
END IF
END DO
END SELECT ! flag_reg
END subroutine gener_seed
SUBROUTINE simseed(specnum,nseed)
USE data_species
use data_simul
use data_stand
IMPLICIT NONE
REAL :: pequal
INTEGER :: nseed,specnum
REAL :: seedmax
! calculation of max. seedrate of patch from max. seedrate per m2
seedmax=spar(specnum)%seedrate*kpatchsize
CALL random_number(pequal)
CALL random_number(pequal)
nseed=-seedmax*alog(1.-pequal)
IF (flag_mg ==4 .and. time.eq.1) THEN
nseed = NINT(spar(specnum)%seedrate*kpatchsize)
ELSE IF(flag_mg ==4.and. time.gt.1)THEN
nseed = 0
END IF
end
SUBROUTINE seed_ini(nseed,nsp)
USE data_species
use data_stand
use data_help
use data_out
use data_simul
use data_soil
IMPLICIT NONE
integer :: nseed, nr, j
integer :: nsp
REAL :: shoot
REAL :: x1,x2,xacc,root
REAL :: rtflsp
REAL :: troot2
TYPE(cohort) ::tree_ini
external weight
external rtflsp
if (flag_trace) write (unit_trace, '(I4,I10,A)') iday, time_cur, ' seed_ini'
IF(nseed.eq.0) RETURN
hnspec = nsp
max_coh = max_coh + 1
! nullify of all elements
call coh_initial (tree_ini)
tree_ini%ident = max_coh
tree_ini%species = nsp
tree_ini%ntreea = nseed
tree_ini%nta = nseed
tree_ini%x_age = 1
mschelp = spar(nsp)%seedmass/1000. ! g ---> kg
x1 = 0.
x2 = 0.1
xacc = (1.0e-10) * (x1+x2)/2
root = rtflsp(weight,x1,x2,xacc)
tree_ini%x_sap = root
shoot = root*1000. ! [kg]
tree_ini%x_fol= (spar(nsp)%seeda*(tree_ini%x_sap** spar(nsp)%seedb)) ![kg]
tree_ini%x_frt = tree_ini%x_fol ! [kg]
tree_ini%med_sla = spar(nsp)%psla_min + spar(nsp)%psla_a*0.5
tree_ini%t_leaf = tree_ini%med_sla* tree_ini%x_fol ! [m-2]
tree_ini%ca_ini = tree_ini%t_leaf
! initialize pheno state variables
IF(spar(tree_ini%species)%Phmodel==1) THEN
tree_ini%P=0
tree_ini%I=1
ELSE
tree_ini%P=0
tree_ini%I=0
tree_ini%Tcrit=0
END IF
! tranformation of shoot biomass kg --> mg
if(nsp.ne.2)tree_ini%height = spar(nsp)%pheight1*(shoot*1000.)**spar(nsp)%pheight2 ! [cm] calculated from shoot biomass (mg); berechnet aus shoot biomass (mg)
if(nsp.eq.2) tree_ini%height = 10**(spar(nsp)%pheight1+ spar(nsp)%pheight2*LOG10(shoot*1000.)+ &
spar(nsp)%pheight3*(LOG10(shoot*1000.))**2)
IF(nseed.ne.0.) then
IF (.not. associated(pt%first)) THEN
ALLOCATE (pt%first)
pt%first%coh = tree_ini
NULLIFY(pt%first%next)
! root distribution
call root_depth (1, pt%first%coh%species, pt%first%coh%x_age, pt%first%coh%height, pt%first%coh%x_frt, pt%first%coh%x_crt, nr, troot2, pt%first%coh%x_rdpt, pt%first%coh%nroot)
pt%first%coh%nroot = nr
do j=1,nr
pt%first%coh%rooteff = 1. ! assumption for the first use
enddo
do j=nr+1, nlay
pt%first%coh%rooteff = 0. ! layers with no roots
enddo
ELSE
ALLOCATE(zeig)
zeig%coh = tree_ini
zeig%next => pt%first
pt%first => zeig
! root distribution
call root_depth (1, zeig%coh%species, zeig%coh%x_age, zeig%coh%height, zeig%coh%x_frt, zeig%coh%x_crt, nr, troot2, zeig%coh%x_rdpt, zeig%coh%nroot)
zeig%coh%nroot = nr
do j=1,nr
zeig%coh%rooteff = 1. ! assumption for the first use
enddo
do j=nr+1, nlay
zeig%coh%rooteff = 0. ! layers with no roots
enddo
END IF
anz_coh=anz_coh+1
END IF
END SUBROUTINE seed_ini
SUBROUTINE growth_seed
USE data_stand
USE data_species
USE data_simul
USE data_par
use data_out
IMPLICIT NONE
REAL :: lambdaf = 0., & ! partitioning functions
lambdas = 0., &
lambdar = 0., &
NPP = 0., & ! annual NPP
F = 0., & ! state variables: foliage,
S = 0., & ! shoot biomass,
R = 0., & ! fine roots,
H = 0., & ! total tree height
FNew, SNew, & ! new states
RNew, &
sigmaf = 0., & ! current leaf activity rate
sigman = 0., & ! current root activity rate
betar = 0., &
ar = 0
REAL :: Sf, & ! senescence rates
Sr, &
Gf, & ! growth rates
Gs, &
Gr
real :: pab,helpdr,helpsum
TYPE(coh_obj), POINTER :: p
if (flag_trace) write (unit_trace, '(I4,I10,A)') iday, time_cur, ' growth_seed'
flag_standup = 2 ! call stand_balance and root_distribution later
p=>pt%first
DO
if(.not.associated(p)) exit
if( p%coh%height.lt.thr_height.and. p%coh%species.le.nspec_tree) then
ns = p%coh%species
F = p%coh%x_fol
S = p%coh%x_sap
R = p%coh%x_frt
NPP = p%coh%NPP
IF (flag_reg .eq. 2) NPP = p%coh%NPPpool ! [kg]
H = p%coh%height
Sf = p%coh%sfol
Sr = p%coh%sfrt
! only allocate if enough NPP is available
1 IF (NPP>1.0E-9.or. NPP.ge.(Sf+Sr).and.(sr+Sf)>1.0E-9) THEN
! calculate leaf activity based on net PS and leaf mass
sigmaf = NPP/F
! calculate root activity based on drought index
helpdr= p%coh%drIndAl / p%coh%nDaysGr
IF (flag_sign.eq.1) THEN
sigman = amax1(spar(ns)%sigman*10*(((5.-spar(ns)%stol)*1.-p%coh%crown_area)/(5.-spar(ns)%stol)*1.),spar(ns)%sigman) * p%coh%drIndAl / p%coh%nDaysGr
ELSE
sigman = spar(ns)%sigman * p%coh%drIndAl / p%coh%nDaysGr
END IF
! auxiliary variables for fine roots
if(helpdr.lt.0.001) ar = 0.
ar = spar(ns)%pcnr * sigmaf / sigman
betar = (Sr - R + ar*(F-Sf)) / NPP
! calculate coefficients for roots and foliage and shoot
select case (ns)
case (1)
pab = 0.487
case(2)
pab = 0.826
case(3)
pab=1.9
case(4)
pab=1.002
! Pinus contorta
case(6)
! Gholz
pab = 0.236
! Populus tremula
case(8)
pab = 0.3233
case(9)
! Pinus halepensis
pab = 1.42335
case(10)
! pseudotsuga menziesii
pab = 0.8515
case(11)
! Robinia
pab = 0.8594
end select
lambdaf = (pab*(1-betar)+ (Sf/NPP))/(1 + pab*(1. + ar))
lambdar = ar * lambdaf + betar
lambdas = 1.- lambdaf - lambdar
! consistency
ELSE
lambdaf = 0.
lambdas = 0.
lambdar = 0.
END IF
if ( lambdas.lt.0.) then
lambdas = 0.
lambdaf = (1.-betar)/(ar+1)
lambdar = 1.-lambdaf
if( lambdar.lt.0) then
lambdar=0
lambdaf=1
end if
if(lambdaf.lt.0) then
lambdaf =1
lambdar = 0.
end if
endif
helpsum = lambdaf + lambdar+ lambdas
Gf = lambdaf*NPP
Gr = lambdar*NPP
Gs = lambdas*NPP
p%coh%gfol = Gf
p%coh%gfrt = Gr
p%coh%gsap = Gs
! update of state vector
FNew = F + Gf - Sf
SNew = S + Gs
RNew = R + Gr - Sr
p%coh%x_fol = FNew
p%coh%x_sap = SNew
p%coh%x_frt = RNew
p%coh%fol_inc_old = p%coh%fol_inc
p%coh%fol_inc = Gf - Sf
p%coh%stem_inc = Gs
! update height and shoot base diameter (regression functions from Schall 1998)
IF(ns.ne.2) p%coh%height = spar(ns)%pheight1* (snew*1000000.) **spar(ns)%pheight2
IF(ns.eq.2) p%coh%height = 10**(spar(ns)%pheight1+ spar(ns)%pheight2*LOG10(snew*1000000.)+ &
spar(ns)%pheight3*(LOG10(snew*1000000.))**2)
p%coh%height_ini = p%coh%height
! update foliage area, parameter med_sla
SELECT CASE (flag_light)
CASE (1:2)
p%coh%med_sla = spar(ns)%psla_min + spar(ns)%psla_a*(1.- vstruct(lowest_layer)%irel)
CASE(3,4)
p%coh%med_sla = spar(ns)%psla_min + spar(ns)%psla_a*(1.-irelpool(lowest_layer))
END SELECT
! total leaf area of a tree in this cohort [m**2]
p%coh%ca_ini = p%coh%med_sla * p%coh%x_fol
! update age -now not necessary this is done in stand_bal
p%coh%notViable = (FNew <= 0.) .OR. (SNew <= 0.) .OR. &
(RNew <= 0.)
p%coh%litC_fol = p%coh%litC_fol + p%coh%ntreea * Sf * cpart
p%coh%litC_frt = p%coh%litC_frt + p%coh%ntreea * Sr * cpart
! with species specific N content and reallocation factor (see species.par)
p%coh%litN_fol = p%coh%litN_fol + p%coh%ntreea * Sf * cpart * spar(ns)%reallo_fol / spar(ns)%cnr_fol
p%coh%litN_frt = p%coh%litN_frt + p%coh%ntreea * Sr * cpart * spar(ns)%reallo_frt / spar(ns)%cnr_frt
end if ! seedling cohort test
p=> p%next
END DO
END SUBROUTINE growth_seed
SUBROUTINE mort_seed
USE data_species
USE data_simul
use data_stand
use data_par
use data_out
IMPLICIT NONE
integer :: taxnr
integer :: hage
real :: intmort
real :: strmort
real :: totmort
real :: ntdead
real :: ntahelp
TYPE(coh_obj), POINTER :: p
if (flag_trace) write (unit_trace, '(I4,I10,A)') iday, time_cur, ' mort_seed'
p=>pt%first
DO
IF(.not.associated(p)) EXIT
IF(p%coh%height.lt.thr_height) THEN
IF(p%coh%notViable) then
PRINT*,time, p%coh%notViable
p%coh%ntreed = p%coh%ntreea
p%coh%ntreea = 0
ENDIF
END IF
p => p%next
END DO
p => pt%first
DO
IF(.not.associated(p)) EXIT
IF(p%coh%height.lt.thr_height .and. p%coh%species.le.nspec_tree) THEN
taxnr = p%coh%species
if(p%coh%ntreea .eq.0) goto 1000
hage = p%coh%x_age
IF( p%coh%fol_inc.le.0.) THEN
p%coh%x_stress = p%coh%x_stress +1
p%coh%x_health = 0
ELSE
p%coh%x_health = p%coh%x_health +1
IF(p%coh%x_stress .gt. 0.) p%coh%x_stress = p%coh%x_stress -1
ENDIF
! intrinsic mortality
CALL int_mort_weib(taxnr, intmort, hage)
! stress mortality
IF(p%coh%x_stress.gt.0) THEN
strmort = weibal*spar(taxnr)%weibla*p%coh%x_stress**(weibal-1)
ELSE
strmort = 0.
ENDIF
totmort=intmort+(1-intmort)*strmort
! calculation of real number of dying stems
ntdead = totmort*p%coh%ntreeA
! update of real stem number nta and number of dead stems
p%coh%nta = p%coh%nta -ntdead
p%coh%nTreeD = p%coh%nTreeA-NINT(p%coh%nta)
! help variable for comparison
ntahelp = p%coh%nTreeA
! update of integer stem number
p%coh%nTreeA = NINT(p%coh%nta)
! update of integer stem number
if(p%coh%nta.lt.1.) p%coh%nTreeA=0.
! update of real stem number if integer stem number was changed
if (ntahelp .ne. p%coh%nTreeA ) p%coh%nta = p%coh%nTreeA
1000 if (p%coh%ntreeD.ne.0) then
p%coh%litC_fol = p%coh%litC_fol + p%coh%ntreeD*(1.-spar(taxnr)%psf)*p%coh%x_fol*cpart
p%coh%litN_fol = p%coh%litN_fol + p%coh%ntreeD*((1.-spar(taxnr)%psf)*p%coh%x_fol*cpart)/spar(taxnr)%cnr_fol
p%coh%litC_frt = p%coh%litC_frt + p%coh%ntreeD*p%coh%x_frt*cpart
p%coh%litN_frt = p%coh%litN_frt + p%coh%ntreeD*p%coh%x_frt*cpart/spar(taxnr)%cnr_frt
p%coh%litC_tb = p%coh%litC_tb + p%coh%ntreeD*p%coh%x_tb*cpart
p%coh%litN_tb = p%coh%litN_tb + p%coh%ntreeD*p%coh%x_tb*cpart/spar(taxnr)%cnr_tbc
p%coh%litC_crt = p%coh%litC_crt + p%coh%ntreeD*p%coh%x_crt*cpart
p%coh%litN_crt = p%coh%litN_crt + p%coh%ntreeD*p%coh%x_crt*cpart/spar(taxnr)%cnr_tbc
p%coh%litC_stem = p%coh%litC_stem + p%coh%ntreeD*(p%coh%x_sap)*cpart
p%coh%litN_stem = p%coh%litC_stem/spar(taxnr)%cnr_stem
endif
END IF
p => p%next
ENDDO
END SUBROUTINE mort_seed