1 | ! Light competition |
---|
2 | ! |
---|
3 | ! If canopy is almost closed (fpc > fpc_crit), then trees outcompete grasses. |
---|
4 | ! fpc_crit is normally fpc_crit. |
---|
5 | ! Here, fpc ("foilage protected cover") also takes into account the minimum fraction |
---|
6 | ! of space covered by trees through branches etc. This is done to prevent strong relative |
---|
7 | ! changes of fpc from one day to another for deciduous trees at the beginning of their |
---|
8 | ! growing season, which would yield to strong cutbacks (see 3.2.1.1.2) |
---|
9 | ! No competition between woody pfts (height of individuals is not considered) ! |
---|
10 | ! Exception: when one woody pft is overwhelming (i.e. fpc > fpc_crit). In that |
---|
11 | ! case, eliminate all other woody pfts and reduce dominant pft to fpc_crit. |
---|
12 | ! Age of individuals is not considered. In reality, light competition would more |
---|
13 | ! easily kill young individuals, thus increasing the mean age of the stand. |
---|
14 | ! Exclude agricultural pfts from competition |
---|
15 | ! |
---|
16 | ! $Header: /home/ssipsl/CVSREP/ORCHIDEE/src_stomate/lpj_light.f90,v 1.8 2009/01/06 15:01:25 ssipsl Exp $ |
---|
17 | ! IPSL (2006) |
---|
18 | ! This software is governed by the CeCILL licence see ORCHIDEE/ORCHIDEE_CeCILL.LIC |
---|
19 | ! |
---|
20 | MODULE lpj_light |
---|
21 | |
---|
22 | ! modules used: |
---|
23 | |
---|
24 | USE ioipsl |
---|
25 | USE stomate_constants |
---|
26 | USE constantes_veg |
---|
27 | |
---|
28 | IMPLICIT NONE |
---|
29 | |
---|
30 | ! private & public routines |
---|
31 | |
---|
32 | PRIVATE |
---|
33 | PUBLIC light, light_clear |
---|
34 | |
---|
35 | ! first call |
---|
36 | LOGICAL, SAVE :: firstcall = .TRUE. |
---|
37 | |
---|
38 | CONTAINS |
---|
39 | |
---|
40 | SUBROUTINE light_clear |
---|
41 | firstcall=.TRUE. |
---|
42 | END SUBROUTINE light_clear |
---|
43 | |
---|
44 | SUBROUTINE light (npts, dt, & |
---|
45 | PFTpresent, cn_ind, lai, maxfpc_lastyear, & |
---|
46 | ind, biomass, veget_lastlight, bm_to_litter) |
---|
47 | |
---|
48 | ! |
---|
49 | ! 0 declarations |
---|
50 | ! |
---|
51 | |
---|
52 | ! 0.1 input |
---|
53 | |
---|
54 | ! Domain size |
---|
55 | INTEGER(i_std), INTENT(in) :: npts |
---|
56 | ! Time step (days) |
---|
57 | REAL(r_std), INTENT(in) :: dt |
---|
58 | ! Is pft there |
---|
59 | LOGICAL, DIMENSION(npts,nvm), INTENT(in) :: PFTpresent |
---|
60 | ! crown area of individuals (m**2) |
---|
61 | REAL(r_std), DIMENSION(npts,nvm), INTENT(in) :: cn_ind |
---|
62 | ! leaf area index OF AN INDIVIDUAL PLANT |
---|
63 | REAL(r_std), DIMENSION(npts,nvm), INTENT(in) :: lai |
---|
64 | ! last year's maximum fpc for each natural PFT, on ground |
---|
65 | REAL(r_std), DIMENSION(npts,nvm), INTENT(in) :: maxfpc_lastyear |
---|
66 | |
---|
67 | ! 0.2 modified fields |
---|
68 | |
---|
69 | ! Number of individuals / m2 |
---|
70 | REAL(r_std), DIMENSION(npts,nvm), INTENT(inout) :: ind |
---|
71 | ! biomass (gC/(m**2 of ground)) |
---|
72 | REAL(r_std), DIMENSION(npts,nvm,nparts), INTENT(inout) :: biomass |
---|
73 | ! Vegetation cover after last light competition |
---|
74 | REAL(r_std), DIMENSION(npts,nvm), INTENT(inout) :: veget_lastlight |
---|
75 | ! biomass taken away (gC/m**2) |
---|
76 | REAL(r_std), DIMENSION(npts,nvm,nparts), INTENT(inout) :: bm_to_litter |
---|
77 | |
---|
78 | ! 0.3 local |
---|
79 | |
---|
80 | ! maximum total number of grass individuals in a closed canopy |
---|
81 | REAL(r_std), PARAMETER :: grass_mercy = 0.01 |
---|
82 | ! minimum fraction of trees that survive even in a closed canopy |
---|
83 | REAL(r_std), PARAMETER :: tree_mercy = 0.01 |
---|
84 | ! for diagnosis of fpc increase, compare today's fpc to last year's maximum (T) or |
---|
85 | ! to fpc of last time step (F)? |
---|
86 | LOGICAL, PARAMETER :: annual_increase = .TRUE. |
---|
87 | ! index |
---|
88 | INTEGER(i_std) :: i,j |
---|
89 | ! total natural fpc |
---|
90 | REAL(r_std), DIMENSION(npts) :: sumfpc |
---|
91 | ! total natural woody fpc |
---|
92 | REAL(r_std) :: sumfpc_wood |
---|
93 | ! change in total woody fpc |
---|
94 | REAL(r_std) :: sumdelta_fpc_wood |
---|
95 | ! maximum wood fpc |
---|
96 | REAL(r_std) :: maxfpc_wood |
---|
97 | ! which woody pft is maximum |
---|
98 | INTEGER(i_std) :: optpft_wood |
---|
99 | ! total natural grass fpc |
---|
100 | REAL(r_std) :: sumfpc_grass |
---|
101 | ! this year's foliage protected cover on natural part of the grid cell |
---|
102 | REAL(r_std), DIMENSION(npts,nvm) :: fpc_nat |
---|
103 | ! fpc change within last year |
---|
104 | REAL(r_std), DIMENSION(nvm) :: deltafpc |
---|
105 | ! Relative change of number of individuals for trees |
---|
106 | REAL(r_std) :: reduct |
---|
107 | ! Fraction of plants that survive |
---|
108 | REAL(r_std), DIMENSION(nvm) :: survive |
---|
109 | ! number of grass PFTs present in the grid box |
---|
110 | INTEGER(i_std) :: num_grass |
---|
111 | ! New total grass fpc |
---|
112 | REAL(r_std) :: sumfpc_grass2 |
---|
113 | ! fraction of plants that dies each day (1/day) |
---|
114 | REAL(r_std), DIMENSION(npts,nvm) :: light_death |
---|
115 | |
---|
116 | ! ========================================================================= |
---|
117 | |
---|
118 | IF (bavard.GE.3) WRITE(numout,*) 'Entering light' |
---|
119 | |
---|
120 | ! |
---|
121 | ! 1 first call |
---|
122 | ! |
---|
123 | |
---|
124 | IF ( firstcall ) THEN |
---|
125 | |
---|
126 | WRITE(numout,*) 'light:' |
---|
127 | |
---|
128 | WRITE(numout,*) ' > Maximum total number of grass individuals in' |
---|
129 | WRITE(numout,*) ' a closed canopy: ', grass_mercy |
---|
130 | |
---|
131 | WRITE(numout,*) ' > Minimum fraction of trees that survive even in' |
---|
132 | WRITE(numout,*) ' a closed canopy: ', tree_mercy |
---|
133 | |
---|
134 | WRITE(numout,*) ' > For trees, minimum fraction of crown area covered' |
---|
135 | WRITE(numout,*) ' (due to its branches etc.)', min_cover |
---|
136 | |
---|
137 | WRITE(numout,*) ' > for diagnosis of fpc increase, compare today''s fpc' |
---|
138 | IF ( annual_increase ) THEN |
---|
139 | WRITE(numout,*) ' to last year''s maximum.' |
---|
140 | ELSE |
---|
141 | WRITE(numout,*) ' to fpc of the last time step.' |
---|
142 | ENDIF |
---|
143 | |
---|
144 | firstcall = .FALSE. |
---|
145 | |
---|
146 | ENDIF |
---|
147 | |
---|
148 | ! |
---|
149 | ! 2 fpc characteristics |
---|
150 | ! |
---|
151 | |
---|
152 | ! |
---|
153 | ! 2.1 calculate fpc on natural part of grid cell. |
---|
154 | ! |
---|
155 | |
---|
156 | DO j = 2, nvm |
---|
157 | |
---|
158 | IF ( natural(j) ) THEN |
---|
159 | |
---|
160 | ! 2.1.1 natural PFTs |
---|
161 | |
---|
162 | IF ( tree(j) ) THEN |
---|
163 | |
---|
164 | ! 2.1.1.1 trees: minimum cover due to stems, branches etc. |
---|
165 | |
---|
166 | DO i = 1, npts |
---|
167 | IF (lai(i,j) == val_exp) THEN |
---|
168 | fpc_nat(i,j) = cn_ind(i,j) * ind(i,j) |
---|
169 | ELSE |
---|
170 | fpc_nat(i,j) = cn_ind(i,j) * ind(i,j) * & |
---|
171 | MAX( ( 1._r_std - exp( -lai(i,j) * ext_coeff(j) ) ), min_cover ) |
---|
172 | ENDIF |
---|
173 | ENDDO |
---|
174 | |
---|
175 | ELSE |
---|
176 | |
---|
177 | ! 2.1.1.2 bare ground |
---|
178 | IF (j == ibare_sechiba) THEN |
---|
179 | fpc_nat(:,j) = cn_ind(:,j) * ind(:,j) |
---|
180 | |
---|
181 | ! 2.1.1.3 grasses |
---|
182 | ELSE |
---|
183 | DO i = 1, npts |
---|
184 | IF (lai(i,j) == val_exp) THEN |
---|
185 | fpc_nat(i,j) = cn_ind(i,j) * ind(i,j) |
---|
186 | ELSE |
---|
187 | fpc_nat(i,j) = cn_ind(i,j) * ind(i,j) * & |
---|
188 | ( 1._r_std - exp( -lai(i,j) * ext_coeff(j) ) ) |
---|
189 | ENDIF |
---|
190 | ENDDO |
---|
191 | ENDIF |
---|
192 | ENDIF ! tree/grass |
---|
193 | |
---|
194 | ELSE |
---|
195 | |
---|
196 | ! 2.1.2 agricultural PFTs: not present on natural part |
---|
197 | |
---|
198 | fpc_nat(:,j) = 0.0 |
---|
199 | |
---|
200 | ENDIF ! natural/agricultural |
---|
201 | |
---|
202 | ENDDO |
---|
203 | |
---|
204 | ! |
---|
205 | ! 2.2 sum natural fpc for every grid point |
---|
206 | ! |
---|
207 | |
---|
208 | sumfpc(:) = zero |
---|
209 | DO j = 2,nvm |
---|
210 | !SZ bug correction MERGE: need to subtract agricultural area! |
---|
211 | sumfpc(:) = sumfpc(:) + fpc_nat(:,j) |
---|
212 | ENDDO |
---|
213 | |
---|
214 | ! |
---|
215 | ! 3 Light competition |
---|
216 | ! |
---|
217 | |
---|
218 | light_death(:,:) = 0.0 |
---|
219 | |
---|
220 | DO i = 1, npts ! SZ why this loop and not a vector statement ? |
---|
221 | |
---|
222 | ! Only if vegetation cover is dense |
---|
223 | |
---|
224 | IF ( sumfpc(i) .GT. fpc_crit ) THEN |
---|
225 | |
---|
226 | ! fpc change for each pft |
---|
227 | ! There are two possibilities: either we compare today's fpc with the fpc after the last |
---|
228 | ! time step, or we compare it to last year's maximum fpc of that PFT. In the first case, |
---|
229 | ! the fpc increase will be strong for seasonal PFTs at the beginning of the growing season. |
---|
230 | ! As for trees, the cutback is proportional to this increase, this means that seasonal trees |
---|
231 | ! will be disadvantaged compared to evergreen trees. In the original LPJ model, with its |
---|
232 | ! annual time step, the second method was used (this corresponds to annual_increase=.TRUE.) |
---|
233 | |
---|
234 | IF ( annual_increase ) THEN |
---|
235 | deltafpc(:) = MAX( (fpc_nat(i,:)-maxfpc_lastyear(i,:)), 0._r_std ) |
---|
236 | ELSE |
---|
237 | deltafpc(:) = MAX( (fpc_nat(i,:)-veget_lastlight(i,:)), 0._r_std ) |
---|
238 | ENDIF |
---|
239 | |
---|
240 | ! default: survive |
---|
241 | |
---|
242 | survive(:) = 1.0 |
---|
243 | |
---|
244 | ! |
---|
245 | ! 3.1 determine some characteristics of the fpc distribution |
---|
246 | ! |
---|
247 | |
---|
248 | sumfpc_wood = 0.0 |
---|
249 | sumdelta_fpc_wood = 0.0 |
---|
250 | maxfpc_wood = 0.0 |
---|
251 | optpft_wood = 0 |
---|
252 | sumfpc_grass = 0.0 |
---|
253 | num_grass = 0 |
---|
254 | |
---|
255 | DO j = 2,nvm |
---|
256 | |
---|
257 | ! only natural pfts |
---|
258 | |
---|
259 | IF ( natural(j) ) THEN |
---|
260 | |
---|
261 | IF ( tree(j) ) THEN |
---|
262 | |
---|
263 | ! trees |
---|
264 | |
---|
265 | ! total woody fpc |
---|
266 | |
---|
267 | sumfpc_wood = sumfpc_wood + fpc_nat(i,j) |
---|
268 | |
---|
269 | ! how much did the woody fpc increase |
---|
270 | |
---|
271 | sumdelta_fpc_wood = sumdelta_fpc_wood + deltafpc(j) |
---|
272 | |
---|
273 | ! which woody pft is preponderant |
---|
274 | |
---|
275 | IF ( fpc_nat(i,j) .GT. maxfpc_wood ) THEN |
---|
276 | |
---|
277 | optpft_wood = j |
---|
278 | |
---|
279 | maxfpc_wood = fpc_nat(i,j) |
---|
280 | |
---|
281 | ENDIF |
---|
282 | |
---|
283 | ELSE |
---|
284 | |
---|
285 | ! grasses |
---|
286 | |
---|
287 | ! total (natural) grass fpc |
---|
288 | |
---|
289 | sumfpc_grass = sumfpc_grass + fpc_nat(i,j) |
---|
290 | |
---|
291 | ! number of grass PFTs present in the grid box |
---|
292 | |
---|
293 | IF ( PFTpresent(i,j) ) THEN |
---|
294 | num_grass = num_grass + 1 |
---|
295 | ENDIF |
---|
296 | |
---|
297 | ENDIF ! tree or grass |
---|
298 | |
---|
299 | ENDIF ! natural |
---|
300 | |
---|
301 | ENDDO ! loop over pfts |
---|
302 | |
---|
303 | ! |
---|
304 | ! 3.2 light competition: assume wood outcompetes grass |
---|
305 | ! |
---|
306 | |
---|
307 | IF (sumfpc_wood .GE. fpc_crit ) THEN |
---|
308 | |
---|
309 | ! |
---|
310 | ! 3.2.1 all allowed natural space is covered by wood: |
---|
311 | ! cut back trees to fpc_crit. |
---|
312 | ! Original DGVM: kill grasses. Modified: we let a very |
---|
313 | ! small fraction of grasses survive. |
---|
314 | ! |
---|
315 | |
---|
316 | DO j = 2,nvm |
---|
317 | |
---|
318 | ! only present and natural pfts compete |
---|
319 | |
---|
320 | IF ( PFTpresent(i,j) .AND. natural(j) ) THEN |
---|
321 | |
---|
322 | IF ( tree(j) ) THEN |
---|
323 | |
---|
324 | ! |
---|
325 | ! 3.2.1.1 tree |
---|
326 | ! |
---|
327 | |
---|
328 | IF ( maxfpc_wood .GE. fpc_crit ) THEN |
---|
329 | |
---|
330 | ! 3.2.1.1.1 one single woody pft is overwhelming |
---|
331 | |
---|
332 | IF ( j .eq. optpft_wood ) THEN |
---|
333 | |
---|
334 | ! reduction for this dominant pft |
---|
335 | |
---|
336 | reduct = 1. - fpc_crit / fpc_nat(i,j) |
---|
337 | |
---|
338 | ELSE |
---|
339 | |
---|
340 | ! strongly reduce all other woody pfts |
---|
341 | ! (original DGVM: tree_mercy = 0.0 ) |
---|
342 | |
---|
343 | reduct = 1. - tree_mercy |
---|
344 | |
---|
345 | ENDIF ! pft = dominant woody pft |
---|
346 | |
---|
347 | ELSE |
---|
348 | |
---|
349 | ! 3.2.1.1.2 no single woody pft is overwhelming |
---|
350 | ! (original DGVM: tree_mercy = 0.0 ) |
---|
351 | ! The reduction rate is proportional to the ratio deltafpc/fpc. |
---|
352 | |
---|
353 | IF ( fpc_nat(i,j) .GE. min_stomate ) THEN |
---|
354 | |
---|
355 | reduct = MIN( ( ( deltafpc(j)/sumdelta_fpc_wood * & |
---|
356 | (sumfpc_wood-fpc_crit) ) / fpc_nat(i,j) ), & |
---|
357 | ( 1._r_std - tree_mercy ) ) |
---|
358 | |
---|
359 | ELSE |
---|
360 | |
---|
361 | ! tree fpc didn't icrease or it started from nothing |
---|
362 | |
---|
363 | reduct = 0. |
---|
364 | |
---|
365 | ENDIF |
---|
366 | |
---|
367 | ENDIF ! maxfpc_wood > fpc_crit |
---|
368 | |
---|
369 | survive(j) = 1. - reduct |
---|
370 | |
---|
371 | ELSE |
---|
372 | |
---|
373 | ! |
---|
374 | ! 3.2.1.2 grass: let a very small fraction survive (the sum of all |
---|
375 | ! grass individuals may make up a maximum cover of |
---|
376 | ! grass_mercy [for lai -> infinity]). |
---|
377 | ! In the original DGVM, grasses were killed in that case, |
---|
378 | ! corresponding to grass_mercy = 0. |
---|
379 | ! |
---|
380 | |
---|
381 | survive(j) = ( grass_mercy / REAL( num_grass,r_std ) ) / ind(i,j) |
---|
382 | |
---|
383 | survive(j) = MIN( 1._r_std, survive(j) ) |
---|
384 | |
---|
385 | ENDIF ! tree or grass |
---|
386 | |
---|
387 | ENDIF ! pft there and natural |
---|
388 | |
---|
389 | ENDDO ! loop over pfts |
---|
390 | |
---|
391 | ELSE |
---|
392 | |
---|
393 | ! |
---|
394 | ! 3.2.2 not too much wood so that grasses can subsist |
---|
395 | ! |
---|
396 | |
---|
397 | ! new total grass fpc |
---|
398 | sumfpc_grass2 = fpc_crit - sumfpc_wood |
---|
399 | |
---|
400 | DO j = 2,nvm |
---|
401 | |
---|
402 | ! only present and natural PFTs compete |
---|
403 | |
---|
404 | IF ( PFTpresent(i,j) .AND. natural(j) ) THEN |
---|
405 | |
---|
406 | IF ( tree(j) ) THEN |
---|
407 | |
---|
408 | ! no change for trees |
---|
409 | |
---|
410 | survive(j) = 1.0 |
---|
411 | |
---|
412 | ELSE |
---|
413 | |
---|
414 | ! grass: fractional loss is the same for all grasses |
---|
415 | |
---|
416 | IF ( sumfpc_grass .GT. min_stomate ) THEN |
---|
417 | survive(j) = sumfpc_grass2 / sumfpc_grass |
---|
418 | ELSE |
---|
419 | survive(j)= 0.0 |
---|
420 | ENDIF |
---|
421 | |
---|
422 | ENDIF |
---|
423 | |
---|
424 | ENDIF ! pft there and natural |
---|
425 | |
---|
426 | ENDDO ! loop over pfts |
---|
427 | |
---|
428 | ENDIF ! sumfpc_wood > fpc_crit |
---|
429 | |
---|
430 | ! |
---|
431 | ! 3.3 update output variables |
---|
432 | ! |
---|
433 | |
---|
434 | DO j = 2,nvm |
---|
435 | |
---|
436 | IF ( PFTpresent(i,j) .AND. natural(j) ) THEN |
---|
437 | |
---|
438 | bm_to_litter(i,j,:) = bm_to_litter(i,j,:) + & |
---|
439 | biomass(i,j,:) * ( 1. - survive(j) ) |
---|
440 | |
---|
441 | biomass(i,j,:) = biomass(i,j,:) * survive(j) |
---|
442 | |
---|
443 | IF ( control%ok_dgvm ) THEN |
---|
444 | ind(i,j) = ind(i,j) * survive(j) |
---|
445 | ENDIF |
---|
446 | |
---|
447 | ! fraction of plants that dies each day. |
---|
448 | ! exact formulation: light_death(i,j) = 1. - survive(j) ** (1/dt) |
---|
449 | light_death(i,j) = ( 1. - survive(j) ) / dt |
---|
450 | |
---|
451 | ENDIF ! pft there and natural |
---|
452 | |
---|
453 | ENDDO ! loop over pfts |
---|
454 | |
---|
455 | ENDIF ! sumfpc > fpc_crit |
---|
456 | |
---|
457 | ENDDO ! loop over grid points |
---|
458 | |
---|
459 | ! |
---|
460 | ! 4 recalculate fpc on natural part of grid cell (for next light competition) |
---|
461 | ! |
---|
462 | |
---|
463 | DO j = 2,nvm |
---|
464 | |
---|
465 | IF ( natural(j) ) THEN |
---|
466 | |
---|
467 | ! |
---|
468 | ! 4.1 natural PFTs |
---|
469 | ! |
---|
470 | |
---|
471 | IF ( tree(j) ) THEN |
---|
472 | |
---|
473 | ! 4.1.1 trees: minimum cover due to stems, branches etc. |
---|
474 | |
---|
475 | DO i = 1, npts |
---|
476 | IF (lai(i,j) == val_exp) THEN |
---|
477 | veget_lastlight(i,j) = cn_ind(i,j) * ind(i,j) |
---|
478 | ELSE |
---|
479 | veget_lastlight(i,j) = & |
---|
480 | cn_ind(i,j) * ind(i,j) * & |
---|
481 | MAX( ( 1._r_std - exp( -lai(i,j) * ext_coeff(j) ) ), min_cover ) |
---|
482 | ENDIF |
---|
483 | ENDDO |
---|
484 | |
---|
485 | ELSE |
---|
486 | |
---|
487 | ! 4.1.2 grasses |
---|
488 | DO i = 1, npts |
---|
489 | IF (lai(i,j) == val_exp) THEN |
---|
490 | veget_lastlight(i,j) = cn_ind(i,j) * ind(i,j) |
---|
491 | ELSE |
---|
492 | veget_lastlight(i,j) = cn_ind(i,j) * ind(i,j) * & |
---|
493 | ( 1. - exp( -lai(i,j) * ext_coeff(j) ) ) |
---|
494 | ENDIF |
---|
495 | ENDDO |
---|
496 | ENDIF ! tree/grass |
---|
497 | |
---|
498 | ELSE |
---|
499 | |
---|
500 | ! |
---|
501 | ! 4.2 agricultural PFTs: not present on natural part |
---|
502 | ! |
---|
503 | |
---|
504 | veget_lastlight(:,j) = 0.0 |
---|
505 | |
---|
506 | ENDIF ! natural/agricultural |
---|
507 | |
---|
508 | ENDDO |
---|
509 | |
---|
510 | ! |
---|
511 | ! 5 history |
---|
512 | ! |
---|
513 | |
---|
514 | CALL histwrite (hist_id_stomate, 'LIGHT_DEATH', itime, & |
---|
515 | light_death, npts*nvm, horipft_index) |
---|
516 | |
---|
517 | IF (bavard.GE.4) WRITE(numout,*) 'Leaving light' |
---|
518 | |
---|
519 | END SUBROUTINE light |
---|
520 | |
---|
521 | END MODULE lpj_light |
---|