source: branches/publications/ORCHIDEE_2.2_r7266/ORCHIDEE/src_stomate/stomate_npp.f90 @ 7541

Last change on this file since 7541 was 7541, checked in by fabienne.maignan, 2 years ago
  1. Zhang publication on coupling factor
File size: 29.8 KB
Line 
1! =================================================================================================================================
2! MODULE          : stomate_npp
3!
4! CONTACT         : orchidee-help _at_ listes.ipsl.fr
5!
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: svn://forge.ipsl.jussieu.fr/orchidee/branches/ORCHIDEE_2_2/ORCHIDEE/src_stomate/stomate_npp.f90 $
22!! $Date: 2019-08-05 11:11:40 +0200 (Mon, 05 Aug 2019) $
23!! $Revision: 6151 $
24!! \n
25!_ ================================================================================================================================
26
27MODULE stomate_npp
28
29  ! modules used:
30  USE xios_orchidee
31  USE ioipsl_para
32  USE stomate_data
33  USE constantes
34  USE constantes_soil
35  USE pft_parameters
36
37  IMPLICIT NONE
38
39  ! private & public routines
40
41  PRIVATE
42  PUBLIC npp_calc,npp_calc_clear
43
44  LOGICAL, SAVE                                              :: firstcall_npp = .TRUE.         !! first call
45!$OMP THREADPRIVATE(firstcall_npp)
46
47CONTAINS
48
49!! ================================================================================================================================
50!! SUBROUTINE   : npp_calc_clear
51!!
52!>\BRIEF        : Set the flag ::firstcall_npp to .TRUE. and as such activate section
53!! 1.1 of the subroutine npp_calc (see below).\n
54!_ ================================================================================================================================
55
56  SUBROUTINE npp_calc_clear
57    firstcall_npp=.TRUE.
58  END SUBROUTINE npp_calc_clear
59
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
115  SUBROUTINE npp_calc (npts, dt, &
116       PFTpresent, veget_cov_max, &
117       t2m, tsoil, lai, rprof, &
118       gpp, f_alloc, bm_alloc, resp_maint_part,&
119       biomass, leaf_age, leaf_frac, age, &
120       resp_maint, resp_growth, npp, co2_to_bm)
121   
122!! 0 Variable and parameter declaration
123
124    !! 0.1 Input variables
125
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)
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
132    REAL(r_std), DIMENSION(npts), INTENT(in)                  :: t2m              !! Temperature at 2 meter (K)
133    REAL(r_std), DIMENSION(npts,nslm), INTENT(in)             :: tsoil            !! Soil temperature of each soil layer (K)
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
144
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         
151    REAL(r_std), DIMENSION(npts,nvm,nparts,nelements), INTENT(out) :: bm_alloc    !! PFT biomass increase, i.e. NPP per plant part
152                                                                                  !! @tex $(gC.m^{-2}dt^{-1})$ @endtex         
153
154    !! 0.3 Modified variables
155
156    REAL(r_std), DIMENSION(npts,nvm,nparts,nelements), INTENT(inout) :: biomass   !! PFT total biomass of each plant part
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)
162    REAL(r_std), DIMENSION(npts,nvm), INTENT(inout)           :: co2_to_bm        !! virtual gpp @tex $(gC.m^{-2})$ @endtex
163
164    !! 0.4 Local variables
165
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         
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
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)
204    INTEGER(i_std)                                            :: ier              !! Error handling
205
206!_ ================================================================================================================================
207
208    IF (printlev>=3) WRITE(numout,*) 'Entering npp'
209   
210 !! 1. Initializations
211   
212    !! 1.1 First call
213    IF ( firstcall_npp ) THEN
214
215       !! 1.1.2 Output message
216       !  Write message including value used for tax_max       
217       IF (printlev >= 2) THEN
218          WRITE(numout,*) 'npp:'
219
220          WRITE(numout,*) '   > max. fraction of allocatable biomass used for'// &
221               ' maint. resp.:', tax_max
222       END IF
223       firstcall_npp = .FALSE.
224
225    ENDIF ! End if first call
226
227    !! 1.2 Set output variables to zero
228    bm_alloc(:,:,:,:) = zero
229    resp_maint(:,:) = zero
230    resp_growth(:,:) = zero
231    npp(:,:) = zero
232    resp_maint_part_weighted(:,:) = zero
233    resp_growth_part_weighted(:,:) = zero
234
235    !! 1.3 Total allocatable biomass
236    ! total allocatable biomass during this time step determined from GPP.
237    ! GPP was calculated as CO2 assimilation in enerbil.f90
238    bm_alloc_tot(:,:) = gpp(:,:) * dt
239
240   
241 
242    !! 3. Calculate maintenance and growth respiration
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
250
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:
256       resp_maint(:,j) = zero
257
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.
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
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
278       bm_tax_max(:) = tax_max * bm_alloc_tot(:,j)
279
280       DO i = 1, npts   ! Loop over # of pixels
281
282          ! If there is enough allocatable biomass to cover maintenance respiration,
283          ! then biomass associated with maintenance respiration is removed from allocatable biomass
284          IF ( bm_alloc_tot(i,j) .GT. zero ) THEN
285               IF ( ( resp_maint(i,j) * dt ) .LT. bm_tax_max(i) )  THEN
286       
287                  bm_alloc_tot(i,j) = bm_alloc_tot(i,j) - resp_maint(i,j) * dt
288
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
292             
293                  bm_alloc_tot(i,j) = bm_alloc_tot(i,j) - bm_tax_max(i)
294
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)
299
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
316             biomass(i,j,icarbres,icarbon) = biomass(i,j,icarbres,icarbon) + & 
317                  bm_alloc_tot(i,j) - resp_maint(i,j) * dt 
318             bm_alloc_tot(i,j) = 0. 
319          ENDIF ! End if there is enough allocatable biomass to cover maintenance respiration
320
321       ENDDO   ! Fortran95: WHERE - ELSEWHERE construct
322
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)
327       DO k = 1, nparts
328          bm_alloc(:,j,k,icarbon) = f_alloc(:,j,k) * bm_alloc_tot(:,j)
329       ENDDO
330
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.
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)
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       
343       resp_growth(:,j) = zero
344
345       DO k = 1, nparts
346          resp_growth(:,j) = resp_growth(:,j) + resp_growth_part(:,k)
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)
349       ENDDO
350
351    ENDDO ! # End Loop over # of PFTs
352
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
358    lm_old(:,:) = biomass(:,:,ileaf,icarbon)
359    biomass(:,:,:,:) = biomass(:,:,:,:) + bm_alloc(:,:,:,:)
360
361   
362 !! 5. Deal with negative biomasses
363   
364    !  Biomass can become negative in some rare cases, as the GPP can be negative. This corresponds to 
365    !  situations that can be seen as the 'creation' of a seed ('virtual photosynthesis'). In this case, we set
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.
368    DO k = 1, nparts    ! Loop over # of plant parts
369
370       DO j = 2,nvm     ! Loop over # of PFTs
371
372          WHERE ( biomass(:,j,k,icarbon) .LT. zero )
373           
374             bm_create(:,j) = min_stomate - biomass(:,j,k,icarbon)
375
376             ! Set biomass to min_stomate
377             biomass(:,j,k,icarbon) = biomass(:,j,k,icarbon) + bm_create(:,j)
378
379             co2_to_bm(:,j) = co2_to_bm(:,j) + bm_create(:,j) 
380
381          ENDWHERE
382
383       ENDDO    ! Loop over # of PFTs
384
385    ENDDO       ! Loop over # plant parts
386
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
393       npp(:,j) = gpp(:,j) - resp_growth(:,j) - resp_maint(:,j)
394    ENDDO       ! Loop over # PFTs
395
396   
397 !! 7. Update leaf age
398
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.
408    DO j = 2,nvm
409       leaf_mass_young(:,j) = leaf_frac(:,j,1) * lm_old(:,j) + bm_alloc(:,j,ileaf,icarbon)
410    ENDDO
411
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)'
414    DO j = 2,nvm
415       WHERE ( ( bm_alloc(:,j,ileaf,icarbon) .GT. zero ) .AND. &
416         ( leaf_mass_young(:,j) .GT. min_sechiba ) )
417
418          leaf_age(:,j,1) = MAX ( zero, &
419               & leaf_age(:,j,1) * &
420               & ( leaf_mass_young(:,j) - bm_alloc(:,j,ileaf,icarbon) ) / &
421               & leaf_mass_young(:,j) )
422         
423       ENDWHERE
424    ENDDO
425
426    !! 7.2 Update leaf age
427    !      Update fractions of leaf biomass in each age class (fraction in youngest class increases)
428
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
433    DO j = 2,nvm
434       WHERE ( biomass(:,j,ileaf,icarbon) .GT. min_stomate )
435
436          leaf_frac(:,j,1) = leaf_mass_young(:,j) / biomass(:,j,ileaf,icarbon)
437
438       ENDWHERE
439    ENDDO
440
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
446
447       DO j = 2,nvm     ! Loop over # PFTs
448          WHERE ( biomass(:,j,ileaf,icarbon) .GT. min_stomate )
449
450             leaf_frac(:,j,m) = leaf_frac(:,j,m) * lm_old(:,j) / biomass(:,j,ileaf,icarbon)
451
452          ENDWHERE
453       ENDDO
454
455    ENDDO       ! Loop over # leaf age classes
456
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.
463    WHERE ( PFTpresent(:,:) )
464
465       age(:,:) = age(:,:) + dt/one_year
466
467    ELSEWHERE
468
469       age(:,:) = zero
470
471    ENDWHERE
472
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).
481    DO j = 2,nvm
482
483       IF ( .NOT. is_tree(j) ) THEN
484
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)
489
490          WHERE ( ( bm_new(:) .GT. min_sechiba ) .AND. ( bm_add(:) .GT. zero ) )
491             age(:,j) = age(:,j) * ( bm_new(:) - bm_add(:) ) / bm_new(:)
492          ENDWHERE
493
494       ENDIF
495
496    ENDDO
497
498 !! 9. Write history files
499
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
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)
509
510
511    ! Save in history file the variables describing the biomass allocated to the plant parts
512    CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_LEAF', itime, &
513         bm_alloc(:,:,ileaf,icarbon), npts*nvm, horipft_index)
514    CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_SAP_AB', itime, &
515         bm_alloc(:,:,isapabove,icarbon), npts*nvm, horipft_index)
516    CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_SAP_BE', itime, &
517         bm_alloc(:,:,isapbelow,icarbon), npts*nvm, horipft_index)
518    CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_ROOT', itime, &
519         bm_alloc(:,:,iroot,icarbon), npts*nvm, horipft_index)
520    CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_FRUIT', itime, &
521         bm_alloc(:,:,ifruit,icarbon), npts*nvm, horipft_index)
522    CALL histwrite_p (hist_id_stomate, 'BM_ALLOC_RES', itime, &
523         bm_alloc(:,:,icarbres,icarbon), npts*nvm, horipft_index)
524
525
526    IF (printlev>=4) WRITE(numout,*) 'Leaving npp'
527
528  END SUBROUTINE npp_calc
529
530END MODULE stomate_npp
Note: See TracBrowser for help on using the repository browser.