[947] | 1 | ! ================================================================================================================================= |
---|
| 2 | ! MODULE : stomate_npp |
---|
[8] | 3 | ! |
---|
[4470] | 4 | ! CONTACT : orchidee-help _at_ listes.ipsl.fr |
---|
[8] | 5 | ! |
---|
[947] | 6 | ! LICENCE : IPSL (2006) |
---|
| 7 | ! This software is governed by the CeCILL licence see ORCHIDEE/ORCHIDEE_CeCILL.LIC |
---|
| 8 | ! |
---|
| 9 | !>\BRIEF This modules calculates NPP: Maintenance and growth respiration |
---|
| 10 | !! |
---|
| 11 | !!\n DESCRIPTION: We calculate first the maintenance respiration. This is substracted from the |
---|
| 12 | !! allocatable biomass (and from the present biomass if the GPP is too low).\n |
---|
| 13 | !! Of the rest, a part is lost as growth respiration, while the other part is |
---|
| 14 | !! effectively allocated. |
---|
| 15 | !! |
---|
| 16 | !! RECENT CHANGE(S): None |
---|
| 17 | !! |
---|
| 18 | !! REFERENCE(S) : |
---|
| 19 | !! |
---|
| 20 | !! SVN : |
---|
| 21 | !! $HeadURL$ |
---|
| 22 | !! $Date$ |
---|
| 23 | !! $Revision$ |
---|
| 24 | !! \n |
---|
| 25 | !_ ================================================================================================================================ |
---|
| 26 | |
---|
[8] | 27 | MODULE stomate_npp |
---|
| 28 | |
---|
| 29 | ! modules used: |
---|
[1788] | 30 | USE xios_orchidee |
---|
[1078] | 31 | USE ioipsl_para |
---|
[511] | 32 | USE stomate_data |
---|
| 33 | USE constantes |
---|
[947] | 34 | USE constantes_soil |
---|
[511] | 35 | USE pft_parameters |
---|
[8] | 36 | |
---|
| 37 | IMPLICIT NONE |
---|
| 38 | |
---|
| 39 | ! private & public routines |
---|
| 40 | |
---|
| 41 | PRIVATE |
---|
| 42 | PUBLIC npp_calc,npp_calc_clear |
---|
| 43 | |
---|
[2738] | 44 | LOGICAL, SAVE :: firstcall_npp = .TRUE. !! first call |
---|
| 45 | !$OMP THREADPRIVATE(firstcall_npp) |
---|
[8] | 46 | |
---|
| 47 | CONTAINS |
---|
| 48 | |
---|
[947] | 49 | !! ================================================================================================================================ |
---|
| 50 | !! SUBROUTINE : npp_calc_clear |
---|
| 51 | !! |
---|
[2738] | 52 | !>\BRIEF : Set the flag ::firstcall_npp to .TRUE. and as such activate section |
---|
[947] | 53 | !! 1.1 of the subroutine npp_calc (see below).\n |
---|
| 54 | !_ ================================================================================================================================ |
---|
| 55 | |
---|
[8] | 56 | SUBROUTINE npp_calc_clear |
---|
[2738] | 57 | firstcall_npp=.TRUE. |
---|
[8] | 58 | END SUBROUTINE npp_calc_clear |
---|
| 59 | |
---|
[947] | 60 | |
---|
| 61 | |
---|
| 62 | |
---|
| 63 | |
---|
| 64 | !! ================================================================================================================================ |
---|
| 65 | !! SUBROUTINE : npp_calc |
---|
| 66 | !! |
---|
| 67 | !>\BRIEF Calculate NPP as the difference between GPP and respiration (= growth + maintenance respiration). |
---|
| 68 | !! Update biomass of all compartments after calculating respiration and allocation. |
---|
| 69 | !! |
---|
| 70 | !! |
---|
| 71 | !! DESCRIPTION : NPP is calculated from three components: Gross Primary Productivity (GPP), maintenance respiration |
---|
| 72 | !! and growth respiration (all in @tex $ gC.m^{-2}dt^{-1} $ @endtex), following the convention that positive fluxes denote |
---|
| 73 | !! fluxes plants to the atmosphere. GPP is the input variable from which, in the end, NPP or total allocatable biomass |
---|
| 74 | !! @tex $(gC.m^{-2}dt^{-1}))$ @endtex is calculated. Net primary production is then calculated as:\n |
---|
| 75 | !! NPP = GPP - growth_resp - maint-resp [eq. 1]\n |
---|
| 76 | !! |
---|
| 77 | !! The calculation of maintenance respiration is done in routine stomate_resp.f90. Maintenance respiration is calculated for |
---|
| 78 | !! the whole plant and is therefore removed from the total allocatable biomass. In order to prevent all allocatable biomass |
---|
| 79 | !! from being used for maintenance respiration, a limit fraction of total allocatable biomass, tax_max, is defined (in |
---|
| 80 | !! variables declaration). If maintenance respiration exceeds tax_max (::bm_tax_max), the maximum allowed allocatable biomass |
---|
| 81 | !! will be respired and the remaining respiration, required in excess of tax_max, is taken out from tissues already present in |
---|
| 82 | !! the plant (biomass).\n |
---|
| 83 | !! |
---|
| 84 | !! After total allocatable biomass has been updated by removing maintenance respiration, total allocatable biomass is distributed |
---|
| 85 | !! to all plant compartments according to the f_alloc fractions calculated in stomate_alloc.f90.\n |
---|
| 86 | !! |
---|
| 87 | !! Growth respiration is calculated as a fraction of allocatable biomass for each part of the plant. The fraction coefficient |
---|
| 88 | !! ::frac_growth_resp is defined in stomate_constants.f90 and is currently set to be the same for all plant compartments. |
---|
| 89 | !! Allocatable biomass of all plant compartments are updated by removing what is lost through growth respiration. Net allocatable |
---|
| 90 | !! biomass (total allocatable biomass after maintenance and growth respiration) is added to the current biomass for each plant |
---|
| 91 | !! compartment. |
---|
| 92 | !! |
---|
| 93 | !! Finally, leaf age and plant age are updated. Leaf age is described with the concept of "leaf age classes". A number of leaf |
---|
| 94 | !! age classes (nleafages) is defined in stomate_constants.f90. Each leaf age class contains a fraction (::leaf_frac) of the |
---|
| 95 | !! total leaf biomass. When new biomass is added to leaves, the age of the biomass in the youngest leaf age class is decreased. |
---|
| 96 | !! The fractions of leaves in the other leaf ages classes are also updated as the total biomass has increased. Plant age is |
---|
| 97 | !! updated first by increasing the age of the previous biomass by one time step, and then by adjusting this age as the average |
---|
| 98 | !! of the ages of the previous and the new biomass. |
---|
| 99 | !! |
---|
| 100 | !! RECENT CHANGE(S): None |
---|
| 101 | !! |
---|
| 102 | !! MAIN OUTPUT VARIABLE(S): ::npp |
---|
| 103 | !! |
---|
| 104 | !! REFERENCE(S) : |
---|
| 105 | !! - F.W.T.Penning De Vries, A.H.M. Brunsting, H.H. Van Laar. 1974. Products, requirements and efficiency of biosynthesis a |
---|
| 106 | !! quantitative approach. Journal of Theoretical Biology, Volume 45, Issue 2, June 1974, Pages 339-377. |
---|
| 107 | !! |
---|
| 108 | !! FLOWCHART : |
---|
| 109 | !! \latexonly |
---|
| 110 | !! \includegraphics[scale=0.14]{stomate_npp_flow.jpg} |
---|
| 111 | !! \endlatexonly |
---|
| 112 | !! \n |
---|
| 113 | !_ ================================================================================================================================ |
---|
| 114 | |
---|
[8] | 115 | SUBROUTINE npp_calc (npts, dt, & |
---|
[6151] | 116 | PFTpresent, veget_cov_max, & |
---|
[2441] | 117 | t2m, tsoil, lai, rprof, & |
---|
[8] | 118 | gpp, f_alloc, bm_alloc, resp_maint_part,& |
---|
| 119 | biomass, leaf_age, leaf_frac, age, & |
---|
[4919] | 120 | resp_maint, resp_growth, npp, co2_to_bm) |
---|
[947] | 121 | |
---|
| 122 | !! 0 Variable and parameter declaration |
---|
[8] | 123 | |
---|
[947] | 124 | !! 0.1 Input variables |
---|
[8] | 125 | |
---|
[947] | 126 | INTEGER(i_std), INTENT(in) :: npts !! Domain size - number of pixels (unitless) |
---|
| 127 | REAL(r_std), INTENT(in) :: dt !! Time step (days) |
---|
| 128 | LOGICAL, DIMENSION(npts,nvm), INTENT(in) :: PFTpresent !! PFT exists (true/false) |
---|
[6151] | 129 | REAL(r_std), DIMENSION(npts,nvm), INTENT(in) :: veget_cov_max !! PFT "Maximal" coverage fraction of a PFT |
---|
| 130 | !! (= ind*cn_ind) |
---|
| 131 | !! @tex $(m^2 m^{-2})$ @endtex |
---|
[947] | 132 | REAL(r_std), DIMENSION(npts), INTENT(in) :: t2m !! Temperature at 2 meter (K) |
---|
[4631] | 133 | REAL(r_std), DIMENSION(npts,nslm), INTENT(in) :: tsoil !! Soil temperature of each soil layer (K) |
---|
[947] | 134 | REAL(r_std), DIMENSION(npts,nvm), INTENT(in) :: lai !! PFT leaf area index (unitless) |
---|
| 135 | REAL(r_std), DIMENSION(npts,nvm), INTENT(in) :: rprof !! PFT root depth as calculated in stomate.f90 |
---|
| 136 | !! from root profile parameter humcste (m) |
---|
| 137 | REAL(r_std), DIMENSION(npts,nvm), INTENT(in) :: gpp !! PFT gross primary productivity |
---|
| 138 | !! @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
| 139 | REAL(r_std), DIMENSION(npts,nvm,nparts), INTENT(in) :: f_alloc !! Fraction of total allocatable biomass that |
---|
| 140 | !! goes into each plant part (unitless) |
---|
| 141 | REAL(r_std), DIMENSION(npts,nvm,nparts), INTENT(in) :: resp_maint_part !! Maintenance respiration of different plant |
---|
| 142 | !! parts @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
| 143 | !! 0.2 Output variables |
---|
[8] | 144 | |
---|
[947] | 145 | REAL(r_std), DIMENSION(npts,nvm), INTENT(out) :: resp_maint !! PFT maintenance respiration |
---|
| 146 | !! @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
| 147 | REAL(r_std), DIMENSION(npts,nvm), INTENT(out) :: resp_growth !! PFT growth respiration |
---|
| 148 | !! @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
| 149 | REAL(r_std), DIMENSION(npts,nvm), INTENT(out) :: npp !! PFT net primary productivity |
---|
| 150 | !! @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
[1170] | 151 | REAL(r_std), DIMENSION(npts,nvm,nparts,nelements), INTENT(out) :: bm_alloc !! PFT biomass increase, i.e. NPP per plant part |
---|
[947] | 152 | !! @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
[8] | 153 | |
---|
[947] | 154 | !! 0.3 Modified variables |
---|
[8] | 155 | |
---|
[1170] | 156 | REAL(r_std), DIMENSION(npts,nvm,nparts,nelements), INTENT(inout) :: biomass !! PFT total biomass of each plant part |
---|
[947] | 157 | !! @tex $(gC.m^{-2})$ @endtex |
---|
| 158 | REAL(r_std), DIMENSION(npts,nvm,nleafages), INTENT(inout) :: leaf_age !! PFT age of different leaf age classes (days) |
---|
| 159 | REAL(r_std), DIMENSION(npts,nvm,nleafages), INTENT(inout) :: leaf_frac !! PFT fraction of total leaves in leaf age |
---|
| 160 | !! class (unitless) |
---|
| 161 | REAL(r_std), DIMENSION(npts,nvm), INTENT(inout) :: age !! PFT age (years) |
---|
[4919] | 162 | REAL(r_std), DIMENSION(npts,nvm), INTENT(inout) :: co2_to_bm !! virtual gpp @tex $(gC.m^{-2})$ @endtex |
---|
[8] | 163 | |
---|
[947] | 164 | !! 0.4 Local variables |
---|
[8] | 165 | |
---|
[947] | 166 | REAL(r_std), DIMENSION(npts,nvm) :: t_root !! Root temperature (convolution of root and |
---|
| 167 | !! soil temperature profiles)(K) |
---|
| 168 | REAL(r_std), DIMENSION(npts,nvm,nparts) :: coeff_maint !! PFT maintenance respiration coefficients of |
---|
| 169 | !! different plant compartments at 0 deg C |
---|
| 170 | !! @tex $(g.g^{-1}dt^{-1})$ @endtex |
---|
| 171 | REAL(r_std), DIMENSION(npts,nparts) :: t_maint !! Temperature which is pertinent for maintenance |
---|
| 172 | !! respiration, which is air/root temperature for |
---|
| 173 | !! above/below-ground compartments (K) |
---|
| 174 | REAL(r_std), DIMENSION(npts) :: rpc !! Scaling factor for integrating vertical soil |
---|
| 175 | !! profiles (unitless) |
---|
| 176 | REAL(r_std), DIMENSION(npts) :: tl !! Long term annual mean temperature (C) |
---|
| 177 | REAL(r_std), DIMENSION(npts) :: slope !! Slope of maintenance respiration coefficient |
---|
| 178 | !! (1/K) |
---|
| 179 | REAL(r_std), DIMENSION(npts,nparts) :: resp_growth_part !! Growth respiration of different plant parts |
---|
| 180 | !! @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
[6151] | 181 | REAL(r_std), DIMENSION(npts,nparts) :: resp_growth_part_weighted !! Growth respiration of different plant |
---|
| 182 | !! parts per total ground area weighted |
---|
| 183 | !! over PFT fractions |
---|
| 184 | !! @tex $(gC m^{-2}dt^{-1})$ @endtex |
---|
| 185 | REAL(r_std), DIMENSION(npts,nparts) :: resp_maint_part_weighted !! Maintenance respiration of different |
---|
| 186 | !! plantparts per total ground area weighted |
---|
| 187 | !! over PFT fractions |
---|
| 188 | !! @tex $(gC m^{-2}dt^{-1})$ @endtex |
---|
[947] | 189 | REAL(r_std), DIMENSION(npts,nvm) :: bm_alloc_tot !! Allocatable biomass for the whole plant |
---|
| 190 | !! @tex $(gC.m^{-2})$ @endtex |
---|
| 191 | REAL(r_std), DIMENSION(npts) :: bm_add !! Biomass increase @tex $(gC.m^{-2})$ @endtex |
---|
| 192 | REAL(r_std), DIMENSION(npts) :: bm_new !! New biomass @tex $(gC.m^{-2})$ @endtex |
---|
| 193 | REAL(r_std), DIMENSION(npts,nvm) :: leaf_mass_young !! Leaf mass in youngest age class |
---|
| 194 | !! @tex $(gC.m^{-2})$ @endtex |
---|
| 195 | REAL(r_std), DIMENSION(npts,nvm) :: lm_old !! Leaf mass after maintenance respiration |
---|
| 196 | !! @tex $(gC.m^{-2})$ @endtex |
---|
| 197 | REAL(r_std), DIMENSION(npts,nvm) :: bm_create !! Biomass created when biomass<0 because of dark |
---|
| 198 | !! respiration @tex $(gC.m^{-2})$ @endtex |
---|
| 199 | REAL(r_std), DIMENSION(npts) :: bm_tax_max !! Maximum part of allocatable biomass used for |
---|
| 200 | !! respiration @tex $(gC.m^{-2})$ @endtex |
---|
| 201 | REAL(r_std), DIMENSION(npts) :: bm_pump !! Biomass that remains to be taken away |
---|
| 202 | !! @tex $(gC.m^{-2})$ @endtex |
---|
| 203 | INTEGER(i_std) :: i,j,k,l,m !! Indeces(unitless) |
---|
[2917] | 204 | INTEGER(i_std) :: ier !! Error handling |
---|
[8] | 205 | |
---|
[947] | 206 | !_ ================================================================================================================================ |
---|
[8] | 207 | |
---|
[2348] | 208 | IF (printlev>=3) WRITE(numout,*) 'Entering npp' |
---|
[947] | 209 | |
---|
| 210 | !! 1. Initializations |
---|
| 211 | |
---|
| 212 | !! 1.1 First call |
---|
[2738] | 213 | IF ( firstcall_npp ) THEN |
---|
[8] | 214 | |
---|
[947] | 215 | !! 1.1.2 Output message |
---|
| 216 | ! Write message including value used for tax_max |
---|
[4693] | 217 | IF (printlev >= 2) THEN |
---|
| 218 | WRITE(numout,*) 'npp:' |
---|
[8] | 219 | |
---|
[4693] | 220 | WRITE(numout,*) ' > max. fraction of allocatable biomass used for'// & |
---|
| 221 | ' maint. resp.:', tax_max |
---|
| 222 | END IF |
---|
[2738] | 223 | firstcall_npp = .FALSE. |
---|
[8] | 224 | |
---|
[947] | 225 | ENDIF ! End if first call |
---|
[8] | 226 | |
---|
[947] | 227 | !! 1.2 Set output variables to zero |
---|
[1170] | 228 | bm_alloc(:,:,:,:) = zero |
---|
[8] | 229 | resp_maint(:,:) = zero |
---|
| 230 | resp_growth(:,:) = zero |
---|
| 231 | npp(:,:) = zero |
---|
[6151] | 232 | resp_maint_part_weighted(:,:) = zero |
---|
| 233 | resp_growth_part_weighted(:,:) = zero |
---|
[8] | 234 | |
---|
[1884] | 235 | !! 1.3 Total allocatable biomass |
---|
[947] | 236 | ! total allocatable biomass during this time step determined from GPP. |
---|
| 237 | ! GPP was calculated as CO2 assimilation in enerbil.f90 |
---|
[8] | 238 | bm_alloc_tot(:,:) = gpp(:,:) * dt |
---|
| 239 | |
---|
[947] | 240 | |
---|
| 241 | |
---|
[1884] | 242 | !! 3. Calculate maintenance and growth respiration |
---|
[947] | 243 | ! First, total maintenance respiration for the whole plant is calculated by summing maintenance |
---|
| 244 | ! respiration of the different plant compartments. Then, maintenance respiration is subtracted |
---|
| 245 | ! from whole-plant allocatable biomass (up to a maximum fraction of the total allocatable biomass). |
---|
| 246 | ! Growth respiration is then calculated for each plant compartment as a fraction of remaining |
---|
| 247 | ! allocatable biomass for this compartment. NPP is calculated by substracting total autotrophic |
---|
| 248 | ! respiration from GPP i.e. NPP = GPP - maintenance resp - growth resp. |
---|
| 249 | DO j = 2,nvm ! Loop over # of PFTs |
---|
[8] | 250 | |
---|
[947] | 251 | !! 3.1 Maintenance respiration of the different plant parts |
---|
| 252 | ! Maintenance respiration of the different plant parts is calculated in |
---|
| 253 | ! stomate_resp.f90 as a function of the plant's temperature, |
---|
| 254 | ! the long term temperature and plant coefficients |
---|
| 255 | ! VPP killer: |
---|
[8] | 256 | resp_maint(:,j) = zero |
---|
| 257 | |
---|
[947] | 258 | ! Following the calculation of hourly maintenance respiration, verify that |
---|
| 259 | ! the PFT has not been killed after calcul of resp_maint_part in stomate. |
---|
[8] | 260 | DO k= 1, nparts |
---|
| 261 | WHERE (PFTpresent(:,j)) |
---|
| 262 | resp_maint(:,j) = resp_maint(:,j) + resp_maint_part(:,j,k) |
---|
| 263 | ENDWHERE |
---|
| 264 | ENDDO |
---|
[947] | 265 | |
---|
| 266 | !! 3.2 Substract maintenance respiration from allocatable biomass |
---|
| 267 | ! The total maintenance respiration calculated in 3.2 is substracted from the newly |
---|
| 268 | ! produced allocatable biomass (bm_alloc_tot). However, ensure that not all allocatable |
---|
| 269 | ! biomass is removed by setting a maximum to the fraction of allocatable biomass used |
---|
| 270 | ! for maintenance respiration: tax_max. If the maintenance respiration is larger than |
---|
| 271 | ! tax_max,the amount tax_max is taken from allocatable biomass, and the remaining of |
---|
| 272 | ! maintenance respiration is taken from the tissues themselves (biomass). We suppose |
---|
| 273 | ! that respiration is not dependent on leaf age -> therefore the leaf age structure is |
---|
| 274 | ! not changed. |
---|
| 275 | ! The maximum fraction of allocatable biomass used for respiration is defined as tax_max. |
---|
| 276 | ! The value of tax_max is set in the declarations section (0.4 Local variables) of this |
---|
| 277 | ! routine |
---|
[8] | 278 | bm_tax_max(:) = tax_max * bm_alloc_tot(:,j) |
---|
| 279 | |
---|
[947] | 280 | DO i = 1, npts ! Loop over # of pixels |
---|
[8] | 281 | |
---|
[947] | 282 | ! If there is enough allocatable biomass to cover maintenance respiration, |
---|
| 283 | ! then biomass associated with maintenance respiration is removed from allocatable biomass |
---|
[2031] | 284 | IF ( bm_alloc_tot(i,j) .GT. zero ) THEN |
---|
| 285 | IF ( ( resp_maint(i,j) * dt ) .LT. bm_tax_max(i) ) THEN |
---|
[947] | 286 | |
---|
[2031] | 287 | bm_alloc_tot(i,j) = bm_alloc_tot(i,j) - resp_maint(i,j) * dt |
---|
[8] | 288 | |
---|
[2031] | 289 | ! If there is not enough allocatable biomass to cover maintenance respiration, the |
---|
| 290 | ! - maximum allowed allocatable biomass (bm_tax_max) is removed from allocatable biomass. |
---|
| 291 | ELSE |
---|
[947] | 292 | |
---|
[2031] | 293 | bm_alloc_tot(i,j) = bm_alloc_tot(i,j) - bm_tax_max(i) |
---|
[8] | 294 | |
---|
[2031] | 295 | ! ::bm_pump is the amount of maintenance respiration that exceeds the maximum allocatable biomass |
---|
| 296 | ! This amount of biomass still needs to be respired and will be removed from tissues biomass of each |
---|
| 297 | ! plant compartment |
---|
| 298 | bm_pump(i) = resp_maint(i,j) * dt - bm_tax_max(i) |
---|
[8] | 299 | |
---|
[2031] | 300 | ! The biomass is removed from each plant compartment tissues as the ratio of the maintenance |
---|
| 301 | ! respiration of the plant compartment to the total maintenance respiration (resp_maint_part/resp_maint) |
---|
| 302 | biomass(i,j,ileaf,icarbon) = biomass(i,j,ileaf,icarbon) - & |
---|
| 303 | bm_pump(i) * resp_maint_part(i,j,ileaf) / resp_maint(i,j) |
---|
| 304 | biomass(i,j,isapabove,icarbon) = biomass(i,j,isapabove,icarbon) - & |
---|
| 305 | bm_pump(i) * resp_maint_part(i,j,isapabove) / resp_maint(i,j) |
---|
| 306 | biomass(i,j,isapbelow,icarbon) = biomass(i,j,isapbelow,icarbon) - & |
---|
| 307 | bm_pump(i) * resp_maint_part(i,j,isapbelow) / resp_maint(i,j) |
---|
| 308 | biomass(i,j,iroot,icarbon) = biomass(i,j,iroot,icarbon) - & |
---|
| 309 | bm_pump(i) * resp_maint_part(i,j,iroot) / resp_maint(i,j) |
---|
| 310 | biomass(i,j,ifruit,icarbon) = biomass(i,j,ifruit,icarbon) - & |
---|
| 311 | bm_pump(i) * resp_maint_part(i,j,ifruit) / resp_maint(i,j) |
---|
| 312 | biomass(i,j,icarbres,icarbon) = biomass(i,j,icarbres,icarbon) - & |
---|
| 313 | bm_pump(i) * resp_maint_part(i,j,icarbres) / resp_maint(i,j) |
---|
| 314 | ENDIF |
---|
| 315 | ELSE |
---|
[4728] | 316 | biomass(i,j,icarbres,icarbon) = biomass(i,j,icarbres,icarbon) + & |
---|
[2031] | 317 | bm_alloc_tot(i,j) - resp_maint(i,j) * dt |
---|
| 318 | bm_alloc_tot(i,j) = 0. |
---|
[947] | 319 | ENDIF ! End if there is enough allocatable biomass to cover maintenance respiration |
---|
[8] | 320 | |
---|
| 321 | ENDDO ! Fortran95: WHERE - ELSEWHERE construct |
---|
| 322 | |
---|
[947] | 323 | |
---|
| 324 | !! 3.3 Allocate allocatable biomass to different plant compartments. |
---|
| 325 | ! The amount of allocatable biomass of each compartment is a fraction according f_alloc of total |
---|
| 326 | ! allocatable biomass (the f_alloc of the different plant parts are calculated in stomate_alloc.f90) |
---|
[8] | 327 | DO k = 1, nparts |
---|
[1170] | 328 | bm_alloc(:,j,k,icarbon) = f_alloc(:,j,k) * bm_alloc_tot(:,j) |
---|
[8] | 329 | ENDDO |
---|
| 330 | |
---|
[947] | 331 | |
---|
| 332 | !! 3.4 Calculate growth respiration of each plant compartment. |
---|
| 333 | ! Growth respiration of a plant compartment is a fraction of the allocatable biomass remaining after |
---|
| 334 | ! maintenance respiration losses have been taken into account. The fraction of allocatable biomass |
---|
| 335 | ! removed for growth respiration is the same for all plant compartments and is defined by the parameter |
---|
| 336 | ! frac_growth_resp in stomate_constants.f90. Allocatable biomass ::bm_alloc is updated as a result of |
---|
| 337 | ! the removal of growth resp. |
---|
[2282] | 338 | resp_growth_part(:,:) = frac_growthresp(j) * bm_alloc(:,j,:,icarbon) / dt |
---|
| 339 | bm_alloc(:,j,:,icarbon) = ( un - frac_growthresp(j) ) * bm_alloc(:,j,:,icarbon) |
---|
[947] | 340 | |
---|
| 341 | !! 3.5 Total growth respiration |
---|
| 342 | ! Calculate total growth respiration of the plant as the sum of growth respiration of all plant parts |
---|
[8] | 343 | resp_growth(:,j) = zero |
---|
| 344 | |
---|
| 345 | DO k = 1, nparts |
---|
| 346 | resp_growth(:,j) = resp_growth(:,j) + resp_growth_part(:,k) |
---|
[6151] | 347 | resp_growth_part_weighted(:,k) = resp_growth_part_weighted(:,k) + resp_growth_part(:,k)*veget_cov_max(:,j) |
---|
| 348 | resp_maint_part_weighted(:,k) = resp_maint_part_weighted(:,k) + resp_maint_part(:,j,k)*veget_cov_max(:,j) |
---|
[8] | 349 | ENDDO |
---|
| 350 | |
---|
[947] | 351 | ENDDO ! # End Loop over # of PFTs |
---|
[8] | 352 | |
---|
[947] | 353 | |
---|
| 354 | !! 4. Update the biomass with newly allocated biomass after respiration |
---|
| 355 | |
---|
| 356 | ! Save the old leaf biomass for later. "old" leaf mass is leaf mass after maintenance respiration in the case |
---|
| 357 | ! where maintenance respiration has required taking biomass from tissues in section 3.3 |
---|
[1170] | 358 | lm_old(:,:) = biomass(:,:,ileaf,icarbon) |
---|
| 359 | biomass(:,:,:,:) = biomass(:,:,:,:) + bm_alloc(:,:,:,:) |
---|
[8] | 360 | |
---|
[947] | 361 | |
---|
| 362 | !! 5. Deal with negative biomasses |
---|
| 363 | |
---|
[4919] | 364 | ! Biomass can become negative in some rare cases, as the GPP can be negative. This corresponds to |
---|
[947] | 365 | ! situations that can be seen as the 'creation' of a seed ('virtual photosynthesis'). In this case, we set |
---|
[4919] | 366 | ! biomass to a small value (min_stomate). For carbon budget to remain balanced, this creation of matter (carbon) |
---|
| 367 | ! is added to co2_to_bm. In previous versions, this carbon was taken from the autotrophic respiration. |
---|
[947] | 368 | DO k = 1, nparts ! Loop over # of plant parts |
---|
[8] | 369 | |
---|
[947] | 370 | DO j = 2,nvm ! Loop over # of PFTs |
---|
[8] | 371 | |
---|
[1170] | 372 | WHERE ( biomass(:,j,k,icarbon) .LT. zero ) |
---|
[4919] | 373 | |
---|
| 374 | bm_create(:,j) = min_stomate - biomass(:,j,k,icarbon) |
---|
[8] | 375 | |
---|
[4919] | 376 | ! Set biomass to min_stomate |
---|
[1170] | 377 | biomass(:,j,k,icarbon) = biomass(:,j,k,icarbon) + bm_create(:,j) |
---|
[8] | 378 | |
---|
[4919] | 379 | co2_to_bm(:,j) = co2_to_bm(:,j) + bm_create(:,j) |
---|
| 380 | |
---|
[8] | 381 | ENDWHERE |
---|
| 382 | |
---|
[947] | 383 | ENDDO ! Loop over # of PFTs |
---|
[8] | 384 | |
---|
[947] | 385 | ENDDO ! Loop over # plant parts |
---|
[8] | 386 | |
---|
[947] | 387 | |
---|
| 388 | !! 6. Calculate NPP (See Eq 1 in header) |
---|
| 389 | |
---|
| 390 | ! Calculate the NPP @tex $(gC.m^{-2}dt^{-1})$ @endtex as the difference between GPP |
---|
| 391 | ! and autotrophic respiration (maintenance and growth respirations) |
---|
| 392 | DO j = 2,nvm ! Loop over # PFTs |
---|
[8] | 393 | npp(:,j) = gpp(:,j) - resp_growth(:,j) - resp_maint(:,j) |
---|
[947] | 394 | ENDDO ! Loop over # PFTs |
---|
[8] | 395 | |
---|
[947] | 396 | |
---|
| 397 | !! 7. Update leaf age |
---|
[8] | 398 | |
---|
[947] | 399 | ! Leaf age is needed for calculation of turnover and vmax in stomate_turnover.f90 and stomate_vmax.f90 routines. |
---|
| 400 | ! Leaf biomass is distributed according to its age into several "age classes" with age class=1 representing the |
---|
| 401 | ! youngest class, and consisting of the most newly allocated leaf biomass |
---|
| 402 | |
---|
| 403 | !! 7.1 Update quantity and age of the leaf biomass in the youngest class |
---|
| 404 | ! The new amount of leaf biomass in the youngest age class (leaf_mass_young) is the sum of : |
---|
| 405 | ! - the leaf biomass that was already in the youngest age class (leaf_frac(:,j,1) * lm_old(:,j)) with the |
---|
| 406 | ! leaf age given in leaf_age(:,j,1) |
---|
| 407 | ! - and the new biomass allocated to leaves (bm_alloc(:,j,ileaf)) with a leaf age of zero. |
---|
[8] | 408 | DO j = 2,nvm |
---|
[1170] | 409 | leaf_mass_young(:,j) = leaf_frac(:,j,1) * lm_old(:,j) + bm_alloc(:,j,ileaf,icarbon) |
---|
[8] | 410 | ENDDO |
---|
| 411 | |
---|
[947] | 412 | ! The age of the updated youngest age class is the average of the ages of its 2 components: bm_alloc(leaf) of age |
---|
| 413 | ! '0', and leaf_frac*lm_old(=leaf_mass_young-bm_alloc) of age 'leaf_age(:,j,1)' |
---|
[8] | 414 | DO j = 2,nvm |
---|
[1170] | 415 | WHERE ( ( bm_alloc(:,j,ileaf,icarbon) .GT. zero ) .AND. & |
---|
[4624] | 416 | ( leaf_mass_young(:,j) .GT. min_sechiba ) ) |
---|
[8] | 417 | |
---|
| 418 | leaf_age(:,j,1) = MAX ( zero, & |
---|
| 419 | & leaf_age(:,j,1) * & |
---|
[1170] | 420 | & ( leaf_mass_young(:,j) - bm_alloc(:,j,ileaf,icarbon) ) / & |
---|
[8] | 421 | & leaf_mass_young(:,j) ) |
---|
| 422 | |
---|
| 423 | ENDWHERE |
---|
| 424 | ENDDO |
---|
| 425 | |
---|
[947] | 426 | !! 7.2 Update leaf age |
---|
| 427 | ! Update fractions of leaf biomass in each age class (fraction in youngest class increases) |
---|
[8] | 428 | |
---|
[947] | 429 | !! 7.2.1 Update age of youngest leaves |
---|
| 430 | ! For age class 1 (youngest class), because we have added biomass to the youngest class, we need to update |
---|
| 431 | ! the fraction of total leaf biomass that belongs to the youngest age class : updated mass in class divided |
---|
| 432 | ! by new total leaf mass |
---|
[8] | 433 | DO j = 2,nvm |
---|
[1170] | 434 | WHERE ( biomass(:,j,ileaf,icarbon) .GT. min_stomate ) |
---|
[8] | 435 | |
---|
[1170] | 436 | leaf_frac(:,j,1) = leaf_mass_young(:,j) / biomass(:,j,ileaf,icarbon) |
---|
[8] | 437 | |
---|
| 438 | ENDWHERE |
---|
| 439 | ENDDO |
---|
| 440 | |
---|
[947] | 441 | !! 7.2.2 Update age of other age classes |
---|
| 442 | ! Because the total leaf biomass has changed, we need to update the fraction of leaves in each age class: |
---|
| 443 | ! mass in leaf age class (from previous fraction of leaves in this class and previous total leaf biomass) |
---|
| 444 | ! divided by new total mass |
---|
| 445 | DO m = 2, nleafages ! Loop over # leaf age classes |
---|
[8] | 446 | |
---|
[947] | 447 | DO j = 2,nvm ! Loop over # PFTs |
---|
[1170] | 448 | WHERE ( biomass(:,j,ileaf,icarbon) .GT. min_stomate ) |
---|
[8] | 449 | |
---|
[1170] | 450 | leaf_frac(:,j,m) = leaf_frac(:,j,m) * lm_old(:,j) / biomass(:,j,ileaf,icarbon) |
---|
[8] | 451 | |
---|
| 452 | ENDWHERE |
---|
| 453 | ENDDO |
---|
| 454 | |
---|
[947] | 455 | ENDDO ! Loop over # leaf age classes |
---|
[8] | 456 | |
---|
[947] | 457 | !! 8. Update whole-plant age |
---|
| 458 | |
---|
| 459 | !! 8.1 PFT age |
---|
| 460 | ! At every time step, increase age of the biomass that was already present at previous time step. |
---|
| 461 | ! Age is expressed in years, and the time step 'dt' in days so age increase is: dt divided by number |
---|
| 462 | ! of days in a year. |
---|
[8] | 463 | WHERE ( PFTpresent(:,:) ) |
---|
| 464 | |
---|
| 465 | age(:,:) = age(:,:) + dt/one_year |
---|
| 466 | |
---|
| 467 | ELSEWHERE |
---|
| 468 | |
---|
| 469 | age(:,:) = zero |
---|
| 470 | |
---|
| 471 | ENDWHERE |
---|
| 472 | |
---|
[947] | 473 | !! 8.2 Age of grasses and crops |
---|
| 474 | ! For grasses and crops, biomass with age 0 has been added to the whole plant with age 'age'. New biomass is the sum of |
---|
| 475 | ! the current total biomass in all plant parts (bm_new), bm_new(:) = SUM( biomass(:,j,:), DIM=2 ). The biomass that has |
---|
| 476 | ! just been added is the sum of the allocatable biomass of all plant parts (bm_add), its age is zero. bm_add(:) = |
---|
| 477 | ! SUM( bm_alloc(:,j,:), DIM=2 ). Before allocation, the plant biomass is bm_new-bm_add, its age is "age(:,j)". The age of |
---|
| 478 | ! the new biomass is the average of the ages of previous and added biomass. |
---|
| 479 | ! For trees, age is treated in "establish" if vegetation is dynamic, and in turnover routines if it is static (in this |
---|
| 480 | ! case, only the age of the heartwood is accounted for). |
---|
[8] | 481 | DO j = 2,nvm |
---|
| 482 | |
---|
[1091] | 483 | IF ( .NOT. is_tree(j) ) THEN |
---|
[8] | 484 | |
---|
[1170] | 485 | bm_new(:) = biomass(:,j,ileaf,icarbon) + biomass(:,j,isapabove,icarbon) + & |
---|
| 486 | biomass(:,j,iroot,icarbon) + biomass(:,j,ifruit,icarbon) |
---|
| 487 | bm_add(:) = bm_alloc(:,j,ileaf,icarbon) + bm_alloc(:,j,isapabove,icarbon) + & |
---|
| 488 | bm_alloc(:,j,iroot,icarbon) + bm_alloc(:,j,ifruit,icarbon) |
---|
[8] | 489 | |
---|
[4624] | 490 | WHERE ( ( bm_new(:) .GT. min_sechiba ) .AND. ( bm_add(:) .GT. zero ) ) |
---|
[8] | 491 | age(:,j) = age(:,j) * ( bm_new(:) - bm_add(:) ) / bm_new(:) |
---|
| 492 | ENDWHERE |
---|
| 493 | |
---|
| 494 | ENDIF |
---|
| 495 | |
---|
| 496 | ENDDO |
---|
| 497 | |
---|
[947] | 498 | !! 9. Write history files |
---|
[8] | 499 | |
---|
[1788] | 500 | CALL xios_orchidee_send_field("BM_ALLOC_LEAF",bm_alloc(:,:,ileaf,icarbon)) |
---|
| 501 | CALL xios_orchidee_send_field("BM_ALLOC_SAP_AB",bm_alloc(:,:,isapabove,icarbon)) |
---|
| 502 | CALL xios_orchidee_send_field("BM_ALLOC_SAP_BE",bm_alloc(:,:,isapbelow,icarbon)) |
---|
| 503 | CALL xios_orchidee_send_field("BM_ALLOC_ROOT",bm_alloc(:,:,iroot,icarbon)) |
---|
| 504 | CALL xios_orchidee_send_field("BM_ALLOC_FRUIT",bm_alloc(:,:,ifruit,icarbon)) |
---|
| 505 | CALL xios_orchidee_send_field("BM_ALLOC_RES",bm_alloc(:,:,icarbres,icarbon)) |
---|
| 506 | |
---|
[6151] | 507 | CALL xios_orchidee_send_field("resp_maint_part_weighted",resp_maint_part_weighted) |
---|
| 508 | CALL xios_orchidee_send_field("resp_growth_part_weighted",resp_growth_part_weighted) |
---|
[1788] | 509 | |
---|
[6151] | 510 | |
---|
[947] | 511 | ! Save in history file the variables describing the biomass allocated to the plant parts |
---|
[1078] | 512 | CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_LEAF', itime, & |
---|
[1170] | 513 | bm_alloc(:,:,ileaf,icarbon), npts*nvm, horipft_index) |
---|
[1078] | 514 | CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_SAP_AB', itime, & |
---|
[1170] | 515 | bm_alloc(:,:,isapabove,icarbon), npts*nvm, horipft_index) |
---|
[1078] | 516 | CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_SAP_BE', itime, & |
---|
[1170] | 517 | bm_alloc(:,:,isapbelow,icarbon), npts*nvm, horipft_index) |
---|
[1078] | 518 | CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_ROOT', itime, & |
---|
[1170] | 519 | bm_alloc(:,:,iroot,icarbon), npts*nvm, horipft_index) |
---|
[1078] | 520 | CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_FRUIT', itime, & |
---|
[1170] | 521 | bm_alloc(:,:,ifruit,icarbon), npts*nvm, horipft_index) |
---|
[1078] | 522 | CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_RES', itime, & |
---|
[1170] | 523 | bm_alloc(:,:,icarbres,icarbon), npts*nvm, horipft_index) |
---|
[8] | 524 | |
---|
[1788] | 525 | |
---|
[2348] | 526 | IF (printlev>=4) WRITE(numout,*) 'Leaving npp' |
---|
[8] | 527 | |
---|
| 528 | END SUBROUTINE npp_calc |
---|
| 529 | |
---|
| 530 | END MODULE stomate_npp |
---|