source: palm/trunk/SOURCE/plant_canopy_model_mod.f90 @ 4460

Last change on this file since 4460 was 4457, checked in by raasch, 5 years ago

ghost point exchange modularized, bugfix for wrong 2d-exchange

  • Property svn:keywords set to Id
File size: 110.1 KB
Line 
1!> @file plant_canopy_model_mod.f90
2!------------------------------------------------------------------------------!
3! This file is part of the PALM model system.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 1997-2020 Leibniz Universitaet Hannover
18! Copyright 2017-2020 Institute of Computer Science of the
19!                     Czech Academy of Sciences, Prague
20!------------------------------------------------------------------------------!
21!
22! Current revisions:
23! ------------------
24!
25!
26! Former revisions:
27! -----------------
28!
29! use statement for exchange horiz added
30!
31!
32! $Id: plant_canopy_model_mod.f90 4457 2020-03-11 14:20:43Z oliver.maas $
33! (salim) removed the error message PA0672 to consider PC 3d data via ascii file
34!
35! 4392 2020-01-31 16:14:57Z pavelkrc (resler)
36! Make pcm_heatrate_av, pcm_latentrate_av public to allow calculation
37! of averaged Bowen ratio in the user procedure
38!
39! 4381 2020-01-20 13:51:46Z suehring
40! Give error message 313 only once
41!
42! 4363 2020-01-07 18:11:28Z suehring
43! Fix for last commit
44!
45! 4362 2020-01-07 17:15:02Z suehring
46! Input of plant canopy variables from static driver moved to plant-canopy
47! model
48!
49! 4361 2020-01-07 12:22:38Z suehring
50! - Remove unused arrays in pmc_rrd_local
51! - Remove one exchange of ghost points
52!
53! 4360 2020-01-07 11:25:50Z suehring
54! - Bugfix, read restart data for time-averaged pcm output quantities
55! - Output of plant-canopy quantities will fill values
56!
57! 4356 2019-12-20 17:09:33Z suehring
58! Correct single message call, local check must be given by the respective
59! mpi rank.
60!
61! 4346 2019-12-18 11:55:56Z motisi
62! Introduction of wall_flags_total_0, which currently sets bits based on static
63! topography information used in wall_flags_static_0
64!
65! 4342 2019-12-16 13:49:14Z Giersch
66! Use statements moved to module level, ocean dependency removed, redundant
67! variables removed
68!
69! 4341 2019-12-16 10:43:49Z motisi
70! - Unification of variable names: pc_-variables now pcm_-variables
71!   (pc_latent_rate, pc_heating_rate, pc_transpiration_rate)
72! - Removal of pcm_bowenratio output
73! - Renamed canopy-mode 'block' to 'homogeneous'
74! - Renamed value 'read_from_file_3d' to 'read_from_file'
75! - Removal of confusing comment lines
76! - Replacement of k_wall by topo_top_ind
77! - Removal of Else-Statement in tendency-calculation
78!
79! 4335 2019-12-12 16:39:05Z suehring
80! Fix for LAD at building edges also implemented in vector branch.
81!
82! 4331 2019-12-10 18:25:02Z suehring
83! Typo corrected
84!
85! 4329 2019-12-10 15:46:36Z motisi
86! Renamed wall_flags_0 to wall_flags_static_0
87!
88! 4314 2019-11-29 10:29:20Z suehring
89! - Bugfix, plant canopy was still considered at building edges on for the u-
90!   and v-component.
91! - Relax restriction of LAD on building tops. LAD is only omitted at
92!   locations where building grid points emerged artificially by the
93!   topography filtering.
94!
95! 4309 2019-11-26 18:49:59Z suehring
96! Typo
97!
98! 4302 2019-11-22 13:15:56Z suehring
99! Omit tall canopy mapped on top of buildings
100!
101! 4279 2019-10-29 08:48:17Z scharf
102! unused variables removed
103!
104! 4258 2019-10-07 13:29:08Z scharf
105! changed check for static driver and fixed bugs in initialization and header
106!
107! 4258 2019-10-07 13:29:08Z suehring
108! Check if any LAD is prescribed when plant-canopy model is applied.
109!
110! 4226 2019-09-10 17:03:24Z suehring
111! Bugfix, missing initialization of heating rate
112!
113! 4221 2019-09-09 08:50:35Z suehring
114! Further bugfix in 3d data output for plant canopy
115!
116! 4216 2019-09-04 09:09:03Z suehring
117! Bugfixes in 3d data output
118!
119! 4205 2019-08-30 13:25:00Z suehring
120! Missing working precision + bugfix in calculation of wind speed
121!
122! 4188 2019-08-26 14:15:47Z suehring
123! Minor adjustment in error number
124!
125! 4187 2019-08-26 12:43:15Z suehring
126! Give specific error numbers instead of PA0999
127!
128! 4182 2019-08-22 15:20:23Z scharf
129! Corrected "Former revisions" section
130!
131! 4168 2019-08-16 13:50:17Z suehring
132! Replace function get_topography_top_index by topo_top_ind
133!
134! 4127 2019-07-30 14:47:10Z suehring
135! Output of 3D plant canopy variables changed. It is now relative to the local
136! terrain rather than located at the acutal vertical level in the model. This
137! way, the vertical dimension of the output can be significantly reduced.
138! (merge from branch resler)
139!
140! 3885 2019-04-11 11:29:34Z kanani
141! Changes related to global restructuring of location messages and introduction
142! of additional debug messages
143!
144! 3864 2019-04-05 09:01:56Z monakurppa
145! unsed variables removed
146!
147! 3745 2019-02-15 18:57:56Z suehring
148! Bugfix in transpiration, floating invalid when temperature
149! becomes > 40 degrees
150!
151! 3744 2019-02-15 18:38:58Z suehring
152! Some interface calls moved to module_interface + cleanup
153!
154! 3655 2019-01-07 16:51:22Z knoop
155! unused variables removed
156!
157! 138 2007-11-28 10:03:58Z letzel
158! Initial revision
159!
160! Description:
161! ------------
162!> 1) Initialization of the canopy model, e.g. construction of leaf area density
163!> profile (subroutine pcm_init).
164!> 2) Calculation of sinks and sources of momentum, heat and scalar concentration
165!> due to canopy elements (subroutine pcm_tendency).
166!
167! @todo - precalculate constant terms in pcm_calc_transpiration_rate
168! @todo - unify variable names (pcm_, pc_, ...)
169!------------------------------------------------------------------------------!
170 MODULE plant_canopy_model_mod
171
172    USE arrays_3d,                                                             &
173        ONLY:  dzu, dzw, e, exner, hyp, pt, q, s, tend, u, v, w, zu, zw
174
175    USE basic_constants_and_equations_mod,                                     &
176        ONLY:  c_p, degc_to_k, l_v, lv_d_cp, r_d, rd_d_rv
177
178    USE bulk_cloud_model_mod,                                                  &
179        ONLY: bulk_cloud_model, microphysics_seifert
180
181    USE control_parameters,                                                    &
182        ONLY: average_count_3d,                                                &
183              coupling_char,                                                   &
184              debug_output,                                                    &
185              dt_3d,                                                           &
186              dz,                                                              &
187              humidity,                                                        &
188              length,                                                          &
189              message_string,                                                  &
190              ocean_mode,                                                      &
191              passive_scalar,                                                  &
192              plant_canopy,                                                    &
193              restart_string,                                                  &
194              urban_surface
195
196    USE grid_variables,                                                        &
197        ONLY:  dx, dy
198
199    USE indices,                                                               &
200        ONLY:  nbgp, nxl, nxlg, nxlu, nxr, nxrg, nyn, nyng, nys, nysg, nysv,   &
201               nz, nzb, nzt, topo_top_ind, wall_flags_total_0
202
203    USE kinds
204
205    USE netcdf_data_input_mod,                                                 &
206        ONLY:  input_pids_static,                                              &
207               char_fill,                                                      &
208               check_existence,                                                &
209               close_input_file,                                               &
210               get_attribute,                                                  &
211               get_dimension_length,                                           &
212               get_variable,                                                   &
213               inquire_num_variables,                                          &
214               inquire_variable_names,                                         &
215               input_file_static,                                              &
216               num_var_pids,                                                   &
217               open_read_file,                                                 &
218               pids_id,                                                        &
219               real_3d,                                                        &
220               vars_pids
221
222    USE pegrid
223
224    USE surface_mod,                                                           &
225        ONLY: surf_def_h, surf_lsm_h, surf_usm_h
226
227
228    IMPLICIT NONE
229
230    CHARACTER (LEN=30)   ::  canopy_mode = 'homogeneous'           !< canopy coverage
231    LOGICAL              ::  plant_canopy_transpiration = .FALSE.  !< flag to switch calculation of transpiration and corresponding latent heat
232                                                                   !< for resolved plant canopy inside radiation model
233                                                                   !< (calls subroutine pcm_calc_transpiration_rate from module plant_canopy_mod)
234
235    INTEGER(iwp) ::  pch_index = 0                                 !< plant canopy height/top index
236    INTEGER(iwp) ::  lad_vertical_gradient_level_ind(10) = -9999   !< lad-profile levels (index)
237
238    INTEGER(iwp), DIMENSION(:,:), ALLOCATABLE ::  pch_index_ji     !< local plant canopy top
239
240    LOGICAL ::  calc_beta_lad_profile = .FALSE.   !< switch for calc. of lad from beta func.
241
242    REAL(wp) ::  alpha_lad = 9999999.9_wp         !< coefficient for lad calculation
243    REAL(wp) ::  beta_lad = 9999999.9_wp          !< coefficient for lad calculation
244    REAL(wp) ::  canopy_drag_coeff = 0.0_wp       !< canopy drag coefficient (parameter)
245    REAL(wp) ::  cthf = 0.0_wp                    !< canopy top heat flux
246    REAL(wp) ::  dt_plant_canopy = 0.0_wp         !< timestep account. for canopy drag
247    REAL(wp) ::  ext_coef = 0.6_wp                !< extinction coefficient
248    REAL(wp) ::  lad_surface = 0.0_wp             !< lad surface value
249    REAL(wp) ::  lai_beta = 0.0_wp                !< leaf area index (lai) for lad calc.
250    REAL(wp) ::  leaf_scalar_exch_coeff = 0.0_wp  !< canopy scalar exchange coeff.
251    REAL(wp) ::  leaf_surface_conc = 0.0_wp       !< leaf surface concentration
252
253    REAL(wp) ::  lad_vertical_gradient(10) = 0.0_wp              !< lad gradient
254    REAL(wp) ::  lad_vertical_gradient_level(10) = -9999999.9_wp !< lad-prof. levels (in m)
255
256    REAL(wp) ::  lad_type_coef(0:10) = 1.0_wp   !< multiplicative coeficients for particular types
257                                                !< of plant canopy (e.g. deciduous tree during winter)
258
259    REAL(wp), DIMENSION(:), ALLOCATABLE ::  lad            !< leaf area density
260    REAL(wp), DIMENSION(:), ALLOCATABLE ::  pre_lad        !< preliminary lad
261   
262    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  cum_lai_hf               !< cumulative lai for heatflux calc.
263    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  lad_s                    !< lad on scalar-grid
264    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  pcm_heating_rate         !< plant canopy heating rate
265    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  pcm_transpiration_rate   !< plant canopy transpiration rate
266    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  pcm_latent_rate          !< plant canopy latent heating rate
267
268    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  pcm_heatrate_av          !< array for averaging plant canopy sensible heating rate
269    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  pcm_latentrate_av        !< array for averaging plant canopy latent heating rate
270    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  pcm_transpirationrate_av !< array for averaging plant canopy transpiration rate
271
272    TYPE(real_3d) ::  basal_area_density_f    !< input variable for basal area density - resolved vegetation
273    TYPE(real_3d) ::  leaf_area_density_f     !< input variable for leaf area density - resolved vegetation
274    TYPE(real_3d) ::  root_area_density_lad_f !< input variable for root area density - resolved vegetation
275
276    SAVE
277
278    PRIVATE
279   
280!
281!-- Public functions
282    PUBLIC pcm_calc_transpiration_rate,                                       &
283           pcm_check_data_output,                                             &
284           pcm_check_parameters,                                              &
285           pcm_3d_data_averaging,                                             &
286           pcm_data_output_3d,                                                &
287           pcm_define_netcdf_grid,                                            &
288           pcm_header,                                                        &
289           pcm_init,                                                          &
290           pcm_parin,                                                         &
291           pcm_rrd_local,                                                     &
292           pcm_tendency,                                                      &
293           pcm_wrd_local
294
295!
296!-- Public variables and constants
297    PUBLIC canopy_drag_coeff, pcm_heating_rate, pcm_transpiration_rate,       &
298           pcm_latent_rate, canopy_mode, cthf, dt_plant_canopy, lad, lad_s,   &
299           pch_index, plant_canopy_transpiration,                             &
300           pcm_heatrate_av, pcm_latentrate_av
301
302    INTERFACE pcm_calc_transpiration_rate
303       MODULE PROCEDURE pcm_calc_transpiration_rate
304    END INTERFACE pcm_calc_transpiration_rate
305
306    INTERFACE pcm_check_data_output
307       MODULE PROCEDURE pcm_check_data_output
308    END INTERFACE pcm_check_data_output
309   
310    INTERFACE pcm_check_parameters
311       MODULE PROCEDURE pcm_check_parameters
312    END INTERFACE pcm_check_parameters
313
314    INTERFACE pcm_3d_data_averaging
315       MODULE PROCEDURE pcm_3d_data_averaging
316    END INTERFACE pcm_3d_data_averaging
317
318    INTERFACE pcm_data_output_3d
319       MODULE PROCEDURE pcm_data_output_3d
320    END INTERFACE pcm_data_output_3d
321
322    INTERFACE pcm_define_netcdf_grid
323       MODULE PROCEDURE pcm_define_netcdf_grid
324    END INTERFACE pcm_define_netcdf_grid
325   
326     INTERFACE pcm_header
327       MODULE PROCEDURE pcm_header
328    END INTERFACE pcm_header       
329   
330    INTERFACE pcm_init
331       MODULE PROCEDURE pcm_init
332    END INTERFACE pcm_init
333
334    INTERFACE pcm_parin
335       MODULE PROCEDURE pcm_parin
336    END INTERFACE pcm_parin
337
338    INTERFACE pcm_read_plant_canopy_3d
339       MODULE PROCEDURE pcm_read_plant_canopy_3d
340    END INTERFACE pcm_read_plant_canopy_3d
341
342    INTERFACE pcm_rrd_local
343       MODULE PROCEDURE pcm_rrd_local
344    END INTERFACE pcm_rrd_local
345
346    INTERFACE pcm_tendency
347       MODULE PROCEDURE pcm_tendency
348       MODULE PROCEDURE pcm_tendency_ij
349    END INTERFACE pcm_tendency
350
351    INTERFACE pcm_wrd_local
352       MODULE PROCEDURE pcm_wrd_local
353    END INTERFACE pcm_wrd_local
354
355
356 CONTAINS
357 
358 
359!------------------------------------------------------------------------------!
360! Description:
361! ------------
362!> Calculation of the plant canopy transpiration rate based on the Jarvis-Stewart
363!> with parametrizations described in Daudet et al. (1999; Agricult. and Forest
364!> Meteorol. 97) and Ngao, Adam and Saudreau (2017;  Agricult. and Forest Meteorol
365!> 237-238). Model functions f1-f4 were adapted from Stewart (1998; Agric.
366!> and Forest. Meteorol. 43) instead, because they are valid for broader intervals
367!> of values. Funcion f4 used in form present in van Wijk et al. (1998;
368!> Tree Physiology 20).
369!>
370!> This subroutine is called from subroutine radiation_interaction
371!> after the calculation of radiation in plant canopy boxes.
372!> (arrays pcbinsw and pcbinlw).
373!>
374!------------------------------------------------------------------------------!
375 SUBROUTINE pcm_calc_transpiration_rate(i, j, k, kk, pcbsw, pcblw, pcbtr, pcblh)
376
377!
378!--  input parameters
379     INTEGER(iwp), INTENT(IN) ::  i, j, k, kk        !< indices of the pc gridbox
380     REAL(wp), INTENT(IN)     ::  pcbsw              !< sw radiation in gridbox (W)
381     REAL(wp), INTENT(IN)     ::  pcblw              !< lw radiation in gridbox (W)
382     REAL(wp), INTENT(OUT)    ::  pcbtr              !< transpiration rate dq/dt (kg/kg/s)
383     REAL(wp), INTENT(OUT)    ::  pcblh              !< latent heat from transpiration dT/dt (K/s)
384
385!--  variables and parameters for calculation of transpiration rate
386     REAL(wp)             ::  sat_press, sat_press_d, temp, v_lad
387     REAL(wp)             ::  d_fact, g_b, g_s, wind_speed, evapor_rate
388     REAL(wp)             ::  f1, f2, f3, f4, vpd, rswc, e_eq, e_imp, rad
389     REAL(wp), PARAMETER  ::  gama_psychr = 66.0_wp !< psychrometric constant (Pa/K)
390     REAL(wp), PARAMETER  ::  g_s_max = 0.01        !< maximum stomatal conductivity (m/s)
391     REAL(wp), PARAMETER  ::  m_soil = 0.4_wp       !< soil water content (needs to adjust or take from LSM)
392     REAL(wp), PARAMETER  ::  m_wilt = 0.01_wp      !< wilting point soil water content (needs to adjust or take from LSM)
393     REAL(wp), PARAMETER  ::  m_sat = 0.51_wp       !< saturation soil water content (needs to adjust or take from LSM)
394     REAL(wp), PARAMETER  ::  t2_min = 0.0_wp       !< minimal temperature for calculation of f2
395     REAL(wp), PARAMETER  ::  t2_max = 40.0_wp      !< maximal temperature for calculation of f2
396
397
398!--  Temperature (deg C)
399     temp = pt(k,j,i) * exner(k) - degc_to_k
400!--  Coefficient for conversion of radiation to grid to radiation to unit leaves surface
401     v_lad = 1.0_wp / ( MAX( lad_s(kk,j,i), 1.0E-10_wp ) * dx * dy * dz(1) )
402!--  Magnus formula for the saturation pressure (see Ngao, Adam and Saudreau (2017) eq. 1)
403!--  There are updated formulas available, kept consistent with the rest of the parametrization
404     sat_press = 610.8_wp * exp(17.27_wp * temp/(temp + 237.3_wp))
405!--  Saturation pressure derivative (derivative of the above)
406     sat_press_d = sat_press * 17.27_wp * 237.3_wp / (temp + 237.3_wp)**2
407!--  Wind speed
408     wind_speed = SQRT( ( 0.5_wp * ( u(k,j,i) + u(k,j,i+1) ) )**2 +            &
409                        ( 0.5_wp * ( v(k,j,i) + v(k,j+1,i) ) )**2 +            &
410                        ( 0.5_wp * ( w(k,j,i) + w(k-1,j,i) ) )**2 )
411!--  Aerodynamic conductivity (Daudet et al. (1999) eq. 14
412     g_b = 0.01_wp * wind_speed + 0.0071_wp
413!--  Radiation flux per leaf surface unit
414     rad = pcbsw * v_lad
415!--  First function for calculation of stomatal conductivity (radiation dependency)
416!--  Stewart (1988; Agric. and Forest. Meteorol. 43) eq. 17
417     f1 = rad * (1000.0_wp+42.1_wp) / 1000.0_wp / (rad+42.1_wp)
418!--  Second function for calculation of stomatal conductivity (temperature dependency)
419!--  Stewart (1988; Agric. and Forest. Meteorol. 43) eq. 21
420     f2 = MAX(t2_min, (temp-t2_min) * MAX(0.0_wp,t2_max-temp)**((t2_max-16.9_wp)/(16.9_wp-t2_min)) / &
421              ((16.9_wp-t2_min) * (t2_max-16.9_wp)**((t2_max-16.9_wp)/(16.9_wp-t2_min))) )
422!--  Water pressure deficit
423!--  Ngao, Adam and Saudreau (2017) eq. 6 but with water vapour partial pressure
424     vpd = max( sat_press - q(k,j,i) * hyp(k) / rd_d_rv, 0._wp )
425!--  Third function for calculation of stomatal conductivity (water pressure deficit dependency)
426!--  Ngao, Adam and Saudreau (2017) Table 1, limited from below according to Stewart (1988)
427!--  The coefficients of the linear dependence should better correspond to broad-leaved trees
428!--  than the coefficients from Stewart (1988) which correspond to conifer trees.
429     vpd = MIN(MAX(vpd,770.0_wp),3820.0_wp)
430     f3 = -2E-4_wp * vpd + 1.154_wp
431!--  Fourth function for calculation of stomatal conductivity (soil moisture dependency)
432!--  Residual soil water content
433!--  van Wijk et al. (1998; Tree Physiology 20) eq. 7
434!--  TODO - over LSM surface might be calculated from LSM parameters
435     rswc = ( m_sat - m_soil ) / ( m_sat - m_wilt )
436!--  van Wijk et al. (1998; Tree Physiology 20) eq. 5-6 (it is a reformulation of eq. 22-23 of Stewart(1988))
437     f4 = MAX(0.0_wp, MIN(1.0_wp - 0.041_wp * EXP(3.2_wp * rswc), 1.0_wp - 0.041_wp))
438!--  Stomatal conductivity
439!--  Stewart (1988; Agric. and Forest. Meteorol. 43) eq. 12
440!--  (notation according to Ngao, Adam and Saudreau (2017) and others)
441     g_s = g_s_max * f1 * f2 * f3 * f4 + 1.0E-10_wp
442!--  Decoupling factor
443!--  Daudet et al. (1999) eq. 6
444     d_fact = (sat_press_d / gama_psychr + 2.0_wp ) /                        &
445              (sat_press_d / gama_psychr + 2.0_wp + 2.0_wp * g_b / g_s )
446!--  Equilibrium evaporation rate
447!--  Daudet et al. (1999) eq. 4
448     e_eq = (pcbsw + pcblw) * v_lad * sat_press_d /                         &
449                 gama_psychr /( sat_press_d / gama_psychr + 2.0_wp ) / l_v
450!--  Imposed evaporation rate
451!--  Daudet et al. (1999) eq. 5
452     e_imp = r_d * pt(k,j,i) * exner(k) / hyp(k) * c_p * g_s * vpd / gama_psychr / l_v
453!--  Evaporation rate
454!--  Daudet et al. (1999) eq. 3
455!--  (evaporation rate is limited to non-negative values)
456     evapor_rate = MAX(d_fact * e_eq + ( 1.0_wp - d_fact ) * e_imp, 0.0_wp)
457!--  Conversion of evaporation rate to q tendency in gridbox
458!--  dq/dt = E * LAD * V_g / (rho_air * V_g)
459     pcbtr = evapor_rate * r_d * pt(k,j,i) * exner(k) * lad_s(kk,j,i) / hyp(k)  !-- = dq/dt
460!--  latent heat from evaporation
461     pcblh = pcbtr * lv_d_cp  !-- = - dT/dt
462
463 END SUBROUTINE pcm_calc_transpiration_rate
464
465
466!------------------------------------------------------------------------------!
467! Description:
468! ------------
469!> Check data output for plant canopy model
470!------------------------------------------------------------------------------!
471 SUBROUTINE pcm_check_data_output( var, unit )
472
473    CHARACTER (LEN=*) ::  unit  !<
474    CHARACTER (LEN=*) ::  var   !<
475
476
477    SELECT CASE ( TRIM( var ) )
478
479       CASE ( 'pcm_heatrate' )
480          IF ( cthf == 0.0_wp  .AND. .NOT.  urban_surface )  THEN
481             message_string = 'output of "' // TRIM( var ) // '" requi' //  &
482                              'res setting of parameter cthf /= 0.0'
483             CALL message( 'pcm_check_data_output', 'PA1000', 1, 2, 0, 6, 0 )
484          ENDIF
485          unit = 'K s-1'
486   
487       CASE ( 'pcm_transpirationrate' )
488          unit = 'kg kg-1 s-1'
489
490       CASE ( 'pcm_latentrate' )
491          unit = 'K s-1'
492
493       CASE ( 'pcm_lad' )
494          unit = 'm2 m-3'
495
496
497       CASE DEFAULT
498          unit = 'illegal'
499
500    END SELECT
501
502
503 END SUBROUTINE pcm_check_data_output
504 
505 
506!------------------------------------------------------------------------------!
507! Description:
508! ------------
509!> Check parameters routine for plant canopy model
510!------------------------------------------------------------------------------!
511    SUBROUTINE pcm_check_parameters
512           
513       IF ( ocean_mode )  THEN
514          message_string = 'plant_canopy = .TRUE. is not allowed in the '//    &
515                           'ocean'
516          CALL message( 'pcm_check_parameters', 'PA0696', 1, 2, 0, 6, 0 )
517       ENDIF
518           
519       IF ( canopy_drag_coeff == 0.0_wp )  THEN
520          message_string = 'plant_canopy = .TRUE. requires a non-zero drag '// &
521                           'coefficient & given value is canopy_drag_coeff = 0.0'
522          CALL message( 'pcm_check_parameters', 'PA0041', 1, 2, 0, 6, 0 )
523       ENDIF
524
525       IF ( ( alpha_lad /= 9999999.9_wp  .AND.  beta_lad == 9999999.9_wp ) .OR.&
526              beta_lad /= 9999999.9_wp   .AND.  alpha_lad == 9999999.9_wp )  THEN
527          message_string = 'using the beta function for the construction ' //  &
528                           'of the leaf area density profile requires '    //  &
529                           'both alpha_lad and beta_lad to be /= 9999999.9'
530          CALL message( 'pcm_check_parameters', 'PA0118', 1, 2, 0, 6, 0 )
531       ENDIF
532
533       IF ( calc_beta_lad_profile  .AND.  lai_beta == 0.0_wp )  THEN
534          message_string = 'using the beta function for the construction ' //  &
535                           'of the leaf area density profile requires '    //  &
536                           'a non-zero lai_beta, but given value is '      //  &
537                           'lai_beta = 0.0'
538          CALL message( 'pcm_check_parameters', 'PA0119', 1, 2, 0, 6, 0 )
539       ENDIF
540
541       IF ( calc_beta_lad_profile  .AND.  lad_surface /= 0.0_wp )  THEN
542          message_string = 'simultaneous setting of alpha_lad /= 9999999.9 '// &
543                           'combined with beta_lad /= 9999999.9 '           // &
544                           'and lad_surface /= 0.0 is not possible, '       // &
545                           'use either vertical gradients or the beta '     // &
546                           'function for the construction of the leaf area '// &
547                           'density profile'
548          CALL message( 'pcm_check_parameters', 'PA0120', 1, 2, 0, 6, 0 )
549       ENDIF
550
551       IF ( bulk_cloud_model  .AND.  microphysics_seifert )  THEN
552          message_string = 'plant_canopy = .TRUE. requires cloud_scheme /=' // &
553                          ' seifert_beheng'
554          CALL message( 'pcm_check_parameters', 'PA0360', 1, 2, 0, 6, 0 )
555       ENDIF
556
557    END SUBROUTINE pcm_check_parameters 
558 
559
560!------------------------------------------------------------------------------!
561!
562! Description:
563! ------------
564!> Subroutine for averaging 3D data
565!------------------------------------------------------------------------------!
566 SUBROUTINE pcm_3d_data_averaging( mode, variable )
567
568    CHARACTER (LEN=*) ::  mode    !<
569    CHARACTER (LEN=*) :: variable !<
570
571    INTEGER(iwp) ::  i            !<
572    INTEGER(iwp) ::  j            !<
573    INTEGER(iwp) ::  k            !<
574
575
576    IF ( mode == 'allocate' )  THEN
577
578       SELECT CASE ( TRIM( variable ) )
579
580          CASE ( 'pcm_heatrate' )
581             IF ( .NOT. ALLOCATED( pcm_heatrate_av ) )  THEN
582                ALLOCATE( pcm_heatrate_av(0:pch_index,nysg:nyng,nxlg:nxrg) )
583             ENDIF
584             pcm_heatrate_av = 0.0_wp
585
586
587          CASE ( 'pcm_latentrate' )
588             IF ( .NOT. ALLOCATED( pcm_latentrate_av ) )  THEN
589                ALLOCATE( pcm_latentrate_av(0:pch_index,nysg:nyng,nxlg:nxrg) )
590             ENDIF
591             pcm_latentrate_av = 0.0_wp
592
593
594          CASE ( 'pcm_transpirationrate' )
595             IF ( .NOT. ALLOCATED( pcm_transpirationrate_av ) )  THEN
596                ALLOCATE( pcm_transpirationrate_av(0:pch_index,nysg:nyng,nxlg:nxrg) )
597             ENDIF
598             pcm_transpirationrate_av = 0.0_wp
599
600          CASE DEFAULT
601             CONTINUE
602
603       END SELECT
604
605    ELSEIF ( mode == 'sum' )  THEN
606
607       SELECT CASE ( TRIM( variable ) )
608
609          CASE ( 'pcm_heatrate' )
610             IF ( ALLOCATED( pcm_heatrate_av ) ) THEN
611                DO  i = nxl, nxr
612                   DO  j = nys, nyn
613                      IF ( pch_index_ji(j,i) /= 0 )  THEN
614                         DO  k = 0, pch_index_ji(j,i)
615                            pcm_heatrate_av(k,j,i) = pcm_heatrate_av(k,j,i) + pcm_heating_rate(k,j,i)
616                         ENDDO
617                      ENDIF
618                   ENDDO
619                ENDDO
620             ENDIF
621
622
623          CASE ( 'pcm_latentrate' )
624             IF ( ALLOCATED( pcm_latentrate_av ) ) THEN
625                DO  i = nxl, nxr
626                   DO  j = nys, nyn
627                      IF ( pch_index_ji(j,i) /= 0 )  THEN
628                         DO  k = 0, pch_index_ji(j,i)
629                            pcm_latentrate_av(k,j,i) = pcm_latentrate_av(k,j,i) + pcm_latent_rate(k,j,i)
630                         ENDDO
631                      ENDIF
632                   ENDDO
633                ENDDO
634             ENDIF
635
636
637          CASE ( 'pcm_transpirationrate' )
638             IF ( ALLOCATED( pcm_transpirationrate_av ) ) THEN
639                DO  i = nxl, nxr
640                   DO  j = nys, nyn
641                      IF ( pch_index_ji(j,i) /= 0 )  THEN
642                         DO  k = 0, pch_index_ji(j,i)
643                            pcm_transpirationrate_av(k,j,i) = pcm_transpirationrate_av(k,j,i) + pcm_transpiration_rate(k,j,i)
644                         ENDDO
645                      ENDIF
646                   ENDDO
647                ENDDO
648             ENDIF
649
650          CASE DEFAULT
651             CONTINUE
652
653       END SELECT
654
655    ELSEIF ( mode == 'average' )  THEN
656
657       SELECT CASE ( TRIM( variable ) )
658
659          CASE ( 'pcm_heatrate' )
660             IF ( ALLOCATED( pcm_heatrate_av ) ) THEN
661                DO  i = nxlg, nxrg
662                   DO  j = nysg, nyng
663                      IF ( pch_index_ji(j,i) /= 0 )  THEN
664                         DO  k = 0, pch_index_ji(j,i)
665                            pcm_heatrate_av(k,j,i) = pcm_heatrate_av(k,j,i)                 &
666                                                     / REAL( average_count_3d, KIND=wp )
667                         ENDDO
668                      ENDIF
669                   ENDDO
670                ENDDO
671             ENDIF
672
673
674          CASE ( 'pcm_latentrate' )
675             IF ( ALLOCATED( pcm_latentrate_av ) ) THEN
676                DO  i = nxlg, nxrg
677                   DO  j = nysg, nyng
678                      IF ( pch_index_ji(j,i) /= 0 )  THEN
679                         DO  k = 0, pch_index_ji(j,i)
680                            pcm_latentrate_av(k,j,i) = pcm_latentrate_av(k,j,i)              &
681                                                       / REAL( average_count_3d, KIND=wp )
682                         ENDDO
683                      ENDIF
684                   ENDDO
685                ENDDO
686             ENDIF
687
688
689          CASE ( 'pcm_transpirationrate' )
690             IF ( ALLOCATED( pcm_transpirationrate_av ) ) THEN
691                DO  i = nxlg, nxrg
692                   DO  j = nysg, nyng
693                      IF ( pch_index_ji(j,i) /= 0 )  THEN
694                         DO  k = 0, pch_index_ji(j,i)
695                            pcm_transpirationrate_av(k,j,i) = pcm_transpirationrate_av(k,j,i)  &
696                                                              / REAL( average_count_3d, KIND=wp )
697                         ENDDO
698                      ENDIF
699                   ENDDO
700                ENDDO
701             ENDIF
702
703       END SELECT
704
705    ENDIF
706
707 END SUBROUTINE pcm_3d_data_averaging
708
709!------------------------------------------------------------------------------!
710!
711! Description:
712! ------------
713!> Subroutine defining 3D output variables.
714!> Note, 3D plant-canopy output has it's own vertical output dimension, meaning
715!> that 3D output is relative to the model surface now rather than at the actual
716!> grid point where the plant canopy is located.
717!------------------------------------------------------------------------------!
718 SUBROUTINE pcm_data_output_3d( av, variable, found, local_pf, fill_value,     &
719                                nzb_do, nzt_do )
720
721    CHARACTER (LEN=*) ::  variable !< treated variable
722
723    INTEGER(iwp) ::  av     !< flag indicating instantaneous or averaged data output
724    INTEGER(iwp) ::  i      !< grid index x-direction
725    INTEGER(iwp) ::  j      !< grid index y-direction
726    INTEGER(iwp) ::  k      !< grid index z-direction
727    INTEGER(iwp) ::  nzb_do !< lower limit of the data output (usually 0)
728    INTEGER(iwp) ::  nzt_do !< vertical upper limit of the data output (usually nz_do3d)
729
730    LOGICAL      ::  found  !< flag indicating if variable is found
731
732    REAL(wp)     ::  fill_value !< fill value
733    REAL(sp), DIMENSION(nxl:nxr,nys:nyn,nzb_do:nzt_do) ::  local_pf !< data output array
734
735
736    found = .TRUE.
737
738    local_pf = REAL( fill_value, KIND = 4 )
739
740    SELECT CASE ( TRIM( variable ) )
741!
742!--    Note, to save memory arrays for heating are allocated from 0:pch_index.
743!--    Thus, output must be relative to these array indices. Further, check
744!--    whether the output is within the vertical output range,
745!--    i.e. nzb_do:nzt_do, which is necessary as local_pf is only allocated
746!--    for this index space. Note, plant-canopy output has a separate
747!--    vertical output coordinate zlad, so that output is mapped down to the
748!--    surface.
749       CASE ( 'pcm_heatrate' )
750          IF ( av == 0 )  THEN
751             DO  i = nxl, nxr
752                DO  j = nys, nyn
753                   DO  k = MAX( 1, nzb_do ), MIN( pch_index_ji(j,i), nzt_do )
754                      local_pf(i,j,k) = pcm_heating_rate(k,j,i)
755                   ENDDO
756                ENDDO
757             ENDDO
758          ELSE
759             DO  i = nxl, nxr
760                DO  j = nys, nyn
761                   DO  k = MAX( 1, nzb_do ), MIN( pch_index_ji(j,i), nzt_do )
762                      local_pf(i,j,k) = pcm_heatrate_av(k,j,i)
763                   ENDDO
764                ENDDO
765             ENDDO
766          ENDIF
767
768       CASE ( 'pcm_latentrate' )
769          IF ( av == 0 )  THEN
770             DO  i = nxl, nxr
771                DO  j = nys, nyn
772                   DO  k = MAX( 1, nzb_do ), MIN( pch_index_ji(j,i), nzt_do )
773                      local_pf(i,j,k) = pcm_latent_rate(k,j,i)
774                   ENDDO
775                ENDDO
776             ENDDO
777          ELSE
778             DO  i = nxl, nxr
779                DO  j = nys, nyn
780                   DO  k = MAX( 1, nzb_do ), MIN( pch_index_ji(j,i), nzt_do )
781                      local_pf(i,j,k) = pcm_latentrate_av(k,j,i)
782                   ENDDO
783                ENDDO
784             ENDDO
785          ENDIF
786
787       CASE ( 'pcm_transpirationrate' )
788          IF ( av == 0 )  THEN
789             DO  i = nxl, nxr
790                DO  j = nys, nyn
791                   DO  k = MAX( 1, nzb_do ), MIN( pch_index_ji(j,i), nzt_do )
792                      local_pf(i,j,k) = pcm_transpiration_rate(k,j,i)
793                   ENDDO
794                ENDDO
795             ENDDO
796          ELSE
797             DO  i = nxl, nxr
798                DO  j = nys, nyn
799                   DO  k = MAX( 1, nzb_do ), MIN( pch_index_ji(j,i), nzt_do )
800                      local_pf(i,j,k) = pcm_transpirationrate_av(k,j,i)
801                   ENDDO
802                ENDDO
803             ENDDO
804          ENDIF
805
806       CASE ( 'pcm_lad' )
807          IF ( av == 0 )  THEN
808             DO  i = nxl, nxr
809                DO  j = nys, nyn
810                   DO  k = MAX( 1, nzb_do ), MIN( pch_index_ji(j,i), nzt_do )
811                      local_pf(i,j,k) = lad_s(k,j,i)
812                   ENDDO
813                ENDDO
814             ENDDO
815          ENDIF
816
817       CASE DEFAULT
818          found = .FALSE.
819
820    END SELECT
821
822 END SUBROUTINE pcm_data_output_3d 
823         
824!------------------------------------------------------------------------------!
825!
826! Description:
827! ------------
828!> Subroutine defining appropriate grid for netcdf variables.
829!> It is called from subroutine netcdf.
830!------------------------------------------------------------------------------!
831 SUBROUTINE pcm_define_netcdf_grid( var, found, grid_x, grid_y, grid_z )
832
833     CHARACTER (LEN=*), INTENT(IN)  ::  var         !<
834     LOGICAL, INTENT(OUT)           ::  found       !<
835     CHARACTER (LEN=*), INTENT(OUT) ::  grid_x      !<
836     CHARACTER (LEN=*), INTENT(OUT) ::  grid_y      !<
837     CHARACTER (LEN=*), INTENT(OUT) ::  grid_z      !<
838
839     found  = .TRUE.
840
841!
842!--  Check for the grid. zpc is zu(nzb:nzb+pch_index)
843     SELECT CASE ( TRIM( var ) )
844
845        CASE ( 'pcm_heatrate', 'pcm_lad', 'pcm_transpirationrate', 'pcm_latentrate')
846           grid_x = 'x'
847           grid_y = 'y'
848           grid_z = 'zpc'
849
850        CASE DEFAULT
851           found  = .FALSE.
852           grid_x = 'none'
853           grid_y = 'none'
854           grid_z = 'none'
855     END SELECT
856
857 END SUBROUTINE pcm_define_netcdf_grid
858 
859 
860!------------------------------------------------------------------------------!
861! Description:
862! ------------
863!> Header output for plant canopy model
864!------------------------------------------------------------------------------!
865 SUBROUTINE pcm_header ( io )
866 
867    CHARACTER (LEN=10) ::  coor_chr            !<
868
869    CHARACTER (LEN=86) ::  coordinates         !<
870    CHARACTER (LEN=86) ::  gradients           !<
871    CHARACTER (LEN=86) ::  leaf_area_density   !<
872    CHARACTER (LEN=86) ::  slices              !<
873 
874    INTEGER(iwp) :: i                !<
875    INTEGER(iwp),  INTENT(IN) ::  io !< Unit of the output file
876    INTEGER(iwp) :: k                !<       
877 
878    REAL(wp) ::  canopy_height       !< canopy height (in m)
879   
880    canopy_height = zw(pch_index)
881
882    WRITE ( io, 1 )  canopy_mode, canopy_height, pch_index,                    &
883                       canopy_drag_coeff                                       
884    IF ( passive_scalar )  THEN                                               
885       WRITE ( io, 2 )  leaf_scalar_exch_coeff,                                &
886                          leaf_surface_conc
887    ENDIF
888
889!
890!   Heat flux at the top of vegetation
891    WRITE ( io, 3 )  cthf
892
893!
894!   Leaf area density profile, calculated either from given vertical
895!   gradients or from beta probability density function.
896    IF (  .NOT.  calc_beta_lad_profile )  THEN
897
898!      Building output strings, starting with surface value
899       WRITE ( leaf_area_density, '(F7.4)' )  lad_surface
900       gradients = '------'
901       slices = '     0'
902       coordinates = '   0.0'
903       DO i = 1, UBOUND(lad_vertical_gradient_level_ind, DIM=1)
904          IF  ( lad_vertical_gradient_level_ind(i) /= -9999 ) THEN
905
906             WRITE (coor_chr,'(F7.2)') lad(lad_vertical_gradient_level_ind(i))
907             leaf_area_density = TRIM( leaf_area_density ) // ' ' // TRIM( coor_chr )
908
909             WRITE (coor_chr,'(F7.2)') lad_vertical_gradient(i)
910             gradients = TRIM( gradients ) // ' ' // TRIM( coor_chr )
911
912             WRITE (coor_chr,'(I7)') lad_vertical_gradient_level_ind(i)
913             slices = TRIM( slices ) // ' ' // TRIM( coor_chr )
914
915             WRITE (coor_chr,'(F7.1)') lad_vertical_gradient_level(i)
916             coordinates = TRIM( coordinates ) // ' '  // TRIM( coor_chr )
917          ELSE
918             EXIT
919          ENDIF
920       ENDDO
921
922       WRITE ( io, 4 )  TRIM( coordinates ), TRIM( leaf_area_density ),        &
923                          TRIM( gradients ), TRIM( slices )
924
925    ELSE
926   
927       WRITE ( leaf_area_density, '(F7.4)' )  lad_surface
928       coordinates = '   0.0'
929       
930       DO  k = 1, pch_index
931
932          WRITE (coor_chr,'(F7.2)')  lad(k)
933          leaf_area_density = TRIM( leaf_area_density ) // ' ' //              &
934                              TRIM( coor_chr )                                 
935                                                                               
936          WRITE (coor_chr,'(F7.1)')  zu(k)                                     
937          coordinates = TRIM( coordinates ) // ' '  // TRIM( coor_chr )       
938                                                                               
939       ENDDO                                                                   
940                                                                               
941       WRITE ( io, 5 ) TRIM( coordinates ), TRIM( leaf_area_density ),         &
942                       alpha_lad, beta_lad, lai_beta
943
944    ENDIF 
945
9461   FORMAT (//' Vegetation canopy (drag) model:'/                              &
947              ' ------------------------------'//                              &
948              ' Canopy mode: ', A /                                            &
949              ' Canopy height: ',F6.2,'m (',I4,' grid points)' /               &
950              ' Leaf drag coefficient: ',F6.2 /)
9512   FORMAT (/ ' Scalar exchange coefficient: ',F6.2 /                          &
952              ' Scalar concentration at leaf surfaces in kg/m**3: ',F6.2 /)
9533   FORMAT (' Predefined constant heatflux at the top of the vegetation: ',    &
954             F6.2, ' K m/s')
9554   FORMAT (/ ' Characteristic levels of the leaf area density:'//             &
956              ' Height:              ',A,'  m'/                                &
957              ' Leaf area density:   ',A,'  m**2/m**3'/                        &
958              ' Gradient:            ',A,'  m**2/m**4'/                        &
959              ' Gridpoint:           ',A)
9605   FORMAT (//' Characteristic levels of the leaf area density and coefficients:'&
961          //  ' Height:              ',A,'  m'/                                &
962              ' Leaf area density:   ',A,'  m**2/m**3'/                        &
963              ' Coefficient alpha: ',F6.2 /                                    &
964              ' Coefficient beta: ',F6.2 /                                     &
965              ' Leaf area index: ',F6.2,'  m**2/m**2' /)   
966       
967    END SUBROUTINE pcm_header
968 
969 
970!------------------------------------------------------------------------------!
971! Description:
972! ------------
973!> Initialization of the plant canopy model
974!------------------------------------------------------------------------------!
975    SUBROUTINE pcm_init
976
977       USE exchange_horiz_mod,                                                    &
978           ONLY:  exchange_horiz
979
980       INTEGER(iwp) ::  i   !< running index
981       INTEGER(iwp) ::  j   !< running index
982       INTEGER(iwp) ::  k   !< running index
983       INTEGER(iwp) ::  m   !< running index
984
985       LOGICAL      ::  lad_on_top = .FALSE.  !< dummy flag to indicate that LAD is defined on a building roof
986
987       REAL(wp) ::  canopy_height   !< canopy height for lad-profile construction
988       REAL(wp) ::  gradient        !< gradient for lad-profile construction
989       REAL(wp) ::  int_bpdf        !< vertical integral for lad-profile construction     
990       REAL(wp) ::  lad_max         !< maximum LAD value in the model domain, used to perform a check
991
992       IF ( debug_output )  CALL debug_message( 'pcm_init', 'start' )
993!
994!--    Allocate one-dimensional arrays for the computation of the
995!--    leaf area density (lad) profile
996       ALLOCATE( lad(0:nz+1), pre_lad(0:nz+1) )
997       lad = 0.0_wp
998       pre_lad = 0.0_wp
999
1000!
1001!--    Set flag that indicates that the lad-profile shall be calculated by using
1002!--    a beta probability density function
1003       IF ( alpha_lad /= 9999999.9_wp  .AND.  beta_lad /= 9999999.9_wp )  THEN
1004          calc_beta_lad_profile = .TRUE.
1005       ENDIF
1006       
1007       
1008!
1009!--    Compute the profile of leaf area density used in the plant
1010!--    canopy model. The profile can either be constructed from
1011!--    prescribed vertical gradients of the leaf area density or by
1012!--    using a beta probability density function (see e.g. Markkanen et al.,
1013!--    2003: Boundary-Layer Meteorology, 106, 437-459)
1014       IF (  .NOT.  calc_beta_lad_profile )  THEN   
1015
1016!
1017!--       Use vertical gradients for lad-profile construction   
1018          i = 1
1019          gradient = 0.0_wp
1020
1021          lad(0) = lad_surface
1022          lad_vertical_gradient_level_ind(1) = 0
1023
1024          DO k = 1, pch_index
1025             IF ( i < 11 )  THEN
1026                IF ( lad_vertical_gradient_level(i) < zu(k)  .AND.          &
1027                     lad_vertical_gradient_level(i) >= 0.0_wp )  THEN
1028                   gradient = lad_vertical_gradient(i)
1029                   lad_vertical_gradient_level_ind(i) = k - 1
1030                   i = i + 1
1031                ENDIF
1032             ENDIF
1033             IF ( gradient /= 0.0_wp )  THEN
1034                IF ( k /= 1 )  THEN
1035                   lad(k) = lad(k-1) + dzu(k) * gradient
1036                ELSE
1037                   lad(k) = lad_surface + dzu(k) * gradient
1038                ENDIF
1039             ELSE
1040                lad(k) = lad(k-1)
1041             ENDIF
1042          ENDDO
1043
1044!
1045!--       In case of no given leaf area density gradients, choose a vanishing
1046!--       gradient. This information is used for the HEADER and the RUN_CONTROL
1047!--       file.
1048          IF ( lad_vertical_gradient_level(1) == -9999999.9_wp )  THEN
1049             lad_vertical_gradient_level(1) = 0.0_wp
1050          ENDIF
1051
1052       ELSE
1053
1054!
1055!--       Use beta function for lad-profile construction
1056          int_bpdf = 0.0_wp
1057          canopy_height = zw(pch_index)
1058
1059          DO k = 0, pch_index
1060             int_bpdf = int_bpdf +                                             &
1061                      ( ( ( zw(k) / canopy_height )**( alpha_lad-1.0_wp ) ) *  &
1062                      ( ( 1.0_wp - ( zw(k) / canopy_height ) )**(              &
1063                          beta_lad-1.0_wp ) )                                  &
1064                      * ( ( zw(k+1)-zw(k) ) / canopy_height ) )
1065          ENDDO
1066
1067!
1068!--       Preliminary lad profile (defined on w-grid)
1069          DO k = 0, pch_index
1070             pre_lad(k) =  lai_beta *                                          &
1071                        ( ( ( zw(k) / canopy_height )**( alpha_lad-1.0_wp ) )  &
1072                        * ( ( 1.0_wp - ( zw(k) / canopy_height ) )**(          &
1073                              beta_lad-1.0_wp ) ) / int_bpdf                   &
1074                        ) / canopy_height
1075          ENDDO
1076
1077!
1078!--       Final lad profile (defined on scalar-grid level, since most prognostic
1079!--       quantities are defined there, hence, less interpolation is required
1080!--       when calculating the canopy tendencies)
1081          lad(0) = pre_lad(0)
1082          DO k = 1, pch_index
1083             lad(k) = 0.5 * ( pre_lad(k-1) + pre_lad(k) )
1084          ENDDO
1085
1086       ENDIF
1087
1088!
1089!--    Allocate 3D-array for the leaf area density (lad_s).
1090       ALLOCATE( lad_s(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
1091
1092!
1093!--    Initialization of the canopy coverage in the model domain:
1094!--    Setting the parameter canopy_mode = 'homogeneous' initializes a canopy, which
1095!--    fully covers the domain surface
1096       SELECT CASE ( TRIM( canopy_mode ) )
1097
1098          CASE( 'homogeneous' )
1099
1100             DO  i = nxlg, nxrg
1101                DO  j = nysg, nyng
1102                   lad_s(:,j,i) = lad(:)
1103                ENDDO
1104             ENDDO
1105
1106          CASE ( 'read_from_file' )
1107!
1108!--          Read plant canopy
1109             IF ( input_pids_static )  THEN
1110!
1111!--             Open the static input file
1112#if defined( __netcdf )
1113                CALL open_read_file( TRIM( input_file_static ) //              &
1114                                     TRIM( coupling_char ),                    &
1115                                     pids_id )
1116
1117                CALL inquire_num_variables( pids_id, num_var_pids )
1118!
1119!--             Allocate memory to store variable names and read them
1120                ALLOCATE( vars_pids(1:num_var_pids) )
1121                CALL inquire_variable_names( pids_id, vars_pids )
1122!
1123!--             Read leaf area density - resolved vegetation
1124                IF ( check_existence( vars_pids, 'lad' ) )  THEN
1125                   leaf_area_density_f%from_file = .TRUE.
1126                   CALL get_attribute( pids_id, char_fill,                     &
1127                                       leaf_area_density_f%fill,               &
1128                                       .FALSE., 'lad' )
1129!
1130!--                Inquire number of vertical vegetation layer
1131                   CALL get_dimension_length( pids_id,                         &
1132                                              leaf_area_density_f%nz,          &
1133                                              'zlad' )
1134!
1135!--                Allocate variable for leaf-area density
1136                   ALLOCATE( leaf_area_density_f%var                           &
1137                                                (0:leaf_area_density_f%nz-1,   &
1138                                                 nys:nyn,nxl:nxr) )
1139
1140                   CALL get_variable( pids_id, 'lad', leaf_area_density_f%var, &
1141                                      nxl, nxr, nys, nyn,                      &
1142                                      0, leaf_area_density_f%nz-1 )
1143
1144                ELSE
1145                   leaf_area_density_f%from_file = .FALSE.
1146                ENDIF
1147!
1148!--             Read basal area density - resolved vegetation
1149                IF ( check_existence( vars_pids, 'bad' ) )  THEN
1150                   basal_area_density_f%from_file = .TRUE.
1151                   CALL get_attribute( pids_id, char_fill,                     &
1152                                       basal_area_density_f%fill,              &
1153                                       .FALSE., 'bad' )
1154!
1155!--                Inquire number of vertical vegetation layer
1156                   CALL get_dimension_length( pids_id,                         &
1157                                              basal_area_density_f%nz,         & 
1158                                              'zlad' )
1159!
1160!--                Allocate variable
1161                   ALLOCATE( basal_area_density_f%var                          &
1162                                              (0:basal_area_density_f%nz-1,    &
1163                                               nys:nyn,nxl:nxr) )
1164
1165                   CALL get_variable( pids_id, 'bad', basal_area_density_f%var,&
1166                                      nxl, nxr, nys, nyn,                      &
1167                                      0,  basal_area_density_f%nz-1 )
1168                ELSE
1169                   basal_area_density_f%from_file = .FALSE.
1170                ENDIF
1171!
1172!--             Read root area density - resolved vegetation
1173                IF ( check_existence( vars_pids, 'root_area_dens_r' ) )  THEN
1174                   root_area_density_lad_f%from_file = .TRUE.
1175                   CALL get_attribute( pids_id, char_fill,                     &
1176                                       root_area_density_lad_f%fill,           &
1177                                       .FALSE., 'root_area_dens_r' )
1178!
1179!--                Inquire number of vertical soil layers
1180                   CALL get_dimension_length( pids_id,                         &
1181                                              root_area_density_lad_f%nz,      &
1182                                              'zsoil' )
1183!
1184!--                Allocate variable
1185                   ALLOCATE( root_area_density_lad_f%var                       &
1186                                               (0:root_area_density_lad_f%nz-1,&
1187                                                nys:nyn,nxl:nxr) )
1188
1189                   CALL get_variable( pids_id, 'root_area_dens_r',             &
1190                                      root_area_density_lad_f%var,             &
1191                                      nxl, nxr, nys, nyn,                      &
1192                                      0,  root_area_density_lad_f%nz-1 )
1193                ELSE
1194                   root_area_density_lad_f%from_file = .FALSE.
1195                ENDIF
1196
1197                DEALLOCATE( vars_pids )
1198!
1199!--             Finally, close the input file and deallocate temporary array
1200                CALL close_input_file( pids_id )
1201#endif
1202             ENDIF
1203
1204!
1205!--          Initialize LAD with data from file. If LAD is given in NetCDF file,
1206!--          use these values, else take LAD profiles from ASCII file.
1207!--          Please note, in NetCDF file LAD is only given up to the maximum
1208!--          canopy top, indicated by leaf_area_density_f%nz. 
1209             lad_s = 0.0_wp
1210             IF ( leaf_area_density_f%from_file )  THEN
1211!
1212!--             Set also pch_index, used to be the upper bound of the vertical
1213!--             loops. Therefore, use the global top of the canopy layer.
1214                pch_index = leaf_area_density_f%nz - 1
1215
1216                DO  i = nxl, nxr
1217                   DO  j = nys, nyn
1218                      DO  k = 0, leaf_area_density_f%nz - 1
1219                         IF ( leaf_area_density_f%var(k,j,i) /=                &
1220                              leaf_area_density_f%fill )                       &
1221                         lad_s(k,j,i) = leaf_area_density_f%var(k,j,i)
1222                      ENDDO
1223!
1224!--                   Check if resolved vegetation is mapped onto buildings.
1225!--                   In general, this is allowed and also meaningful, e.g.
1226!--                   when trees carry across roofs. However, due to the
1227!--                   topography filtering, new building grid points can emerge
1228!--                   at location where also plant canopy is defined. As a
1229!--                   result, plant canopy is mapped on top of roofs, with
1230!--                   siginficant impact on the downstream flow field and the
1231!--                   nearby surface radiation. In order to avoid that
1232!--                   plant canopy is mistakenly mapped onto building roofs,
1233!--                   check for building grid points (bit 6) that emerge from
1234!--                   the filtering (bit 4) and set LAD to zero at these
1235!--                   artificially  created building grid points. This case,
1236!--                   an informative message is given.
1237                      IF ( ANY( lad_s(:,j,i) /= 0.0_wp )  .AND.                &
1238                           ANY( BTEST( wall_flags_total_0(:,j,i), 6 ) ) .AND.  &
1239                           ANY( BTEST( wall_flags_total_0(:,j,i), 4 ) ) )  THEN
1240                         lad_s(:,j,i) = 0.0_wp
1241                         lad_on_top   = .TRUE.
1242                      ENDIF
1243                   ENDDO
1244                ENDDO
1245#if defined( __parallel )
1246               CALL MPI_ALLREDUCE( MPI_IN_PLACE, lad_on_top, 1, MPI_LOGICAL,  &
1247                                   MPI_LOR, comm2d, ierr)
1248#endif
1249                IF ( lad_on_top )  THEN
1250                   WRITE( message_string, * )                                  &
1251                                        'Resolved plant-canopy is ' //         &
1252                                        'defined on top of an artificially '// &
1253                                        'created building grid point(s) ' //   &
1254                                        '(emerged from the filtering) - ' //   &
1255                                        'LAD profile is omitted at this / ' // &
1256                                        'these grid point(s).'
1257                   CALL message( 'pcm_init', 'PA0313', 0, 0, 0, 6, 0 )
1258                ENDIF
1259                CALL exchange_horiz( lad_s, nbgp )
1260!
1261!            ASCII file
1262!--          Initialize canopy parameters canopy_drag_coeff,
1263!--          leaf_scalar_exch_coeff, leaf_surface_conc
1264!--          from file which contains complete 3D data (separate vertical profiles for
1265!--          each location).
1266             ELSE
1267                CALL pcm_read_plant_canopy_3d
1268             ENDIF
1269
1270          CASE DEFAULT
1271!
1272!--          The DEFAULT case is reached either if the parameter
1273!--          canopy mode contains a wrong character string or if the
1274!--          user has coded a special case in the user interface.
1275!--          There, the subroutine user_init_plant_canopy checks
1276!--          which of these two conditions applies.
1277             CALL user_init_plant_canopy
1278 
1279       END SELECT
1280!
1281!--    Check that at least one grid point has an LAD /= 0, else this may
1282!--    cause errors in the radiation model.
1283       lad_max = MAXVAL( lad_s )
1284#if defined( __parallel )
1285       CALL MPI_ALLREDUCE( MPI_IN_PLACE, lad_max, 1, MPI_REAL, MPI_MAX,        &
1286                           comm2d, ierr)
1287#endif
1288       IF ( lad_max <= 0.0_wp )  THEN
1289          message_string = 'Plant-canopy model is switched-on but no ' //      &
1290                           'plant canopy is present in the model domain.'
1291          CALL message( 'pcm_init', 'PA0685', 1, 2, 0, 6, 0 )
1292       ENDIF
1293   
1294!
1295!--    Initialize 2D index array indicating canopy top index.
1296       ALLOCATE( pch_index_ji(nysg:nyng,nxlg:nxrg) )
1297       pch_index_ji = 0
1298       
1299       DO  i = nxlg, nxrg
1300          DO  j = nysg, nyng
1301             DO  k = 0, pch_index
1302                IF ( lad_s(k,j,i) /= 0 )  pch_index_ji(j,i) = k
1303             ENDDO
1304!
1305!--          Check whether topography and local vegetation on top exceed
1306!--          height of the model domain.
1307             IF ( topo_top_ind(j,i,0) + pch_index_ji(j,i) >= nzt + 1 )  THEN
1308                message_string =  'Local vegetation height on top of ' //      &
1309                                  'topography exceeds height of model domain.'
1310                CALL message( 'pcm_init', 'PA0674', 2, 2, myid, 6, 0 )
1311             ENDIF
1312
1313          ENDDO
1314       ENDDO
1315!
1316!--    Calculate global pch_index value (index of top of plant canopy from ground)
1317       pch_index = MAXVAL( pch_index_ji )
1318!
1319!--    Exchange pch_index from all processors
1320#if defined( __parallel )
1321       CALL MPI_ALLREDUCE( MPI_IN_PLACE, pch_index, 1, MPI_INTEGER,            &
1322                           MPI_MAX, comm2d, ierr)
1323#endif
1324!
1325!--    Allocation of arrays pcm_heating_rate, pcm_transpiration_rate and pcm_latent_rate
1326       ALLOCATE( pcm_heating_rate(0:pch_index,nysg:nyng,nxlg:nxrg) )
1327       pcm_heating_rate = 0.0_wp
1328       
1329       IF ( humidity )  THEN
1330          ALLOCATE( pcm_transpiration_rate(0:pch_index,nysg:nyng,nxlg:nxrg) )
1331          pcm_transpiration_rate = 0.0_wp
1332          ALLOCATE( pcm_latent_rate(0:pch_index,nysg:nyng,nxlg:nxrg) )
1333          pcm_latent_rate = 0.0_wp
1334       ENDIF
1335!
1336!--    Initialization of the canopy heat source distribution due to heating
1337!--    of the canopy layers by incoming solar radiation, in case that a non-zero
1338!--    value is set for the canopy top heat flux (cthf), which equals the
1339!--    available net radiation at canopy top.
1340!--    The heat source distribution is calculated by a decaying exponential
1341!--    function of the downward cumulative leaf area index (cum_lai_hf),
1342!--    assuming that the foliage inside the plant canopy is heated by solar
1343!--    radiation penetrating the canopy layers according to the distribution
1344!--    of net radiation as suggested by Brown & Covey (1966; Agric. Meteorol. 3,
1345!--    73–96). This approach has been applied e.g. by Shaw & Schumann (1992;
1346!--    Bound.-Layer Meteorol. 61, 47–64).
1347!--    When using the radiation_interactions, canopy heating (pcm_heating_rate)
1348!--    and plant canopy transpiration (pcm_transpiration_rate, pcm_latent_rate)
1349!--    are calculated in the RTM after the calculation of radiation.
1350       IF ( cthf /= 0.0_wp )  THEN
1351
1352          ALLOCATE( cum_lai_hf(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
1353!
1354!--       Piecewise calculation of the cumulative leaf area index by vertical
1355!--       integration of the leaf area density
1356          cum_lai_hf(:,:,:) = 0.0_wp
1357          DO  i = nxlg, nxrg
1358             DO  j = nysg, nyng
1359                DO  k = pch_index_ji(j,i)-1, 0, -1
1360                   IF ( k == pch_index_ji(j,i)-1 )  THEN
1361                      cum_lai_hf(k,j,i) = cum_lai_hf(k+1,j,i) +                &
1362                         ( 0.5_wp * lad_s(k+1,j,i) *                           &
1363                           ( zw(k+1) - zu(k+1) ) )  +                          &
1364                         ( 0.5_wp * ( 0.5_wp * ( lad_s(k+1,j,i) +              &
1365                                                 lad_s(k,j,i) ) +              &
1366                                      lad_s(k+1,j,i) ) *                       &
1367                           ( zu(k+1) - zw(k) ) ) 
1368                   ELSE
1369                      cum_lai_hf(k,j,i) = cum_lai_hf(k+1,j,i) +                &
1370                         ( 0.5_wp * ( 0.5_wp * ( lad_s(k+2,j,i) +              &
1371                                                 lad_s(k+1,j,i) ) +            &
1372                                      lad_s(k+1,j,i) ) *                       &
1373                           ( zw(k+1) - zu(k+1) ) )  +                          &
1374                         ( 0.5_wp * ( 0.5_wp * ( lad_s(k+1,j,i) +              &
1375                                                 lad_s(k,j,i) ) +              &
1376                                      lad_s(k+1,j,i) ) *                       &
1377                           ( zu(k+1) - zw(k) ) )
1378                   ENDIF
1379                ENDDO
1380             ENDDO
1381          ENDDO
1382
1383!
1384!--       In areas with canopy the surface value of the canopy heat
1385!--       flux distribution overrides the surface heat flux (shf)
1386!--       Start with default surface type
1387          DO  m = 1, surf_def_h(0)%ns
1388             i = surf_def_h(0)%i(m)
1389             j = surf_def_h(0)%j(m)
1390             IF ( cum_lai_hf(0,j,i) /= 0.0_wp )                                &
1391                surf_def_h(0)%shf(m) = cthf * exp( -ext_coef * cum_lai_hf(0,j,i) )
1392          ENDDO
1393!
1394!--       Natural surfaces
1395          DO  m = 1, surf_lsm_h%ns
1396             i = surf_lsm_h%i(m)
1397             j = surf_lsm_h%j(m)
1398             IF ( cum_lai_hf(0,j,i) /= 0.0_wp )                                &
1399                surf_lsm_h%shf(m) = cthf * exp( -ext_coef * cum_lai_hf(0,j,i) )
1400          ENDDO
1401!
1402!--       Urban surfaces
1403          DO  m = 1, surf_usm_h%ns
1404             i = surf_usm_h%i(m)
1405             j = surf_usm_h%j(m)
1406             IF ( cum_lai_hf(0,j,i) /= 0.0_wp )                                &
1407                surf_usm_h%shf(m) = cthf * exp( -ext_coef * cum_lai_hf(0,j,i) )
1408          ENDDO
1409!
1410!
1411!--       Calculation of the heating rate (K/s) within the different layers of
1412!--       the plant canopy. Calculation is only necessary in areas covered with
1413!--       canopy.
1414!--       Within the different canopy layers the plant-canopy heating
1415!--       rate (pcm_heating_rate) is calculated as the vertical
1416!--       divergence of the canopy heat fluxes at the top and bottom
1417!--       of the respective layer
1418          DO  i = nxlg, nxrg
1419             DO  j = nysg, nyng
1420                DO  k = 1, pch_index_ji(j,i)
1421                   IF ( cum_lai_hf(0,j,i) /= 0.0_wp )  THEN
1422                      pcm_heating_rate(k,j,i) = cthf *                          &
1423                                ( exp(-ext_coef*cum_lai_hf(k,j,i)) -           &
1424                                  exp(-ext_coef*cum_lai_hf(k-1,j,i) ) ) / dzw(k)
1425                   ENDIF
1426                ENDDO
1427             ENDDO
1428          ENDDO
1429
1430       ENDIF
1431
1432       IF ( debug_output )  CALL debug_message( 'pcm_init', 'end' )
1433
1434    END SUBROUTINE pcm_init
1435
1436
1437!------------------------------------------------------------------------------!
1438! Description:
1439! ------------
1440!> Parin for &plant_canopy_parameters for plant canopy model
1441!------------------------------------------------------------------------------!
1442    SUBROUTINE pcm_parin
1443
1444       CHARACTER (LEN=80) ::  line  !< dummy string that contains the current line of the parameter file
1445       
1446       NAMELIST /plant_canopy_parameters/                                      &
1447                                  alpha_lad, beta_lad, canopy_drag_coeff,      &
1448                                  canopy_mode, cthf,                           &
1449                                  lad_surface, lad_type_coef,                  & 
1450                                  lad_vertical_gradient,                       &
1451                                  lad_vertical_gradient_level,                 &
1452                                  lai_beta,                                    &
1453                                  leaf_scalar_exch_coeff,                      &
1454                                  leaf_surface_conc, pch_index,                &
1455                                  plant_canopy_transpiration
1456
1457       NAMELIST /canopy_par/      alpha_lad, beta_lad, canopy_drag_coeff,      &
1458                                  canopy_mode, cthf,                           &
1459                                  lad_surface, lad_type_coef,                  & 
1460                                  lad_vertical_gradient,                       &
1461                                  lad_vertical_gradient_level,                 &
1462                                  lai_beta,                                    &
1463                                  leaf_scalar_exch_coeff,                      &
1464                                  leaf_surface_conc, pch_index,                &
1465                                  plant_canopy_transpiration
1466
1467       line = ' '
1468
1469!
1470!--    Try to find plant-canopy model package
1471       REWIND ( 11 )
1472       line = ' '
1473       DO WHILE ( INDEX( line, '&plant_canopy_parameters' ) == 0 )
1474          READ ( 11, '(A)', END=12 )  line
1475       ENDDO
1476       BACKSPACE ( 11 )
1477
1478!
1479!--    Read user-defined namelist
1480       READ ( 11, plant_canopy_parameters, ERR = 10 )
1481
1482!
1483!--    Set flag that indicates that the plant-canopy model is switched on
1484       plant_canopy = .TRUE.
1485
1486       GOTO 14
1487
1488 10    BACKSPACE( 11 )
1489       READ( 11 , '(A)') line
1490       CALL parin_fail_message( 'plant_canopy_parameters', line )
1491!
1492!--    Try to find old namelist
1493 12    REWIND ( 11 )
1494       line = ' '
1495       DO WHILE ( INDEX( line, '&canopy_par' ) == 0 )
1496          READ ( 11, '(A)', END=14 )  line
1497       ENDDO
1498       BACKSPACE ( 11 )
1499
1500!
1501!--    Read user-defined namelist
1502       READ ( 11, canopy_par, ERR = 13, END = 14 )
1503
1504       message_string = 'namelist canopy_par is deprecated and will be ' // &
1505                     'removed in near future. Please use namelist ' //      &
1506                     'plant_canopy_parameters instead'
1507       CALL message( 'pcm_parin', 'PA0487', 0, 1, 0, 6, 0 )
1508
1509!
1510!--    Set flag that indicates that the plant-canopy model is switched on
1511       plant_canopy = .TRUE.
1512
1513       GOTO 14
1514
1515 13    BACKSPACE( 11 )
1516       READ( 11 , '(A)') line
1517       CALL parin_fail_message( 'canopy_par', line )
1518
1519 14    CONTINUE
1520
1521    END SUBROUTINE pcm_parin
1522
1523
1524!------------------------------------------------------------------------------!
1525! Description:
1526! ------------
1527!
1528!> Loads 3D plant canopy data from file. File format is as follows:
1529!>
1530!> num_levels
1531!> dtype,x,y,pctype,value(nzb),value(nzb+1), ... ,value(nzb+num_levels-1)
1532!> dtype,x,y,pctype,value(nzb),value(nzb+1), ... ,value(nzb+num_levels-1)
1533!> dtype,x,y,pctype,value(nzb),value(nzb+1), ... ,value(nzb+num_levels-1)
1534!> ...
1535!>
1536!> i.e. first line determines number of levels and further lines represent plant
1537!> canopy data, one line per column and variable. In each data line,
1538!> dtype represents variable to be set:
1539!>
1540!> dtype=1: leaf area density (lad_s)
1541!> dtype=2....n: some additional plant canopy input data quantity
1542!>
1543!> Zeros are added automatically above num_levels until top of domain.  Any
1544!> non-specified (x,y) columns have zero values as default.
1545!------------------------------------------------------------------------------!
1546    SUBROUTINE pcm_read_plant_canopy_3d
1547
1548       USE exchange_horiz_mod,                                                    &
1549           ONLY:  exchange_horiz
1550
1551       INTEGER(iwp)                        ::  dtype     !< type of input data (1=lad)
1552       INTEGER(iwp)                        ::  pctype    !< type of plant canopy (deciduous,non-deciduous,...)
1553       INTEGER(iwp)                        ::  i, j      !< running index
1554       INTEGER(iwp)                        ::  nzp       !< number of vertical layers of plant canopy
1555       INTEGER(iwp)                        ::  nzpltop   !<
1556       INTEGER(iwp)                        ::  nzpl      !<
1557       INTEGER(iwp)                        ::  kk        !<
1558       
1559       REAL(wp), DIMENSION(:), ALLOCATABLE ::  col   !< vertical column of input data
1560
1561!
1562!--    Initialize lad_s array
1563       lad_s = 0.0_wp
1564       
1565!
1566!--    Open and read plant canopy input data
1567       OPEN(152, FILE='PLANT_CANOPY_DATA_3D' // TRIM( coupling_char ),         &
1568                 ACCESS='SEQUENTIAL', ACTION='READ', STATUS='OLD',             &
1569                 FORM='FORMATTED', ERR=515)
1570       READ(152, *, ERR=516, END=517)  nzp   !< read first line = number of vertical layers
1571       nzpltop = MIN(nzt+1, nzb+nzp-1)
1572       nzpl = nzpltop - nzb + 1    !< no. of layers to assign
1573       ALLOCATE( col(0:nzp-1) )
1574
1575       DO
1576          READ(152, *, ERR=516, END=517) dtype, i, j, pctype, col(:)
1577          IF ( i < nxlg  .OR.  i > nxrg  .OR.  j < nysg  .OR.  j > nyng )  CYCLE
1578         
1579          SELECT CASE (dtype)
1580             CASE( 1 )   !< leaf area density
1581!
1582!--             This is just the pure canopy layer assumed to be grounded to
1583!--             a flat domain surface. At locations where plant canopy sits
1584!--             on top of any kind of topography, the vertical plant column
1585!--             must be "lifted", which is done in SUBROUTINE pcm_tendency.           
1586                IF ( pctype < 0  .OR.  pctype > 10 )  THEN   !< incorrect plant canopy type
1587                   WRITE( message_string, * ) 'Incorrect type of plant canopy. '   //  &
1588                                              'Allowed values 0 <= pctype <= 10, ' //  &
1589                                              'but pctype is ', pctype
1590                   CALL message( 'pcm_read_plant_canopy_3d', 'PA0349', 1, 2, 0, 6, 0 )
1591                ENDIF
1592                kk = topo_top_ind(j,i,0)
1593                lad_s(nzb:nzpltop-kk, j, i) = col(kk:nzpl-1)*lad_type_coef(pctype)
1594             CASE DEFAULT
1595                WRITE(message_string, '(a,i2,a)')   &
1596                     'Unknown record type in file PLANT_CANOPY_DATA_3D: "', dtype, '"'
1597                CALL message( 'pcm_read_plant_canopy_3d', 'PA0530', 1, 2, 0, 6, 0 )
1598          END SELECT
1599       ENDDO
1600
1601515    message_string = 'error opening file PLANT_CANOPY_DATA_3D'
1602       CALL message( 'pcm_read_plant_canopy_3d', 'PA0531', 1, 2, 0, 6, 0 )
1603
1604516    message_string = 'error reading file PLANT_CANOPY_DATA_3D'
1605       CALL message( 'pcm_read_plant_canopy_3d', 'PA0532', 1, 2, 0, 6, 0 )
1606
1607517    CLOSE(152)
1608       DEALLOCATE( col )
1609       
1610       CALL exchange_horiz( lad_s, nbgp )
1611       
1612    END SUBROUTINE pcm_read_plant_canopy_3d
1613
1614!------------------------------------------------------------------------------!
1615! Description:
1616! ------------
1617!> Subroutine reads local (subdomain) restart data
1618!------------------------------------------------------------------------------!
1619    SUBROUTINE pcm_rrd_local( k, nxlf, nxlc, nxl_on_file, nxrf, nxrc,          &
1620                              nxr_on_file, nynf, nync, nyn_on_file, nysf,      &
1621                              nysc, nys_on_file, found )
1622
1623       INTEGER(iwp) ::  k               !<
1624       INTEGER(iwp) ::  nxlc            !<
1625       INTEGER(iwp) ::  nxlf            !<
1626       INTEGER(iwp) ::  nxl_on_file     !<
1627       INTEGER(iwp) ::  nxrc            !<
1628       INTEGER(iwp) ::  nxrf            !<
1629       INTEGER(iwp) ::  nxr_on_file     !<
1630       INTEGER(iwp) ::  nync            !<
1631       INTEGER(iwp) ::  nynf            !<
1632       INTEGER(iwp) ::  nyn_on_file     !<
1633       INTEGER(iwp) ::  nysc            !<
1634       INTEGER(iwp) ::  nysf            !<
1635       INTEGER(iwp) ::  nys_on_file     !<
1636
1637       LOGICAL, INTENT(OUT)  :: found
1638
1639       REAL(wp), DIMENSION(0:pch_index,                                        &
1640                           nys_on_file-nbgp:nyn_on_file+nbgp,                  &
1641                           nxl_on_file-nbgp:nxr_on_file+nbgp) :: tmp_3d2  !< temporary 3D array for entire vertical
1642                                                                          !< extension of canopy layer
1643       found = .TRUE.
1644
1645       SELECT CASE ( restart_string(1:length) )
1646
1647          CASE ( 'pcm_heatrate_av' )
1648             IF ( .NOT. ALLOCATED( pcm_heatrate_av ) )  THEN
1649                ALLOCATE( pcm_heatrate_av(0:pch_index,nysg:nyng,nxlg:nxrg) )
1650                pcm_heatrate_av = 0.0_wp
1651             ENDIF 
1652             IF ( k == 1 )  READ ( 13 )  tmp_3d2
1653             pcm_heatrate_av(0:pch_index,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
1654                        tmp_3d2(0:pch_index,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
1655
1656          CASE ( 'pcm_latentrate_av' )
1657             IF ( .NOT. ALLOCATED( pcm_latentrate_av ) )  THEN
1658                ALLOCATE( pcm_latentrate_av(0:pch_index,nysg:nyng,nxlg:nxrg) )
1659                pcm_latentrate_av = 0.0_wp
1660             ENDIF 
1661             IF ( k == 1 )  READ ( 13 )  tmp_3d2
1662             pcm_latentrate_av(0:pch_index,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
1663                        tmp_3d2(0:pch_index,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
1664
1665          CASE ( 'pcm_transpirationrate_av' )
1666             IF ( .NOT. ALLOCATED( pcm_transpirationrate_av ) )  THEN
1667                ALLOCATE( pcm_transpirationrate_av(0:pch_index,nysg:nyng,nxlg:nxrg) )
1668                pcm_transpirationrate_av = 0.0_wp
1669             ENDIF 
1670             IF ( k == 1 )  READ ( 13 )  tmp_3d2
1671             pcm_transpirationrate_av(0:pch_index,nysc-nbgp:nync+nbgp,nxlc-nbgp:nxrc+nbgp) = &
1672                        tmp_3d2(0:pch_index,nysf-nbgp:nynf+nbgp,nxlf-nbgp:nxrf+nbgp)
1673
1674          CASE DEFAULT
1675
1676             found = .FALSE.
1677
1678       END SELECT
1679
1680    END SUBROUTINE pcm_rrd_local
1681
1682!------------------------------------------------------------------------------!
1683! Description:
1684! ------------
1685!> Calculation of the tendency terms, accounting for the effect of the plant
1686!> canopy on momentum and scalar quantities.
1687!>
1688!> The canopy is located where the leaf area density lad_s(k,j,i) > 0.0
1689!> (defined on scalar grid), as initialized in subroutine pcm_init.
1690!> The lad on the w-grid is vertically interpolated from the surrounding
1691!> lad_s. The upper boundary of the canopy is defined on the w-grid at
1692!> k = pch_index. Here, the lad is zero.
1693!>
1694!> The canopy drag must be limited (previously accounted for by calculation of
1695!> a limiting canopy timestep for the determination of the maximum LES timestep
1696!> in subroutine timestep), since it is physically impossible that the canopy
1697!> drag alone can locally change the sign of a velocity component. This
1698!> limitation is realized by calculating preliminary tendencies and velocities.
1699!> It is subsequently checked if the preliminary new velocity has a different
1700!> sign than the current velocity. If so, the tendency is limited in a way that
1701!> the velocity can at maximum be reduced to zero by the canopy drag.
1702!>
1703!>
1704!> Call for all grid points
1705!------------------------------------------------------------------------------!
1706    SUBROUTINE pcm_tendency( component )
1707
1708       INTEGER(iwp) ::  component !< prognostic variable (u,v,w,pt,q,e)
1709       INTEGER(iwp) ::  i         !< running index
1710       INTEGER(iwp) ::  j         !< running index
1711       INTEGER(iwp) ::  k         !< running index
1712       INTEGER(iwp) ::  kk        !< running index for flat lad arrays
1713
1714       LOGICAL ::  building_edge_e !< control flag indicating an eastward-facing building edge
1715       LOGICAL ::  building_edge_n !< control flag indicating a north-facing building edge
1716       LOGICAL ::  building_edge_s !< control flag indicating a south-facing building edge
1717       LOGICAL ::  building_edge_w !< control flag indicating a westward-facing building edge
1718
1719       REAL(wp) ::  ddt_3d    !< inverse of the LES timestep (dt_3d)
1720       REAL(wp) ::  lad_local !< local lad value
1721       REAL(wp) ::  pre_tend  !< preliminary tendency
1722       REAL(wp) ::  pre_u     !< preliminary u-value
1723       REAL(wp) ::  pre_v     !< preliminary v-value
1724       REAL(wp) ::  pre_w     !< preliminary w-value
1725
1726
1727       ddt_3d = 1.0_wp / dt_3d
1728 
1729!
1730!--    Compute drag for the three velocity components and the SGS-TKE:
1731       SELECT CASE ( component )
1732
1733!
1734!--       u-component
1735          CASE ( 1 )
1736             DO  i = nxlu, nxr
1737                DO  j = nys, nyn
1738!
1739!--                Set control flags indicating east- and westward-orientated
1740!--                building edges. Note, building_egde_w is set from the perspective
1741!--                of the potential rooftop grid point, while building_edge_e is
1742!--                is set from the perspective of the non-building grid point.
1743                   building_edge_w = ANY( BTEST( wall_flags_total_0(:,j,i),   6 ) )&
1744                        .AND.  .NOT. ANY( BTEST( wall_flags_total_0(:,j,i-1), 6 ) )
1745                   building_edge_e = ANY( BTEST( wall_flags_total_0(:,j,i-1), 6 ) )&
1746                        .AND.  .NOT. ANY( BTEST( wall_flags_total_0(:,j,i),   6 ) )
1747!
1748!--                Determine topography-top index on u-grid
1749                   DO  k = topo_top_ind(j,i,1)+1, topo_top_ind(j,i,1) + pch_index_ji(j,i)
1750
1751                      kk = k - topo_top_ind(j,i,1)   !- lad arrays are defined flat
1752!
1753!--                   In order to create sharp boundaries of the plant canopy,
1754!--                   the lad on the u-grid at index (k,j,i) is equal to lad_s(k,j,i),
1755!--                   rather than being interpolated from the surrounding lad_s,
1756!--                   because this would yield smaller lad at the canopy boundaries
1757!--                   than inside of the canopy.
1758!--                   For the same reason, the lad at the rightmost(i+1)canopy
1759!--                   boundary on the u-grid equals lad_s(k,j,i), which is considered
1760!--                   in the next if-statement. Note, at left-sided building edges
1761!--                   this is not applied, here the LAD is equals the LAD at grid
1762!--                   point (k,j,i), in order to avoid that LAD is mistakenly mapped
1763!--                   on top of a roof where (usually) is no LAD is defined.
1764                      lad_local = lad_s(kk,j,i)
1765                      IF ( lad_local == 0.0_wp .AND. lad_s(kk,j,i-1) > 0.0_wp  &
1766                           .AND.  .NOT. building_edge_w )  lad_local = lad_s(kk,j,i-1)
1767!
1768!--                   In order to avoid that LAD is mistakenly considered at right-
1769!--                   sided building edges (here the topography-top index for the
1770!--                   u-component at index j,i is still on the building while the
1771!--                   topography top for the scalar isn't), LAD is taken from grid
1772!--                   point (j,i-1).
1773                      IF ( lad_local > 0.0_wp .AND. lad_s(kk,j,i-1) == 0.0_wp  &
1774                           .AND.  building_edge_e )  lad_local = lad_s(kk,j,i-1)
1775
1776                      pre_tend = 0.0_wp
1777                      pre_u = 0.0_wp
1778!
1779!--                   Calculate preliminary value (pre_tend) of the tendency
1780                      pre_tend = - canopy_drag_coeff *                         &
1781                                   lad_local *                                 &
1782                                   SQRT( u(k,j,i)**2 +                         &
1783                                         ( 0.25_wp * ( v(k,j,i-1) +            &
1784                                                       v(k,j,i)   +            &
1785                                                       v(k,j+1,i) +            &
1786                                                       v(k,j+1,i-1) )          &
1787                                         )**2 +                                &
1788                                         ( 0.25_wp * ( w(k-1,j,i-1) +          &
1789                                                       w(k-1,j,i)   +          &
1790                                                       w(k,j,i-1)   +          &
1791                                                       w(k,j,i) )              &
1792                                         )**2                                  &
1793                                       ) *                                     &
1794                                   u(k,j,i)
1795
1796!
1797!--                   Calculate preliminary new velocity, based on pre_tend
1798                      pre_u = u(k,j,i) + dt_3d * pre_tend
1799!
1800!--                   Compare sign of old velocity and new preliminary velocity,
1801!--                   and in case the signs are different, limit the tendency
1802                      IF ( SIGN(pre_u,u(k,j,i)) /= pre_u )  THEN
1803                         pre_tend = - u(k,j,i) * ddt_3d
1804                      ENDIF
1805!
1806!--                   Calculate final tendency
1807                      tend(k,j,i) = tend(k,j,i) + pre_tend
1808
1809                   ENDDO
1810                ENDDO
1811             ENDDO
1812
1813!
1814!--       v-component
1815          CASE ( 2 )
1816             DO  i = nxl, nxr
1817                DO  j = nysv, nyn
1818!
1819!--                Set control flags indicating north- and southward-orientated
1820!--                building edges. Note, building_egde_s is set from the perspective
1821!--                of the potential rooftop grid point, while building_edge_n is
1822!--                is set from the perspective of the non-building grid point.
1823                   building_edge_s = ANY( BTEST( wall_flags_total_0(:,j,i),   6 ) )&
1824                        .AND.  .NOT. ANY( BTEST( wall_flags_total_0(:,j-1,i), 6 ) )
1825                   building_edge_n = ANY( BTEST( wall_flags_total_0(:,j-1,i), 6 ) )&
1826                        .AND.  .NOT. ANY( BTEST( wall_flags_total_0(:,j,i),   6 ) )
1827!
1828!--                Determine topography-top index on v-grid
1829                   DO  k = topo_top_ind(j,i,2)+1, topo_top_ind(j,i,2) + pch_index_ji(j,i)
1830
1831                      kk = k - topo_top_ind(j,i,2)   !- lad arrays are defined flat
1832!
1833!--                   In order to create sharp boundaries of the plant canopy,
1834!--                   the lad on the v-grid at index (k,j,i) is equal to lad_s(k,j,i),
1835!--                   rather than being interpolated from the surrounding lad_s,
1836!--                   because this would yield smaller lad at the canopy boundaries
1837!--                   than inside of the canopy.
1838!--                   For the same reason, the lad at the northmost(j+1)canopy
1839!--                   boundary on the v-grid equals lad_s(k,j,i), which is considered
1840!--                   in the next if-statement. Note, at left-sided building edges
1841!--                   this is not applied, here the LAD is equals the LAD at grid
1842!--                   point (k,j,i), in order to avoid that LAD is mistakenly mapped
1843!--                   on top of a roof where (usually) is no LAD is defined.
1844                      lad_local = lad_s(kk,j,i)
1845                      IF ( lad_local == 0.0_wp .AND. lad_s(kk,j-1,i) > 0.0_wp &
1846                       .AND.  .NOT. building_edge_s )  lad_local = lad_s(kk,j-1,i)
1847!
1848!--                   In order to avoid that LAD is mistakenly considered at right-
1849!--                   sided building edges (here the topography-top index for the
1850!--                   u-component at index j,i is still on the building while the
1851!--                   topography top for the scalar isn't), LAD is taken from grid
1852!--                   point (j,i-1).
1853                      IF ( lad_local > 0.0_wp .AND. lad_s(kk,j-1,i) == 0.0_wp  &
1854                       .AND.  building_edge_n )  lad_local = lad_s(kk,j-1,i)
1855
1856                      pre_tend = 0.0_wp
1857                      pre_v = 0.0_wp
1858!
1859!--                   Calculate preliminary value (pre_tend) of the tendency
1860                      pre_tend = - canopy_drag_coeff *                         &
1861                                   lad_local *                                 &
1862                                   SQRT( ( 0.25_wp * ( u(k,j-1,i)   +          &
1863                                                       u(k,j-1,i+1) +          &
1864                                                       u(k,j,i)     +          &
1865                                                       u(k,j,i+1) )            &
1866                                         )**2 +                                &
1867                                         v(k,j,i)**2 +                         &
1868                                         ( 0.25_wp * ( w(k-1,j-1,i) +          &
1869                                                       w(k-1,j,i)   +          &
1870                                                       w(k,j-1,i)   +          &
1871                                                       w(k,j,i) )              &
1872                                         )**2                                  &
1873                                       ) *                                     &
1874                                   v(k,j,i)
1875
1876!
1877!--                   Calculate preliminary new velocity, based on pre_tend
1878                      pre_v = v(k,j,i) + dt_3d * pre_tend
1879!
1880!--                   Compare sign of old velocity and new preliminary velocity,
1881!--                   and in case the signs are different, limit the tendency
1882                      IF ( SIGN(pre_v,v(k,j,i)) /= pre_v )  THEN
1883                         pre_tend = - v(k,j,i) * ddt_3d
1884                      ELSE
1885                         pre_tend = pre_tend
1886                      ENDIF
1887!
1888!--                   Calculate final tendency
1889                      tend(k,j,i) = tend(k,j,i) + pre_tend
1890
1891                   ENDDO
1892                ENDDO
1893             ENDDO
1894
1895!
1896!--       w-component
1897          CASE ( 3 )
1898             DO  i = nxl, nxr
1899                DO  j = nys, nyn
1900!
1901!--                Determine topography-top index on w-grid
1902                   DO  k = topo_top_ind(j,i,3)+1, topo_top_ind(j,i,3) + pch_index_ji(j,i) - 1
1903
1904                      kk = k - topo_top_ind(j,i,3)   !- lad arrays are defined flat
1905
1906                      pre_tend = 0.0_wp
1907                      pre_w = 0.0_wp
1908!
1909!--                   Calculate preliminary value (pre_tend) of the tendency
1910                      pre_tend = - canopy_drag_coeff *                         &
1911                                   (0.5_wp *                                   &
1912                                      ( lad_s(kk+1,j,i) + lad_s(kk,j,i) )) *   &
1913                                   SQRT( ( 0.25_wp * ( u(k,j,i)   +            &
1914                                                       u(k,j,i+1) +            &
1915                                                       u(k+1,j,i) +            &
1916                                                       u(k+1,j,i+1) )          &
1917                                         )**2 +                                &
1918                                         ( 0.25_wp * ( v(k,j,i)   +            &
1919                                                       v(k,j+1,i) +            &
1920                                                       v(k+1,j,i) +            &
1921                                                       v(k+1,j+1,i) )          &
1922                                         )**2 +                                &
1923                                         w(k,j,i)**2                           &
1924                                       ) *                                     &
1925                                   w(k,j,i)
1926!
1927!--                   Calculate preliminary new velocity, based on pre_tend
1928                      pre_w = w(k,j,i) + dt_3d * pre_tend
1929!
1930!--                   Compare sign of old velocity and new preliminary velocity,
1931!--                   and in case the signs are different, limit the tendency
1932                      IF ( SIGN(pre_w,w(k,j,i)) /= pre_w )  THEN
1933                         pre_tend = - w(k,j,i) * ddt_3d
1934                      ELSE
1935                         pre_tend = pre_tend
1936                      ENDIF
1937!
1938!--                   Calculate final tendency
1939                      tend(k,j,i) = tend(k,j,i) + pre_tend
1940
1941                   ENDDO
1942                ENDDO
1943             ENDDO
1944
1945!
1946!--       potential temperature
1947          CASE ( 4 )
1948             IF ( humidity ) THEN
1949                DO  i = nxl, nxr
1950                   DO  j = nys, nyn
1951!--                   Determine topography-top index on scalar-grid
1952                      DO  k = topo_top_ind(j,i,0)+1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
1953                         kk = k - topo_top_ind(j,i,0)   !- lad arrays are defined flat
1954                         tend(k,j,i) = tend(k,j,i) + pcm_heating_rate(kk,j,i) - pcm_latent_rate(kk,j,i)
1955                      ENDDO
1956                   ENDDO
1957                ENDDO
1958             ELSE
1959                DO  i = nxl, nxr
1960                   DO  j = nys, nyn
1961!--                   Determine topography-top index on scalar-grid
1962                      DO  k = topo_top_ind(j,i,0)+1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
1963                         kk = k - topo_top_ind(j,i,0)   !- lad arrays are defined flat
1964                         tend(k,j,i) = tend(k,j,i) + pcm_heating_rate(kk,j,i)
1965                      ENDDO
1966                   ENDDO
1967                ENDDO
1968             ENDIF
1969
1970!
1971!--       humidity
1972          CASE ( 5 )
1973             DO  i = nxl, nxr
1974                DO  j = nys, nyn
1975!
1976!--                Determine topography-top index on scalar-grid
1977                   DO  k = topo_top_ind(j,i,0)+1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
1978
1979                      kk = k - topo_top_ind(j,i,0)   !- lad arrays are defined flat
1980
1981                      IF ( .NOT. plant_canopy_transpiration ) THEN
1982                         ! pcm_transpiration_rate is calculated in radiation model
1983                         ! in case of plant_canopy_transpiration = .T.
1984                         ! to include also the dependecy to the radiation
1985                         ! in the plant canopy box
1986                         pcm_transpiration_rate(kk,j,i) =  - leaf_scalar_exch_coeff &
1987                                          * lad_s(kk,j,i) *                         &
1988                                          SQRT( ( 0.5_wp * ( u(k,j,i) +             &
1989                                                             u(k,j,i+1) )           &
1990                                                )**2 +                              &
1991                                                ( 0.5_wp * ( v(k,j,i) +             &
1992                                                             v(k,j+1,i) )           &
1993                                                )**2 +                              &
1994                                                ( 0.5_wp * ( w(k-1,j,i) +           &
1995                                                             w(k,j,i) )             &
1996                                                )**2                                &
1997                                              ) *                                   &
1998                                          ( q(k,j,i) - leaf_surface_conc )
1999                      ENDIF
2000
2001                      tend(k,j,i) = tend(k,j,i) + pcm_transpiration_rate(kk,j,i)
2002                   ENDDO
2003                ENDDO
2004             ENDDO
2005
2006!
2007!--       sgs-tke
2008          CASE ( 6 )
2009             DO  i = nxl, nxr
2010                DO  j = nys, nyn
2011!
2012!--                Determine topography-top index on scalar-grid
2013                   DO  k = topo_top_ind(j,i,0)+1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
2014
2015                      kk = k - topo_top_ind(j,i,0)   !- lad arrays are defined flat
2016                      tend(k,j,i) = tend(k,j,i) -                              &
2017                                       2.0_wp * canopy_drag_coeff *            &
2018                                       lad_s(kk,j,i) *                         &
2019                                       SQRT( ( 0.5_wp * ( u(k,j,i) +           &
2020                                                          u(k,j,i+1) )         &
2021                                             )**2 +                            &
2022                                             ( 0.5_wp * ( v(k,j,i) +           &
2023                                                          v(k,j+1,i) )         &
2024                                             )**2 +                            &
2025                                             ( 0.5_wp * ( w(k,j,i) +           &
2026                                                          w(k+1,j,i) )         &
2027                                             )**2                              &
2028                                           ) *                                 &
2029                                       e(k,j,i)
2030                   ENDDO
2031                ENDDO
2032             ENDDO 
2033!
2034!--       scalar concentration
2035          CASE ( 7 )
2036             DO  i = nxl, nxr
2037                DO  j = nys, nyn
2038!
2039!--                Determine topography-top index on scalar-grid
2040                   DO  k = topo_top_ind(j,i,0)+1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
2041
2042                      kk = k - topo_top_ind(j,i,0)   !- lad arrays are defined flat
2043                      tend(k,j,i) = tend(k,j,i) -                              &
2044                                       leaf_scalar_exch_coeff *                &
2045                                       lad_s(kk,j,i) *                         &
2046                                       SQRT( ( 0.5_wp * ( u(k,j,i) +           &
2047                                                          u(k,j,i+1) )         &
2048                                             )**2 +                            &
2049                                             ( 0.5_wp * ( v(k,j,i) +           &
2050                                                          v(k,j+1,i) )         &
2051                                             )**2 +                            &
2052                                             ( 0.5_wp * ( w(k-1,j,i) +         & 
2053                                                          w(k,j,i) )           &
2054                                             )**2                              &
2055                                           ) *                                 &
2056                                       ( s(k,j,i) - leaf_surface_conc )
2057                   ENDDO
2058                ENDDO
2059             ENDDO   
2060
2061
2062
2063          CASE DEFAULT
2064
2065             WRITE( message_string, * ) 'wrong component: ', component
2066             CALL message( 'pcm_tendency', 'PA0279', 1, 2, 0, 6, 0 ) 
2067
2068       END SELECT
2069
2070    END SUBROUTINE pcm_tendency
2071
2072
2073!------------------------------------------------------------------------------!
2074! Description:
2075! ------------
2076!> Calculation of the tendency terms, accounting for the effect of the plant
2077!> canopy on momentum and scalar quantities.
2078!>
2079!> The canopy is located where the leaf area density lad_s(k,j,i) > 0.0
2080!> (defined on scalar grid), as initialized in subroutine pcm_init.
2081!> The lad on the w-grid is vertically interpolated from the surrounding
2082!> lad_s. The upper boundary of the canopy is defined on the w-grid at
2083!> k = pch_index. Here, the lad is zero.
2084!>
2085!> The canopy drag must be limited (previously accounted for by calculation of
2086!> a limiting canopy timestep for the determination of the maximum LES timestep
2087!> in subroutine timestep), since it is physically impossible that the canopy
2088!> drag alone can locally change the sign of a velocity component. This
2089!> limitation is realized by calculating preliminary tendencies and velocities.
2090!> It is subsequently checked if the preliminary new velocity has a different
2091!> sign than the current velocity. If so, the tendency is limited in a way that
2092!> the velocity can at maximum be reduced to zero by the canopy drag.
2093!>
2094!>
2095!> Call for grid point i,j
2096!------------------------------------------------------------------------------!
2097    SUBROUTINE pcm_tendency_ij( i, j, component )
2098
2099       INTEGER(iwp) ::  component !< prognostic variable (u,v,w,pt,q,e)
2100       INTEGER(iwp) ::  i         !< running index
2101       INTEGER(iwp) ::  j         !< running index
2102       INTEGER(iwp) ::  k         !< running index
2103       INTEGER(iwp) ::  kk        !< running index for flat lad arrays
2104
2105       LOGICAL ::  building_edge_e !< control flag indicating an eastward-facing building edge
2106       LOGICAL ::  building_edge_n !< control flag indicating a north-facing building edge
2107       LOGICAL ::  building_edge_s !< control flag indicating a south-facing building edge
2108       LOGICAL ::  building_edge_w !< control flag indicating a westward-facing building edge
2109
2110       REAL(wp) ::  ddt_3d    !< inverse of the LES timestep (dt_3d)
2111       REAL(wp) ::  lad_local !< local lad value
2112       REAL(wp) ::  pre_tend  !< preliminary tendency
2113       REAL(wp) ::  pre_u     !< preliminary u-value
2114       REAL(wp) ::  pre_v     !< preliminary v-value
2115       REAL(wp) ::  pre_w     !< preliminary w-value
2116
2117
2118       ddt_3d = 1.0_wp / dt_3d
2119!
2120!--    Compute drag for the three velocity components and the SGS-TKE
2121       SELECT CASE ( component )
2122
2123!
2124!--       u-component
2125          CASE ( 1 )
2126!
2127!--          Set control flags indicating east- and westward-orientated
2128!--          building edges. Note, building_egde_w is set from the perspective
2129!--          of the potential rooftop grid point, while building_edge_e is
2130!--          is set from the perspective of the non-building grid point.
2131             building_edge_w = ANY( BTEST( wall_flags_total_0(:,j,i),   6 ) )  .AND. &
2132                         .NOT. ANY( BTEST( wall_flags_total_0(:,j,i-1), 6 ) )
2133             building_edge_e = ANY( BTEST( wall_flags_total_0(:,j,i-1), 6 ) )  .AND. &
2134                         .NOT. ANY( BTEST( wall_flags_total_0(:,j,i),   6 ) )
2135!
2136!--          Determine topography-top index on u-grid
2137             DO  k = topo_top_ind(j,i,1) + 1, topo_top_ind(j,i,1) + pch_index_ji(j,i)
2138
2139                kk = k - topo_top_ind(j,i,1)  !- lad arrays are defined flat
2140
2141!
2142!--             In order to create sharp boundaries of the plant canopy,
2143!--             the lad on the u-grid at index (k,j,i) is equal to lad_s(k,j,i),
2144!--             rather than being interpolated from the surrounding lad_s,
2145!--             because this would yield smaller lad at the canopy boundaries
2146!--             than inside of the canopy.
2147!--             For the same reason, the lad at the rightmost(i+1)canopy
2148!--             boundary on the u-grid equals lad_s(k,j,i), which is considered
2149!--             in the next if-statement. Note, at left-sided building edges
2150!--             this is not applied, here the LAD is equals the LAD at grid
2151!--             point (k,j,i), in order to avoid that LAD is mistakenly mapped
2152!--             on top of a roof where (usually) is no LAD is defined.
2153                lad_local = lad_s(kk,j,i)
2154                IF ( lad_local == 0.0_wp .AND. lad_s(kk,j,i-1) > 0.0_wp  .AND. &
2155                     .NOT. building_edge_w )  lad_local = lad_s(kk,j,i-1)
2156!
2157!--             In order to avoid that LAD is mistakenly considered at right-
2158!--             sided building edges (here the topography-top index for the
2159!--             u-component at index j,i is still on the building while the
2160!--             topography top for the scalar isn't), LAD is taken from grid
2161!--             point (j,i-1).
2162                IF ( lad_local > 0.0_wp .AND. lad_s(kk,j,i-1) == 0.0_wp  .AND. &
2163                     building_edge_e )  lad_local = lad_s(kk,j,i-1)
2164
2165                pre_tend = 0.0_wp
2166                pre_u = 0.0_wp
2167!
2168!--             Calculate preliminary value (pre_tend) of the tendency
2169                pre_tend = - canopy_drag_coeff *                               &
2170                             lad_local *                                       &   
2171                             SQRT( u(k,j,i)**2 +                               &
2172                                   ( 0.25_wp * ( v(k,j,i-1)  +                 &
2173                                                 v(k,j,i)    +                 &
2174                                                 v(k,j+1,i)  +                 &
2175                                                 v(k,j+1,i-1) )                &
2176                                   )**2 +                                      &
2177                                   ( 0.25_wp * ( w(k-1,j,i-1) +                &
2178                                                 w(k-1,j,i)   +                &
2179                                                 w(k,j,i-1)   +                &
2180                                                 w(k,j,i) )                    &
2181                                   )**2                                        &
2182                                 ) *                                           &
2183                             u(k,j,i)
2184
2185!
2186!--             Calculate preliminary new velocity, based on pre_tend
2187                pre_u = u(k,j,i) + dt_3d * pre_tend
2188!
2189!--             Compare sign of old velocity and new preliminary velocity,
2190!--             and in case the signs are different, limit the tendency
2191                IF ( SIGN(pre_u,u(k,j,i)) /= pre_u )  THEN
2192                   pre_tend = - u(k,j,i) * ddt_3d
2193                ELSE
2194                   pre_tend = pre_tend
2195                ENDIF
2196!
2197!--             Calculate final tendency
2198                tend(k,j,i) = tend(k,j,i) + pre_tend
2199             ENDDO
2200
2201
2202!
2203!--       v-component
2204          CASE ( 2 )
2205!
2206!--          Set control flags indicating north- and southward-orientated
2207!--          building edges. Note, building_egde_s is set from the perspective
2208!--          of the potential rooftop grid point, while building_edge_n is
2209!--          is set from the perspective of the non-building grid point.
2210             building_edge_s = ANY( BTEST( wall_flags_total_0(:,j,i),   6 ) )  .AND. &
2211                         .NOT. ANY( BTEST( wall_flags_total_0(:,j-1,i), 6 ) )
2212             building_edge_n = ANY( BTEST( wall_flags_total_0(:,j-1,i), 6 ) )  .AND. &
2213                         .NOT. ANY( BTEST( wall_flags_total_0(:,j,i),   6 ) )
2214!
2215!--          Determine topography-top index on v-grid
2216             DO  k = topo_top_ind(j,i,2) + 1, topo_top_ind(j,i,2) + pch_index_ji(j,i)
2217
2218                kk = k - topo_top_ind(j,i,2)  !- lad arrays are defined flat
2219!
2220!--             In order to create sharp boundaries of the plant canopy,
2221!--             the lad on the v-grid at index (k,j,i) is equal to lad_s(k,j,i),
2222!--             rather than being interpolated from the surrounding lad_s,
2223!--             because this would yield smaller lad at the canopy boundaries
2224!--             than inside of the canopy.
2225!--             For the same reason, the lad at the northmost(j+1)canopy
2226!--             boundary on the v-grid equals lad_s(k,j,i), which is considered
2227!--             in the next if-statement. Note, at left-sided building edges
2228!--             this is not applied, here the LAD is equals the LAD at grid
2229!--             point (k,j,i), in order to avoid that LAD is mistakenly mapped
2230!--             on top of a roof where (usually) is no LAD is defined.
2231                lad_local = lad_s(kk,j,i)
2232                IF ( lad_local == 0.0_wp .AND. lad_s(kk,j-1,i) > 0.0_wp  .AND. &
2233                     .NOT. building_edge_s )  lad_local = lad_s(kk,j-1,i)
2234!
2235!--             In order to avoid that LAD is mistakenly considered at right-
2236!--             sided building edges (here the topography-top index for the
2237!--             u-component at index j,i is still on the building while the
2238!--             topography top for the scalar isn't), LAD is taken from grid
2239!--             point (j,i-1).
2240                IF ( lad_local > 0.0_wp .AND. lad_s(kk,j-1,i) == 0.0_wp  .AND. &
2241                     building_edge_n )  lad_local = lad_s(kk,j-1,i)
2242
2243                pre_tend = 0.0_wp
2244                pre_v = 0.0_wp
2245!
2246!--             Calculate preliminary value (pre_tend) of the tendency
2247                pre_tend = - canopy_drag_coeff *                               &
2248                             lad_local *                                       &
2249                             SQRT( ( 0.25_wp * ( u(k,j-1,i)   +                &
2250                                                 u(k,j-1,i+1) +                &
2251                                                 u(k,j,i)     +                &
2252                                                 u(k,j,i+1) )                  &
2253                                   )**2 +                                      &
2254                                   v(k,j,i)**2 +                               &
2255                                   ( 0.25_wp * ( w(k-1,j-1,i) +                &
2256                                                 w(k-1,j,i)   +                &
2257                                                 w(k,j-1,i)   +                &
2258                                                 w(k,j,i) )                    &
2259                                   )**2                                        &
2260                                 ) *                                           &
2261                             v(k,j,i)
2262
2263!
2264!--             Calculate preliminary new velocity, based on pre_tend
2265                pre_v = v(k,j,i) + dt_3d * pre_tend
2266!
2267!--             Compare sign of old velocity and new preliminary velocity,
2268!--             and in case the signs are different, limit the tendency
2269                IF ( SIGN(pre_v,v(k,j,i)) /= pre_v )  THEN
2270                   pre_tend = - v(k,j,i) * ddt_3d
2271                ELSE
2272                   pre_tend = pre_tend
2273                ENDIF
2274!
2275!--             Calculate final tendency
2276                tend(k,j,i) = tend(k,j,i) + pre_tend
2277             ENDDO
2278
2279
2280!
2281!--       w-component
2282          CASE ( 3 )
2283!
2284!--          Determine topography-top index on w-grid
2285             DO  k = topo_top_ind(j,i,3) + 1, topo_top_ind(j,i,3) + pch_index_ji(j,i) - 1
2286
2287                kk = k - topo_top_ind(j,i,3)  !- lad arrays are defined flat
2288
2289                pre_tend = 0.0_wp
2290                pre_w = 0.0_wp
2291!
2292!--             Calculate preliminary value (pre_tend) of the tendency
2293                pre_tend = - canopy_drag_coeff *                               &
2294                             (0.5_wp *                                         &
2295                                ( lad_s(kk+1,j,i) + lad_s(kk,j,i) )) *         &
2296                             SQRT( ( 0.25_wp * ( u(k,j,i)    +                 & 
2297                                                 u(k,j,i+1)  +                 &
2298                                                 u(k+1,j,i)  +                 &
2299                                                 u(k+1,j,i+1) )                &
2300                                   )**2 +                                      &
2301                                   ( 0.25_wp * ( v(k,j,i)    +                 &
2302                                                 v(k,j+1,i)  +                 &
2303                                                 v(k+1,j,i)  +                 &
2304                                                 v(k+1,j+1,i) )                &
2305                                   )**2 +                                      &
2306                                   w(k,j,i)**2                                 &
2307                                 ) *                                           &
2308                             w(k,j,i)
2309!
2310!--             Calculate preliminary new velocity, based on pre_tend
2311                pre_w = w(k,j,i) + dt_3d * pre_tend
2312!
2313!--             Compare sign of old velocity and new preliminary velocity,
2314!--             and in case the signs are different, limit the tendency
2315                IF ( SIGN(pre_w,w(k,j,i)) /= pre_w )  THEN
2316                   pre_tend = - w(k,j,i) * ddt_3d
2317                ELSE
2318                   pre_tend = pre_tend
2319                ENDIF
2320!
2321!--             Calculate final tendency
2322                tend(k,j,i) = tend(k,j,i) + pre_tend
2323             ENDDO
2324
2325!
2326!--       potential temperature
2327          CASE ( 4 )
2328!
2329!--          Determine topography-top index on scalar grid
2330             IF ( humidity ) THEN
2331                DO  k = topo_top_ind(j,i,0) + 1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
2332                   kk = k - topo_top_ind(j,i,0)  !- lad arrays are defined flat
2333                   tend(k,j,i) = tend(k,j,i) + pcm_heating_rate(kk,j,i) -       &
2334                                 pcm_latent_rate(kk,j,i)
2335                ENDDO
2336             ELSE
2337                DO  k = topo_top_ind(j,i,0) + 1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
2338                   kk = k - topo_top_ind(j,i,0)  !- lad arrays are defined flat
2339                   tend(k,j,i) = tend(k,j,i) + pcm_heating_rate(kk,j,i)
2340                ENDDO
2341             ENDIF
2342
2343!
2344!--       humidity
2345          CASE ( 5 )
2346!
2347!--          Determine topography-top index on scalar grid
2348             DO  k = topo_top_ind(j,i,0) + 1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
2349                kk = k - topo_top_ind(j,i,0)  !- lad arrays are defined flat
2350                IF ( .NOT. plant_canopy_transpiration ) THEN
2351                   ! pcm_transpiration_rate is calculated in radiation model
2352                   ! in case of plant_canopy_transpiration = .T.
2353                   ! to include also the dependecy to the radiation
2354                   ! in the plant canopy box
2355                   pcm_transpiration_rate(kk,j,i) = - leaf_scalar_exch_coeff   &
2356                                    * lad_s(kk,j,i) *                          &
2357                                    SQRT( ( 0.5_wp * ( u(k,j,i) +              &
2358                                                       u(k,j,i+1) )            &
2359                                          )**2  +                              &
2360                                          ( 0.5_wp * ( v(k,j,i) +              &
2361                                                       v(k,j+1,i) )            &
2362                                          )**2 +                               &
2363                                          ( 0.5_wp * ( w(k-1,j,i) +            &
2364                                                       w(k,j,i) )              &
2365                                          )**2                                 &
2366                                        ) *                                    &
2367                                    ( q(k,j,i) - leaf_surface_conc )
2368                ENDIF
2369
2370                tend(k,j,i) = tend(k,j,i) + pcm_transpiration_rate(kk,j,i)
2371
2372             ENDDO   
2373
2374!
2375!--       sgs-tke
2376          CASE ( 6 )
2377!
2378!--          Determine topography-top index on scalar grid
2379             DO  k = topo_top_ind(j,i,0) + 1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
2380
2381                kk = k - topo_top_ind(j,i,0)
2382                tend(k,j,i) = tend(k,j,i) -                                    &
2383                                 2.0_wp * canopy_drag_coeff *                  &
2384                                 lad_s(kk,j,i) *                               &
2385                                 SQRT( ( 0.5_wp * ( u(k,j,i) +                 &
2386                                                    u(k,j,i+1) )               &
2387                                       )**2 +                                  & 
2388                                       ( 0.5_wp * ( v(k,j,i) +                 &
2389                                                    v(k,j+1,i) )               &
2390                                       )**2 +                                  &
2391                                       ( 0.5_wp * ( w(k,j,i) +                 &
2392                                                    w(k+1,j,i) )               &
2393                                       )**2                                    &
2394                                     ) *                                       &
2395                                 e(k,j,i)
2396             ENDDO
2397             
2398!
2399!--       scalar concentration
2400          CASE ( 7 )
2401!
2402!--          Determine topography-top index on scalar grid
2403             DO  k = topo_top_ind(j,i,0) + 1, topo_top_ind(j,i,0) + pch_index_ji(j,i)
2404
2405                kk = k - topo_top_ind(j,i,0)
2406                tend(k,j,i) = tend(k,j,i) -                                    &
2407                                 leaf_scalar_exch_coeff *                      &
2408                                 lad_s(kk,j,i) *                               &
2409                                 SQRT( ( 0.5_wp * ( u(k,j,i) +                 &
2410                                                    u(k,j,i+1) )               &
2411                                       )**2  +                                 &
2412                                       ( 0.5_wp * ( v(k,j,i) +                 &
2413                                                    v(k,j+1,i) )               &
2414                                       )**2 +                                  &
2415                                       ( 0.5_wp * ( w(k-1,j,i) +               &
2416                                                    w(k,j,i) )                 &
2417                                       )**2                                    &
2418                                     ) *                                       &
2419                                 ( s(k,j,i) - leaf_surface_conc )
2420             ENDDO               
2421
2422       CASE DEFAULT
2423
2424          WRITE( message_string, * ) 'wrong component: ', component
2425          CALL message( 'pcm_tendency', 'PA0279', 1, 2, 0, 6, 0 ) 
2426
2427       END SELECT
2428
2429    END SUBROUTINE pcm_tendency_ij
2430
2431!------------------------------------------------------------------------------!
2432! Description:
2433! ------------
2434!> Subroutine writes local (subdomain) restart data
2435!------------------------------------------------------------------------------!
2436    SUBROUTINE pcm_wrd_local
2437
2438       IF ( ALLOCATED( pcm_heatrate_av ) )  THEN
2439          CALL wrd_write_string( 'pcm_heatrate_av' )
2440          WRITE ( 14 )  pcm_heatrate_av
2441       ENDIF
2442
2443       IF ( ALLOCATED( pcm_latentrate_av ) )  THEN
2444          CALL wrd_write_string( 'pcm_latentrate_av' )
2445          WRITE ( 14 )  pcm_latentrate_av
2446       ENDIF
2447
2448       IF ( ALLOCATED( pcm_transpirationrate_av ) )  THEN
2449          CALL wrd_write_string( 'pcm_transpirationrate_av' )
2450          WRITE ( 14 )  pcm_transpirationrate_av
2451       ENDIF
2452
2453    END SUBROUTINE pcm_wrd_local
2454
2455
2456 END MODULE plant_canopy_model_mod
Note: See TracBrowser for help on using the repository browser.