1 | ! ================================================================================================================================ |
---|
2 | ! MODULE : function_library |
---|
3 | ! |
---|
4 | ! CONTACT : orchidee-help _at_ ipsl.jussieu.fr |
---|
5 | ! |
---|
6 | ! LICENCE : IPSL (2006) |
---|
7 | ! This software is governed by the CeCILL licence see ORCHIDEE/ORCHIDEE_CeCILL.LIC |
---|
8 | ! |
---|
9 | !>\BRIEF Collection of functions that are used throughout the ORCHIDEE code |
---|
10 | !! |
---|
11 | !!\n DESCRIPTION: Collection of modules to : (1) convert one variable into another i.e. basal area |
---|
12 | !! to diameter, diamter to tree height, diameter to crown area, etc. (2) ... |
---|
13 | !! |
---|
14 | !! RECENT CHANGE(S): None |
---|
15 | !! |
---|
16 | !! REFERENCE(S) : |
---|
17 | !! |
---|
18 | !! SVN : |
---|
19 | !! $HeadURL: svn://forge.ipsl.jussieu.fr/orchidee/branches/ORCHIDEE-DOFOCO/ORCHIDEE/src_stomate/stomate_prescribe.f90 $ |
---|
20 | !! $Date: 2013-01-04 16:50:56 +0100 (Fri, 04 Jan 2013) $ |
---|
21 | !! $Revision: 1126 $ |
---|
22 | !! \n |
---|
23 | !_ ================================================================================================================================ |
---|
24 | |
---|
25 | MODULE function_library |
---|
26 | |
---|
27 | ! modules used: |
---|
28 | |
---|
29 | USE pft_parameters |
---|
30 | USE constantes |
---|
31 | |
---|
32 | IMPLICIT NONE |
---|
33 | |
---|
34 | ! private & public routines |
---|
35 | |
---|
36 | PRIVATE |
---|
37 | PUBLIC calculate_c0_alloc, & |
---|
38 | wood_to_ba_eff, & |
---|
39 | wood_to_ba, & |
---|
40 | wood_to_height, & |
---|
41 | wood_to_qmheight, & |
---|
42 | wood_to_height_eff, & |
---|
43 | wood_to_volume, & |
---|
44 | wood_to_dia, & |
---|
45 | wood_to_qmdia, & |
---|
46 | wood_to_circ, & |
---|
47 | wood_to_cn_dia, & |
---|
48 | wood_to_cv, & |
---|
49 | cc_to_biomass, & |
---|
50 | biomass_to_cc, & |
---|
51 | cc_to_lai, & |
---|
52 | biomass_to_lai, & |
---|
53 | lai_to_biomass, & |
---|
54 | Nmax, & |
---|
55 | calculate_rdi, & |
---|
56 | check_vegetation_area, & |
---|
57 | check_mass_balance, & |
---|
58 | intermediate_mass_balance_check, & |
---|
59 | check_pixel_area, & |
---|
60 | check_area_change, & |
---|
61 | check_variable_change, & |
---|
62 | check_variable_swap, & |
---|
63 | check_biomass_change, & |
---|
64 | biomass_to_coupled_lai, & |
---|
65 | sort_circ_class_biomass, & |
---|
66 | Arrhenius, & |
---|
67 | Arrhenius_modified, & |
---|
68 | Arrhenius_modified_nodim |
---|
69 | |
---|
70 | INTERFACE biomass_to_lai |
---|
71 | MODULE PROCEDURE biomass_to_lai_0d, biomass_to_lai_1d |
---|
72 | END INTERFACE |
---|
73 | |
---|
74 | INTERFACE lai_to_biomass |
---|
75 | MODULE PROCEDURE lai_to_biomass_0d, lai_to_biomass_1d |
---|
76 | END INTERFACE |
---|
77 | |
---|
78 | INTERFACE cc_to_biomass |
---|
79 | MODULE PROCEDURE cc_to_biomass_2d, cc_to_biomass_4d |
---|
80 | END INTERFACE cc_to_biomass |
---|
81 | |
---|
82 | INTERFACE biomass_to_cc |
---|
83 | MODULE PROCEDURE biomass_to_cc_1d, biomass_to_cc_3d |
---|
84 | END INTERFACE biomass_to_cc |
---|
85 | |
---|
86 | INTERFACE cc_to_lai |
---|
87 | MODULE PROCEDURE cc_to_lai_0d, cc_to_lai_1d |
---|
88 | END INTERFACE |
---|
89 | |
---|
90 | INTERFACE Arrhenius |
---|
91 | MODULE PROCEDURE Arrhenius_0d, Arrhenius_1d |
---|
92 | END INTERFACE |
---|
93 | |
---|
94 | INTERFACE Arrhenius_modified |
---|
95 | MODULE PROCEDURE Arrhenius_modified_0d, Arrhenius_modified_1d |
---|
96 | END INTERFACE |
---|
97 | |
---|
98 | CONTAINS |
---|
99 | |
---|
100 | |
---|
101 | !! ================================================================================================================================ |
---|
102 | !! FUNCTION : biomass_to_coupled_lai |
---|
103 | !! |
---|
104 | !>\BRIEF Calculate the coupled_LAI based on biomass and veget of each pft |
---|
105 | !! |
---|
106 | !! DESCRIPTION : Calculates the lai that is coupled with the atmosphere |
---|
107 | !! |
---|
108 | !! |
---|
109 | !! |
---|
110 | !! RECENT CHANGE(S): None |
---|
111 | !! |
---|
112 | !! RETURN VALUE : ::coupled_lai (m2/m2) |
---|
113 | !! |
---|
114 | !! REFERENCE(S) : |
---|
115 | !! |
---|
116 | !! FLOWCHART : None |
---|
117 | !! \n |
---|
118 | !_ ================================================================================================================================ |
---|
119 | |
---|
120 | FUNCTION biomass_to_coupled_lai(biomass_leaf, veget, pft) |
---|
121 | |
---|
122 | !! 0. Variable and parameter declaration |
---|
123 | |
---|
124 | !! 0.1 Input variables |
---|
125 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
126 | REAL(r_std) :: veget !! 1-Pgap or the vegetation cover |
---|
127 | REAL(r_std) :: biomass_leaf !! Biomass of an individual tree within a circ |
---|
128 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
129 | |
---|
130 | !! 0.2 Output variables |
---|
131 | REAL(r_std) :: biomass_to_coupled_lai !! What we get out of this function, depends on the on which |
---|
132 | !! leaf biomass is passed to the function; |
---|
133 | !! is it at the tree or the stand level. At the tree level |
---|
134 | !! it corresponds to the leaf area per tree (m2). At the |
---|
135 | !! stand levels it is the fraction of the LAI that is |
---|
136 | !! assumed to interact with the atmosphere |
---|
137 | !! @tex $(m^{2} m^{-2})$ @endtex |
---|
138 | !! 0.3 Modified variables |
---|
139 | |
---|
140 | !! 0.4 Local variables |
---|
141 | REAL(r_std) :: lai !! Leaf area index |
---|
142 | !! @tex $(m^{2} m^{-2})$ @endtex |
---|
143 | !_ ================================================================================================================================ |
---|
144 | |
---|
145 | lai = biomass_to_lai(biomass_leaf, pft) |
---|
146 | |
---|
147 | !+++CHECK+++ |
---|
148 | ! In a closed canopy not all the leaves fully interact with the |
---|
149 | ! atmosphere because leaves can shelter each other. In a more |
---|
150 | ! open canopy most leaves can interact with the atmosphere. |
---|
151 | ! For the moment we are not clear how to calculate the fraction of |
---|
152 | ! the canopy that is coupled to the atmosphere. Also, based on the |
---|
153 | ! simulated evapotranspiration we need the entire canopy to be |
---|
154 | ! coupled to the atmosphere to obtain simulations which are close |
---|
155 | ! to the observations (Jung's upscaled product). |
---|
156 | IF (veget .GT. min_sechiba) THEN |
---|
157 | |
---|
158 | biomass_to_coupled_lai = lai |
---|
159 | |
---|
160 | ELSE |
---|
161 | |
---|
162 | ! There are so many gaps that veget is extremely small. It is fair to |
---|
163 | ! assume that the whole canopy is coupled to the atmosphere. |
---|
164 | biomass_to_coupled_lai = lai |
---|
165 | |
---|
166 | ENDIF |
---|
167 | |
---|
168 | END FUNCTION biomass_to_coupled_lai |
---|
169 | |
---|
170 | |
---|
171 | !! ================================================================================================================================ |
---|
172 | !! FUNCTION : biomass_to_lai_0d |
---|
173 | !! |
---|
174 | !>\BRIEF Calculate the LAI based on the leaf biomass |
---|
175 | !! |
---|
176 | !! DESCRIPTION : Calculates the LAI of a PFT/grid square based on the leaf biomass |
---|
177 | !! |
---|
178 | !! RECENT CHANGE(S): None |
---|
179 | !! |
---|
180 | !! RETURN VALUE : ::LAI [m**2 m**{-2}] |
---|
181 | !! |
---|
182 | !! REFERENCE(S) : |
---|
183 | !! |
---|
184 | !! FLOWCHART : None |
---|
185 | !! \n |
---|
186 | !_ ================================================================================================================================ |
---|
187 | |
---|
188 | FUNCTION biomass_to_lai_0d(leaf_biomass, pft) |
---|
189 | |
---|
190 | !! 0. Variable and parameter declaration |
---|
191 | |
---|
192 | !! 0.1 Input variables |
---|
193 | |
---|
194 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
195 | REAL(r_std) :: leaf_biomass !! Biomass of the leaves |
---|
196 | !! @tex $(gC m^{-2})$ @endtex |
---|
197 | |
---|
198 | |
---|
199 | !! 0.2 Output variables |
---|
200 | |
---|
201 | REAL(r_std) :: biomass_to_lai_0d !! Leaf area index |
---|
202 | !! @tex $(m^{2} m^{-2})$ @endtex |
---|
203 | |
---|
204 | !! 0.3 Modified variables |
---|
205 | |
---|
206 | !! 0.4 Local variables |
---|
207 | REAL(r_std) :: impose_lai !! LAI read from run.def |
---|
208 | !_ ================================================================================================================================ |
---|
209 | |
---|
210 | !! 1. Calculate the LAI from the leaf biomass |
---|
211 | IF(sla_dyn) THEN |
---|
212 | biomass_to_lai_0d = log(1.+ ext_coeff_N(pft) * leaf_biomass * slainit(pft))/(ext_coeff_N(pft)) |
---|
213 | ELSE |
---|
214 | biomass_to_lai_0d = leaf_biomass * sla(pft) |
---|
215 | ENDIF |
---|
216 | |
---|
217 | !!$ !+++HACK+++ |
---|
218 | !!$ ! This is the perfect place to hack the code to make it run with |
---|
219 | !!$ ! constant lai |
---|
220 | !!$ WRITE(numout,*) 'WARNING: Using fake lai values for testing!' |
---|
221 | !!$ biomass_to_lai_1d(:)=3.79052 |
---|
222 | !!$ !++++++++++ |
---|
223 | |
---|
224 | END FUNCTION biomass_to_lai_0d |
---|
225 | |
---|
226 | |
---|
227 | !! ================================================================================================================================ |
---|
228 | !! FUNCTION : biomass_to_lai_1d |
---|
229 | !! |
---|
230 | !>\BRIEF Calculate the LAI based on the leaf biomass |
---|
231 | !! |
---|
232 | !! DESCRIPTION : Calculates the LAI of a PFT/grid square based on the leaf biomass |
---|
233 | !! |
---|
234 | !! RECENT CHANGE(S): None |
---|
235 | !! |
---|
236 | !! RETURN VALUE : ::LAI [m**2 m**{-2}] |
---|
237 | !! |
---|
238 | !! REFERENCE(S) : |
---|
239 | !! |
---|
240 | !! FLOWCHART : None |
---|
241 | !! \n |
---|
242 | !_ ================================================================================================================================ |
---|
243 | |
---|
244 | FUNCTION biomass_to_lai_1d(leaf_biomass, npts, pft) |
---|
245 | |
---|
246 | !! 0. Variable and parameter declaration |
---|
247 | |
---|
248 | !! 0.1 Input variables |
---|
249 | INTEGER(i_std) :: npts |
---|
250 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
251 | REAL(r_std), DIMENSION(npts) :: leaf_biomass !! Biomass of the leaves |
---|
252 | !! @tex $(gC m^{-2})$ @endtex |
---|
253 | |
---|
254 | !! 0.2 Output variables |
---|
255 | |
---|
256 | REAL(r_std), DIMENSION(npts) :: biomass_to_lai_1d !! Leaf area index |
---|
257 | !! @tex $(m^{2} m^{-2})$ @endtex |
---|
258 | !_ ================================================================================================================================ |
---|
259 | |
---|
260 | !! 1. Calculate the LAI from the leaf biomass |
---|
261 | IF(sla_dyn) THEN |
---|
262 | biomass_to_lai_1d = log(1.+ ext_coeff_N(pft) * leaf_biomass * slainit(pft))/(ext_coeff_N(pft)) |
---|
263 | ELSE |
---|
264 | biomass_to_lai_1d = leaf_biomass * sla(pft) |
---|
265 | ENDIF |
---|
266 | |
---|
267 | !!$ !+++HACK+++ |
---|
268 | !!$ ! This is the perfect place to hack the code to make it run with |
---|
269 | !!$ ! constant lai |
---|
270 | !!$ WRITE(numout,*) 'WARNING: Using fake lai values for testing!' |
---|
271 | !!$ biomass_to_lai_1d(:)=3.79052 |
---|
272 | !!$ !++++++++++ |
---|
273 | |
---|
274 | END FUNCTION biomass_to_lai_1d |
---|
275 | |
---|
276 | |
---|
277 | !! ================================================================================================================================ |
---|
278 | !! FUNCTION : lai_to_biomass_0d |
---|
279 | !! |
---|
280 | !>\BRIEF Calculate leaf biomass from lai |
---|
281 | !! |
---|
282 | !! DESCRIPTION : Calculates leaf biomass (m2 m-2) from leaf biomass (gC m-2) |
---|
283 | !! |
---|
284 | !! RECENT CHANGE(S): None |
---|
285 | !! |
---|
286 | !! RETURN VALUE : ::Leaf biomass [gC m^{-2}] |
---|
287 | !! |
---|
288 | !! REFERENCE(S) : |
---|
289 | !! |
---|
290 | !! FLOWCHART : None |
---|
291 | !! \n |
---|
292 | !_ ================================================================================================================================ |
---|
293 | |
---|
294 | FUNCTION lai_to_biomass_0d(lai, pft) |
---|
295 | |
---|
296 | !! 0. Variable and parameter declaration |
---|
297 | |
---|
298 | !! 0.1 Input variables |
---|
299 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
300 | REAL(r_std) :: lai !! Leaf Area Index |
---|
301 | !! @tex $(m^{2} m^{-2})$ @endtex |
---|
302 | |
---|
303 | |
---|
304 | !! 0.2 Output variables |
---|
305 | |
---|
306 | REAL(r_std) :: lai_to_biomass_0d !! Leaf area index |
---|
307 | !! @tex $(gC m^{-2})$ @endtex |
---|
308 | |
---|
309 | !_ ================================================================================================================================ |
---|
310 | |
---|
311 | !! 1. Calculate the LAI from the leaf biomass |
---|
312 | IF(sla_dyn) THEN |
---|
313 | lai_to_biomass_0d = ( exp(lai*ext_coeff_N(pft)) - 1.) / & |
---|
314 | (ext_coeff_N(pft) * slainit(pft)) |
---|
315 | ELSE |
---|
316 | lai_to_biomass_0d = lai / sla(pft) |
---|
317 | ENDIF |
---|
318 | |
---|
319 | END FUNCTION lai_to_biomass_0d |
---|
320 | |
---|
321 | |
---|
322 | |
---|
323 | !! ================================================================================================================================ |
---|
324 | !! FUNCTION : lai_to_biomass_1d |
---|
325 | !! |
---|
326 | !>\BRIEF Calculate leaf biomass from lai |
---|
327 | !! |
---|
328 | !! DESCRIPTION : Calculates leaf biomass (m2 m-2) from leaf biomass (gC m-2) |
---|
329 | !! |
---|
330 | !! RECENT CHANGE(S): None |
---|
331 | !! |
---|
332 | !! RETURN VALUE : ::Leaf biomass [gC m^{-2}] |
---|
333 | !! |
---|
334 | !! REFERENCE(S) : |
---|
335 | !! |
---|
336 | !! FLOWCHART : None |
---|
337 | !! \n |
---|
338 | !_ ================================================================================================================================ |
---|
339 | |
---|
340 | FUNCTION lai_to_biomass_1d(lai, npts, pft) |
---|
341 | |
---|
342 | !! 0. Variable and parameter declaration |
---|
343 | |
---|
344 | !! 0.1 Input variables |
---|
345 | INTEGER(i_std) :: npts |
---|
346 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
347 | REAL(r_std), DIMENSION(npts) :: lai !! Leaf Area Index |
---|
348 | !! @tex $(m^{2} m^{-2})$ @endtex |
---|
349 | |
---|
350 | |
---|
351 | !! 0.2 Output variables |
---|
352 | |
---|
353 | REAL(r_std), DIMENSION(npts) :: lai_to_biomass_1d !! Leaf area index |
---|
354 | !! @tex $(gC m^{-2})$ @endtex |
---|
355 | |
---|
356 | !_ ================================================================================================================================ |
---|
357 | |
---|
358 | !! 1. Calculate the LAI from the leaf biomass |
---|
359 | IF(sla_dyn) THEN |
---|
360 | lai_to_biomass_1d = ( exp(lai*ext_coeff_N(pft)) - 1.) / & |
---|
361 | (ext_coeff_N(pft) * slainit(pft)) |
---|
362 | ELSE |
---|
363 | lai_to_biomass_1d = lai / sla(pft) |
---|
364 | ENDIF |
---|
365 | |
---|
366 | END FUNCTION lai_to_biomass_1d |
---|
367 | |
---|
368 | |
---|
369 | !! ================================================================================================================================ |
---|
370 | !! FUNCTION : calculate_c0_alloc |
---|
371 | !! |
---|
372 | !>\BRIEF Calculate the baseline root vs sapwood allocation |
---|
373 | !! |
---|
374 | !! DESCRIPTION : Calculates the baseline root vs sapwood allocation based on the |
---|
375 | !! parameters of the pipe model (hydraulic conductivities) and the |
---|
376 | !! turnover of the different components |
---|
377 | !! |
---|
378 | !! RECENT CHANGE(S): None |
---|
379 | !! |
---|
380 | !! RETURN VALUE : ::c0_alloc (m) |
---|
381 | !! |
---|
382 | !! REFERENCE(S) : |
---|
383 | !! |
---|
384 | !! FLOWCHART : None |
---|
385 | !! \n |
---|
386 | !_ ================================================================================================================================ |
---|
387 | |
---|
388 | FUNCTION calculate_c0_alloc(pts, pft, longevity_eff_root, longevity_eff_sap) |
---|
389 | |
---|
390 | !! 0. Variable and parameter declaration |
---|
391 | |
---|
392 | !! 0.1 Input variables |
---|
393 | |
---|
394 | INTEGER(i_std) :: pts !! Pixel number (-) |
---|
395 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
396 | REAL(r_std) :: longevity_eff_root !! Effective longivety for leaves (days) |
---|
397 | REAL(r_std) :: longevity_eff_sap !! Effective longivety for leaves (days) |
---|
398 | |
---|
399 | !! 0.2 Output variables |
---|
400 | |
---|
401 | REAL(r_std) :: calculate_c0_alloc !! quadratic mean height (m) |
---|
402 | |
---|
403 | !! 0.3 Modified variables |
---|
404 | |
---|
405 | !! 0.4 Local variables |
---|
406 | REAL(r_std) :: sapwood_density |
---|
407 | REAL(r_std) :: qm_dia !! quadratic mean diameter (m) |
---|
408 | |
---|
409 | !_ ================================================================================================================================ |
---|
410 | |
---|
411 | !! 1. Calculate c0_alloc |
---|
412 | IF ( is_tree(pft) ) THEN |
---|
413 | |
---|
414 | sapwood_density = deux * pipe_density(pft) / kilo_to_unit |
---|
415 | calculate_c0_alloc = sqrt(k_belowground(pft)/k_sap(pft)*longevity_eff_sap/longevity_eff_root*sapwood_density) |
---|
416 | |
---|
417 | ! Grasses and croplands |
---|
418 | ELSE |
---|
419 | |
---|
420 | !+++CHECK+++ |
---|
421 | ! Simply copied the same formulation as for trees but note |
---|
422 | ! that the sapwood in trees vs grasses and crops has a very |
---|
423 | ! meaning. In grasses and crops is structural carbon to ensure |
---|
424 | ! that the allocation works. In trees it really is the sapwood |
---|
425 | sapwood_density = deux * pipe_density(pft) / kilo_to_unit |
---|
426 | calculate_c0_alloc = sqrt(k_belowground(pft)/k_sap(pft)*longevity_eff_sap/longevity_eff_root*sapwood_density) |
---|
427 | !+++++++++++ |
---|
428 | |
---|
429 | ENDIF ! is_tree(j) |
---|
430 | |
---|
431 | END FUNCTION calculate_c0_alloc |
---|
432 | |
---|
433 | |
---|
434 | !! ================================================================================================================================ |
---|
435 | !! FUNCTION : wood_to_ba_eff |
---|
436 | !! |
---|
437 | !>\BRIEF Calculate effective basal area from woody biomass making use of allometric relationships |
---|
438 | !! |
---|
439 | !! DESCRIPTION : Calculate basal area of an individual tree from the woody biomass of that tree making |
---|
440 | !! use of allometric relationships. Effective basal area accounts for both above and below ground carbon |
---|
441 | !! and is the basis for the application of the rule of Deleuze and Dhote. |
---|
442 | !! (i) woodmass = tree_ff * pipe_density*ba*height |
---|
443 | !! (ii) height = pipe_tune2 * sqrt(4/pi*ba) ** pipe_tune_3 |
---|
444 | !! |
---|
445 | !! RECENT CHANGE(S): None |
---|
446 | !! |
---|
447 | !! RETURN VALUE : effective basal area (m2 ind-1) |
---|
448 | !! |
---|
449 | !! REFERENCE(S) : |
---|
450 | !! |
---|
451 | !! FLOWCHART : None |
---|
452 | !! \n |
---|
453 | !_ ================================================================================================================================ |
---|
454 | |
---|
455 | FUNCTION wood_to_ba_eff(biomass_temp, pft) |
---|
456 | |
---|
457 | !! 0. Variable and parameter declaration |
---|
458 | |
---|
459 | !! 0.1 Input variables |
---|
460 | |
---|
461 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
462 | REAL(r_std), DIMENSION(:,:) :: biomass_temp !! Biomass of an individual tree within a circ |
---|
463 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
464 | |
---|
465 | !! 0.2 Output variables |
---|
466 | |
---|
467 | REAL(r_std), DIMENSION(ncirc) :: wood_to_ba_eff !! Effective basal area of an individual tree within a circ |
---|
468 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
469 | |
---|
470 | !! 0.3 Modified variables |
---|
471 | |
---|
472 | !! 0.4 Local variables |
---|
473 | INTEGER(i_std) :: l !! Index |
---|
474 | REAL(r_std) :: woodmass_ind !! Woodmass of an individual tree |
---|
475 | !! @tex $(gC ind^{-1})$ @endtex |
---|
476 | REAL(r_std) :: temp !! temporary variable |
---|
477 | |
---|
478 | !_ ================================================================================================================================ |
---|
479 | |
---|
480 | !! 1. Calculate basal area from woodmass |
---|
481 | |
---|
482 | IF ( is_tree(pft) ) THEN |
---|
483 | |
---|
484 | DO l = 1,ncirc |
---|
485 | |
---|
486 | ! Woodmass of an individual tree |
---|
487 | woodmass_ind = biomass_temp(l,isapabove) + biomass_temp(l,isapbelow) + & |
---|
488 | biomass_temp(l,iheartabove) + biomass_temp(l,iheartbelow) |
---|
489 | |
---|
490 | temp = woodmass_ind/(tree_ff(pft)*pipe_density(pft)*pipe_tune2(pft)) |
---|
491 | |
---|
492 | IF (temp.LT.EPSILON(un)) THEN |
---|
493 | ! Expect an overflow when taking an exponent of such a small number |
---|
494 | wood_to_ba_eff(l) = min_stomate |
---|
495 | ELSE |
---|
496 | ! Basal area of that individual (m2 ind-1) |
---|
497 | wood_to_ba_eff(l) =(pi/4*(woodmass_ind/(tree_ff(pft)*pipe_density(pft)*pipe_tune2(pft))) & |
---|
498 | **(2./pipe_tune3(pft)))**(pipe_tune3(pft)/(pipe_tune3(pft)+2)) |
---|
499 | |
---|
500 | ENDIF |
---|
501 | |
---|
502 | ENDDO |
---|
503 | |
---|
504 | ELSE |
---|
505 | |
---|
506 | WRITE(numout,*) 'pft ',pft |
---|
507 | CALL ipslerr_p (3,'wood_to_ba_eff', & |
---|
508 | 'wood_to_ba_eff is not defined for this PFT.', & |
---|
509 | 'See the output file for more details.','') |
---|
510 | |
---|
511 | ENDIF |
---|
512 | |
---|
513 | END FUNCTION wood_to_ba_eff |
---|
514 | |
---|
515 | |
---|
516 | !! ================================================================================================================================ |
---|
517 | !! FUNCTION : wood_to_ba |
---|
518 | !! |
---|
519 | !>\BRIEF Calculate basal area from woody biomass making use of allometric relationships |
---|
520 | !! |
---|
521 | !! DESCRIPTION : Calculate basal area of an individual tree from the woody biomass of that tree making |
---|
522 | !! use of allometric relationships given below. Here basal area is defined in line with its classical |
---|
523 | !! forestry meaning. |
---|
524 | !! (i) woodmass = tree_ff * pipe_density*ba*height |
---|
525 | !! (ii) height = pipe_tune2 * sqrt(4/pi*ba) ** pipe_tune_3 |
---|
526 | !! |
---|
527 | !! RECENT CHANGE(S): None |
---|
528 | !! |
---|
529 | !! RETURN VALUE : basal area (m2 ind-1) |
---|
530 | !! |
---|
531 | !! REFERENCE(S) : |
---|
532 | !! |
---|
533 | !! FLOWCHART : None |
---|
534 | !! \n |
---|
535 | !_ ================================================================================================================================ |
---|
536 | |
---|
537 | FUNCTION wood_to_ba(biomass_temp, pft) |
---|
538 | |
---|
539 | !! 0. Variable and parameter declaration |
---|
540 | |
---|
541 | !! 0.1 Input variables |
---|
542 | |
---|
543 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
544 | REAL(r_std), DIMENSION(:,:) :: biomass_temp !! Biomass of an individual tree within a circ |
---|
545 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
546 | |
---|
547 | !! 0.2 Output variables |
---|
548 | |
---|
549 | REAL(r_std), DIMENSION(ncirc) :: wood_to_ba !! Basal area of an individual tree within a circ |
---|
550 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
551 | |
---|
552 | !! 0.3 Modified variables |
---|
553 | |
---|
554 | !! 0.4 Local variables |
---|
555 | INTEGER(i_std) :: l !! Index |
---|
556 | REAL(r_std) :: woodmass_ind !! Woodmass of an individual tree |
---|
557 | !! @tex $(gC ind^{-1})$ @endtex |
---|
558 | REAL(r_std) :: temp !! Temporary variable |
---|
559 | |
---|
560 | !_ ================================================================================================================================ |
---|
561 | |
---|
562 | !! 1. Calculate basal area from woodmass |
---|
563 | |
---|
564 | IF ( is_tree(pft) ) THEN |
---|
565 | |
---|
566 | DO l = 1,ncirc |
---|
567 | |
---|
568 | ! Woodmass of an individual tree |
---|
569 | woodmass_ind = biomass_temp(l,iheartabove) + biomass_temp(l,isapabove) |
---|
570 | |
---|
571 | temp = woodmass_ind/(tree_ff(pft)*pipe_density(pft)*pipe_tune2(pft)) |
---|
572 | |
---|
573 | IF (temp.LT.EPSILON(un)) THEN |
---|
574 | ! Expect an overflow when taking an exponent of such a small number |
---|
575 | wood_to_ba(l) = min_stomate |
---|
576 | ELSE |
---|
577 | ! Basal area of that individual (m2 ind-1) |
---|
578 | wood_to_ba(l) = (pi/4*(woodmass_ind/(tree_ff(pft)*pipe_density(pft)*pipe_tune2(pft))) & |
---|
579 | **(2./pipe_tune3(pft)))**(pipe_tune3(pft)/(pipe_tune3(pft)+2)) |
---|
580 | ENDIF |
---|
581 | |
---|
582 | ENDDO |
---|
583 | |
---|
584 | ELSE |
---|
585 | |
---|
586 | WRITE(numout,*) 'pft ',pft |
---|
587 | CALL ipslerr_p (3,'wood_to_ba', & |
---|
588 | 'wood_to_ba is not defined for this PFT.', & |
---|
589 | 'See the output file for more details.','') |
---|
590 | |
---|
591 | ENDIF |
---|
592 | |
---|
593 | END FUNCTION wood_to_ba |
---|
594 | |
---|
595 | |
---|
596 | !! ================================================================================================================================ |
---|
597 | !! FUNCTION : ccbio_to_biomass |
---|
598 | !! |
---|
599 | !>\BRIEF Calculate total biomass from circ_class_biomass |
---|
600 | !! |
---|
601 | !! DESCRIPTION : circ_class_biomass is expressed in gC tree-1 and thus needs to |
---|
602 | !! be multiplied by the number of trees per circumference class |
---|
603 | !! circ_class_n expressed in tree m-2 to calculate the total |
---|
604 | !! biomass in gC m-2. |
---|
605 | !! |
---|
606 | !! RECENT CHANGE(S): None |
---|
607 | !! |
---|
608 | !! RETURN VALUE : total biomass (gC(N) m-2) |
---|
609 | !! |
---|
610 | !! REFERENCE(S) : |
---|
611 | !! |
---|
612 | !! FLOWCHART : None |
---|
613 | !! \n |
---|
614 | !_ ================================================================================================================================ |
---|
615 | |
---|
616 | FUNCTION cc_to_biomass_2d(npts,ivm,ccbio,ccind) |
---|
617 | |
---|
618 | !! 0. Variable and parameter declaration |
---|
619 | |
---|
620 | !! 0.1 Input variables |
---|
621 | |
---|
622 | INTEGER(i_std), INTENT(in) :: npts !! Domain size (unitless) |
---|
623 | INTEGER(i_std), INTENT(in) :: ivm !! number of the specific PFT (unitless) |
---|
624 | REAL(r_std), DIMENSION(:,:,:) :: ccbio !! circ_class_biomass. Biomass of an individual |
---|
625 | !! tree @tex $(gC(N) ind^{-1})$ @endtex |
---|
626 | REAL(r_std), DIMENSION(:) :: ccind !! circ_class_n. Number of trees per circumference |
---|
627 | !! class |
---|
628 | |
---|
629 | !! 0.2 Output variables |
---|
630 | |
---|
631 | REAL(r_std), DIMENSION(nparts,nelements) :: cc_to_biomass_2d !! biomass @tex $(gC(N) m^{2})$ @endtex |
---|
632 | |
---|
633 | !! 0.3 Modified variables |
---|
634 | |
---|
635 | !! 0.4 Local variables |
---|
636 | INTEGER(i_std) :: iele,icir,ipar !! Index |
---|
637 | |
---|
638 | !_ ================================================================================================================================ |
---|
639 | |
---|
640 | cc_to_biomass_2d(:,:) = zero |
---|
641 | |
---|
642 | DO iele = 1,nelements |
---|
643 | |
---|
644 | ! Note that when used in 2d ivm is a single PFT |
---|
645 | ! Use MAX to prevent precision (-10e-16) issues. |
---|
646 | IF ( is_tree(ivm) ) THEN |
---|
647 | |
---|
648 | DO ipar = 1,nparts |
---|
649 | |
---|
650 | DO icir = 1,ncirc |
---|
651 | |
---|
652 | cc_to_biomass_2d(ipar,iele) = MAX(zero,cc_to_biomass_2d(ipar,iele) + & |
---|
653 | ccbio(icir,ipar,iele) * ccind(icir)) |
---|
654 | |
---|
655 | ENDDO |
---|
656 | |
---|
657 | ENDDO |
---|
658 | |
---|
659 | ELSE |
---|
660 | |
---|
661 | ! Grasses and cropland only have one circumference class |
---|
662 | DO ipar = 1,nparts |
---|
663 | |
---|
664 | cc_to_biomass_2d(ipar,iele) = MAX(zero,cc_to_biomass_2d(ipar,iele) + & |
---|
665 | ccbio(1,ipar,iele) * ccind(1)) |
---|
666 | |
---|
667 | ENDDO |
---|
668 | |
---|
669 | ENDIF |
---|
670 | |
---|
671 | ENDDO |
---|
672 | |
---|
673 | END FUNCTION cc_to_biomass_2d |
---|
674 | |
---|
675 | |
---|
676 | !! ================================================================================================================================ |
---|
677 | |
---|
678 | FUNCTION cc_to_biomass_4d(npts,nvm,ccbio,ccind) |
---|
679 | |
---|
680 | !! 0. Variable and parameter declaration |
---|
681 | |
---|
682 | !! 0.1 Input variables |
---|
683 | |
---|
684 | INTEGER(i_std), INTENT(in) :: npts !! Domain size (unitless) |
---|
685 | INTEGER(i_std), INTENT(in) :: nvm !! Total number of PFTs (unitless) |
---|
686 | REAL(r_std), DIMENSION(:,:,:,:,:) :: ccbio !! circ_class_biomass. Biomass of an individual |
---|
687 | !! tree @tex $(gC(N) ind^{-1})$ @endtex |
---|
688 | REAL(r_std), DIMENSION(:,:,:) :: ccind !! circ_class_n. Number of trees per circumference |
---|
689 | !! class |
---|
690 | |
---|
691 | !! 0.2 Output variables |
---|
692 | |
---|
693 | REAL(r_std), DIMENSION(npts,nvm,nparts,nelements) :: cc_to_biomass_4d !! biomass @tex $(gC(N) m^{2})$ @endtex |
---|
694 | |
---|
695 | !! 0.3 Modified variables |
---|
696 | |
---|
697 | !! 0.4 Local variables |
---|
698 | INTEGER(i_std) :: iele,icir,ipar,ivm !! Index |
---|
699 | |
---|
700 | !_ ================================================================================================================================ |
---|
701 | |
---|
702 | cc_to_biomass_4d(:,:,:,:) = zero |
---|
703 | |
---|
704 | DO iele = 1,nelements |
---|
705 | |
---|
706 | ! Note that when used in 4d, nvm rather than ivm |
---|
707 | ! should be passed. Now the function will loop over all |
---|
708 | ! PFTs instead of just 1 PFT for the 2d version of this |
---|
709 | ! function. Use MAX to prevent precision (-10e-16) issues. |
---|
710 | DO ivm = 2,nvm |
---|
711 | |
---|
712 | IF ( is_tree(ivm) ) THEN |
---|
713 | |
---|
714 | DO ipar = 1,nparts |
---|
715 | |
---|
716 | DO icir = 1,ncirc |
---|
717 | |
---|
718 | cc_to_biomass_4d(:,ivm,ipar,iele) = MAX(zero,cc_to_biomass_4d(:,ivm,ipar,iele) + & |
---|
719 | ccbio(:,ivm,icir,ipar,iele) * ccind(:,ivm,icir)) |
---|
720 | |
---|
721 | ENDDO |
---|
722 | |
---|
723 | ENDDO |
---|
724 | |
---|
725 | ELSE |
---|
726 | |
---|
727 | ! Grasses and cropland only have one circumference class |
---|
728 | DO ipar = 1,nparts |
---|
729 | |
---|
730 | cc_to_biomass_4d(:,ivm,ipar,iele) = MAX(zero,cc_to_biomass_4d(:,ivm,ipar,iele) + & |
---|
731 | ccbio(:,ivm,1,ipar,iele) * ccind(:,ivm,1)) |
---|
732 | |
---|
733 | ENDDO |
---|
734 | |
---|
735 | ENDIF |
---|
736 | |
---|
737 | ENDDO |
---|
738 | |
---|
739 | ENDDO |
---|
740 | |
---|
741 | END FUNCTION cc_to_biomass_4d |
---|
742 | |
---|
743 | |
---|
744 | !! ================================================================================================================================ |
---|
745 | !! FUNCTION : biomass_to_cc |
---|
746 | !! |
---|
747 | !>\BRIEF Calculate circ_class_biomass from biomass |
---|
748 | !! |
---|
749 | !! DESCRIPTION : The labile and carbres pools are often dealt with at the stand |
---|
750 | !! level for simplicity but then need to be stored at the plant |
---|
751 | !! level. This is needed because labile and carbres C is lost when |
---|
752 | !! plants are dying. Also, all plant C and N should be stored in a |
---|
753 | !! single variable. |
---|
754 | !! |
---|
755 | !! RECENT CHANGE(S): None |
---|
756 | !! |
---|
757 | !! RETURN VALUE : total biomass (gC(N) m-2) |
---|
758 | !! |
---|
759 | !! REFERENCE(S) : |
---|
760 | !! |
---|
761 | !! FLOWCHART : None |
---|
762 | !! \n |
---|
763 | !_ ================================================================================================================================ |
---|
764 | |
---|
765 | FUNCTION biomass_to_cc_1d(bio,ccbio,ccind) |
---|
766 | |
---|
767 | !! 0. Variable and parameter declaration |
---|
768 | |
---|
769 | !! 0.1 Input variables |
---|
770 | |
---|
771 | REAL(r_std) :: bio !! biomass. Biomass of a specific pool of |
---|
772 | !! a whole stand |
---|
773 | !! @tex $(gC(N) m^{-2})$ @endtex |
---|
774 | REAL(r_std), DIMENSION(:) :: ccbio !! circ_class_biomass. Biomass of a specif pool of |
---|
775 | !! the individual trees in each circumference class |
---|
776 | !! @tex $(gC(N) ind^{-1})$ @endtex |
---|
777 | REAL(r_std), DIMENSION(:) :: ccind !! circ_class_n. Number of trees per circumference |
---|
778 | !! class |
---|
779 | |
---|
780 | !! 0.2 Output variables |
---|
781 | |
---|
782 | REAL(r_std), DIMENSION(ncirc) :: biomass_to_cc_1d !! biomass @tex $(gC(N) m^{2})$ @endtex |
---|
783 | |
---|
784 | !! 0.3 Modified variables |
---|
785 | |
---|
786 | !! 0.4 Local variables |
---|
787 | |
---|
788 | INTEGER(i_std) :: icir !! Index |
---|
789 | REAL(r_std), DIMENSION(ncirc) :: share_ncirc !! ratio of specific pool |
---|
790 | !! across circumference classes |
---|
791 | |
---|
792 | !_ ================================================================================================================================ |
---|
793 | |
---|
794 | biomass_to_cc_1d(:) = zero |
---|
795 | |
---|
796 | ! Convert the pools |
---|
797 | IF (SUM(ccbio(:)*ccind(:)) .GT. zero) THEN |
---|
798 | |
---|
799 | ! Proportional to the present pools |
---|
800 | share_ncirc(:) = (ccbio(:)*ccind(:))/SUM(ccbio(:)*ccind(:)) |
---|
801 | |
---|
802 | ELSEIF (SUM(ccind(:)) .GT. zero) THEN |
---|
803 | |
---|
804 | ! There are no pools at present. Make it proportional |
---|
805 | ! to the number of trees |
---|
806 | share_ncirc(:) = ccind(:)/SUM(ccind(:)) |
---|
807 | |
---|
808 | ELSE |
---|
809 | |
---|
810 | ! There is no biomass in circ_class_biomass or individuals |
---|
811 | share_ncirc(:) = zero |
---|
812 | |
---|
813 | |
---|
814 | ENDIF |
---|
815 | |
---|
816 | share_ncirc(1) = zero |
---|
817 | share_ncirc(1) = 1 - SUM(share_ncirc(:)) |
---|
818 | |
---|
819 | ! Distribute bio over the ncirc circumference classes of biomass_to_cc |
---|
820 | ! biomass_to_cc will eventually be assigned to circ_class_biomass |
---|
821 | DO icir = 1,ncirc |
---|
822 | |
---|
823 | IF (ccind(icir) .GT. zero) THEN |
---|
824 | |
---|
825 | biomass_to_cc_1d(icir) = bio / ccind(icir) * share_ncirc(icir) |
---|
826 | |
---|
827 | ELSE |
---|
828 | |
---|
829 | biomass_to_cc_1d(icir) = zero |
---|
830 | |
---|
831 | ENDIF |
---|
832 | |
---|
833 | ENDDO |
---|
834 | |
---|
835 | END FUNCTION biomass_to_cc_1d |
---|
836 | |
---|
837 | !! ================================================================================================================================ |
---|
838 | FUNCTION biomass_to_cc_3d(bio,ccbio,ccind,npts,nvm) |
---|
839 | |
---|
840 | !! 0. Variable and parameter declaration |
---|
841 | |
---|
842 | !! 0.1 Input variables |
---|
843 | INTEGER(i_std), INTENT(in) :: npts !! Domain size (unitless) |
---|
844 | INTEGER(i_std), INTENT(in) :: nvm !! Total number of PFTs (unitless) |
---|
845 | REAL(r_std),DIMENSION(:,:) :: bio !! biomass. Biomass of a specific pool of |
---|
846 | !! a whole stand. dimensions are npts and nvm |
---|
847 | !! @tex $(gC(N) m^{-2})$ @endtex |
---|
848 | REAL(r_std), DIMENSION(:,:,:) :: ccbio !! circ_class_biomass. Biomass of a specif pool of |
---|
849 | !! the individual trees in each circumference class |
---|
850 | !! @tex $(gC(N) ind^{-1})$ @endtex |
---|
851 | REAL(r_std), DIMENSION(:,:,:) :: ccind !! circ_class_n. Number of trees per circumference |
---|
852 | !! class |
---|
853 | |
---|
854 | !! 0.2 Output variables |
---|
855 | |
---|
856 | REAL(r_std), DIMENSION(npts,nvm,ncirc) :: biomass_to_cc_3d !! biomass @tex $(gC(N) m^{2})$ @endtex |
---|
857 | |
---|
858 | !! 0.3 Modified variables |
---|
859 | |
---|
860 | !! 0.4 Local variables |
---|
861 | |
---|
862 | INTEGER(i_std) :: icir,ipts,ivm !! Index |
---|
863 | REAL(r_std), DIMENSION(ncirc) :: share_ncirc !! ratio of specific pool |
---|
864 | !! across circumference classes |
---|
865 | |
---|
866 | !_ ================================================================================================================================ |
---|
867 | |
---|
868 | biomass_to_cc_3d(:,:,:) = zero |
---|
869 | |
---|
870 | DO ipts = 1,npts |
---|
871 | |
---|
872 | DO ivm = 1,nvm |
---|
873 | |
---|
874 | ! Convert the pools |
---|
875 | IF (is_tree(ivm)) THEN |
---|
876 | |
---|
877 | ! Forests have ncirc circ classes |
---|
878 | IF (SUM(ccbio(ipts,ivm,:)*ccind(ipts,ivm,:)) .GT. zero) THEN |
---|
879 | |
---|
880 | share_ncirc(:) = (ccbio(ipts,ivm,:)*ccind(ipts,ivm,:)) / & |
---|
881 | SUM(ccbio(ipts,ivm,:)*ccind(ipts,ivm,:)) |
---|
882 | |
---|
883 | ELSE |
---|
884 | |
---|
885 | share_ncirc(:) = zero |
---|
886 | |
---|
887 | ENDIF |
---|
888 | |
---|
889 | ELSE |
---|
890 | |
---|
891 | ! Grass and crops |
---|
892 | share_ncirc(:) = zero |
---|
893 | |
---|
894 | ENDIF |
---|
895 | |
---|
896 | ! Make sure that the shares add up to one |
---|
897 | ! and that grass and croplands are properly |
---|
898 | ! dealt with |
---|
899 | share_ncirc(1) = zero |
---|
900 | share_ncirc(1) = 1 - SUM(share_ncirc(:)) |
---|
901 | |
---|
902 | DO icir = 1,ncirc |
---|
903 | |
---|
904 | IF (ccind(ipts,ivm,icir) .GT. zero) THEN |
---|
905 | |
---|
906 | biomass_to_cc_3d(ipts,ivm,icir) = bio(ipts,ivm) / & |
---|
907 | ccind(ipts,ivm,icir) * share_ncirc(icir) |
---|
908 | |
---|
909 | ELSE |
---|
910 | |
---|
911 | biomass_to_cc_3d(ipts,ivm,icir) = zero |
---|
912 | |
---|
913 | ENDIF ! plants are present in this circ_class |
---|
914 | |
---|
915 | ENDDO ! icir |
---|
916 | |
---|
917 | ENDDO ! ivm |
---|
918 | |
---|
919 | ENDDO ! ipts |
---|
920 | |
---|
921 | END FUNCTION biomass_to_cc_3d |
---|
922 | |
---|
923 | !! ================================================================================================================================ |
---|
924 | |
---|
925 | |
---|
926 | |
---|
927 | |
---|
928 | |
---|
929 | |
---|
930 | |
---|
931 | !! ================================================================================================================================ |
---|
932 | !! FUNCTION : cc_to_lai_0d |
---|
933 | !! |
---|
934 | !>\BRIEF Calculate the LAI based on the circ_class_biomass and circ_class_n |
---|
935 | !! |
---|
936 | !! DESCRIPTION : Calculates the LAI of a PFT/grid square based on the leaf biomass |
---|
937 | !! |
---|
938 | !! RECENT CHANGE(S): None |
---|
939 | !! |
---|
940 | !! RETURN VALUE : ::LAI [m**2 m**{-2}] |
---|
941 | !! |
---|
942 | !! REFERENCE(S) : |
---|
943 | !! |
---|
944 | !! FLOWCHART : None |
---|
945 | !! \n |
---|
946 | !_ ================================================================================================================================ |
---|
947 | |
---|
948 | FUNCTION cc_to_lai_0d(ccbio,ccind,pft) |
---|
949 | |
---|
950 | !! 0. Variable and parameter declaration |
---|
951 | |
---|
952 | !! 0.1 Input variables |
---|
953 | INTEGER(i_std), INTENT(in) :: pft !! Number of the PFT under study (unitless) |
---|
954 | REAL(r_std), DIMENSION(:) :: ccbio !! circ_class_biomass. Biomass of an individual |
---|
955 | !! tree @tex $(gC(N) ind^{-1})$ @endtex |
---|
956 | REAL(r_std), DIMENSION(:) :: ccind !! circ_class_n. Number of trees per circumference |
---|
957 | !! class |
---|
958 | |
---|
959 | !! 0.2 Output variables |
---|
960 | REAL(r_std) :: cc_to_lai_0d !! leaf area index @tex $(m^{2} m^{-2})$ @endtex |
---|
961 | |
---|
962 | !! 0.3 Modified variables |
---|
963 | |
---|
964 | !! 0.4 Local variables |
---|
965 | INTEGER(i_std) :: icir !! Index |
---|
966 | REAL(r_std) :: leaf_biomass !! Leaf mass for carbon calculated from |
---|
967 | !! circ_class_biomass and circ_class_n. |
---|
968 | !! @tex $(gC m^{-2})$ @endtex |
---|
969 | !_ ================================================================================================================================ |
---|
970 | |
---|
971 | !! 1. Calculate leaf biomass |
---|
972 | cc_to_lai_0d = zero |
---|
973 | leaf_biomass = zero |
---|
974 | |
---|
975 | IF ( is_tree(pft) ) THEN |
---|
976 | |
---|
977 | DO icir = 1,ncirc |
---|
978 | |
---|
979 | leaf_biomass = leaf_biomass + ccbio(icir) * ccind(icir) |
---|
980 | |
---|
981 | ENDDO |
---|
982 | |
---|
983 | ELSE |
---|
984 | |
---|
985 | ! Grasses and cropland only have one circumference class |
---|
986 | leaf_biomass = ccbio(1) * ccind(1) |
---|
987 | |
---|
988 | ENDIF |
---|
989 | |
---|
990 | !! 2. Calculate the LAI from the leaf biomass |
---|
991 | IF(sla_dyn) THEN |
---|
992 | |
---|
993 | cc_to_lai_0d = log(1.+ ext_coeff_N(pft) * leaf_biomass * & |
---|
994 | slainit(pft))/(ext_coeff_N(pft)) |
---|
995 | |
---|
996 | ELSE |
---|
997 | |
---|
998 | cc_to_lai_0d = leaf_biomass * sla(pft) |
---|
999 | |
---|
1000 | ENDIF |
---|
1001 | |
---|
1002 | END FUNCTION cc_to_lai_0d |
---|
1003 | |
---|
1004 | |
---|
1005 | !! ================================================================================================================================ |
---|
1006 | !! FUNCTION : cc_to_lai_1d |
---|
1007 | !! |
---|
1008 | !>\BRIEF Calculate the LAI based on the circ_class_biomass and circ_class_n |
---|
1009 | !! |
---|
1010 | !! DESCRIPTION : Calculates the LAI of a PFT/grid square based on the leaf biomass |
---|
1011 | !! |
---|
1012 | !! RECENT CHANGE(S): None |
---|
1013 | !! |
---|
1014 | !! RETURN VALUE : ::LAI [m**2 m**{-2}] |
---|
1015 | !! |
---|
1016 | !! REFERENCE(S) : |
---|
1017 | !! |
---|
1018 | !! FLOWCHART : None |
---|
1019 | !! \n |
---|
1020 | !_ ================================================================================================================================ |
---|
1021 | |
---|
1022 | FUNCTION cc_to_lai_1d(npts,ccbio,ccind,pft) |
---|
1023 | |
---|
1024 | !! 0. Variable and parameter declaration |
---|
1025 | |
---|
1026 | !! 0.1 Input variables |
---|
1027 | INTEGER(i_std), INTENT(in) :: npts !! Domain size (unitless) |
---|
1028 | INTEGER(i_std), INTENT(in) :: pft !! number of PFT under study (unitless) |
---|
1029 | REAL(r_std), DIMENSION(:,:,:,:) :: ccbio !! circ_class_biomass. Biomass of an individual |
---|
1030 | !! tree @tex $(gC(N) ind^{-1})$ @endtex |
---|
1031 | REAL(r_std), DIMENSION(:,:) :: ccind !! circ_class_n. Number of trees per circumference |
---|
1032 | !! class |
---|
1033 | |
---|
1034 | !! 0.2 Output variables |
---|
1035 | |
---|
1036 | REAL(r_std), DIMENSION(npts) :: cc_to_lai_1d !! leaf area index @tex $(m^{2} m^{-2})$ @endtex |
---|
1037 | |
---|
1038 | !! 0.3 Modified variables |
---|
1039 | |
---|
1040 | !! 0.4 Local variables |
---|
1041 | INTEGER(i_std) :: icir !! Index |
---|
1042 | REAL(r_std), DIMENSION(npts) :: leaf_biomass !! Leaf mass for carbon calculated from |
---|
1043 | !! circ_class_biomass and circ_class_n. |
---|
1044 | !! @tex $(gC m^{-2})$ @endtex |
---|
1045 | !_ ================================================================================================================================ |
---|
1046 | |
---|
1047 | !! 1. Calculate leaf biomass for a specific PFT |
---|
1048 | cc_to_lai_1d(:) = zero |
---|
1049 | leaf_biomass(:) = zero |
---|
1050 | |
---|
1051 | ! Note that when used in 2d ivm is a single PFT |
---|
1052 | IF ( is_tree(pft) ) THEN |
---|
1053 | |
---|
1054 | DO icir = 1,ncirc |
---|
1055 | |
---|
1056 | leaf_biomass(:) = leaf_biomass(:) + & |
---|
1057 | ccbio(:,icir,ileaf,icarbon) * ccind(:,icir) |
---|
1058 | |
---|
1059 | ENDDO |
---|
1060 | |
---|
1061 | ELSE |
---|
1062 | |
---|
1063 | ! Grasses and cropland only have one circumference class |
---|
1064 | |
---|
1065 | leaf_biomass(:) = ccbio(:,1,ileaf,icarbon) * ccind(:,1) |
---|
1066 | |
---|
1067 | ENDIF |
---|
1068 | |
---|
1069 | !! 2. Calculate the LAI from the leaf biomass |
---|
1070 | IF(sla_dyn) THEN |
---|
1071 | |
---|
1072 | cc_to_lai_1d(:) = log(1.+ ext_coeff_N(pft)* leaf_biomass(:) * & |
---|
1073 | slainit(pft))/(ext_coeff_N(pft)) |
---|
1074 | |
---|
1075 | ELSE |
---|
1076 | |
---|
1077 | cc_to_lai_1d(:) = leaf_biomass(:) * sla(pft) |
---|
1078 | |
---|
1079 | ENDIF |
---|
1080 | |
---|
1081 | END FUNCTION cc_to_lai_1d |
---|
1082 | |
---|
1083 | |
---|
1084 | !! ================================================================================================================================ |
---|
1085 | !! FUNCTION : wood_to_qmheight |
---|
1086 | !! |
---|
1087 | !>\BRIEF Calculate the quadratic mean height from the biomass |
---|
1088 | !! |
---|
1089 | !! DESCRIPTION : Calculates the quadratic mean height from the biomass |
---|
1090 | !! |
---|
1091 | !! RECENT CHANGE(S): None |
---|
1092 | !! |
---|
1093 | !! RETURN VALUE : ::qm_height (m) |
---|
1094 | !! |
---|
1095 | !! REFERENCE(S) : |
---|
1096 | !! |
---|
1097 | !! FLOWCHART : None |
---|
1098 | !! \n |
---|
1099 | !_ ================================================================================================================================ |
---|
1100 | |
---|
1101 | FUNCTION wood_to_qmheight(biomass_temp, ind, pft) |
---|
1102 | |
---|
1103 | !! 0. Variable and parameter declaration |
---|
1104 | |
---|
1105 | !! 0.1 Input variables |
---|
1106 | |
---|
1107 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
1108 | REAL(r_std), DIMENSION(ncirc,nparts) :: biomass_temp !! Biomass of the leaves @tex $(gC m^{-2})$ @endtex |
---|
1109 | REAL(r_std), DIMENSION(ncirc) :: ind !! Number of individuals @tex $(m^{-2})$ @endtex |
---|
1110 | |
---|
1111 | |
---|
1112 | !! 0.2 Output variables |
---|
1113 | |
---|
1114 | REAL(r_std) :: wood_to_qmheight !! quadratic mean height (m) |
---|
1115 | |
---|
1116 | !! 0.3 Modified variables |
---|
1117 | |
---|
1118 | !! 0.4 Local variables |
---|
1119 | REAL(r_std), DIMENSION(ncirc) :: circ_class_ba !! basal area for each circ_class @tex $(m^{2})$ @endtex |
---|
1120 | REAL(r_std) :: qm_dia !! quadratic mean diameter (m) |
---|
1121 | |
---|
1122 | !_ ================================================================================================================================ |
---|
1123 | |
---|
1124 | !! 1. Calculate qm_height from the biomass |
---|
1125 | IF ( is_tree(pft) ) THEN |
---|
1126 | |
---|
1127 | ! Basal area at the tree level (m2 tree-1) |
---|
1128 | circ_class_ba(:) = wood_to_ba(biomass_temp(:,:),pft) |
---|
1129 | |
---|
1130 | IF (SUM(ind(:)) .NE. zero) THEN |
---|
1131 | |
---|
1132 | qm_dia = SQRT( 4/pi*SUM(circ_class_ba(:)*ind(:))/SUM(ind(:)) ) |
---|
1133 | |
---|
1134 | ELSE |
---|
1135 | |
---|
1136 | qm_dia = zero |
---|
1137 | |
---|
1138 | ENDIF |
---|
1139 | |
---|
1140 | wood_to_qmheight = pipe_tune2(pft)*(qm_dia**pipe_tune3(pft)) |
---|
1141 | |
---|
1142 | ELSE |
---|
1143 | |
---|
1144 | ! Grasses and croplands |
---|
1145 | ! Calculate height as a function of the leaf biomass. Ensure that the |
---|
1146 | ! grasslands have a roughness length during the winter. Therefore use a |
---|
1147 | ! lower threshold. |
---|
1148 | IF (SUM(ind(:)) .NE. zero) THEN |
---|
1149 | |
---|
1150 | wood_to_qmheight = MAX(0.2,biomass_temp(1,ileaf)*ind(1)*sla(pft)*lai_to_height(pft)) |
---|
1151 | ELSE |
---|
1152 | |
---|
1153 | wood_to_qmheight = zero |
---|
1154 | |
---|
1155 | ENDIF |
---|
1156 | |
---|
1157 | ENDIF ! is_tree(j) |
---|
1158 | |
---|
1159 | END FUNCTION wood_to_qmheight |
---|
1160 | |
---|
1161 | |
---|
1162 | !! ================================================================================================================================ |
---|
1163 | !! FUNCTION : wood_to_qmdia |
---|
1164 | !! |
---|
1165 | !>\BRIEF Calculate the quadratic mean diameter from the biomass |
---|
1166 | !! |
---|
1167 | !! DESCRIPTION : Calculates the quadratic mean diameter from the aboveground biomass |
---|
1168 | !! |
---|
1169 | !! RECENT CHANGE(S): None |
---|
1170 | !! |
---|
1171 | !! RETURN VALUE : ::qm_dia (m) |
---|
1172 | !! |
---|
1173 | !! REFERENCE(S) : |
---|
1174 | !! |
---|
1175 | !! FLOWCHART : None |
---|
1176 | !! \n |
---|
1177 | !_ ================================================================================================================================ |
---|
1178 | |
---|
1179 | FUNCTION wood_to_qmdia(biomass_temp, ind, pft) |
---|
1180 | |
---|
1181 | !! 0. Variable and parameter declaration |
---|
1182 | |
---|
1183 | !! 0.1 Input variables |
---|
1184 | |
---|
1185 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
1186 | REAL(r_std), DIMENSION(ncirc,nparts) :: biomass_temp !! Biomass of the leaves @tex $(gC m^{-2})$ @endtex |
---|
1187 | REAL(r_std), DIMENSION(ncirc) :: ind !! Number of individuals @tex $(m^{-2})$ @endtex |
---|
1188 | |
---|
1189 | !! 0.2 Output variables |
---|
1190 | |
---|
1191 | REAL(r_std) :: wood_to_qmdia !! quadratic mean diameter (m) |
---|
1192 | |
---|
1193 | !! 0.3 Modified variables |
---|
1194 | |
---|
1195 | !! 0.4 Local variables |
---|
1196 | REAL(r_std), DIMENSION(ncirc) :: circ_class_ba !! basal area for each circ_class @tex $(m^{2})$ @endtex |
---|
1197 | |
---|
1198 | !_ ================================================================================================================================ |
---|
1199 | |
---|
1200 | !! 1. Calculate qm_dia from the biomass |
---|
1201 | IF ( is_tree(pft) ) THEN |
---|
1202 | |
---|
1203 | ! Basal area at the tree level (m2 tree-1) |
---|
1204 | circ_class_ba(:) = wood_to_ba(biomass_temp(:,:),pft) |
---|
1205 | |
---|
1206 | IF (SUM(ind(:)) .NE. zero) THEN |
---|
1207 | |
---|
1208 | wood_to_qmdia = SQRT( 4/pi*SUM(circ_class_ba(:)*ind(:))/SUM(ind(:)) ) |
---|
1209 | |
---|
1210 | ELSE |
---|
1211 | |
---|
1212 | wood_to_qmdia = zero |
---|
1213 | |
---|
1214 | ENDIF |
---|
1215 | |
---|
1216 | |
---|
1217 | ! Grasses and croplands |
---|
1218 | ELSE |
---|
1219 | |
---|
1220 | wood_to_qmdia = zero |
---|
1221 | |
---|
1222 | ENDIF ! is_tree(pft) |
---|
1223 | |
---|
1224 | END FUNCTION wood_to_qmdia |
---|
1225 | |
---|
1226 | |
---|
1227 | !! ================================================================================================================================ |
---|
1228 | !! FUNCTION : wood_to_volume |
---|
1229 | !! |
---|
1230 | !>\BRIEF This allometric function computes volume as a function of |
---|
1231 | !! biomass at stand scale. Volume \f$(m^3 m^{-2}) = f(biomass (gC m^{-2}))\f$ |
---|
1232 | !! |
---|
1233 | !! DESCRIPTION : None |
---|
1234 | !! |
---|
1235 | !! RECENT CHANGE(S): None |
---|
1236 | !! |
---|
1237 | !! RETURN VALUE : biomass_to_volume |
---|
1238 | !! |
---|
1239 | !! REFERENCE(S) : See above, module description. |
---|
1240 | !! |
---|
1241 | !! FLOWCHART : None |
---|
1242 | !! \n |
---|
1243 | !_ ================================================================================================================================ |
---|
1244 | |
---|
1245 | FUNCTION wood_to_volume(npts,ccbio,ccind,pft,branch_ratio,inc_branches) |
---|
1246 | |
---|
1247 | !! 0. Variable and parameter declaration |
---|
1248 | |
---|
1249 | !! 0.1 Input variables |
---|
1250 | INTEGER(i_std), INTENT(in) :: npts !! Domain size (unitless) |
---|
1251 | REAL(r_std), INTENT(in), DIMENSION(:,:,:) :: ccbio !! circ_class_biomass or biomass of an |
---|
1252 | !! individual tree in each circumference |
---|
1253 | !! class @tex $(gC tree^{-1})$ @endtex |
---|
1254 | REAL(r_std), INTENT(in), DIMENSION(:) :: ccind !! Number of trees per circumference class |
---|
1255 | REAL(r_std), INTENT(in) :: branch_ratio !! Branch ratio of sap and heartwood biomass |
---|
1256 | !! unitless |
---|
1257 | INTEGER(i_std), INTENT(in) :: pft !! Plant functional type (unitless) |
---|
1258 | INTEGER(i_std), INTENT(in) :: inc_branches !! Include the branches in the volume calculation? |
---|
1259 | !! 0: exclude the branches from the volume calculation |
---|
1260 | !! (thus correct the biomass for the branch ratio) |
---|
1261 | !! 1: include the branches in the volume calculation |
---|
1262 | !! (thus use all aboveground biomass) |
---|
1263 | |
---|
1264 | |
---|
1265 | |
---|
1266 | !! 0.2 Output variables |
---|
1267 | |
---|
1268 | REAL(r_std) :: wood_to_volume !! The volume of wood per square meter |
---|
1269 | !! @tex $(m^3 m^{-2})$ @endtex |
---|
1270 | |
---|
1271 | !! 0.3 Modified variables |
---|
1272 | |
---|
1273 | !! 0.4 Local variables |
---|
1274 | REAL(r_std), DIMENSION(nparts,nelements) :: biomass !! Total biomass at the stand level |
---|
1275 | !! @tex $(gC m^{-2})$ @endtex |
---|
1276 | REAL(r_std) :: woody_biomass !! Woody biomass at the stand level |
---|
1277 | !! @tex $(gC m^{-2})$ @endtex |
---|
1278 | |
---|
1279 | !_ ================================================================================================================================ |
---|
1280 | |
---|
1281 | !! 1. Volume to biomass |
---|
1282 | |
---|
1283 | ! Calculate stand biomass from circ_class_biomass. In cc_to_biomass_2d |
---|
1284 | ! which is used here, npts is not used but we need to pass it to have |
---|
1285 | ! a consistent call structure for cc_to_biomass_2d and cc_to_biomass_4d |
---|
1286 | biomass = cc_to_biomass(npts,pft,ccbio,ccind) |
---|
1287 | |
---|
1288 | ! Woody biomass used in the calculation |
---|
1289 | IF (inc_branches .EQ. 0) THEN |
---|
1290 | |
---|
1291 | woody_biomass = (biomass(isapabove,icarbon)+biomass(iheartabove,icarbon)) * & |
---|
1292 | (un - branch_ratio) |
---|
1293 | |
---|
1294 | ELSEIF (inc_branches .EQ. 1) THEN |
---|
1295 | |
---|
1296 | woody_biomass = (biomass(isapabove,icarbon)+biomass(iheartabove,icarbon)) |
---|
1297 | |
---|
1298 | ELSE |
---|
1299 | |
---|
1300 | CALL ipslerr_p(3,'ERROR in wood_to_volume',& |
---|
1301 | 'Specify how the branches should be accounted for','','') |
---|
1302 | |
---|
1303 | ENDIF |
---|
1304 | |
---|
1305 | ! Wood volume expressed in m**3 / m**2 |
---|
1306 | wood_to_volume = woody_biomass/(pipe_density(pft)) |
---|
1307 | |
---|
1308 | END FUNCTION wood_to_volume |
---|
1309 | |
---|
1310 | |
---|
1311 | !! ================================================================================================================================ |
---|
1312 | !! FUNCTION : wood_to_height |
---|
1313 | !! |
---|
1314 | !>\BRIEF Calculate tree height from woody biomass making use of allometric relationships |
---|
1315 | !! |
---|
1316 | !! DESCRIPTION : Calculate height of an individual tree from the woody biomass of that tree making |
---|
1317 | !! use of allometric relationships. This is the height used in forestry and for calculating the aerodynamic |
---|
1318 | !! interactions |
---|
1319 | !! (i) height(:) = pipe_tune2(j)*(4/pi*ba(:))**(pipe_tune3(j)/2) and |
---|
1320 | !! (ii) woodmass_ind = tree_ff*pipe_density*ba*height |
---|
1321 | !! |
---|
1322 | !! RECENT CHANGE(S): None |
---|
1323 | !! |
---|
1324 | !! RETURN VALUE : height (m) |
---|
1325 | !! |
---|
1326 | !! REFERENCE(S) : |
---|
1327 | !! |
---|
1328 | !! FLOWCHART : None |
---|
1329 | !! \n |
---|
1330 | !_ ================================================================================================================================ |
---|
1331 | |
---|
1332 | FUNCTION wood_to_height(biomass_temp, pft) |
---|
1333 | |
---|
1334 | !! 0. Variable and parameter declaration |
---|
1335 | |
---|
1336 | !! 0.1 Input variables |
---|
1337 | |
---|
1338 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
1339 | REAL(r_std), DIMENSION(:,:) :: biomass_temp !! Biomass of an individual tree within a circ |
---|
1340 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
1341 | |
---|
1342 | !! 0.2 Output variables |
---|
1343 | |
---|
1344 | REAL(r_std), DIMENSION(ncirc) :: wood_to_height !! Height of an individual tree within a circ |
---|
1345 | !! class (m) |
---|
1346 | |
---|
1347 | !! 0.3 Modified variables |
---|
1348 | |
---|
1349 | !! 0.4 Local variables |
---|
1350 | INTEGER(i_std) :: l !! Index |
---|
1351 | REAL(r_std) :: woodmass_ind !! Woodmass of an individual tree |
---|
1352 | !! @tex $(gC ind{-1})$ @endtex |
---|
1353 | REAL(r_std) :: temp !! Temporary variable |
---|
1354 | !_ ================================================================================================================================ |
---|
1355 | |
---|
1356 | !! 1. Calculate height from woodmass |
---|
1357 | |
---|
1358 | IF ( is_tree(pft) ) THEN |
---|
1359 | |
---|
1360 | DO l = 1,ncirc |
---|
1361 | |
---|
1362 | ! Woodmass of an individual tree (only the aboveground component) |
---|
1363 | woodmass_ind = biomass_temp(l,isapabove) + biomass_temp(l,iheartabove) |
---|
1364 | |
---|
1365 | temp = (woodmass_ind/(tree_ff(pft)*pipe_density(pft))*4/pi) |
---|
1366 | |
---|
1367 | IF (temp.LT.EPSILON(un)) THEN |
---|
1368 | ! Expect an overflow when taking an exponent of such a small number |
---|
1369 | wood_to_height(l) = min_stomate |
---|
1370 | ELSE |
---|
1371 | ! Height of that individual |
---|
1372 | wood_to_height(l) = (((woodmass_ind/(tree_ff(pft)*& |
---|
1373 | pipe_density(pft))*4/pi)**(pipe_tune3(pft)/2))*& |
---|
1374 | pipe_tune2(pft))**(1/(pipe_tune3(pft)/2+1)) |
---|
1375 | ENDIF |
---|
1376 | |
---|
1377 | ENDDO |
---|
1378 | |
---|
1379 | ELSE |
---|
1380 | |
---|
1381 | WRITE(numout,*) 'ERROR: wood_to_height, pft ',pft |
---|
1382 | CALL ipslerr_p (3,'wood_to_height', & |
---|
1383 | 'wood_to_height is not defined for this PFT.', & |
---|
1384 | 'See the output file for more details.','') |
---|
1385 | |
---|
1386 | ENDIF |
---|
1387 | |
---|
1388 | END FUNCTION wood_to_height |
---|
1389 | |
---|
1390 | |
---|
1391 | !! ================================================================================================================================ |
---|
1392 | !! FUNCTION : wood_to_height_eff |
---|
1393 | !! |
---|
1394 | !>\BRIEF Calculate the effective tree height from woody biomass making use of allometric relationships |
---|
1395 | !! |
---|
1396 | !! DESCRIPTION : Calculate the effective height of an individual tree from the woody biomass of that tree making |
---|
1397 | !! use of allometric relationships. Effective height makes use of both above and belowground biomass and is |
---|
1398 | !! used in the calculation of the allocation according to deleuze and dhote, hydraulic architecture because also |
---|
1399 | !! the height of the belowground part should be included. |
---|
1400 | !! (i) height(:) = pipe_tune2(j)*(4/pi*ba(:))**(pipe_tune3(j)/2) and |
---|
1401 | !! (ii) woodmass_ind = tree_ff*pipe_density*ba*height |
---|
1402 | !! |
---|
1403 | !! RECENT CHANGE(S): None |
---|
1404 | !! |
---|
1405 | !! RETURN VALUE : height (m) |
---|
1406 | !! |
---|
1407 | !! REFERENCE(S) : |
---|
1408 | !! |
---|
1409 | !! FLOWCHART : None |
---|
1410 | !! \n |
---|
1411 | !_ ================================================================================================================================ |
---|
1412 | |
---|
1413 | FUNCTION wood_to_height_eff(biomass_temp, pft) |
---|
1414 | |
---|
1415 | !! 0. Variable and parameter declaration |
---|
1416 | |
---|
1417 | !! 0.1 Input variables |
---|
1418 | |
---|
1419 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
1420 | REAL(r_std), DIMENSION(:,:) :: biomass_temp !! Biomass of an individual tree within a circ |
---|
1421 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
1422 | |
---|
1423 | !! 0.2 Output variables |
---|
1424 | |
---|
1425 | REAL(r_std), DIMENSION(ncirc) :: wood_to_height_eff !! Effective height of an individual tree within a circ |
---|
1426 | !! class (m) |
---|
1427 | |
---|
1428 | !! 0.3 Modified variables |
---|
1429 | |
---|
1430 | !! 0.4 Local variables |
---|
1431 | INTEGER(i_std) :: l !! Index |
---|
1432 | REAL(r_std) :: woodmass_ind !! Woodmass of an individual tree |
---|
1433 | !! @tex $(gC ind{-1})$ @endtex |
---|
1434 | REAL(r_std) :: temp !! Temporary variable |
---|
1435 | !_ ================================================================================================================================ |
---|
1436 | |
---|
1437 | !! 1. Calculate height from woodmass |
---|
1438 | |
---|
1439 | IF ( is_tree(pft) ) THEN |
---|
1440 | |
---|
1441 | DO l = 1,ncirc |
---|
1442 | |
---|
1443 | ! Woodmass of an individual tree. Both above and belowground biomass are used |
---|
1444 | woodmass_ind = biomass_temp(l,isapabove) + biomass_temp(l,isapbelow) + & |
---|
1445 | biomass_temp(l,iheartabove) + biomass_temp(l,iheartbelow) |
---|
1446 | |
---|
1447 | temp = (woodmass_ind/(tree_ff(pft)*pipe_density(pft))*4/pi) |
---|
1448 | |
---|
1449 | IF (temp.LT.EPSILON(un)) THEN |
---|
1450 | ! Expect an overflow when taking an exponent of such a small number |
---|
1451 | wood_to_height_eff(l) = min_stomate |
---|
1452 | ELSE |
---|
1453 | ! Height of that individual |
---|
1454 | wood_to_height_eff(l) = (((woodmass_ind/(tree_ff(pft)*pipe_density(pft))*4/pi)**(pipe_tune3(pft)/2))& |
---|
1455 | *pipe_tune2(pft))**(1/(pipe_tune3(pft)/2+1)) |
---|
1456 | ENDIF |
---|
1457 | |
---|
1458 | ENDDO |
---|
1459 | |
---|
1460 | ELSE |
---|
1461 | |
---|
1462 | WRITE(numout,*) 'pft ',pft |
---|
1463 | CALL ipslerr_p (3,'wood_to_height_eff', & |
---|
1464 | 'wood_to_height_eff is not defined for this PFT.', & |
---|
1465 | 'See the output file for more details.','') |
---|
1466 | |
---|
1467 | ENDIF |
---|
1468 | |
---|
1469 | END FUNCTION wood_to_height_eff |
---|
1470 | |
---|
1471 | |
---|
1472 | !! ================================================================================================================================ |
---|
1473 | !! FUNCTION : wood_to_dia |
---|
1474 | !! |
---|
1475 | !>\BRIEF Calculate diameter from woody biomass making use of allometric relationships |
---|
1476 | !! |
---|
1477 | !! DESCRIPTION : Calculate diameter of an individual tree from the woody biomass of that tree making |
---|
1478 | !! use of allometric relationships. Makes only use of the aboveground biomass and relates to the |
---|
1479 | !! typical forestry diameter (but not normalized at 1.3 m) |
---|
1480 | !! (i) woodmass_ind = tree_ff * pipe_density * height * pi/4*dia**2 |
---|
1481 | !! (ii) height = pipe_tune2 * dia * pipe_tune3 |
---|
1482 | !! |
---|
1483 | !! RECENT CHANGE(S): None |
---|
1484 | !! |
---|
1485 | !! RETURN VALUE : diameter (m) |
---|
1486 | !! |
---|
1487 | !! REFERENCE(S) : |
---|
1488 | !! |
---|
1489 | !! FLOWCHART : None |
---|
1490 | !! \n |
---|
1491 | !_ ================================================================================================================================ |
---|
1492 | |
---|
1493 | FUNCTION wood_to_dia(biomass_temp, pft) |
---|
1494 | |
---|
1495 | |
---|
1496 | !! 0. Variable and parameter declaration |
---|
1497 | |
---|
1498 | |
---|
1499 | !! 0.1 Input variables |
---|
1500 | |
---|
1501 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
1502 | REAL(r_std), DIMENSION(:,:) :: biomass_temp !! Biomass of an individual tree within a circ |
---|
1503 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
1504 | !! 0.2 Output variables |
---|
1505 | |
---|
1506 | REAL(r_std), DIMENSION(ncirc) :: wood_to_dia !! Diameter of an individual tree within a circ |
---|
1507 | !! class (m) |
---|
1508 | |
---|
1509 | !! 0.3 Modified variables |
---|
1510 | |
---|
1511 | !! 0.4 Local variables |
---|
1512 | INTEGER(i_std) :: l !! Index |
---|
1513 | REAL(r_std) :: woodmass_ind !! Woodmass of an individual tree |
---|
1514 | !! @tex $(gC ind^{-1})$ @endtex |
---|
1515 | REAL(r_std) :: temp !! temporary variable |
---|
1516 | !_ ================================================================================================================================ |
---|
1517 | |
---|
1518 | !! 1. Calculate basal area from woodmass |
---|
1519 | |
---|
1520 | IF ( is_tree(pft) ) THEN |
---|
1521 | |
---|
1522 | DO l = 1,ncirc |
---|
1523 | |
---|
1524 | ! Woodmass of an individual tree |
---|
1525 | woodmass_ind = biomass_temp(l,isapabove) + biomass_temp(l,iheartabove) |
---|
1526 | |
---|
1527 | temp = 4/pi*woodmass_ind/(tree_ff(pft)*pipe_density(pft)*pipe_tune2(pft)) |
---|
1528 | |
---|
1529 | IF (temp.LT.EPSILON(un)) THEN |
---|
1530 | ! Expect an overflow when taking an exponent of such a small number |
---|
1531 | wood_to_dia(l) = min_stomate |
---|
1532 | ELSE |
---|
1533 | ! Basal area of that individual (m2 ind-1) |
---|
1534 | wood_to_dia(l) = (4/pi*woodmass_ind/(tree_ff(pft)*pipe_density(pft)*pipe_tune2(pft))) ** & |
---|
1535 | (1./(2+pipe_tune3(pft))) |
---|
1536 | ENDIF |
---|
1537 | ENDDO |
---|
1538 | |
---|
1539 | ELSE |
---|
1540 | |
---|
1541 | WRITE(numout,*) 'pft ',pft |
---|
1542 | CALL ipslerr_p (3,'wood_to_dia', & |
---|
1543 | 'wood_to_dia is not defined for this PFT.', & |
---|
1544 | 'See the output file for more details.','') |
---|
1545 | |
---|
1546 | ENDIF |
---|
1547 | |
---|
1548 | END FUNCTION wood_to_dia |
---|
1549 | |
---|
1550 | |
---|
1551 | !! ================================================================================================================================ |
---|
1552 | !! FUNCTION : wood_to_circ |
---|
1553 | !! |
---|
1554 | !>\BRIEF Calculate circumference from woody biomass making use of allometric relationships |
---|
1555 | !! |
---|
1556 | !! DESCRIPTION : All this does it computer the diameter using a different routine, and then |
---|
1557 | !! convert that into a circumference. |
---|
1558 | !! |
---|
1559 | !! RECENT CHANGE(S): None |
---|
1560 | !! |
---|
1561 | !! RETURN VALUE : circumference (m) |
---|
1562 | !! |
---|
1563 | !! REFERENCE(S) : |
---|
1564 | !! |
---|
1565 | !! FLOWCHART : None |
---|
1566 | !! \n |
---|
1567 | !_ ================================================================================================================================ |
---|
1568 | |
---|
1569 | FUNCTION wood_to_circ(biomass_temp, pft) |
---|
1570 | |
---|
1571 | !! 0. Variable and parameter declaration |
---|
1572 | |
---|
1573 | !! 0.1 Input variables |
---|
1574 | |
---|
1575 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
1576 | REAL(r_std), DIMENSION(:,:) :: biomass_temp !! Biomass of an individual tree within a circ |
---|
1577 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
1578 | |
---|
1579 | !! 0.2 Output variables |
---|
1580 | |
---|
1581 | REAL(r_std), DIMENSION(ncirc) :: wood_to_circ !! Circumference of an individual tree within a circ |
---|
1582 | !! class (m) |
---|
1583 | |
---|
1584 | !! 0.3 Modified variables |
---|
1585 | |
---|
1586 | !! 0.4 Local variables |
---|
1587 | |
---|
1588 | !_ ================================================================================================================================ |
---|
1589 | |
---|
1590 | !! 1. Calculate diameter from woodmass |
---|
1591 | |
---|
1592 | wood_to_circ(:)=val_exp |
---|
1593 | |
---|
1594 | wood_to_circ(:)=wood_to_dia(biomass_temp(:,:),pft) |
---|
1595 | |
---|
1596 | ! convert to a circumference (m) |
---|
1597 | wood_to_circ(:) = wood_to_circ(:)*pi |
---|
1598 | |
---|
1599 | END FUNCTION wood_to_circ |
---|
1600 | |
---|
1601 | |
---|
1602 | !! ================================================================================================================================ |
---|
1603 | ! SUBROUTINE : wood_to_cn_dia |
---|
1604 | !! |
---|
1605 | !>\BRIEF Calculate horizontal crown diameter from woody biomass making use of allometric relationships |
---|
1606 | !! |
---|
1607 | !! DESCRIPTION : Calculate tree height and apply the reduction coefficient crown_to_height and crown_vertohor_dia |
---|
1608 | !! |
---|
1609 | !! RECENT CHANGE(S): None |
---|
1610 | !! |
---|
1611 | !! RETURN VALUE : horizontal crown diameter (m) |
---|
1612 | !! |
---|
1613 | !! REFERENCE(S) : |
---|
1614 | !! |
---|
1615 | !! FLOWCHART : None |
---|
1616 | !! \n |
---|
1617 | !_ ================================================================================================================================ |
---|
1618 | SUBROUTINE wood_to_cn_dia(biomass_temp, ind, pft, dia_hor, dia_ver) |
---|
1619 | |
---|
1620 | !! 0. Variable and parameter declaration |
---|
1621 | |
---|
1622 | !! 0.1 Input variables |
---|
1623 | |
---|
1624 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
1625 | REAL(r_std), DIMENSION(:,:) :: biomass_temp !! Biomass of an individual tree within a circ |
---|
1626 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
1627 | REAL(r_std), DIMENSION(:) :: ind !! Number of individuals within a circ class |
---|
1628 | !! @tex $(ind m^{2})$ @endtex |
---|
1629 | |
---|
1630 | !! 0.2 Output variables |
---|
1631 | |
---|
1632 | REAL(r_std), DIMENSION(ncirc) :: dia_hor !! Horizontal crown diameter |
---|
1633 | !! for each individual tree within a circ |
---|
1634 | !! class (m) |
---|
1635 | REAL(r_std), DIMENSION(ncirc) :: dia_ver !! Vertical crown diameter (in othe words, crown |
---|
1636 | !! depth) for each individual tree within a circ |
---|
1637 | !! class (m) |
---|
1638 | |
---|
1639 | !! 0.3 Modified variables |
---|
1640 | |
---|
1641 | !! 0.4 Local variables |
---|
1642 | INTEGER(i_std) :: icir !! Index |
---|
1643 | REAL(r_std) :: woodmass_ind !! Woodmass of an individual tree |
---|
1644 | !! @tex $(gC ind{-1})$ @endtex |
---|
1645 | REAL(r_std) :: temp !! Temporary variable |
---|
1646 | REAL(r_std) :: cn_vol !! Crown volume of a individual tree within a circ class (m) |
---|
1647 | REAL(r_std) :: total_cn_vol !! Total crown volume of the stand across all circ classes (m) |
---|
1648 | REAL(r_std) :: max_height !! Volume of the entire canopy space (surface area * tree height |
---|
1649 | !! but normalized for surface area) (m) |
---|
1650 | REAL(r_std) :: adjusted_crown_vertohor_dia !! calculated ratio between vertical and horizontal |
---|
1651 | !! crown diameter. The calculated value guarantees that the |
---|
1652 | !! canopys space is filled for 74% (given as ::crown_packing) |
---|
1653 | REAL(r_std) :: adjusted_crown_to_height !! Calculate ratio between tree height and vertical |
---|
1654 | !! crown diameter. The calculated value guarantees that the |
---|
1655 | !! canopys space is filled for 74% (given as ::crown_packing) |
---|
1656 | |
---|
1657 | !_ ================================================================================================================================ |
---|
1658 | |
---|
1659 | !! 1. Calculate horizontal crown diameter from woodmass |
---|
1660 | |
---|
1661 | IF ( is_tree(pft) ) THEN |
---|
1662 | |
---|
1663 | ! Initialize |
---|
1664 | total_cn_vol=zero |
---|
1665 | |
---|
1666 | ! Use wood mass to calculate the prescribed vertical and horizontal crown |
---|
1667 | ! diameters |
---|
1668 | DO icir = 1,ncirc |
---|
1669 | |
---|
1670 | ! Woodmass of an individual tree (only the aboveground component) |
---|
1671 | woodmass_ind = biomass_temp(icir,isapabove) + biomass_temp(icir,iheartabove) |
---|
1672 | |
---|
1673 | temp = (woodmass_ind/(tree_ff(pft)*pipe_density(pft))*4/pi) |
---|
1674 | |
---|
1675 | IF (temp.LT.EPSILON(un)) THEN |
---|
1676 | |
---|
1677 | ! Expect an overflow when taking an exponent of such a small number |
---|
1678 | dia_hor(icir) = min_stomate |
---|
1679 | dia_ver(icir) = min_stomate |
---|
1680 | |
---|
1681 | ELSE |
---|
1682 | |
---|
1683 | ! Horizonatal crown diameter of an individual based on the height |
---|
1684 | ! and prescribed ratios. |
---|
1685 | dia_hor(icir) = crown_vertohor_dia(pft) * crown_to_height(pft) * & |
---|
1686 | (((woodmass_ind/(tree_ff(pft)*& |
---|
1687 | pipe_density(pft))*4/pi)**(pipe_tune3(pft)/2))*& |
---|
1688 | pipe_tune2(pft))**(1/(pipe_tune3(pft)/2+1)) |
---|
1689 | ! Vertical crown diameter derived from the height of that individual |
---|
1690 | dia_ver(icir) = crown_to_height(pft)*(((woodmass_ind/(tree_ff(pft)*& |
---|
1691 | pipe_density(pft))*4/pi)**(pipe_tune3(pft)/2))*& |
---|
1692 | pipe_tune2(pft))**(1/(pipe_tune3(pft)/2+1)) |
---|
1693 | |
---|
1694 | ENDIF |
---|
1695 | |
---|
1696 | ! Calculate the crown volume making use of the prescribed crown diameters |
---|
1697 | ! Notice that we don't have to take the surface area of the stand |
---|
1698 | ! into account. total_bm will be in units of gC / m**2, while |
---|
1699 | ! the canopy volume should be in units of m**3 / m**2. The surface |
---|
1700 | ! area would cancel out when we take the ratio. The unit of total_cn_vol |
---|
1701 | ! is thus similar to how precipitation is being expressed. |
---|
1702 | ! Right now, total_cn_vol is in m**3/tree * tree/m**2 thus m |
---|
1703 | cn_vol = pi/6*dia_hor(icir)*dia_hor(icir)*dia_ver(icir) |
---|
1704 | total_cn_vol=total_cn_vol+cn_vol*ind(icir) |
---|
1705 | ENDDO |
---|
1706 | |
---|
1707 | ! Space available to be filled with the crown volumes. The same |
---|
1708 | ! unit convention as above is used (m) |
---|
1709 | max_height = MAXVAL(wood_to_height(biomass_temp(:,:),pft)) |
---|
1710 | |
---|
1711 | |
---|
1712 | IF (total_cn_vol.GT.max_height) THEN |
---|
1713 | |
---|
1714 | ! The prescribed crown diameters take too much space. Adjust the |
---|
1715 | ! horizontal diameters such that the space is more correctly filled |
---|
1716 | ! Given that we have to deal with different tree sizes and that the |
---|
1717 | ! canopies are assumed to be ellipsoids this is a very complex problem |
---|
1718 | ! to calculate exactly. We will make a couple of shortcuts. |
---|
1719 | ! First we will assume that by packing ellipsoids we have the same |
---|
1720 | ! efficiency as close-packing of equal spheres which is around 0.74. |
---|
1721 | ! total_cn_vol = 1/6*pi*dia_hor^2*dia_ver |
---|
1722 | ! dia_hor = crown_vertohor_dia*dia_ver |
---|
1723 | ! <=> total_cn_vol = 1/6*pi*crown_vertohor_dia^2*dia_ver^3 |
---|
1724 | ! Reduce total_cn_vol to max_height * 0.74 (close packing) and calculate |
---|
1725 | ! the adjusted crown_vertohor_dia. |
---|
1726 | ! As an alternative scale both the vertyical and horizontal crown dimensions |
---|
1727 | adjusted_crown_to_height = & |
---|
1728 | ((max_height*crown_packing*6) / & |
---|
1729 | (pi*(crown_vertohor_dia(pft)**2)*SUM(ind(:)*dia_ver(:)**3)))**(1./3.) |
---|
1730 | dia_ver(:) = adjusted_crown_to_height * crown_to_height(pft) * & |
---|
1731 | wood_to_height(biomass_temp(:,:),pft) |
---|
1732 | dia_hor(:) = crown_vertohor_dia(pft) * dia_ver(:) |
---|
1733 | |
---|
1734 | ! Error checking |
---|
1735 | total_cn_vol = zero |
---|
1736 | DO icir = 1,ncirc |
---|
1737 | total_cn_vol = total_cn_vol + & |
---|
1738 | pi/6*dia_hor(icir)*dia_hor(icir)*dia_ver(icir)*ind(icir) |
---|
1739 | END DO |
---|
1740 | IF (ABS(total_cn_vol-crown_packing*max_height).GT.min_stomate) THEN |
---|
1741 | WRITE(numout,*) 'ind, ', ind(:) |
---|
1742 | WRITE(numout,*) 'dia_ver, ', dia_ver(:) |
---|
1743 | WRITE(numout,*) 'dia_hor, ', dia_hor(:) |
---|
1744 | WRITE(numout,*) 'adjusted_crown_vertohor_dia, ',adjusted_crown_vertohor_dia |
---|
1745 | WRITE(numout,*) 'adjusted_crown_to_height, ',adjusted_crown_to_height |
---|
1746 | WRITE(numout,*) 'recalculated total_cn_vol, ',total_cn_vol |
---|
1747 | WRITE(numout,*) 'crown_packing*max_height, ', crown_packing*max_height |
---|
1748 | CALL ipslerr_p(3,'problem with crown packing',& |
---|
1749 | 'adjusted horizonatal diameter is wrong',& |
---|
1750 | 'check the calculations in the code','') |
---|
1751 | END IF |
---|
1752 | |
---|
1753 | END IF |
---|
1754 | |
---|
1755 | ELSE |
---|
1756 | |
---|
1757 | WRITE(numout,*) 'ERROR: wood_to_height, pft ',pft |
---|
1758 | CALL ipslerr_p (3,'wood_to_height', & |
---|
1759 | 'wood_to_height is not defined for this PFT.', & |
---|
1760 | 'See the output file for more details.','') |
---|
1761 | |
---|
1762 | ENDIF |
---|
1763 | |
---|
1764 | END SUBROUTINE wood_to_cn_dia |
---|
1765 | |
---|
1766 | |
---|
1767 | !! ================================================================================================================================ |
---|
1768 | !! FUNCTION : wood_to_cv |
---|
1769 | !! |
---|
1770 | !>\BRIEF Calculate crown volume from woody biomass making use of the vertical and horizontal crown diameters |
---|
1771 | !! |
---|
1772 | !! DESCRIPTION : Calculate the volume of an elipsoid. V = 1/6 * pi * dia_hor**2 * dia_ver |
---|
1773 | !! |
---|
1774 | !! RECENT CHANGE(S): None |
---|
1775 | !! |
---|
1776 | !! RETURN VALUE : crown volume (m3 ind-1) |
---|
1777 | !! |
---|
1778 | !! REFERENCE(S) : |
---|
1779 | !! |
---|
1780 | !! FLOWCHART : None |
---|
1781 | !! \n |
---|
1782 | !_ ================================================================================================================================ |
---|
1783 | |
---|
1784 | FUNCTION wood_to_cv(biomass_temp, ind, pft) |
---|
1785 | |
---|
1786 | !! 0. Variable and parameter declaration |
---|
1787 | |
---|
1788 | !! 0.1 Input variables |
---|
1789 | |
---|
1790 | INTEGER(i_std) :: pft !! PFT number (-) |
---|
1791 | REAL(r_std), DIMENSION(:,:) :: biomass_temp !! Biomass of an individual tree within a circ |
---|
1792 | !! class @tex $(m^{2} ind^{-1})$ @endtex |
---|
1793 | REAL(r_std), DIMENSION(: ) :: ind !! Number of individuals within a circ class |
---|
1794 | !! @tex $(ind m^{2})$ @endtex |
---|
1795 | |
---|
1796 | !! 0.2 Output variables |
---|
1797 | |
---|
1798 | REAL(r_std), DIMENSION(ncirc) :: wood_to_cv !! Crown volume of an individual tree |
---|
1799 | !! @tex $(m^{2} ind{-1})$ @endtex |
---|
1800 | |
---|
1801 | !! 0.3 Modified variables |
---|
1802 | |
---|
1803 | !! 0.4 Local variables |
---|
1804 | INTEGER(i_std) :: l !! Index |
---|
1805 | REAL(r_std) :: woodmass_ind !! Woodmass of an individual tree |
---|
1806 | !! @tex $(gC ind^{-1})$ @endtex |
---|
1807 | REAL(r_std), DIMENSION(ncirc) :: dia_ver !! vertical crown diameter of an individual tree (m) |
---|
1808 | REAL(r_std), DIMENSION(ncirc) :: dia_hor !! horizontal crown diameter of an individual tree (m) |
---|
1809 | |
---|
1810 | !_ ================================================================================================================================ |
---|
1811 | |
---|
1812 | !! 1. Calculate crown volume from woodmass |
---|
1813 | |
---|
1814 | IF ( is_tree(pft) ) THEN |
---|
1815 | |
---|
1816 | ! Crown diameter of the individual tree (m2 ind-1) |
---|
1817 | CALL wood_to_cn_dia(biomass_temp, ind, pft, dia_hor, dia_ver) |
---|
1818 | wood_to_cv(:) = pi/6.*dia_ver(:)*dia_hor(:)*dia_hor(:) |
---|
1819 | ! WRITE(numout,*) 'wood_to_cv_eff, ', wood_to_cv_eff(:) |
---|
1820 | |
---|
1821 | ELSE |
---|
1822 | |
---|
1823 | WRITE(numout,*) 'pft ',pft |
---|
1824 | CALL ipslerr_p (3,'wood_to_cv_eff', & |
---|
1825 | 'wood_to_cv_eff is not defined for this PFT.', & |
---|
1826 | 'See the output file for more details.','') |
---|
1827 | |
---|
1828 | ENDIF |
---|
1829 | |
---|
1830 | END FUNCTION wood_to_cv |
---|
1831 | |
---|
1832 | |
---|
1833 | !! ================================================================================================================================ |
---|
1834 | !! FUNCTION : Nmax |
---|
1835 | !! |
---|
1836 | !>\BRIEF This function determines the maximum number of trees per hectare for |
---|
1837 | !! a given quadratic mean diameter (Dg). It applies the self-thinning principle |
---|
1838 | !! of Reineke (1933), with Dg instead of mean diameter (Dhote 1999). |
---|
1839 | !! Parameterization: Dhote (1999) for broad-leaved and Vacchiano (2008) |
---|
1840 | !! for needle-leaved. |
---|
1841 | !! |
---|
1842 | !! DESCRIPTION : None |
---|
1843 | !! |
---|
1844 | !! RECENT CHANGE(S): None |
---|
1845 | !! |
---|
1846 | !! RETURN VALUE : Nmax |
---|
1847 | !! |
---|
1848 | !! REFERENCE(S) : See above, module description. |
---|
1849 | !! |
---|
1850 | !! FLOWCHART : None |
---|
1851 | !! \n |
---|
1852 | !_ ================================================================================================================================ |
---|
1853 | |
---|
1854 | FUNCTION Nmax(Dg,no_pft) |
---|
1855 | |
---|
1856 | !! 0. Variable and parameter declaration |
---|
1857 | |
---|
1858 | !! 0.1 Input variables |
---|
1859 | |
---|
1860 | REAL(r_std) :: Dg !! Quadratic mean diameter (cm) |
---|
1861 | INTEGER(i_std) :: no_pft !! Plant functional type (unitless) |
---|
1862 | |
---|
1863 | !! 0.2 Output variables |
---|
1864 | |
---|
1865 | REAL(r_std) :: Nmax !! Maximum number of trees according to the self-thinning model in (trees ha-1) |
---|
1866 | |
---|
1867 | !! 0.3 Modified variables |
---|
1868 | |
---|
1869 | !! 0.4 Local variables |
---|
1870 | |
---|
1871 | !_ ================================================================================================================================ |
---|
1872 | !! 1. maximum number of trees per hectare for a given quadratic mean diameter |
---|
1873 | |
---|
1874 | IF (is_tree(no_pft)) THEN |
---|
1875 | |
---|
1876 | ! thinning curve of the MTC |
---|
1877 | Nmax = (Dg/alpha_self_thinning(no_pft))**(un/beta_self_thinning(no_pft)) |
---|
1878 | |
---|
1879 | ! Truncate the range to avoid huge numbers due the exponental model used to describe self-thinning |
---|
1880 | ! Don't set to ntreesmax else stomate_mark_kill will assume we are at self-thinning and |
---|
1881 | ! won't apply background mortality. |
---|
1882 | ! Nmax = MIN( Nmax, ntreesmax(no_pft)) |
---|
1883 | Nmax = MAX( Nmax, dens_target(no_pft) ) |
---|
1884 | |
---|
1885 | ELSE |
---|
1886 | |
---|
1887 | WRITE(numout,*) 'Self thinning is not defined for PFT, ', no_pft |
---|
1888 | CALL ipslerr_p (3,'nmax', & |
---|
1889 | 'Self thinning is not defined for this PFT.', & |
---|
1890 | 'See the output file for more details.','') |
---|
1891 | |
---|
1892 | ENDIF |
---|
1893 | |
---|
1894 | END FUNCTION Nmax |
---|
1895 | |
---|
1896 | !! ================================================================================================================================ |
---|
1897 | !! FUNCTION : calculate_rdi |
---|
1898 | !! |
---|
1899 | !>\BRIEF Calculate the relative density index of a stand |
---|
1900 | !! |
---|
1901 | !! DESCRIPTION : None |
---|
1902 | !! |
---|
1903 | !! RECENT CHANGE(S): None |
---|
1904 | !! |
---|
1905 | !! RETURN VALUE : calculate_rdi |
---|
1906 | !! |
---|
1907 | !! REFERENCE(S) : Bellassen, V., Le Maire, G., Dhote, J.F., Viovy, N., Ciais, P., 2010. |
---|
1908 | !! Modeling forest management within a global vegetation model â Part 1: |
---|
1909 | !! model structure and general behaviour. Ecological Modelling 221, 2458â2474. |
---|
1910 | !! |
---|
1911 | !! FLOWCHART : None |
---|
1912 | !! \n |
---|
1913 | !_ ================================================================================================================================ |
---|
1914 | |
---|
1915 | FUNCTION calculate_rdi(diameters_temp,circ_class_n_temp,ivm) |
---|
1916 | |
---|
1917 | !! 0. Variable and parameter declaration |
---|
1918 | |
---|
1919 | IMPLICIT NONE |
---|
1920 | |
---|
1921 | !! 0.1 Input variables |
---|
1922 | REAL(r_std),DIMENSION(ncirc),INTENT(in) :: circ_class_n_temp !! The distribution of individuals |
---|
1923 | !! for a given grid square and PFT |
---|
1924 | REAL(r_std),DIMENSION(ncirc),INTENT(in) :: diameters_temp !! The diameters of the trunks |
---|
1925 | !! for each circ class (m) |
---|
1926 | INTEGER(i_std),INTENT(IN) :: ivm !! The number of the PFT |
---|
1927 | !! (unitless) |
---|
1928 | |
---|
1929 | !! 0.2 Output variables |
---|
1930 | REAL(r_std) :: calculate_rdi !! The RDI of the stand |
---|
1931 | !! (unitless, always positive) |
---|
1932 | |
---|
1933 | !! 0.3 Modified variables |
---|
1934 | |
---|
1935 | !! 0.4 Local variables |
---|
1936 | REAL(r_std) :: Dg !! The quadratic mean diameter |
---|
1937 | REAL(r_std) :: ind_loc |
---|
1938 | INTEGER(i_std) :: icir !! Indices |
---|
1939 | |
---|
1940 | !_ ================================================================================================================================ |
---|
1941 | |
---|
1942 | !! 1. Calculate the relative density index for a stand, based on |
---|
1943 | !! the number of trees in each circumference class and the |
---|
1944 | !! the diameter of a model tree in each class. |
---|
1945 | ind_loc=SUM(circ_class_n_temp(:)) |
---|
1946 | |
---|
1947 | Dg=zero |
---|
1948 | |
---|
1949 | DO icir=1,ncirc |
---|
1950 | Dg=Dg+circ_class_n_temp(icir)*m2_to_ha*(diameters_temp(icir)*m_to_cm)**2 |
---|
1951 | ENDDO |
---|
1952 | Dg=SQRT(Dg/(ind_loc*m2_to_ha)) |
---|
1953 | |
---|
1954 | calculate_rdi=(ind_loc*m2_to_ha)/Nmax(Dg,ivm) |
---|
1955 | |
---|
1956 | END FUNCTION calculate_rdi |
---|
1957 | |
---|
1958 | |
---|
1959 | !! ================================================================================================================================ |
---|
1960 | !! SUBROUTINE : check_vegetation_area |
---|
1961 | !! |
---|
1962 | !>\BRIEF |
---|
1963 | !! |
---|
1964 | !! DESCRIPTION : |
---|
1965 | !! RECENT CHANGE(S): None |
---|
1966 | !! |
---|
1967 | !! MAIN OUTPUT VARIABLE(S): |
---|
1968 | !! |
---|
1969 | !! REFERENCE(S) : None |
---|
1970 | !! |
---|
1971 | !! FLOWCHART : None |
---|
1972 | !! \n |
---|
1973 | !_ ================================================================================================================================ |
---|
1974 | SUBROUTINE check_vegetation_area(check_point, npts, veget_max_begin, & |
---|
1975 | veget_max, test_type, change_nobio) |
---|
1976 | |
---|
1977 | !! 0. Variable and parameter description |
---|
1978 | |
---|
1979 | !! 0.1 Input variables |
---|
1980 | INTEGER(i_std), INTENT(in) :: npts !! Domain size (unitless) |
---|
1981 | CHARACTER(*),INTENT(in) :: check_point !! A flag to indicate at which |
---|
1982 | !! point in the code we're doing |
---|
1983 | !! this check |
---|
1984 | CHARACTER(*), INTENT(in) :: test_type !! Which test do we want to run on veget_max |
---|
1985 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: veget_max !! "maximal" coverage fraction of a PFT |
---|
1986 | !! (LAI -> infinity) on ground. May sum to |
---|
1987 | !! less than unity if the pixel has |
---|
1988 | !! nobio area. (unitless; 0-1) |
---|
1989 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: veget_max_begin !! temporary storage of veget_max to check area conservation |
---|
1990 | REAL(r_std), DIMENSION(:), INTENT(in), OPTIONAL :: change_nobio !! Change in the nobio fraction due to urbanisation or possibly glacier retreat |
---|
1991 | |
---|
1992 | !! 0.2 Output variables |
---|
1993 | |
---|
1994 | !! 0.3 Modified variables |
---|
1995 | |
---|
1996 | !! 0.4 Local variables |
---|
1997 | INTEGER(i_std) :: iele, ipts, ivm !! Indices |
---|
1998 | INTEGER(i_std) :: ipar, icir !! Indices |
---|
1999 | INTEGER(i_std) :: ivma,iagec,ipft !! Counter |
---|
2000 | REAL(r_std) :: temp_begin, temp_end !! temporary variables to accumulate veget_max of |
---|
2001 | !! different age classes of the same species |
---|
2002 | |
---|
2003 | !_ ================================================================================================================================ |
---|
2004 | |
---|
2005 | SELECT CASE (test_type) |
---|
2006 | |
---|
2007 | CASE ('pft') |
---|
2008 | |
---|
2009 | ! In all subroutines where veget_max should be preserved at the |
---|
2010 | ! PFT level, the most strict test can be performed |
---|
2011 | DO ipts=1,npts |
---|
2012 | |
---|
2013 | DO ivm = 1,nvm |
---|
2014 | |
---|
2015 | IF (veget_max_begin(ipts,ivm) - veget_max(ipts,ivm) .GT. & |
---|
2016 | min_stomate ) THEN |
---|
2017 | WRITE(numout,*) 'Surface area is not preserved in ', & |
---|
2018 | TRIM(check_point) |
---|
2019 | WRITE(numout,*) 'Area has changed for PFT, ',ipts, ivm |
---|
2020 | WRITE(numout,*) 'Change from, ',veget_max_begin(ipts,ivm), & |
---|
2021 | ' to ', veget_max(ipts,ivm) |
---|
2022 | IF(err_act.GT.1) CALL ipslerr_p (plev, TRIM(check_point), & |
---|
2023 | 'Surface area not preserved','','') |
---|
2024 | ENDIF |
---|
2025 | |
---|
2026 | ENDDO !nvm |
---|
2027 | |
---|
2028 | ! One message per pixel |
---|
2029 | !!$ IF (err_act.GT.1) WRITE(numout,*) 'Surface area preserved in ', & |
---|
2030 | !!$ TRIM(check_point), ipts |
---|
2031 | |
---|
2032 | ENDDO ! npts |
---|
2033 | |
---|
2034 | CASE ('ageclass') |
---|
2035 | |
---|
2036 | ! In subroutines where veget_max can move from one pft to |
---|
2037 | ! another within the same species. This is the test to use |
---|
2038 | DO ipts=1,npts |
---|
2039 | |
---|
2040 | DO ivma=1,nvmap |
---|
2041 | |
---|
2042 | ! get pft number |
---|
2043 | ivm=start_index(ivma) |
---|
2044 | |
---|
2045 | ! If we only have a single age class for this |
---|
2046 | ! PFT, we can simplify the test |
---|
2047 | IF(nagec_pft(ivma) .EQ. 1) THEN |
---|
2048 | |
---|
2049 | IF (veget_max_begin(ipts,ivm) - veget_max(ipts,ivm) .GT. & |
---|
2050 | min_stomate ) THEN |
---|
2051 | WRITE(numout,*) 'Surface area is not preserved in ', & |
---|
2052 | TRIM(check_point) |
---|
2053 | WRITE(numout,*) 'Area has changed for PFT, ',ipts, ivm |
---|
2054 | WRITE(numout,*) 'Change from, ',veget_max_begin(ipts,ivm), & |
---|
2055 | ' to ', veget_max(ipts,ivm) |
---|
2056 | IF(err_act.GT.1) CALL ipslerr_p (plev, TRIM(check_point), & |
---|
2057 | 'Surface area not preserved','','') |
---|
2058 | ENDIF |
---|
2059 | |
---|
2060 | ELSE ! more than 1 age class |
---|
2061 | |
---|
2062 | temp_begin = 0 |
---|
2063 | temp_end = 0 |
---|
2064 | DO iagec = nagec_pft(ivma),1,-1 |
---|
2065 | |
---|
2066 | ! Accumulate veget_max for all pfts/age classes |
---|
2067 | ! that belong to the same species |
---|
2068 | ipft = ivm+iagec-1 |
---|
2069 | temp_begin = temp_begin + veget_max_begin(ipts,ipft) |
---|
2070 | temp_end = temp_end + veget_max(ipts,ipft) |
---|
2071 | |
---|
2072 | ENDDO |
---|
2073 | |
---|
2074 | IF (temp_begin - temp_end .GT. min_stomate ) THEN |
---|
2075 | WRITE(numout,*) 'Surface area is not preserved in ', & |
---|
2076 | TRIM(check_point) |
---|
2077 | WRITE(numout,*) 'Area has changed for PFT, ',ipts, ivm |
---|
2078 | WRITE(numout,*) 'Change from, ',veget_max_begin(ipts,ivm), & |
---|
2079 | ' to ', veget_max(ipts,ivm) |
---|
2080 | IF(err_act.GT.1) CALL ipslerr_p (plev, TRIM(check_point), & |
---|
2081 | 'Surface area not preserved','','') |
---|
2082 | ENDIF |
---|
2083 | |
---|
2084 | ENDIF ! number of age classes |
---|
2085 | |
---|
2086 | ENDDO ! nvmap |
---|
2087 | |
---|
2088 | ! One message per pixel |
---|
2089 | !IF (err_act.GT.1) WRITE(numout,*) 'Surface area preserved in ', & |
---|
2090 | ! TRIM(check_point), ipts |
---|
2091 | |
---|
2092 | ENDDO ! ipts |
---|
2093 | |
---|
2094 | CASE('pixel') |
---|
2095 | |
---|
2096 | ! Use this test in subroutines where veget_max can be moved |
---|
2097 | ! between species. This is the least strict test and only |
---|
2098 | ! test wheter the total veget_max was preserved. |
---|
2099 | DO ipts=1,npts |
---|
2100 | |
---|
2101 | ! Change_nobio is the change in the frac_nobio that may occur in |
---|
2102 | ! LCC. This change should be accounted for in the mass balance check. |
---|
2103 | ! ::change_nobio is defined as an optional element and is only present |
---|
2104 | ! when the surface area is checked in sapiens_lcchange |
---|
2105 | IF(PRESENT(change_nobio))THEN |
---|
2106 | IF (ABS(SUM(veget_max_begin(ipts,:)) - SUM(veget_max(ipts,:)) - change_nobio(ipts)) .GT. & |
---|
2107 | min_stomate ) THEN |
---|
2108 | WRITE(numout,*) 'Surface area is not preserved in ', & |
---|
2109 | TRIM(check_point) |
---|
2110 | WRITE(numout,*) 'Area in pixel ', ipts,' has changed form, ', & |
---|
2111 | SUM(veget_max_begin(ipts,:)), 'to,', SUM(veget_max(ipts,:)) |
---|
2112 | IF(err_act.GT.1) CALL ipslerr_p (plev, TRIM(check_point), & |
---|
2113 | 'Surface area not preserved','','') |
---|
2114 | ENDIF |
---|
2115 | ELSE |
---|
2116 | IF (ABS(SUM(veget_max_begin(ipts,:)) - SUM(veget_max(ipts,:))) .GT. & |
---|
2117 | min_stomate ) THEN |
---|
2118 | WRITE(numout,*) 'Surface area is not preserved in ', & |
---|
2119 | TRIM(check_point) |
---|
2120 | WRITE(numout,*) 'Area in pixel ', ipts,' has changed form, ', & |
---|
2121 | SUM(veget_max_begin(ipts,:)), 'to,', SUM(veget_max(ipts,:)) |
---|
2122 | IF(err_act.GT.1) CALL ipslerr_p (plev, TRIM(check_point), & |
---|
2123 | 'Surface area not preserved','','') |
---|
2124 | ENDIF |
---|
2125 | ENDIF |
---|
2126 | |
---|
2127 | ENDDO ! npts |
---|
2128 | |
---|
2129 | CASE DEFAULT |
---|
2130 | |
---|
2131 | WRITE(numout,*) 'Error: an unknown type/resolution was requested' |
---|
2132 | WRITE(numout,*) ' for the surface area check. Check the cases' |
---|
2133 | WRITE(numout,*) ' defined in src_parameters/function_library or' |
---|
2134 | WRITE(numout,*) ' the spelling of the type in the CALL argument',& |
---|
2135 | test_type |
---|
2136 | CALL ipslerr_p (3,'surface_area_check in function_library',& |
---|
2137 | 'unknown type', 'Check *_out_orchidee for more details','') |
---|
2138 | |
---|
2139 | END SELECT |
---|
2140 | |
---|
2141 | END SUBROUTINE check_vegetation_area |
---|
2142 | |
---|
2143 | !! ================================================================================================================================ |
---|
2144 | !! SUBROUTINE : check_mass balance |
---|
2145 | !! |
---|
2146 | !>\BRIEF |
---|
2147 | !! |
---|
2148 | !! DESCRIPTION : |
---|
2149 | !! RECENT CHANGE(S): None |
---|
2150 | !! |
---|
2151 | !! MAIN OUTPUT VARIABLE(S): |
---|
2152 | !! |
---|
2153 | !! REFERENCE(S) : None |
---|
2154 | !! |
---|
2155 | !! FLOWCHART : None |
---|
2156 | !! \n |
---|
2157 | !_ ================================================================================================================================ |
---|
2158 | SUBROUTINE check_mass_balance(check_point, closure_intern, npts, pool_end, & |
---|
2159 | pool_start, veget_max, test_type, pft) |
---|
2160 | |
---|
2161 | !! 0. Variable and parameter description |
---|
2162 | |
---|
2163 | !! 0.1 Input variables |
---|
2164 | INTEGER(i_std), INTENT(in) :: npts !! Domain size (unitless) |
---|
2165 | CHARACTER(*),INTENT(in) :: check_point !! A flag to indicate at which |
---|
2166 | !! point in the code we're doing |
---|
2167 | !! this check |
---|
2168 | REAL(r_std), DIMENSION(:,:,:), INTENT(in) :: closure_intern !! Check closure of internal mass balance |
---|
2169 | !! @tex $(gC pixel^{-1} dt^{-1})$ @endtex |
---|
2170 | REAL(r_std), DIMENSION(:,:,:), INTENT(in) :: pool_start !! Start and end pool of this routine |
---|
2171 | !! @tex $(gC pixel^{-1} dt^{-1})$ @endtex |
---|
2172 | REAL(r_std), DIMENSION(:,:,:), INTENT(in) :: pool_end !! Start and end pool of this routine |
---|
2173 | CHARACTER(*), INTENT(in) :: test_type !! Which test do we want to run on veget_max |
---|
2174 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: veget_max !! "maximal" coverage fraction of a PFT |
---|
2175 | !! (LAI -> infinity) on ground. May sum to |
---|
2176 | !! less than unity if the pixel has |
---|
2177 | !! nobio area. (unitless; 0-1) |
---|
2178 | INTEGER(i_std), OPTIONAL, INTENT(in) :: pft !! Number of the PFT for which the mass balance has to be checked |
---|
2179 | |
---|
2180 | !! 0.2 Output variables |
---|
2181 | |
---|
2182 | !! 0.3 Modified variables |
---|
2183 | |
---|
2184 | !! 0.4 Local variables |
---|
2185 | INTEGER :: iele, ipts, ivm !! Indices |
---|
2186 | INTEGER :: ipar, icir, err !! Indices |
---|
2187 | INTEGER(i_std) :: ivma, iagec, ipft !! Counter |
---|
2188 | REAL(r_std) :: temp_begin, temp_end !! temporary variables to accumulate veget_max of |
---|
2189 | |
---|
2190 | CHARACTER(LEN=10) :: var_name !! Name of element |
---|
2191 | |
---|
2192 | !_ ================================================================================================================================ |
---|
2193 | |
---|
2194 | SELECT CASE (test_type) |
---|
2195 | |
---|
2196 | CASE ('ipts') |
---|
2197 | |
---|
2198 | ! Close the mass balance for one specific pixel and pft. |
---|
2199 | ! This :test is used for subroutines that are called within |
---|
2200 | ! a DO ipts = 1,npts and DO ivm = 1,nvm loop. The mass |
---|
2201 | ! balance is checked for a single pft at a single pixel. |
---|
2202 | |
---|
2203 | DO iele=1,nelements |
---|
2204 | |
---|
2205 | IF (iele.EQ.icarbon) var_name = 'carbon' |
---|
2206 | IF (iele.EQ.initrogen) var_name = 'nitrogen' |
---|
2207 | err = zero |
---|
2208 | |
---|
2209 | ! Mass balance closure |
---|
2210 | DO ipts=1,npts |
---|
2211 | IF(ABS(SUM(closure_intern(ipts,:,iele))) .GT. min_stomate)THEN |
---|
2212 | |
---|
2213 | ! Count the number of errors |
---|
2214 | err = err + 1 |
---|
2215 | |
---|
2216 | ! Give extra details of where the mass balance |
---|
2217 | ! problem occurs. Stop the model if the user |
---|
2218 | ! asked for it |
---|
2219 | IF(err_act.GT.1) THEN |
---|
2220 | WRITE(numout,*) 'Error: mass balance is not closed in ', & |
---|
2221 | TRIM(check_point), ' for ', var_name |
---|
2222 | WRITE(numout,*) ' Problem occurs in pixel, ',ipts |
---|
2223 | WRITE(numout,*) ' Difference is, ', & |
---|
2224 | SUM(closure_intern(ipts,:,iele)) |
---|
2225 | WRITE(numout,*) ' pool_end,pool_start: ', & |
---|
2226 | SUM(pool_end(ipts,:,iele)), & |
---|
2227 | SUM(pool_start(ipts,:,iele)) |
---|
2228 | |
---|
2229 | ! Exit or write warning depening on plev |
---|
2230 | CALL ipslerr_p(plev, TRIM(check_point), & |
---|
2231 | 'Mass balance error','','') |
---|
2232 | ENDIF |
---|
2233 | |
---|
2234 | ENDIF |
---|
2235 | END DO |
---|
2236 | |
---|
2237 | !+++CHECK+++ |
---|
2238 | ! A lot of output - only write a message if their is a problem |
---|
2239 | !!$ ! One message per pixel. The err condition is needed because under |
---|
2240 | !!$ ! err_act = 2 the model will write an error to the out_orchidee file |
---|
2241 | !!$ ! but will not be stopped. Therefore it should be checked whether we |
---|
2242 | !!$ ! have an error or not |
---|
2243 | !!$ IF (err_act.GT.1 .AND. err.EQ.0) THEN |
---|
2244 | !!$ WRITE(numout,*) 'Mass balance closure in ', & |
---|
2245 | !!$ TRIM(check_point), ' for ',var_name |
---|
2246 | !!$ ENDIF |
---|
2247 | !++++++++++ |
---|
2248 | |
---|
2249 | ENDDO ! nelements |
---|
2250 | |
---|
2251 | CASE ('pft') |
---|
2252 | |
---|
2253 | ! Close mass balance at the pixel and pft level. |
---|
2254 | DO iele=1,nelements |
---|
2255 | |
---|
2256 | IF (iele.EQ.icarbon) var_name = 'carbon' |
---|
2257 | IF (iele.EQ.initrogen) var_name = 'nitrogen' |
---|
2258 | |
---|
2259 | DO ipts=1,npts |
---|
2260 | |
---|
2261 | err = zero |
---|
2262 | |
---|
2263 | DO ivm=1,nvm |
---|
2264 | |
---|
2265 | !check for NaN |
---|
2266 | IF (isnan(pool_start(ipts,ivm,iele))) THEN |
---|
2267 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2268 | TRIM(check_point), ' for ', var_name |
---|
2269 | WRITE(numout,*)'At pixel',ipts,' for element',iele,& |
---|
2270 | ' and for PFT',ivm,' pool_start is NaN' |
---|
2271 | WRITE(numout,*) ' pool_start: ', pool_start(ipts,:,iele) |
---|
2272 | CALL ipslerr_p(plev,TRIM(check_point),'NaN problem','','') |
---|
2273 | ENDIF |
---|
2274 | IF (isnan(pool_end(ipts,ivm,iele))) THEN |
---|
2275 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2276 | TRIM(check_point), ' for ', var_name |
---|
2277 | WRITE(numout,*) 'At the pixel',ipts,' for element',iele,& |
---|
2278 | ' and for PFT',ivm,' pool_end is NaN' |
---|
2279 | WRITE(numout,*) ' pool_end: ', pool_end(ipts,:,iele) |
---|
2280 | CALL ipslerr_p(plev,TRIM(check_point),'NaN problem','','') |
---|
2281 | ENDIF |
---|
2282 | IF (isnan(closure_intern(ipts,ivm,iele))) THEN |
---|
2283 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2284 | TRIM(check_point), ' for ', var_name |
---|
2285 | WRITE(numout,*) 'At the pixel',ipts,' for element',iele,& |
---|
2286 | ' and for PFT',ivm,' closure_intern is NaN' |
---|
2287 | WRITE(numout,*) ' closure_intern: ', closure_intern(ipts,:,iele) |
---|
2288 | CALL ipslerr_p(plev,TRIM(check_point), 'NaN problem','','') |
---|
2289 | ENDIF |
---|
2290 | |
---|
2291 | ! Mass balance closure |
---|
2292 | IF(ABS(closure_intern(ipts,ivm,iele)) .GT. min_stomate)THEN |
---|
2293 | |
---|
2294 | err = err+1 |
---|
2295 | |
---|
2296 | ! If the model is under development or being tested we will |
---|
2297 | ! output extra information to facilitate debugging. |
---|
2298 | IF(err_act.GT.1)THEN |
---|
2299 | WRITE(numout,*) 'Error: mass balance is not closed in ', & |
---|
2300 | TRIM(check_point), ' for ', var_name |
---|
2301 | WRITE(numout,*) ' ipts, ivm; ', ipts,ivm |
---|
2302 | WRITE(numout,*) ' Difference is, ', & |
---|
2303 | closure_intern(ipts,ivm,iele) |
---|
2304 | WRITE(numout,*) ' pool_end,pool_start: ', & |
---|
2305 | pool_end(ipts,ivm,iele), & |
---|
2306 | pool_start(ipts,ivm,iele) |
---|
2307 | |
---|
2308 | ! Exit or write warning depening on plev |
---|
2309 | CALL ipslerr_p(plev, TRIM(check_point), & |
---|
2310 | 'Mass balance error','','') |
---|
2311 | ENDIF |
---|
2312 | ENDIF |
---|
2313 | ENDDO ! nvm |
---|
2314 | |
---|
2315 | !+++CHECK+++ |
---|
2316 | ! A lot of output - only write a message if their is a problem |
---|
2317 | !!$ ! One message per pixel |
---|
2318 | !!$ IF (err_act.GT.1 .AND. err.EQ.zero) THEN |
---|
2319 | !!$ WRITE(numout,*) 'Mass balance closure in ', & |
---|
2320 | !!$ TRIM(check_point), ' for ',var_name |
---|
2321 | !!$ ENDIF |
---|
2322 | !++++++++++ |
---|
2323 | |
---|
2324 | ENDDO ! npts |
---|
2325 | |
---|
2326 | ENDDO ! nelements |
---|
2327 | |
---|
2328 | CASE ('ipft') |
---|
2329 | |
---|
2330 | ! Close mass balance at the pixel and pft level. Check for a |
---|
2331 | ! specific pft. This option is called from within a DO-loop. |
---|
2332 | DO iele=1,nelements |
---|
2333 | |
---|
2334 | IF (iele.EQ.icarbon) var_name = 'carbon' |
---|
2335 | IF (iele.EQ.initrogen) var_name = 'nitrogen' |
---|
2336 | |
---|
2337 | DO ipts=1,npts |
---|
2338 | |
---|
2339 | err = zero |
---|
2340 | |
---|
2341 | !check for NaN |
---|
2342 | IF (isnan(pool_start(ipts,pft,iele))) THEN |
---|
2343 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2344 | TRIM(check_point), ' for ', var_name |
---|
2345 | WRITE(numout,*)'At the pixel',ipts,' for element',iele,& |
---|
2346 | ' and for PFT',pft,' pool_start is NaN' |
---|
2347 | WRITE(numout,*) ' pool_start: ', pool_start(ipts,:,iele) |
---|
2348 | CALL ipslerr_p(plev,TRIM(check_point),'NaN problem','','') |
---|
2349 | ENDIF |
---|
2350 | IF (isnan(pool_end(ipts,pft,iele))) THEN |
---|
2351 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2352 | TRIM(check_point), ' for ', var_name |
---|
2353 | WRITE(numout,*) 'At the pixel',ipts,' for element',iele,& |
---|
2354 | ' and for PFT',pft,' pool_end is NaN' |
---|
2355 | WRITE(numout,*) ' pool_end: ', pool_end(ipts,:,iele) |
---|
2356 | CALL ipslerr_p(plev,TRIM(check_point),'NaN problem','','') |
---|
2357 | ENDIF |
---|
2358 | IF (isnan(closure_intern(ipts,pft,iele))) THEN |
---|
2359 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2360 | TRIM(check_point), ' for ', var_name |
---|
2361 | WRITE(numout,*) 'At the pixel',ipts,' for element',iele,& |
---|
2362 | ' and for PFT',pft,' closure_intern is NaN' |
---|
2363 | WRITE(numout,*) ' closure_intern: ', closure_intern(ipts,:,iele) |
---|
2364 | CALL ipslerr_p(plev,TRIM(check_point), 'NaN problem','','') |
---|
2365 | ENDIF |
---|
2366 | |
---|
2367 | |
---|
2368 | ! Mass balance closure |
---|
2369 | IF(ABS(closure_intern(ipts,pft,iele)) .GT. min_stomate)THEN |
---|
2370 | |
---|
2371 | err = err+1 |
---|
2372 | |
---|
2373 | ! If the model is under development or being tested we will |
---|
2374 | ! output extra information to facilitate debugging. |
---|
2375 | IF(err_act.GT.1)THEN |
---|
2376 | WRITE(numout,*) 'Error: mass balance is not closed in ', & |
---|
2377 | TRIM(check_point), ' for ', var_name |
---|
2378 | WRITE(numout,*) ' ipts, pft; ', ipts,pft |
---|
2379 | WRITE(numout,*) ' Difference is, ', & |
---|
2380 | closure_intern(ipts,pft,iele) |
---|
2381 | WRITE(numout,*) ' pool_end,pool_start: ', & |
---|
2382 | pool_end(ipts,pft,iele), & |
---|
2383 | pool_start(ipts,pft,iele) |
---|
2384 | |
---|
2385 | ! Exit or write warning depening on plev |
---|
2386 | CALL ipslerr_p(plev, TRIM(check_point), & |
---|
2387 | 'Mass balance error','','') |
---|
2388 | ENDIF |
---|
2389 | ENDIF |
---|
2390 | |
---|
2391 | ENDDO ! npts |
---|
2392 | |
---|
2393 | ENDDO ! nelements |
---|
2394 | |
---|
2395 | CASE ('ageclass') |
---|
2396 | |
---|
2397 | ! This option is only used when err_act.GE.2 |
---|
2398 | |
---|
2399 | ! In the subroutine under test, biomass can move |
---|
2400 | ! from one age class to another age class in the |
---|
2401 | ! same species. Test across all age classes for |
---|
2402 | ! the same species. |
---|
2403 | DO iele=1,nelements |
---|
2404 | |
---|
2405 | IF (iele.EQ.icarbon) var_name = 'carbon' |
---|
2406 | IF (iele.EQ.initrogen) var_name = 'nitrogen' |
---|
2407 | |
---|
2408 | DO ipts=1,npts |
---|
2409 | |
---|
2410 | err = zero |
---|
2411 | |
---|
2412 | DO ivma=1,nvmap |
---|
2413 | |
---|
2414 | ! get pft number |
---|
2415 | ivm=start_index(ivma) |
---|
2416 | |
---|
2417 | !check for NaN |
---|
2418 | IF (isnan(pool_start(ipts,ivm,iele))) THEN |
---|
2419 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2420 | TRIM(check_point), ' for ', var_name |
---|
2421 | WRITE(numout,*)'At the pixel',ipts,' for element',iele,& |
---|
2422 | ' and for PFT',ivm,' pool_start is NaN' |
---|
2423 | WRITE(numout,*) ' pool_start: ', pool_start(ipts,:,iele) |
---|
2424 | CALL ipslerr_p(plev,TRIM(check_point),'NaN problem','','') |
---|
2425 | ENDIF |
---|
2426 | IF (isnan(pool_end(ipts,ivm,iele))) THEN |
---|
2427 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2428 | TRIM(check_point), ' for ', var_name |
---|
2429 | WRITE(numout,*) 'At the pixel',ipts,' for element',iele,& |
---|
2430 | ' and for PFT',ivm,' pool_end is NaN' |
---|
2431 | WRITE(numout,*) ' pool_end: ', pool_end(ipts,:,iele) |
---|
2432 | CALL ipslerr_p(plev,TRIM(check_point),'NaN problem','','') |
---|
2433 | ENDIF |
---|
2434 | IF (isnan(closure_intern(ipts,ivm,iele))) THEN |
---|
2435 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2436 | TRIM(check_point), ' for ', var_name |
---|
2437 | WRITE(numout,*) 'At the pixel',ipts,' for element',iele,& |
---|
2438 | ' and for PFT',ivm,' closure_intern is NaN' |
---|
2439 | WRITE(numout,*) ' closure_intern: ', closure_intern(ipts,:,iele) |
---|
2440 | CALL ipslerr_p(plev,TRIM(check_point), 'NaN problem','','') |
---|
2441 | ENDIF |
---|
2442 | |
---|
2443 | ! If we only have a single age class for this |
---|
2444 | ! PFT, we can simplify the test |
---|
2445 | IF(nagec_pft(ivma) .EQ. 1) THEN |
---|
2446 | |
---|
2447 | ! Mass balance closure |
---|
2448 | IF(ABS(closure_intern(ipts,ivm,iele)) .GT. min_stomate)THEN |
---|
2449 | err=err+1 |
---|
2450 | WRITE(numout,*) 'Error: mass balance is not closed in ', & |
---|
2451 | TRIM(check_point), ' for ', var_name |
---|
2452 | WRITE(numout,*) ' ipts, ivm; ', ipts,ivm |
---|
2453 | WRITE(numout,*) ' Difference is, ', & |
---|
2454 | closure_intern(ipts,ivm,iele) |
---|
2455 | WRITE(numout,*) ' pool_end,pool_start: ', & |
---|
2456 | pool_end(ipts,ivm,iele), & |
---|
2457 | pool_start(ipts,ivm,iele) |
---|
2458 | IF (err_act.GT.1) CALL ipslerr_p (plev, TRIM(check_point), & |
---|
2459 | 'Mass balance error','','') |
---|
2460 | |
---|
2461 | ENDIF ! test for closure |
---|
2462 | |
---|
2463 | ELSE ! more than 1 age class |
---|
2464 | |
---|
2465 | temp_begin = 0 |
---|
2466 | DO iagec = nagec_pft(ivma),1,-1 |
---|
2467 | |
---|
2468 | ! Accumulate check_intern for all pfts/age classes |
---|
2469 | ! that belong to the same species |
---|
2470 | ipft = ivm+iagec-1 |
---|
2471 | temp_begin = temp_begin + closure_intern(ipts,ipft,iele) |
---|
2472 | |
---|
2473 | ENDDO ! nagec_pft |
---|
2474 | |
---|
2475 | IF (temp_begin .GT. min_stomate) THEN |
---|
2476 | |
---|
2477 | ! mass balance |
---|
2478 | err=err+1 |
---|
2479 | WRITE(numout,*) 'Error: mass balance is not closed in ', & |
---|
2480 | TRIM(check_point), ' for ', var_name |
---|
2481 | WRITE(numout,*) ' ipts, ivma; ', ipts,ivma |
---|
2482 | WRITE(numout,*) ' first and last pft, ', & |
---|
2483 | start_index(ivma), ipft |
---|
2484 | WRITE(numout,*) ' Difference is, ', & |
---|
2485 | temp_begin |
---|
2486 | IF (err_act.GT.1) CALL ipslerr_p (plev, TRIM(check_point), & |
---|
2487 | 'Mass balance error','','') |
---|
2488 | |
---|
2489 | ENDIF ! test for closure |
---|
2490 | |
---|
2491 | ENDIF ! number of age classes |
---|
2492 | |
---|
2493 | ENDDO ! ivmap |
---|
2494 | |
---|
2495 | |
---|
2496 | !+++CHECK+++ |
---|
2497 | ! A lot of output - only write a message if their is a problem |
---|
2498 | !!$ ! One message per pixel |
---|
2499 | !!$ IF (err_act.GT.1 .AND. err.EQ.zero) THEN |
---|
2500 | !!$ WRITE(numout,*) 'Mass balance closure in ', & |
---|
2501 | !!$ TRIM(check_point), ' for ',var_name |
---|
2502 | !!$ ENDIF |
---|
2503 | !++++++++++ |
---|
2504 | |
---|
2505 | ENDDO ! npts |
---|
2506 | |
---|
2507 | ENDDO ! iele |
---|
2508 | |
---|
2509 | CASE ('pixel') |
---|
2510 | |
---|
2511 | ! For testing subroutines where biomass can also move |
---|
2512 | ! from one species to another. |
---|
2513 | DO iele = 1, nelements |
---|
2514 | |
---|
2515 | IF (iele.EQ.icarbon) var_name = 'carbon' |
---|
2516 | IF (iele.EQ.initrogen) var_name = 'nitrogen' |
---|
2517 | |
---|
2518 | DO ipts=1,npts |
---|
2519 | |
---|
2520 | err = zero |
---|
2521 | |
---|
2522 | !check for NaN |
---|
2523 | IF (isnan(SUM(pool_start(ipts,:,iele)))) THEN |
---|
2524 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2525 | TRIM(check_point), ' for ', var_name |
---|
2526 | WRITE(numout,*)'At the pixel',ipts,' for element',iele,& |
---|
2527 | ' pool_start is NaN' |
---|
2528 | WRITE(numout,*) ' pool_start: ', pool_start(ipts,:,iele) |
---|
2529 | CALL ipslerr_p(plev,TRIM(check_point),'NaN problem','','') |
---|
2530 | ENDIF |
---|
2531 | IF (isnan(SUM(pool_end(ipts,:,iele)))) THEN |
---|
2532 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2533 | TRIM(check_point), ' for ', var_name |
---|
2534 | WRITE(numout,*) 'At the pixel',ipts,' for element',iele,& |
---|
2535 | ' pool_end is NaN' |
---|
2536 | WRITE(numout,*) ' pool_end: ', pool_end(ipts,:,iele) |
---|
2537 | CALL ipslerr_p(plev,TRIM(check_point),'NaN problem','','') |
---|
2538 | ENDIF |
---|
2539 | IF (isnan(SUM(closure_intern(ipts,:,iele)))) THEN |
---|
2540 | WRITE(numout,*) 'Error: found an NaN in ', & |
---|
2541 | TRIM(check_point), ' for ', var_name |
---|
2542 | WRITE(numout,*) 'At the pixel',ipts,' for element',iele,& |
---|
2543 | ' closure_intern is NaN' |
---|
2544 | WRITE(numout,*) ' closure_intern: ', closure_intern(ipts,:,iele) |
---|
2545 | CALL ipslerr_p(plev,TRIM(check_point), 'NaN problem','','') |
---|
2546 | ENDIF |
---|
2547 | |
---|
2548 | ! Mass balance closure |
---|
2549 | IF(ABS(SUM(closure_intern(ipts,:,iele))) .GT. min_stomate)THEN |
---|
2550 | |
---|
2551 | err = err+1 |
---|
2552 | |
---|
2553 | IF(err_act.GT.1)THEN |
---|
2554 | WRITE(numout,*) 'Error: mass balance is not closed in ', & |
---|
2555 | TRIM(check_point), ' for ', var_name |
---|
2556 | WRITE(numout,*) ' ipts, ', ipts |
---|
2557 | WRITE(numout,*) ' Difference is, ', & |
---|
2558 | SUM(closure_intern(ipts,:,iele)) |
---|
2559 | WRITE(numout,*) ' pool_end,pool_start: ', & |
---|
2560 | SUM(pool_end(ipts,:,iele)), & |
---|
2561 | SUM(pool_start(ipts,:,iele)) |
---|
2562 | ! Exit or write warning depening on plev |
---|
2563 | CALL ipslerr_p (plev, TRIM(check_point), & |
---|
2564 | 'Mass balance error','','') |
---|
2565 | ENDIF |
---|
2566 | |
---|
2567 | ENDIF |
---|
2568 | |
---|
2569 | !+++CHECK+++ |
---|
2570 | ! A lot of output - only write a message if their is a problem |
---|
2571 | !!$ ! One message per pixel |
---|
2572 | !!$ IF (err_act.GT.1 .AND. err.EQ.zero) THEN |
---|
2573 | !!$ WRITE(numout,*) 'Mass balance closure in ', & |
---|
2574 | !!$ TRIM(check_point), ' for ',var_name |
---|
2575 | !!$ ENDIF |
---|
2576 | !++++++++++ |
---|
2577 | |
---|
2578 | ENDDO ! npts |
---|
2579 | |
---|
2580 | ENDDO ! iele |
---|
2581 | |
---|
2582 | CASE ('products') |
---|
2583 | |
---|
2584 | ! This option is only used when err_act.GE.2 |
---|
2585 | |
---|
2586 | ! testing mass balance for the product pool. Veget_max is not used |
---|
2587 | ! ivm is not defined for closure_intern |
---|
2588 | DO iele=1,nelements |
---|
2589 | |
---|
2590 | IF (iele.EQ.icarbon) var_name = 'carbon' |
---|
2591 | IF (iele.EQ.initrogen) var_name = 'nitrogen' |
---|
2592 | |
---|
2593 | DO ipts=1,npts |
---|
2594 | |
---|
2595 | err = zero |
---|
2596 | |
---|
2597 | IF(ABS(closure_intern(ipts,1,iele)) .GT. min_stomate)THEN |
---|
2598 | |
---|
2599 | err = err+1 |
---|
2600 | WRITE(numout,*) 'Error: mass balance is not closed'//& |
---|
2601 | 'in basic_product_use', var_name |
---|
2602 | WRITE(numout,*) 'ipts,ivm,iele ', ipts |
---|
2603 | WRITE(numout,*) 'Difference is, ', & |
---|
2604 | closure_intern(ipts,1,iele) |
---|
2605 | WRITE(numout,*) 'pool_end, pool_start: ', & |
---|
2606 | pool_end(ipts,1,iele), pool_start(ipts,1,iele) |
---|
2607 | IF(err_act.GT.1) CALL ipslerr_p (plev,'basic_product_use', & |
---|
2608 | 'Mass balance error.','','') |
---|
2609 | ENDIF |
---|
2610 | |
---|
2611 | !+++CHECK+++ |
---|
2612 | ! A lot of output - only write a message if their is a problem |
---|
2613 | !!$ ! One message per pixel |
---|
2614 | !!$ IF (err_act.GT.1 .AND. err.EQ.zero) THEN |
---|
2615 | !!$ WRITE(numout,*) 'Mass balance closure in ', & |
---|
2616 | !!$ TRIM(check_point), ' for ',var_name |
---|
2617 | !!$ ENDIF |
---|
2618 | !++++++++++ |
---|
2619 | |
---|
2620 | ENDDO |
---|
2621 | ENDDO |
---|
2622 | |
---|
2623 | CASE DEFAULT |
---|
2624 | |
---|
2625 | WRITE(numout,*) 'Error: an unknown type/resolution was requested' |
---|
2626 | WRITE(numout,*) ' for the mass balance check. Check the cases' |
---|
2627 | WRITE(numout,*) ' defined in src_parameters/function_library or' |
---|
2628 | WRITE(numout,*) ' the spelling of the type in the CALL argument',& |
---|
2629 | test_type |
---|
2630 | CALL ipslerr_p (3,'mass_balance_check in function_library',& |
---|
2631 | 'unknown type', 'Check *_out_orchidee for more details','') |
---|
2632 | |
---|
2633 | END SELECT |
---|
2634 | |
---|
2635 | END SUBROUTINE check_mass_balance |
---|
2636 | |
---|
2637 | |
---|
2638 | !! ================================================================================================================================ |
---|
2639 | !! FUNCTION : intermediate_mass_balance_check |
---|
2640 | !! |
---|
2641 | !>\BRIEF |
---|
2642 | !! |
---|
2643 | !! DESCRIPTION : check whether the mass balance is closed in "the middle" of a stomate_growth_fun_all. |
---|
2644 | !! Might be difficult to use the exact same code in other subroutines |
---|
2645 | !! |
---|
2646 | !! RECENT CHANGE(S): None |
---|
2647 | !! |
---|
2648 | !! RETURN VALUE : None |
---|
2649 | !! |
---|
2650 | !! REFERENCE(S) : |
---|
2651 | !! |
---|
2652 | !! FLOWCHART : None |
---|
2653 | !! \n |
---|
2654 | !_ ================================================================================================================================ |
---|
2655 | |
---|
2656 | SUBROUTINE intermediate_mass_balance_check(pool_start, pool_end, circ_class_biomass, & |
---|
2657 | circ_class_n, veget_max, bm_alloc_tot, gpp_daily, atm_to_bm, dt, npts, & |
---|
2658 | resp_maint, resp_growth, check_intern_init, ipts, j, label, test_type) |
---|
2659 | |
---|
2660 | !! 0.1 Input variables |
---|
2661 | INTEGER(i_std), INTENT(in) :: npts !! Domain size (unitless) |
---|
2662 | REAL(r_std), DIMENSION(:,:,:,:,:), INTENT(in) :: circ_class_biomass !! Biomass components of the model tree |
---|
2663 | !! within a circumference class |
---|
2664 | !! class @tex $(g C ind^{-1})$ @endtex |
---|
2665 | REAL(r_std), DIMENSION(:,:,:), INTENT(in) :: circ_class_n !! Number of individuals in each circ class |
---|
2666 | !! @tex $(m^{-2})$ @endtex |
---|
2667 | REAL(r_std), DIMENSION(:,:,:), INTENT(in) :: pool_start !! Start of this routine |
---|
2668 | !! @tex $(gC pixel^{-1} dt^{-1})$ @endtex |
---|
2669 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: veget_max !! PFT "Maximal" coverage fraction of a PFT |
---|
2670 | !! @tex $(m^2 m^{-2})$ @endtex |
---|
2671 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: bm_alloc_tot !! Allocatable biomass for the whole plant |
---|
2672 | !! @tex $(gC.m^{-2})$ @endtex |
---|
2673 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: gpp_daily !! PFT gross primary productivity |
---|
2674 | !! @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
2675 | REAL(r_std), DIMENSION(:,:,:), INTENT(in) :: atm_to_bm !! Nitrogen and carbon which is added to the ecosystem to |
---|
2676 | !! support vegetation growth (gC or gN/m2/day) |
---|
2677 | REAL(r_std), INTENT(in) :: dt !! Time step of the simulations for stomate (days) |
---|
2678 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: resp_maint !! PFT maintenance respiration |
---|
2679 | !! @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
2680 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: resp_growth !! PFT growth respiration |
---|
2681 | !! @tex $(gC.m^{-2}dt^{-1})$ @endtex |
---|
2682 | REAL(r_std), DIMENSION(:,:,:,:), INTENT(in) :: check_intern_init !! Contains the components of the internal |
---|
2683 | !! mass balance chech for this routine |
---|
2684 | !! @tex $(gC pixel^{-1} dt^{-1})$ @endtex |
---|
2685 | INTEGER(i_std), INTENT(in) :: ipts, j !! indices |
---|
2686 | CHARACTER(len=*), INTENT(in) :: label !! label to identify the mass balance check |
---|
2687 | |
---|
2688 | !! 0.2 Output variables |
---|
2689 | |
---|
2690 | !! 0.3 Modified variables |
---|
2691 | REAL(r_std), DIMENSION(:,:,:), INTENT(inout) :: pool_end !! Start and end pool of this routine |
---|
2692 | !! @tex $(gC pixel^{-1} dt^{-1})$ @endtex |
---|
2693 | CHARACTER(*), INTENT(in) :: test_type !! Which test do we want to run on veget_max |
---|
2694 | |
---|
2695 | !! 0.4 Local variables |
---|
2696 | INTEGER(i_std) :: ipar, iele, icir !! Indices |
---|
2697 | INTEGER(i_std) :: imbc !! Indices |
---|
2698 | CHARACTER(len=80) :: message !! Label for error message |
---|
2699 | REAL(r_std), DIMENSION(npts,nvm,nmbcomp,nelements):: check_intern !! Contains the components of the internal |
---|
2700 | !! mass balance chech for this routine |
---|
2701 | !! @tex $(gC pixel^{-1} dt^{-1})$ @endtex |
---|
2702 | REAL(r_std), DIMENSION(npts,nvm,nelements) :: closure_intern !! Check closure of internal mass balance |
---|
2703 | !! @tex $(gC pixel^{-1} dt^{-1})$ @endtex |
---|
2704 | |
---|
2705 | !_ ================================================================================================================================ |
---|
2706 | |
---|
2707 | SELECT CASE(test_type) |
---|
2708 | CASE('pft') |
---|
2709 | ! Calculate pool_end |
---|
2710 | DO ipar = 1,nparts |
---|
2711 | DO iele = 1,nelements |
---|
2712 | DO icir = 1,ncirc |
---|
2713 | pool_end(:,:,iele) = pool_end(:,:,iele) + & |
---|
2714 | (circ_class_biomass(:,:,icir,ipar,iele) * & |
---|
2715 | circ_class_n(:,:,icir) * veget_max(:,:)) |
---|
2716 | ENDDO |
---|
2717 | ENDDO |
---|
2718 | ENDDO |
---|
2719 | |
---|
2720 | ! Calculate mass balance |
---|
2721 | ! Specific processes for carbon |
---|
2722 | check_intern(:,:,:,:) = zero |
---|
2723 | check_intern(:,:,iatm2land,icarbon) = & |
---|
2724 | check_intern_init(:,:,iatm2land,icarbon) + & |
---|
2725 | (gpp_daily(:,:) + atm_to_bm(:,:,icarbon)) * & |
---|
2726 | dt * veget_max(:,:) |
---|
2727 | check_intern(:,:,iatm2land,initrogen) = & |
---|
2728 | check_intern_init(:,:,iatm2land,initrogen) + & |
---|
2729 | atm_to_bm(:,:,initrogen) * dt * veget_max(:,:) |
---|
2730 | check_intern(:,:,iland2atm,icarbon) = -un * & |
---|
2731 | (resp_maint(:,:) + resp_growth(:,:)) * & |
---|
2732 | veget_max(:,:) |
---|
2733 | |
---|
2734 | ! Common processes for icarbon and initrogen |
---|
2735 | DO iele=1,nelements |
---|
2736 | check_intern(:,:,ipoolchange,iele) = -un * (pool_end(:,:,iele) - & |
---|
2737 | pool_start(:,:,iele)) |
---|
2738 | ENDDO |
---|
2739 | |
---|
2740 | closure_intern = zero |
---|
2741 | DO imbc = 1,nmbcomp |
---|
2742 | DO iele=1,nelements |
---|
2743 | closure_intern(:,:,iele) = closure_intern(:,:,iele) + & |
---|
2744 | check_intern(:,:,imbc,iele) |
---|
2745 | ENDDO |
---|
2746 | ENDDO |
---|
2747 | |
---|
2748 | CASE ('ipft') |
---|
2749 | |
---|
2750 | ! Calculate pool_end |
---|
2751 | DO ipar = 1,nparts |
---|
2752 | DO iele = 1,nelements |
---|
2753 | DO icir = 1,ncirc |
---|
2754 | pool_end(ipts,j,iele) = pool_end(ipts,j,iele) + & |
---|
2755 | (circ_class_biomass(ipts,j,icir,ipar,iele) * & |
---|
2756 | circ_class_n(ipts,j,icir) * veget_max(ipts,j)) |
---|
2757 | ENDDO |
---|
2758 | ENDDO |
---|
2759 | ENDDO |
---|
2760 | |
---|
2761 | ! Calculate mass balance |
---|
2762 | ! Specific processes for carbon |
---|
2763 | check_intern(:,:,:,:) = zero |
---|
2764 | check_intern(ipts,j,iatm2land,icarbon) = & |
---|
2765 | check_intern_init(ipts,j,iatm2land,icarbon) + & |
---|
2766 | (gpp_daily(ipts,j) + atm_to_bm(ipts,j,icarbon)) * & |
---|
2767 | dt * veget_max(ipts,j) |
---|
2768 | check_intern(ipts,j,iatm2land,initrogen) = & |
---|
2769 | check_intern_init(ipts,j,iatm2land,initrogen) + & |
---|
2770 | atm_to_bm(ipts,j,initrogen) * dt * veget_max(ipts,j) |
---|
2771 | check_intern(ipts,j,iland2atm,icarbon) = -un * & |
---|
2772 | (resp_maint(ipts,j) + resp_growth(ipts,j)) * & |
---|
2773 | veget_max(ipts,j) |
---|
2774 | |
---|
2775 | ! Common processes for icarbon and initrogen |
---|
2776 | DO iele=1,nelements |
---|
2777 | check_intern(ipts,j,ipoolchange,iele) = -un * (pool_end(ipts,j,iele) - & |
---|
2778 | pool_start(ipts,j,iele)) |
---|
2779 | ENDDO |
---|
2780 | |
---|
2781 | closure_intern = zero |
---|
2782 | DO imbc = 1,nmbcomp |
---|
2783 | DO iele=1,nelements |
---|
2784 | closure_intern(ipts,j,iele) = closure_intern(ipts,j,iele) + & |
---|
2785 | check_intern(ipts,j,imbc,iele) |
---|
2786 | ENDDO |
---|
2787 | ENDDO |
---|
2788 | |
---|
2789 | CASE DEFAULT |
---|
2790 | |
---|
2791 | CALL ipslerr_p(3,'intermediate mass balance check', & |
---|
2792 | 'test_type not correcty defined','case not specified','') |
---|
2793 | |
---|
2794 | END SELECT |
---|
2795 | |
---|
2796 | message = 'Intermediate mass balance check '//TRIM(label) |
---|
2797 | WRITE(numout,*) message, ' for pft, ', j |
---|
2798 | CALL check_mass_balance(message, closure_intern, npts, pool_end, & |
---|
2799 | pool_start, veget_max, test_type, j) |
---|
2800 | |
---|
2801 | END SUBROUTINE intermediate_mass_balance_check |
---|
2802 | |
---|
2803 | |
---|
2804 | !! ================================================================================================================================ |
---|
2805 | !! FUNCTION : check_area_change |
---|
2806 | !! |
---|
2807 | !>\BRIEF |
---|
2808 | !! |
---|
2809 | !! DESCRIPTION : check whether the change in vegetation is cancelled out by the |
---|
2810 | !! change in non-biological land covers |
---|
2811 | !! |
---|
2812 | !! RECENT CHANGE(S): None |
---|
2813 | !! |
---|
2814 | !! RETURN VALUE : None |
---|
2815 | !! |
---|
2816 | !! REFERENCE(S) : |
---|
2817 | !! |
---|
2818 | !! FLOWCHART : None |
---|
2819 | !! \n |
---|
2820 | !_ ================================================================================================================================ |
---|
2821 | |
---|
2822 | SUBROUTINE check_area_change(check_point, npts, frac_nobio, frac_nobio_new, loss_gain) |
---|
2823 | |
---|
2824 | !! 0.1 Input variables |
---|
2825 | INTEGER, INTENT(in) :: npts !! Domain size - number of pixels (unitless) |
---|
2826 | REAL(r_std), DIMENSION(:,:),INTENT(in) :: frac_nobio !! Fraction of grid cell covered by lakes, land |
---|
2827 | !! ice, cities, ... before land cover change (unitless, 0-1) |
---|
2828 | REAL(r_std),DIMENSION(:,:),INTENT(in) :: frac_nobio_new !! Fraction of grid cell covered by lakes, land |
---|
2829 | !! ice, cities, ... after land cover change (unitless, 0-1) |
---|
2830 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: loss_gain !! losses and gains due to LCC distributed over all |
---|
2831 | !! age classes and thus taking the age-classes into |
---|
2832 | !! account (unitless, 0-1) |
---|
2833 | CHARACTER(*),INTENT(in) :: check_point !! A flag to indicate at which |
---|
2834 | !! point in the code we're doing |
---|
2835 | !! this check |
---|
2836 | |
---|
2837 | !! 0.2 Output variables |
---|
2838 | |
---|
2839 | !! 0.3 Modified variables |
---|
2840 | |
---|
2841 | !! 0.4 Local variables |
---|
2842 | INTEGER(i_std) :: ipts !! Index |
---|
2843 | INTEGER(i_std), DIMENSION(npts) :: count !! counter |
---|
2844 | REAL(r_std) :: total !! temporary variable for total area of a pixel (unitless, 0-1) |
---|
2845 | REAL(r_std), DIMENSION(npts) :: change_nobio !! Change in the non biological fraction in a pixel (0-1, unitless) |
---|
2846 | |
---|
2847 | !_ ================================================================================================================================ |
---|
2848 | |
---|
2849 | ! Quality check. It is now expected that the changes cancel out each other |
---|
2850 | ! and are exactley zero. |
---|
2851 | count(:) = zero |
---|
2852 | change_nobio(:) = SUM(frac_nobio_new(:,:) - frac_nobio(:,:),2) |
---|
2853 | WHERE(ABS(SUM(loss_gain(:,:),2)+change_nobio(:)).GT.10*EPSILON(un)) |
---|
2854 | count(:) = un |
---|
2855 | END WHERE |
---|
2856 | |
---|
2857 | ! Error checking |
---|
2858 | IF(SUM(count(:)).GT.zero)THEN |
---|
2859 | |
---|
2860 | ! Refine the error message |
---|
2861 | DO ipts = 1,npts |
---|
2862 | IF (ABS(SUM(loss_gain(ipts,:))+change_nobio(ipts)).GT.10*EPSILON(un)) THEN |
---|
2863 | total = ABS(SUM(loss_gain(ipts,:))+change_nobio(ipts)) |
---|
2864 | WRITE(numout,*) 'ipts, change_nobio, loss_gain, mismatch, ', & |
---|
2865 | ipts, change_nobio(ipts), SUM(loss_gain(ipts,:)), total |
---|
2866 | WRITE(numout,*) 'ipts, frac_nobio_new, frac_nobio. ', & |
---|
2867 | ipts, SUM(frac_nobio_new(ipts,:)), SUM(frac_nobio(ipts,:)) |
---|
2868 | END IF |
---|
2869 | END DO |
---|
2870 | WRITE(numout,*) 'Found ,',SUM(count(:)), & |
---|
2871 | ' pixels for which the total change differs from zero (=0)' |
---|
2872 | CALL ipslerr_p(3,TRIM(check_point), & |
---|
2873 | 'The change in surface areas do not cancel out to zero', '','') |
---|
2874 | |
---|
2875 | END IF |
---|
2876 | |
---|
2877 | END SUBROUTINE check_area_change |
---|
2878 | |
---|
2879 | |
---|
2880 | !! ================================================================================================================================ |
---|
2881 | !! FUNCTION : check_pixel_area |
---|
2882 | !! |
---|
2883 | !>\BRIEF |
---|
2884 | !! |
---|
2885 | !! DESCRIPTION : check whether the vegetation and non-biological fractions |
---|
2886 | !! still add up to one (=1). |
---|
2887 | !! |
---|
2888 | !! RECENT CHANGE(S): None |
---|
2889 | !! |
---|
2890 | !! RETURN VALUE : None |
---|
2891 | !! |
---|
2892 | !! REFERENCE(S) : |
---|
2893 | !! |
---|
2894 | !! FLOWCHART : None |
---|
2895 | !! \n |
---|
2896 | !_ ================================================================================================================================ |
---|
2897 | |
---|
2898 | SUBROUTINE check_pixel_area(check_point, npts, veget_max, frac_nobio) |
---|
2899 | |
---|
2900 | !! 0.1 Input variables |
---|
2901 | INTEGER, INTENT(in) :: npts !! Domain size - number of pixels (unitless) |
---|
2902 | REAL(r_std), DIMENSION(:,:),INTENT(in) :: veget_max !! Cover fraction of the vegetation (unitless, 0-1) |
---|
2903 | REAL(r_std),DIMENSION(:,:),INTENT(in) :: frac_nobio !! Fraction of grid cell covered by lakes, land |
---|
2904 | !! ice, cities, ... (unitless, 0-1) |
---|
2905 | CHARACTER(*),INTENT(in) :: check_point !! A flag to indicate at which |
---|
2906 | !! point in the code we're doing |
---|
2907 | !! this check |
---|
2908 | |
---|
2909 | !! 0.2 Output variables |
---|
2910 | |
---|
2911 | !! 0.3 Modified variables |
---|
2912 | |
---|
2913 | !! 0.4 Local variables |
---|
2914 | INTEGER(i_std) :: ipts !! Index |
---|
2915 | INTEGER(i_std), DIMENSION(npts) :: count !! counter |
---|
2916 | |
---|
2917 | !_ ================================================================================================================================ |
---|
2918 | |
---|
2919 | ! Quality check. It is still expected that the different vegetation |
---|
2920 | ! fractions in each pixel sums up to exactly one. |
---|
2921 | count(:) = zero |
---|
2922 | WHERE(ABS(un-SUM(veget_max(:,:),2)-SUM(frac_nobio(:,:),2)).GT.10*EPSILON(un)) |
---|
2923 | count(:) = un |
---|
2924 | END WHERE |
---|
2925 | |
---|
2926 | ! Error checking |
---|
2927 | IF(SUM(count(:)).GT.zero)THEN |
---|
2928 | |
---|
2929 | ! Refine the error message |
---|
2930 | DO ipts = 1,npts |
---|
2931 | IF (ABS(un-SUM(veget_max(ipts,:))-SUM(frac_nobio(ipts,:))).GT.10*EPSILON(un)) THEN |
---|
2932 | WRITE(numout,*) 'ipts, frac_nobio, veget_max_new, mismatch, ', ipts, & |
---|
2933 | SUM(frac_nobio(ipts,:)), SUM(veget_max(ipts,:)), & |
---|
2934 | un-SUM(veget_max(ipts,:))-SUM(frac_nobio(ipts,:)) |
---|
2935 | END IF |
---|
2936 | END DO |
---|
2937 | WRITE(numout,*) 'Found ,',SUM(count(:)), ' pixels for which the total surface area & |
---|
2938 | is not one' |
---|
2939 | CALL ipslerr_p(3,TRIM(check_point), & |
---|
2940 | 'The sum of the vegetation and non-biological fractions',& |
---|
2941 | 'differs from one','') |
---|
2942 | |
---|
2943 | END IF |
---|
2944 | |
---|
2945 | END SUBROUTINE check_pixel_area |
---|
2946 | |
---|
2947 | |
---|
2948 | !! ================================================================================================================================ |
---|
2949 | !! FUNCTION : check_variable_change |
---|
2950 | !! |
---|
2951 | !>\BRIEF |
---|
2952 | !! |
---|
2953 | !! DESCRIPTION : check whether the relationship between veget_max, veget_max_new and |
---|
2954 | !! loss_gain holds |
---|
2955 | !! |
---|
2956 | !! RECENT CHANGE(S): None |
---|
2957 | !! |
---|
2958 | !! RETURN VALUE : None |
---|
2959 | !! |
---|
2960 | !! REFERENCE(S) : |
---|
2961 | !! |
---|
2962 | !! FLOWCHART : None |
---|
2963 | !! \n |
---|
2964 | !_ ================================================================================================================================ |
---|
2965 | |
---|
2966 | SUBROUTINE check_variable_change(check_point, npts, veget_max, veget_max_new, loss_gain) |
---|
2967 | |
---|
2968 | !! 0.1 Input variables |
---|
2969 | INTEGER, INTENT(in) :: npts !! Domain size - number of pixels (unitless) |
---|
2970 | REAL(r_std), DIMENSION(:,:),INTENT(in) :: veget_max !! Cover fraction of the vegetation before land cover change (unitless, 0-1) |
---|
2971 | REAL(r_std),DIMENSION(:,:),INTENT(in) :: veget_max_new !! Cover fraction of the vegetation after land cover change (unitless, 0-1) |
---|
2972 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: loss_gain !! losses and gains due to LCC distributed over all |
---|
2973 | !! age classes and thus taking the age-classes into |
---|
2974 | !! account (unitless, 0-1) |
---|
2975 | CHARACTER(*),INTENT(in) :: check_point !! A flag to indicate at which |
---|
2976 | !! point in the code we're doing |
---|
2977 | !! this check |
---|
2978 | |
---|
2979 | !! 0.2 Output variables |
---|
2980 | |
---|
2981 | !! 0.3 Modified variables |
---|
2982 | |
---|
2983 | !! 0.4 Local variables |
---|
2984 | INTEGER(i_std) :: ipts !! Index |
---|
2985 | INTEGER(i_std), DIMENSION(npts) :: count !! counter |
---|
2986 | REAL(r_std) :: total !! temporary variable for total area of a pixel (unitless, 0-1) |
---|
2987 | !_ ================================================================================================================================ |
---|
2988 | |
---|
2989 | ! Quality check. In slowproc veget_max_new was calculated as veget_max |
---|
2990 | ! plus loss_gain. If all went well veget_max, loss_gain and |
---|
2991 | ! veget_max_new are not changed in between slowproc and |
---|
2992 | ! sapiens_lcchange. One of the reason this assumption is valid is |
---|
2993 | ! because LCC is calculated at the first day of the year whereas |
---|
2994 | ! the other processes that can change veget_max are calculated |
---|
2995 | ! the last day of the year. If the above is not true we have to |
---|
2996 | ! carefully check what is going on withe veget_max, loss_gain |
---|
2997 | ! and/ot veget_max_new. |
---|
2998 | count(:) = zero |
---|
2999 | WHERE(ABS(SUM(veget_max_new(:,:)-loss_gain(:,:)-veget_max(:,:),2)).GT.10*EPSILON(un)) |
---|
3000 | count(:) = un |
---|
3001 | END WHERE |
---|
3002 | |
---|
3003 | ! Error checking |
---|
3004 | IF(SUM(count(:)).GT.zero)THEN |
---|
3005 | |
---|
3006 | ! Refine the error message |
---|
3007 | DO ipts = 1,npts |
---|
3008 | IF (ABS(SUM(veget_max_new(ipts,:)-loss_gain(ipts,:) - & |
---|
3009 | veget_max(ipts,:))).GT.10*EPSILON(un)) THEN |
---|
3010 | total = ABS(SUM(veget_max_new(ipts,:)-loss_gain(ipts,:) - & |
---|
3011 | veget_max(ipts,:))) |
---|
3012 | WRITE(numout,*) 'ipts, veget_max_new, veget_max, loss_gain, mismatch, ', & |
---|
3013 | ipts, SUM(veget_max_new(ipts,:)), SUM(veget_max(ipts,:)), & |
---|
3014 | SUM(loss_gain(ipts,:)), total |
---|
3015 | END IF |
---|
3016 | END DO |
---|
3017 | WRITE(numout,*) 'Found ,',SUM(count(:)), ' pixels for which the total surface area & |
---|
3018 | is not one' |
---|
3019 | CALL ipslerr_p(3,TRIM(check_point),& |
---|
3020 | 'Too big changes in surface area when updating veget_max_new','','') |
---|
3021 | |
---|
3022 | END IF |
---|
3023 | |
---|
3024 | END SUBROUTINE check_variable_change |
---|
3025 | |
---|
3026 | |
---|
3027 | !! ================================================================================================================================ |
---|
3028 | !! FUNCTION : check_variable_swap |
---|
3029 | !! |
---|
3030 | !>\BRIEF |
---|
3031 | !! |
---|
3032 | !! DESCRIPTION : at one point in sapiens_lcchange veget_max_new should be |
---|
3033 | !! equal to veget_max. Check whether this is the case |
---|
3034 | !! |
---|
3035 | !! RECENT CHANGE(S): None |
---|
3036 | !! |
---|
3037 | !! RETURN VALUE : None |
---|
3038 | !! |
---|
3039 | !! REFERENCE(S) : |
---|
3040 | !! |
---|
3041 | !! FLOWCHART : None |
---|
3042 | !! \n |
---|
3043 | !_ ================================================================================================================================ |
---|
3044 | |
---|
3045 | SUBROUTINE check_variable_swap(check_point, npts, veget_max, veget_max_new) |
---|
3046 | |
---|
3047 | !! 0.1 Input variables |
---|
3048 | INTEGER, INTENT(in) :: npts !! Domain size - number of pixels (unitless) |
---|
3049 | REAL(r_std), DIMENSION(:,:),INTENT(in) :: veget_max !! Cover fraction of the vegetation before land cover change (unitless, 0-1) |
---|
3050 | REAL(r_std),DIMENSION(:,:),INTENT(in) :: veget_max_new !! Cover fraction of the vegetation after land cover change (unitless, 0-1) |
---|
3051 | CHARACTER(*),INTENT(in) :: check_point !! A flag to indicate at which |
---|
3052 | !! point in the code we're doing |
---|
3053 | !! this check |
---|
3054 | |
---|
3055 | !! 0.2 Output variables |
---|
3056 | |
---|
3057 | !! 0.3 Modified variables |
---|
3058 | |
---|
3059 | !! 0.4 Local variables |
---|
3060 | INTEGER(i_std) :: ipts !! Index |
---|
3061 | INTEGER(i_std), DIMENSION(npts) :: count !! counter |
---|
3062 | REAL(r_std) :: total !! temporary variable for total area of a pixel (unitless, 0-1) |
---|
3063 | !_ ================================================================================================================================ |
---|
3064 | |
---|
3065 | count(:) = zero |
---|
3066 | WHERE(ABS(SUM(veget_max(:,:) - veget_max_new(:,:),2)).GT.10*EPSILON(un)) |
---|
3067 | count(:) = un |
---|
3068 | END WHERE |
---|
3069 | |
---|
3070 | ! Error checking |
---|
3071 | IF(SUM(count(:)).GT.zero)THEN |
---|
3072 | |
---|
3073 | ! Refine the error message |
---|
3074 | DO ipts = 1,npts |
---|
3075 | IF (ABS(SUM(veget_max(ipts,:) - veget_max_new(ipts,:))).GT.10*EPSILON(un)) THEN |
---|
3076 | total = ABS(SUM(veget_max(ipts,:) - veget_max_new(ipts,:))) |
---|
3077 | WRITE(numout,*) 'ipts, veget_max, veget_max_new, mismatch, ', & |
---|
3078 | ipts, SUM(veget_max(ipts,:)), SUM(veget_max_new(ipts,:)), total |
---|
3079 | END IF |
---|
3080 | END DO |
---|
3081 | WRITE(numout,*) 'Found ,',SUM(count(:)), & |
---|
3082 | ' pixels for which the updated veget_max differs from veget_max_new' |
---|
3083 | CALL ipslerr_p(3,TRIM(check_point),& |
---|
3084 | 'Updated veget_max but the update differs from veget_max_new', & |
---|
3085 | 'improve slowproc_adjust_delta_vegetmax','') |
---|
3086 | |
---|
3087 | END IF |
---|
3088 | |
---|
3089 | END SUBROUTINE check_variable_swap |
---|
3090 | |
---|
3091 | |
---|
3092 | ! ================================================================================================================================ |
---|
3093 | !! SUBROUTINE : check_biomass_change |
---|
3094 | !! |
---|
3095 | !>\BRIEF Check mass conservation for the biomass pool in sapiens_lcchange |
---|
3096 | !! |
---|
3097 | !! DESCRIPTION : Within sapiens_lcchange, biomass of pfts may change but in a |
---|
3098 | !! predictive way depending on whether there was a loss or gain in veget_max. |
---|
3099 | !! |
---|
3100 | !! RECENT CHANGE(S) : |
---|
3101 | !! |
---|
3102 | !! MAIN OUTPUT VARIABLE(S) : None |
---|
3103 | !! |
---|
3104 | !! REFERENCES : None |
---|
3105 | !! |
---|
3106 | !! FLOWCHART : |
---|
3107 | !! \n |
---|
3108 | !_ ================================================================================================================================ |
---|
3109 | |
---|
3110 | SUBROUTINE check_biomass_change(npts, dt_days, area, circ_class_biomass, & |
---|
3111 | circ_class_n, veget_max, loss_gain, atm_to_bm_old, atm_to_bm, & |
---|
3112 | harvest_pool, harvest_pool_old, fresh_litter, bm_to_litter_old, & |
---|
3113 | biomass_start, biomass_end, n_call) |
---|
3114 | |
---|
3115 | !! 0. Variable declaration |
---|
3116 | |
---|
3117 | !! 0.1 Input variables |
---|
3118 | INTEGER, INTENT(in) :: npts !! Domain size - number of pixels (unitless) |
---|
3119 | REAL(r_std), DIMENSION(:,:,:,:,:), INTENT(in) :: circ_class_biomass !! Biomass components of the model tree within a |
---|
3120 | !! circumference class @tex $(g C ind^{-1})$ @endtex |
---|
3121 | REAL(r_std), DIMENSION(:,:,:), INTENT(in) :: circ_class_n !! Number of individuals in each circ class |
---|
3122 | !! @tex $(ind m^{-2})$ @endtex |
---|
3123 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: veget_max !! "maximal" coverage fraction of a PFT on the ground |
---|
3124 | !! May sum to |
---|
3125 | !! less than unity if the pixel has |
---|
3126 | !! nobio area. (unitless, 0-1) |
---|
3127 | REAL(r_std), DIMENSION(:,:), INTENT(in) :: loss_gain !! losses and gains due to LCC distributed over all |
---|
3128 | !! age classes and thus taking the age-classes into |
---|
3129 | !! account (unitless, 0-1) |
---|
3130 | INTEGER(i_std), INTENT(in) :: n_call !! Number indicating whether it is the first or second call |
---|
3131 | REAL(r_std), DIMENSION(:,:,:), INTENT(in) :: atm_to_bm_old !! Temporary variable to store atm_to_bm at the start of |
---|
3132 | !! the routine @tex (gC.m^{-2}dt^{-1})$ @endtex |
---|
3133 | REAL(r_std), DIMENSION(:,:,:), INTENT(in) :: atm_to_bm !! C and N taken from the atmosphere to get C and N to |
---|
3134 | !! create the seedlings @tex (gC.m^{-2}dt^{-1})$ @endtex |
---|
3135 | REAL(r_std), INTENT(in) :: dt_days !! Time step of vegetation dynamics for stomate (days) |
---|
3136 | REAL(r_std), DIMENSION(:,:,:,:), INTENT(in) :: harvest_pool !! The wood and biomass that have been |
---|
3137 | !! havested by humans @tex $(gC)$ @endtex |
---|
3138 | REAL(r_std),DIMENSION(:,:,:,:), INTENT(in) :: fresh_litter !! Pool of fresh litter that is being released during @tex $(gC)$ @endtex |
---|
3139 | REAL(r_std), DIMENSION(:), INTENT(in) :: area !! surface area of the pixel @tex ($m^{2}$) @endtex |
---|
3140 | REAL(r_std), DIMENSION(:,:,:,:), INTENT(in) :: harvest_pool_old !! Temporary variable to check mass conservation |
---|
3141 | REAL(r_std), DIMENSION(:,:,:,:), INTENT(in) :: bm_to_litter_old !! Temporary transfer of biomass to litter |
---|
3142 | !! @tex $(gC m^{-2} dtslow^{-1})$ @endtex |
---|
3143 | |
---|
3144 | |
---|
3145 | !! 0.2 Output variables |
---|
3146 | |
---|
3147 | !! 0.3 Modified variables |
---|
3148 | REAL(r_std), DIMENSION(:,:,:),INTENT(inout) :: biomass_start !! biomass before LCC in gC or gN. |
---|
3149 | REAL(r_std), DIMENSION(:,:,:),INTENT(inout) :: biomass_end !! biomass after LCC in gC or gN. |
---|
3150 | |
---|
3151 | !! 0.4 Local variables |
---|
3152 | INTEGER(i_std) :: iele,icir,ivm,ipts !! Indices |
---|
3153 | REAL(r_std), DIMENSION(nelements) :: check !! Som of pools and fluxes gC or gN pixel-1. |
---|
3154 | !_ ================================================================================================================================ |
---|
3155 | |
---|
3156 | IF (n_call.EQ.1) THEN |
---|
3157 | ! Calculate the total biomass at the start of the routine |
---|
3158 | DO ipts = 1,npts |
---|
3159 | DO ivm = 1,nvm |
---|
3160 | DO iele = 1, nelements |
---|
3161 | DO icir = 1,ncirc |
---|
3162 | ! Multiply with area to make the units easier to understand. |
---|
3163 | ! The unit of biomass_start is gC pixel-1 |
---|
3164 | biomass_start(ipts,ivm,iele) = biomass_start(ipts,ivm,iele) + & |
---|
3165 | SUM(circ_class_biomass(ipts,ivm,icir,:,iele)) * & |
---|
3166 | circ_class_n(ipts,ivm,icir) * veget_max(ipts,ivm) * area(ipts) |
---|
3167 | END DO |
---|
3168 | END DO |
---|
3169 | END DO |
---|
3170 | END DO |
---|
3171 | END IF ! n_call.eq.1 |
---|
3172 | |
---|
3173 | IF (n_call.EQ.2) THEN |
---|
3174 | ! First calculate the total biomass at the end of the routine |
---|
3175 | DO ipts = 1,npts |
---|
3176 | DO ivm = 1,nvm |
---|
3177 | DO iele = 1, nelements |
---|
3178 | DO icir = 1,ncirc |
---|
3179 | ! Multiply with area to make the units easier to understand. |
---|
3180 | ! The unit of biomass_start is gC pixel-1 |
---|
3181 | biomass_end(ipts,ivm,iele) = biomass_end(ipts,ivm,iele) + & |
---|
3182 | SUM(circ_class_biomass(ipts,ivm,icir,:,iele)) * & |
---|
3183 | circ_class_n(ipts,ivm,icir) * veget_max(ipts,ivm) *area(ipts) |
---|
3184 | END DO |
---|
3185 | END DO |
---|
3186 | |
---|
3187 | ! Check for mass conservation |
---|
3188 | check(:) = zero |
---|
3189 | IF (loss_gain(ipts,ivm).GE.zero) THEN |
---|
3190 | |
---|
3191 | ! Gain in surface area. Biomass_end includes the newly established |
---|
3192 | ! vegetation. The C and N in this vegetation was taken from the air |
---|
3193 | ! and stored in atm_to_bm. Subtracting atm_to_bm from biomass_end should |
---|
3194 | ! give biomass_start. biopmass_start and biomass_end are in |
---|
3195 | ! gG or gN pixel-1. Atm_to_bm is in gC m-2 dt-1. |
---|
3196 | check(:) = (biomass_start(ipts,ivm,:) - biomass_end(ipts,ivm,:) + & |
---|
3197 | (atm_to_bm(ipts,ivm,:) - atm_to_bm_old(ipts,ivm,:)) * & |
---|
3198 | veget_max(ipts,ivm) * area(ipts) * dt_days)/area(ipts) |
---|
3199 | |
---|
3200 | ELSE |
---|
3201 | |
---|
3202 | ! Loss in surface area. When surface area is lost, the biomass was |
---|
3203 | ! moved into the harvest_pool and fresh_litter. If all these pools are |
---|
3204 | ! accounted for in biomass_end, it should be possible to reconstruct |
---|
3205 | ! biomass_start. biomass_end, biomass_start ar in gC or gN pixel-1. |
---|
3206 | ! fresh_litter is in gC or gN m-2. harvest_pool is in gC or gN pixel-1. |
---|
3207 | ! Note that in case of a species change there will already be some |
---|
3208 | ! biomass in the harvest_pool. In case of a classic land cover change |
---|
3209 | ! this is extremely unlikley for the moment (but this could be the |
---|
3210 | ! case if salavage logging following wind, fires or pests happens in |
---|
3211 | ! the same time step). Fresh_litter contains part of biomass that was |
---|
3212 | ! removed as well as bm_to_litter. To check for mass balance conservation |
---|
3213 | ! of the biomass we need to account for the biomass that went into the |
---|
3214 | ! fresh_litter but not for the bm_to_litter. The latter comes from a |
---|
3215 | ! previous mortality event. |
---|
3216 | check(:) = (biomass_start(ipts,ivm,:) - biomass_end(ipts,ivm,:) - & |
---|
3217 | SUM(fresh_litter(ipts,ivm,:,:)-bm_to_litter_old(ipts,ivm,:,:),1) * & |
---|
3218 | ABS(loss_gain(ipts,ivm)) * area(ipts) - & |
---|
3219 | SUM(harvest_pool(ipts,ivm,:,:) - harvest_pool_old(ipts,ivm,:,:),1)) / & |
---|
3220 | area(ipts) |
---|
3221 | |
---|
3222 | END IF |
---|
3223 | |
---|
3224 | ! Check for errors |
---|
3225 | DO iele = 1,nelements |
---|
3226 | IF (ABS(check(iele)).GT.min_stomate) THEN |
---|
3227 | WRITE(numout,*) 'ipts, ivm, iele, ', ipts, ivm, iele |
---|
3228 | WRITE(numout,*) 'loss_gain, check, ', loss_gain(ipts,ivm), check(iele) |
---|
3229 | WRITE(numout,*) 'biomass_start, ', biomass_start(ipts,ivm,iele) |
---|
3230 | WRITE(numout,*) 'biomass_end, ', biomass_end(ipts,ivm,iele) |
---|
3231 | WRITE(numout,*) 'diff, ', biomass_end(ipts,ivm,iele)-biomass_start(ipts,ivm,iele) |
---|
3232 | WRITE(numout,*) 'harvest_pool, ', SUM(harvest_pool(ipts,ivm,:,iele)) |
---|
3233 | WRITE(numout,*) 'fresh_litter from biomass, ', & |
---|
3234 | SUM(fresh_litter(ipts,ivm,:,iele)-bm_to_litter_old(ipts,ivm,:,iele),1) * & |
---|
3235 | ABS(loss_gain(ipts,ivm)) * area(ipts) |
---|
3236 | WRITE(numout,*) 'atm_to_bm, ', (atm_to_bm(ipts,ivm,iele) - atm_to_bm_old(ipts,ivm,iele)) * & |
---|
3237 | veget_max(ipts,ivm) * area(ipts) * dt_days |
---|
3238 | CALL ipslerr_p(3,'sapiens_lcchange','Mass balance error for circ_class_biomass,',& |
---|
3239 | 'harvest_pool, fresh_litter and/or atm_to_bm','') |
---|
3240 | ENDIF |
---|
3241 | END DO |
---|
3242 | |
---|
3243 | END DO |
---|
3244 | |
---|
3245 | END DO |
---|
3246 | |
---|
3247 | ENDIF ! n_call.eq.2 |
---|
3248 | |
---|
3249 | END SUBROUTINE check_biomass_change |
---|
3250 | |
---|
3251 | |
---|
3252 | !! ================================================================================================================================ |
---|
3253 | !! FUNCTION : sort_circ_class_biomass |
---|
3254 | !! |
---|
3255 | !>\BRIEF |
---|
3256 | !! |
---|
3257 | !! DESCRIPTION : sort the diameters in circ_class_biomass from low to high and |
---|
3258 | !! change the order in circ_class_n accordingly |
---|
3259 | !! |
---|
3260 | !! RECENT CHANGE(S): None |
---|
3261 | !! |
---|
3262 | !! RETURN VALUE : ::circ_class_biomass (gC tree-1),circ_class_n (tree m-2) |
---|
3263 | !! |
---|
3264 | !! REFERENCE(S) : |
---|
3265 | !! |
---|
3266 | !! FLOWCHART : None |
---|
3267 | !! \n |
---|
3268 | !_ ================================================================================================================================ |
---|
3269 | |
---|
3270 | SUBROUTINE sort_circ_class_biomass(circ_class_biomass_new,circ_class_n_new) |
---|
3271 | |
---|
3272 | !! 0. Variable and parameter declaration |
---|
3273 | |
---|
3274 | !! 0.1 Input variables |
---|
3275 | |
---|
3276 | !! 0.2 Output variables |
---|
3277 | |
---|
3278 | !! 0.3 Modified variables |
---|
3279 | REAL(r_std), DIMENSION(:), INTENT(inout) :: circ_class_n_new |
---|
3280 | REAL(r_std), DIMENSION(:,:,:), INTENT(inout) :: circ_class_biomass_new |
---|
3281 | |
---|
3282 | !! 0.4 Local variables |
---|
3283 | INTEGER(i_std) :: inc,icir,jcir !! Indices |
---|
3284 | REAL(r_std), DIMENSION(nparts,nelements) :: v1 !! temporay variable for sorting circ_class_biomass |
---|
3285 | REAL(r_std) :: v2 !! temporay variables for sorting circ_class_n |
---|
3286 | REAL(r_std) :: sort !! flag triggering sorting routine (0 or 1) |
---|
3287 | REAL(r_std), DIMENSION(ncirc) :: tree_size !! temporay variables for checking the biomass |
---|
3288 | !! for each circ class @tex ($gC tree^{-1}$) @endtex |
---|
3289 | |
---|
3290 | !_ ================================================================================================================================ |
---|
3291 | |
---|
3292 | ! Calculate the total biomass in each circumference class |
---|
3293 | tree_size(:)=zero |
---|
3294 | DO icir=1,ncirc |
---|
3295 | |
---|
3296 | ! Only check the order of the carbon pools |
---|
3297 | tree_size(icir)=SUM(circ_class_biomass_new(icir,:,icarbon)) |
---|
3298 | |
---|
3299 | ENDDO |
---|
3300 | |
---|
3301 | ! Check whether the order was preserved |
---|
3302 | sort = zero |
---|
3303 | DO icir=2,ncirc |
---|
3304 | |
---|
3305 | IF(tree_size(icir) .LT. tree_size(icir-1))THEN |
---|
3306 | |
---|
3307 | ! The order is not preserved |
---|
3308 | sort = un |
---|
3309 | EXIT |
---|
3310 | |
---|
3311 | ENDIF |
---|
3312 | |
---|
3313 | ENDDO |
---|
3314 | |
---|
3315 | ! Sort the biomasses. Note that at the same time we also |
---|
3316 | ! have to sort circ_class_n. We made use of the Shell sort |
---|
3317 | ! method |
---|
3318 | IF (sort==1) THEN |
---|
3319 | |
---|
3320 | ! Based on nummerical recipies in Fortran |
---|
3321 | inc = 1 |
---|
3322 | |
---|
3323 | DO |
---|
3324 | inc=3*inc+1 |
---|
3325 | IF (inc .GT. ncirc) EXIT |
---|
3326 | |
---|
3327 | ENDDO |
---|
3328 | |
---|
3329 | DO |
---|
3330 | inc = inc/3 |
---|
3331 | |
---|
3332 | DO icir=inc+1,ncirc |
---|
3333 | |
---|
3334 | v1(:,:) = circ_class_biomass_new(icir,:,:) |
---|
3335 | v2 = circ_class_n_new(icir) |
---|
3336 | jcir=icir |
---|
3337 | |
---|
3338 | DO |
---|
3339 | |
---|
3340 | ! Use the carbon pool to sort the circumference classes |
---|
3341 | ! but when moving circ classes around, also move the |
---|
3342 | ! other elements, i.e. nitrogen. |
---|
3343 | IF (SUM(circ_class_biomass_new(jcir-inc,:,icarbon)) .LE. & |
---|
3344 | SUM(v1(:,icarbon))) EXIT |
---|
3345 | circ_class_biomass_new(jcir,:,:) = & |
---|
3346 | circ_class_biomass_new(jcir-inc,:,:) |
---|
3347 | circ_class_n_new(jcir) = circ_class_n_new(jcir-inc) |
---|
3348 | jcir = jcir-inc |
---|
3349 | IF (jcir .LE. inc) EXIT |
---|
3350 | |
---|
3351 | ENDDO |
---|
3352 | |
---|
3353 | circ_class_biomass_new(jcir,:,:)=v1(:,:) |
---|
3354 | circ_class_n_new(jcir)=v2 |
---|
3355 | |
---|
3356 | ENDDO |
---|
3357 | |
---|
3358 | IF (inc .LE. 1) EXIT |
---|
3359 | |
---|
3360 | ENDDO |
---|
3361 | |
---|
3362 | !!$ ! Debug |
---|
3363 | !!$ WRITE(numout,*) 'sort end - carbon', & |
---|
3364 | !!$ SUM(circ_class_biomass_new(:,:,icarbon),2),& |
---|
3365 | !!$ circ_class_n_new(:) |
---|
3366 | !!$ WRITE(numout,*) 'sort end - nitrogen', & |
---|
3367 | !!$ SUM(circ_class_biomass_new(:,:,initrogen),2) |
---|
3368 | !!$ !- |
---|
3369 | |
---|
3370 | ENDIF |
---|
3371 | |
---|
3372 | END SUBROUTINE sort_circ_class_biomass |
---|
3373 | |
---|
3374 | !! ================================================================================================================================ |
---|
3375 | !! SUBROUTINE : Arrhenius_1d |
---|
3376 | !! |
---|
3377 | !>\BRIEF Calculate temperature dependency based on Arrhenius |
---|
3378 | !! |
---|
3379 | !! DESCRIPTION : |
---|
3380 | !! |
---|
3381 | !! RECENT CHANGE(S): None |
---|
3382 | !! |
---|
3383 | !! MAIN OUTPUT VARIABLE(S): :: val_arrhenius |
---|
3384 | !! |
---|
3385 | !! REFERENCE(S) : |
---|
3386 | !! |
---|
3387 | !! FLOWCHART : None |
---|
3388 | !_ ================================================================================================================================ |
---|
3389 | |
---|
3390 | FUNCTION Arrhenius_1d (kjpindex,temp,ref_temp,energy_act) RESULT ( val_arrhenius ) |
---|
3391 | !! 0.1 Input variables |
---|
3392 | |
---|
3393 | INTEGER(i_std),INTENT(in) :: kjpindex !! Domain size (-) |
---|
3394 | REAL(r_std),DIMENSION(kjpindex),INTENT(in) :: temp !! Temperature (K) |
---|
3395 | REAL(r_std), INTENT(in) :: ref_temp !! Temperature of reference (K) |
---|
3396 | REAL(r_std),INTENT(in) :: energy_act !! Activation Energy (J mol-1) |
---|
3397 | |
---|
3398 | !! 0.2 Result |
---|
3399 | |
---|
3400 | REAL(r_std), DIMENSION(kjpindex) :: val_arrhenius !! Temperature dependance based on |
---|
3401 | !! a Arrhenius function (-) |
---|
3402 | !_ ================================================================================================================================ |
---|
3403 | |
---|
3404 | val_arrhenius(:)=EXP(((temp(:)-ref_temp)*energy_act)/(ref_temp*RR*(temp(:)))) |
---|
3405 | END FUNCTION Arrhenius_1d |
---|
3406 | |
---|
3407 | !! |
---|
3408 | !================================================================================================================================ |
---|
3409 | !! SUBROUTINE : Arrhenius_0d |
---|
3410 | !! |
---|
3411 | !>\BRIEF Calculate temperature dependency based on Arrhenius for a |
---|
3412 | !! single pixel |
---|
3413 | !! |
---|
3414 | !! DESCRIPTION : |
---|
3415 | !! |
---|
3416 | !! RECENT CHANGE(S): None |
---|
3417 | !! |
---|
3418 | !! MAIN OUTPUT VARIABLE(S): :: val_arrhenius |
---|
3419 | !! |
---|
3420 | !! REFERENCE(S) : |
---|
3421 | !! |
---|
3422 | !! FLOWCHART : None |
---|
3423 | !_ |
---|
3424 | !================================================================================================================================ |
---|
3425 | |
---|
3426 | FUNCTION Arrhenius_0d (temp,ref_temp,energy_act) RESULT ( val_arrhenius ) |
---|
3427 | !! 0.1 Input variables |
---|
3428 | |
---|
3429 | REAL(r_std),INTENT(in) :: temp !! Temperature (K) |
---|
3430 | REAL(r_std), INTENT(in) :: ref_temp !! Temperature of reference (K) |
---|
3431 | REAL(r_std),INTENT(in) :: energy_act !! Activation Energy (J mol-1) |
---|
3432 | |
---|
3433 | !! 0.2 Result |
---|
3434 | |
---|
3435 | REAL(r_std) :: val_arrhenius !! Temperature dependance based on |
---|
3436 | !! a Arrhenius function (-) |
---|
3437 | !_ |
---|
3438 | !================================================================================================================================ |
---|
3439 | |
---|
3440 | val_arrhenius=EXP(((temp-ref_temp)*energy_act)/(ref_temp*RR*(temp))) |
---|
3441 | END FUNCTION Arrhenius_0d |
---|
3442 | |
---|
3443 | |
---|
3444 | !! ================================================================================================================================ |
---|
3445 | !! SUBROUTINE : Arrhenius_modified_1d |
---|
3446 | !! |
---|
3447 | !>\BRIEF Calculate temperature dependency based on Arrhenius |
---|
3448 | !! |
---|
3449 | !! DESCRIPTION : |
---|
3450 | !! |
---|
3451 | !! RECENT CHANGE(S): None |
---|
3452 | !! |
---|
3453 | !! MAIN OUTPUT VARIABLE(S): :: val_arrhenius |
---|
3454 | !! |
---|
3455 | !! REFERENCE(S) : |
---|
3456 | !! |
---|
3457 | !! FLOWCHART : None |
---|
3458 | !_ ================================================================================================================================ |
---|
3459 | |
---|
3460 | FUNCTION Arrhenius_modified_1d (kjpindex,temp,ref_temp,energy_act,energy_deact,entropy) RESULT ( val_arrhenius ) |
---|
3461 | !! 0.1 Input variables |
---|
3462 | |
---|
3463 | INTEGER(i_std),INTENT(in) :: kjpindex !! Domain size (-) |
---|
3464 | REAL(r_std),DIMENSION(kjpindex),INTENT(in) :: temp !! Temperature (K) |
---|
3465 | REAL(r_std), INTENT(in) :: ref_temp !! Temperature of reference (K) |
---|
3466 | REAL(r_std),INTENT(in) :: energy_act !! Activation Energy (J mol-1) |
---|
3467 | REAL(r_std),INTENT(in) :: energy_deact !! Deactivation Energy (J mol-1) |
---|
3468 | REAL(r_std),DIMENSION(kjpindex),INTENT(in) :: entropy !! Entropy term (J K-1 mol-1) |
---|
3469 | |
---|
3470 | !! 0.2 Result |
---|
3471 | |
---|
3472 | REAL(r_std), DIMENSION(kjpindex) :: val_arrhenius !! Temperature dependance based on |
---|
3473 | !! a Arrhenius function (-) |
---|
3474 | !_ ================================================================================================================================ |
---|
3475 | |
---|
3476 | val_arrhenius(:)=EXP(((temp(:)-ref_temp)*energy_act)/(ref_temp*RR*(temp(:)))) & |
---|
3477 | * (1. + EXP( (ref_temp * entropy(:) - energy_deact) / (ref_temp * RR ))) & |
---|
3478 | / (1. + EXP( (temp(:) * entropy(:) - energy_deact) / ( RR*temp(:)))) |
---|
3479 | |
---|
3480 | END FUNCTION Arrhenius_modified_1d |
---|
3481 | |
---|
3482 | !! ================================================================================================================================ |
---|
3483 | !! SUBROUTINE : Arrhenius_modified_0d |
---|
3484 | !! |
---|
3485 | !>\BRIEF Calculate temperature dependency based on Arrhenius |
---|
3486 | !! |
---|
3487 | !! DESCRIPTION : |
---|
3488 | !! |
---|
3489 | !! RECENT CHANGE(S): None |
---|
3490 | !! |
---|
3491 | !! MAIN OUTPUT VARIABLE(S): :: val_arrhenius |
---|
3492 | !! |
---|
3493 | !! REFERENCE(S) : |
---|
3494 | !! |
---|
3495 | !! FLOWCHART : None |
---|
3496 | !_ ================================================================================================================================ |
---|
3497 | |
---|
3498 | FUNCTION Arrhenius_modified_0d (kjpindex,temp,ref_temp,energy_act,energy_deact,entropy) RESULT ( val_arrhenius ) |
---|
3499 | !! 0.1 Input variables |
---|
3500 | |
---|
3501 | INTEGER(i_std),INTENT(in) :: kjpindex !! Domain size (-) |
---|
3502 | REAL(r_std),DIMENSION(kjpindex),INTENT(in) :: temp !! Temperature (K) |
---|
3503 | REAL(r_std), INTENT(in) :: ref_temp !! Temperature of reference (K) |
---|
3504 | REAL(r_std),INTENT(in) :: energy_act !! Activation Energy (J mol-1) |
---|
3505 | REAL(r_std),INTENT(in) :: energy_deact !! Deactivation Energy (J mol-1) |
---|
3506 | REAL(r_std),INTENT(in) :: entropy !! Entropy term (J K-1 mol-1) |
---|
3507 | |
---|
3508 | !! 0.2 Result |
---|
3509 | |
---|
3510 | REAL(r_std), DIMENSION(kjpindex) :: val_arrhenius !! Temperature dependance based on |
---|
3511 | !! a Arrhenius function (-) |
---|
3512 | !_ ================================================================================================================================ |
---|
3513 | |
---|
3514 | val_arrhenius(:)=EXP(((temp(:)-ref_temp)*energy_act)/(ref_temp*RR*(temp(:)))) & |
---|
3515 | * (1. + EXP( (ref_temp * entropy - energy_deact) / (ref_temp * RR ))) & |
---|
3516 | / (1. + EXP( (temp(:) * entropy - energy_deact) / ( RR*temp(:)))) |
---|
3517 | |
---|
3518 | END FUNCTION Arrhenius_modified_0d |
---|
3519 | |
---|
3520 | !! |
---|
3521 | !================================================================================================================================ |
---|
3522 | !! SUBROUTINE : Arrhenius_modified_nodim |
---|
3523 | !! |
---|
3524 | !>\BRIEF Calculate temperature dependency based on Arrhenius. |
---|
3525 | !! This function is for a single pixel output. |
---|
3526 | !! |
---|
3527 | !! DESCRIPTION : |
---|
3528 | !! |
---|
3529 | !! RECENT CHANGE(S): None |
---|
3530 | !! |
---|
3531 | !! MAIN OUTPUT VARIABLE(S): :: val_arrhenius |
---|
3532 | !! |
---|
3533 | !! REFERENCE(S) : |
---|
3534 | !! |
---|
3535 | !! FLOWCHART : None |
---|
3536 | !_ |
---|
3537 | !================================================================================================================================ |
---|
3538 | |
---|
3539 | FUNCTION Arrhenius_modified_nodim (temp,ref_temp,energy_act,energy_deact,entropy) RESULT (val_arrhenius) |
---|
3540 | !! 0.1 Input variables |
---|
3541 | |
---|
3542 | REAL(r_std),INTENT(in) :: temp !! Temperature (K) |
---|
3543 | REAL(r_std),INTENT(in) :: ref_temp !! Temperature of reference (K) |
---|
3544 | REAL(r_std),INTENT(in) :: energy_act !! Activation Energy (J mol-1) |
---|
3545 | REAL(r_std),INTENT(in) :: energy_deact !! Deactivation Energy (J mol-1) |
---|
3546 | REAL(r_std),INTENT(in) :: entropy !! Entropy term (J K-1 mol-1) |
---|
3547 | |
---|
3548 | !! 0.2 Result |
---|
3549 | |
---|
3550 | REAL(r_std) :: val_arrhenius !! Temperature dependance based on |
---|
3551 | !! a Arrhenius function (-) |
---|
3552 | !_ |
---|
3553 | !================================================================================================================================ |
---|
3554 | |
---|
3555 | val_arrhenius=EXP(((temp-ref_temp)*energy_act)/(ref_temp*RR*(temp))) & |
---|
3556 | * (1. + EXP( (ref_temp * entropy - energy_deact) / (ref_temp * RR ))) & |
---|
3557 | / (1. + EXP( (temp * entropy - energy_deact) / ( RR*temp))) |
---|
3558 | |
---|
3559 | END FUNCTION Arrhenius_modified_nodim |
---|
3560 | |
---|
3561 | END MODULE function_library |
---|