source: palm/trunk/SOURCE/synthetic_turbulence_generator_mod.f90 @ 4442

Last change on this file since 4442 was 4442, checked in by suehring, 4 years ago

last commit documented

  • Property svn:keywords set to Id
File size: 108.6 KB
RevLine 
[2259]1!> @synthetic_turbulence_generator_mod.f90
2!------------------------------------------------------------------------------!
[2696]3! This file is part of the PALM model system.
[2259]4!
[2696]5! PALM is free software: you can redistribute it and/or modify it under the
[2259]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!
[2696]10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
[2259]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!
[3885]17! Copyright 2017-2019 Leibniz Universitaet Hannover
[2259]18!------------------------------------------------------------------------------!
19!
20! Current revisions:
21! -----------------
22!
[4442]23!
[2259]24! Former revisions:
25! -----------------
26! $Id: synthetic_turbulence_generator_mod.f90 4442 2020-03-04 19:21:13Z suehring $
[4442]27! Set back turbulent length scale to 8 x grid spacing in the parametrized mode
28! (was accidantly changed).
29!
30! 4441 2020-03-04 19:20:35Z suehring
[4440]31! Correct misplaced preprocessor directive
32!
33! 4438 2020-03-03 20:49:28Z suehring
[4438]34! Performance optimizations in velocity-seed calculation:
35!  - random number array is only defined and computed locally (except for
36!    normalization to zero mean and unit variance)
37!  - parallel random number generator is applied independent on the 2D random
38!    numbers in other routines
39!  - option to decide wheter velocity seeds are computed locally without any
40!    further communication or are computed by all processes along the
41!    communicator
42!
43! 4346 2019-12-18 11:55:56Z motisi
[4346]44! Introduction of wall_flags_total_0, which currently sets bits based on static
45! topography information used in wall_flags_static_0
46!
47! 4335 2019-12-12 16:39:05Z suehring
[4335]48! Commentation of last commit
49!
50! 4332 2019-12-10 19:44:12Z suehring
[4332]51! Limit initial velocity seeds in restart runs, if not the seed calculation
52! may become unstable. Further, minor bugfix in initial velocity seed
53! calculation.
54!
55! 4329 2019-12-10 15:46:36Z motisi
[4329]56! Renamed wall_flags_0 to wall_flags_static_0
57!
58! 4309 2019-11-26 18:49:59Z suehring
[4309]59! Computation of velocity seeds optimized. This implies that random numbers
60! are computed now using the parallel random number generator. Random numbers
61! are now only computed and normalized locally, while distributed over all 
62! mpi ranks afterwards, instead of computing random numbers on a global array.
63! Further, the number of calls for the time-consuming velocity-seed generation
64! is reduced - now the left and right, as well as the north and south boundary
65! share the same velocity-seed matrices.
66!
67! 4182 2019-08-22 15:20:23Z scharf
[4182]68! Corrected "Former revisions" section
69!
70! 4148 2019-08-08 11:26:00Z suehring
[4148]71! Remove unused variable
72!
73! 4144 2019-08-06 09:11:47Z raasch
[4144]74! relational operators .EQ., .NE., etc. replaced by ==, /=, etc.
75!
76! 4071 2019-07-03 20:02:00Z suehring
[4071]77! Bugfix, initialize mean_inflow_profiles in case turbulence and inflow
78! information is not read from file.
79!
80! 4022 2019-06-12 11:52:39Z suehring
[4022]81! Several bugfixes and improvements
82! - revise bias correction of the imposed perturbations (correction via volume
83!   flow can create instabilities in case the mean volume flow is close to zero)
84! - introduce lower limits in calculation of coefficient matrix, else the
85!   calculation may become numerically unstable
86! - impose perturbations every timestep, even though no new set of perturbations
87!   is generated in case dt_stg_call /= dt_3d
88! - Implement a gradual decrease of Reynolds stress and length scales above
89!   ABL height (within 1 length scale above ABL depth to 1/10) rather than a
90!   discontinuous decrease
91! - Bugfix in non-nested case: use ABL height for parametrized turbulence
92!
93! 3987 2019-05-22 09:52:13Z kanani
[3987]94! Introduce alternative switch for debug output during timestepping
95!
96! 3938 2019-04-29 16:06:25Z suehring
[3938]97! Remove unused variables
98!
99! 3937 2019-04-29 15:09:07Z suehring
[3937]100! Minor bugfix in case of a very early restart where mc_factor is sill not
101! present.
102! Some modification and fixing of potential bugs in the calculation of scaling
103! parameters used for synthetic turbulence parametrization.
104!
105! 3909 2019-04-17 09:13:25Z suehring
[3909]106! Minor bugfix for last commit
107!
108! 3900 2019-04-16 15:17:43Z suehring
[3900]109! Missing re-calculation of perturbation seeds in case of restarts
110!
111! 3891 2019-04-12 17:52:01Z suehring
[3891]112! Bugfix in initialization in case of restart runs.
113!
114! 3885 2019-04-11 11:29:34Z kanani
[3885]115! Changes related to global restructuring of location messages and introduction
116! of additional debug messages
117!
118!
[3775]119! removed unused variables
120!
121! 3719 2019-02-06 13:10:18Z kanani
[3719]122! Removed log_point measurement from stg_init, since this part is counted to
123! log_point(2) 'initialisation' already. Moved other log_points to calls of
124! the subroutines in time_integration for better overview.
125!
[4182]126! 2259 2017-06-08 09:09:11Z gronemeier
127! Initial revision
[3044]128!
[4182]129! Authors:
130! --------
131! @author Tobias Gronemeier, Matthias Suehring, Atsushi Inagaki, Micha Gryschka, Christoph Knigge
132!
133!
[2259]134! Description:
135! ------------
136!> The module generates turbulence at the inflow boundary based on a method by
137!> Xie and Castro (2008) utilizing a Lund rotation (Lund, 1998) and a mass-flux
138!> correction by Kim et al. (2013).
139!> The turbulence is correlated based on length scales in y- and z-direction and
140!> a time scale for each velocity component. The profiles of length and time
141!> scales, mean u, v, w, e and pt, and all components of the Reynolds stress
[3347]142!> tensor can be either read from file STG_PROFILES, or will be parametrized
143!> within the boundary layer.
[2259]144!>
145!> @todo test restart
146!>       enable cyclic_fill
147!>       implement turbulence generation for e and pt
[2945]148!> @todo Input of height-constant length scales via namelist
[2259]149!> @note <Enter notes on the module>
150!> @bug  Height information from input file is not used. Profiles from input
151!>       must match with current PALM grid.
152!>       In case of restart, velocity seeds differ from precursor run if a11,
153!>       a22, or a33 are zero.
154!------------------------------------------------------------------------------!
155 MODULE synthetic_turbulence_generator_mod
156
157
158    USE arrays_3d,                                                             &
[4022]159        ONLY:  dzw,                                                            &
160               ddzw,                                                           &
161               drho_air,                                                       &
162               mean_inflow_profiles,                                           &
163               q,                                                              &
[4071]164               q_init,                                                         &
165               pt,                                                             &
166               pt_init,                                                        &
[4022]167               u,                                                              &
168               u_init,                                                         &
169               v,                                                              &
170               v_init,                                                         &
171               w,                                                              & 
172               zu,                                                             &
173               zw
[2259]174
[3274]175    USE basic_constants_and_equations_mod,                                     &
[4022]176        ONLY:  g,                                                              &
177               kappa,                                                          &
178               pi
[2259]179
180    USE control_parameters,                                                    &
[4022]181        ONLY:  bc_lr,                                                          &
182               bc_ns,                                                          &
183               child_domain,                                                   &
184               coupling_char,                                                  &
185               debug_output_timestep,                                          &
186               dt_3d,                                                          &
187               e_init,                                                         &
[4071]188               humidity,                                                       &
[3885]189               initializing_actions,                                           &
[4022]190               intermediate_timestep_count,                                    &
191               intermediate_timestep_count_max,                                &
192               length,                                                         &
[3885]193               message_string,                                                 &
[4022]194               nesting_offline,                                                &
[4071]195               neutral,                                                        &
[3885]196               num_mean_inflow_profiles,                                       &
[4309]197               random_generator,                                               &
[4022]198               rans_mode,                                                      &
199               restart_string,                                                 &
200               syn_turb_gen,                                                   &
201               time_since_reference_point,                                     &
202               turbulent_inflow
[4438]203
204    USE cpulog,                                                                &
205        ONLY:  cpu_log,                                                        &
206               log_point_s
207
[4022]208    USE grid_variables,                                                        &
209        ONLY:  ddx,                                                            &
210               ddy,                                                            & 
211               dx,                                                             &
212               dy
[2259]213
214    USE indices,                                                               &
[4022]215        ONLY:  nbgp,                                                           & 
216               nz,                                                             & 
217               nzb,                                                            &
218               nzt,                                                            &
219               nx,                                                             & 
220               nxl,                                                            & 
221               nxlu,                                                           &
222               nxr,                                                            & 
223               ny,                                                             &
224               nys,                                                            &
225               nysv,                                                           &
226               nyn,                                                            &
[4346]227               wall_flags_total_0
[2259]228
229    USE kinds
230
[2967]231#if defined( __parallel )  &&  !defined( __mpifh )
[2259]232    USE MPI
[2841]233#endif
[2259]234
[3347]235    USE nesting_offl_mod,                                                      &
[4022]236        ONLY:  nesting_offl_calc_zi,                                           &
237               zi_ribulk
[3347]238
[2259]239    USE pegrid,                                                                &
[4022]240        ONLY:  comm1dx,                                                        &
241               comm1dy,                                                        &
242               comm2d,                                                         &
243               ierr,                                                           &
244               myidx,                                                          &
245               myidy,                                                          &
246               pdims
[4438]247
[4022]248    USE pmc_interface,                                                         &
249        ONLY : rans_mode_parent
[4438]250
251    USE random_generator_parallel,                                             &
252        ONLY:  init_parallel_random_generator,                                 &
253               random_dummy,                                                   &
[4309]254               random_number_parallel,                                         &
[4438]255               random_seed_parallel
[2259]256
257    USE transpose_indices,                                                     &
[4022]258        ONLY: nzb_x,                                                           &
259              nzt_x
[2259]260
[4438]261    USE surface_mod,                                                           &
262        ONLY:  surf_def_h,                                                     &
263               surf_lsm_h,                                                     &
264               surf_usm_h
[2259]265
266    IMPLICIT NONE
267
[2967]268#if defined( __parallel )  &&  defined( __mpifh )
[2841]269    INCLUDE "mpif.h"
270#endif
271
[3182]272
[3347]273    LOGICAL ::  velocity_seed_initialized = .FALSE.     !< true after first call of stg_main
274    LOGICAL ::  parametrize_inflow_turbulence = .FALSE. !< flag indicating that inflow turbulence is either read from file (.FALSE.) or if it parametrized
275    LOGICAL ::  use_syn_turb_gen = .FALSE.              !< switch to use synthetic turbulence generator
[4438]276    LOGICAL ::  compute_velocity_seeds_local = .TRUE.   !< switch to decide whether velocity seeds are computed locally or if computation
277                                                        !< is distributed over several processes
[2259]278
[3038]279    INTEGER(iwp) ::  id_stg_left        !< left lateral boundary core id in case of turbulence generator
280    INTEGER(iwp) ::  id_stg_north       !< north lateral boundary core id in case of turbulence generator
281    INTEGER(iwp) ::  id_stg_right       !< right lateral boundary core id in case of turbulence generator
282    INTEGER(iwp) ::  id_stg_south       !< south lateral boundary core id in case of turbulence generator
[4438]283    INTEGER(iwp) ::  mergp              !< maximum length scale (in gp)
[3038]284    INTEGER(iwp) ::  nzb_x_stg          !< lower bound of z coordinate (required for transposing z on PEs along x)
285    INTEGER(iwp) ::  nzt_x_stg          !< upper bound of z coordinate (required for transposing z on PEs along x)
286    INTEGER(iwp) ::  nzb_y_stg          !< lower bound of z coordinate (required for transposing z on PEs along y)
287    INTEGER(iwp) ::  nzt_y_stg          !< upper bound of z coordinate (required for transposing z on PEs along y)
[4309]288    INTEGER(iwp) ::  stg_type_xz        !< MPI type for full z range
289    INTEGER(iwp) ::  stg_type_xz_small  !< MPI type for small z range
290    INTEGER(iwp) ::  stg_type_yz        !< MPI type for full z range
291    INTEGER(iwp) ::  stg_type_yz_small  !< MPI type for small z range
[2259]292
[4022]293    INTEGER(iwp), DIMENSION(3) ::  nr_non_topo_xz = 0 !< number of non-topography grid points at xz cross-sections,
294                                                      !< required for bias correction of imposed perturbations
295    INTEGER(iwp), DIMENSION(3) ::  nr_non_topo_yz = 0 !< number of non-topography grid points at yz cross-sections,
296                                                      !< required for bias correction of imposed perturbations
297   
[3347]298    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  displs_xz      !< displacement for MPI_GATHERV
299    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  recv_count_xz  !< receive count for MPI_GATHERV
300    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  displs_yz      !< displacement for MPI_GATHERV
301    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  recv_count_yz  !< receive count for MPI_GATHERV
302    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nux            !< length scale of u in x direction (in gp)
303    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nuy            !< length scale of u in y direction (in gp)
304    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nuz            !< length scale of u in z direction (in gp)
305    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nvx            !< length scale of v in x direction (in gp)
306    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nvy            !< length scale of v in y direction (in gp)
307    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nvz            !< length scale of v in z direction (in gp)
308    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nwx            !< length scale of w in x direction (in gp)
309    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nwy            !< length scale of w in y direction (in gp)
310    INTEGER(iwp), DIMENSION(:), ALLOCATABLE ::  nwz            !< length scale of w in z direction (in gp)
[2259]311
[4438]312    INTEGER(isp), DIMENSION(:), ALLOCATABLE   ::  id_rand_xz     !< initial random IDs at xz inflow boundary
313    INTEGER(isp), DIMENSION(:), ALLOCATABLE   ::  id_rand_yz     !< initial random IDs at yz inflow boundary
314    INTEGER(isp), DIMENSION(:,:), ALLOCATABLE ::  seq_rand_xz    !< initial random seeds at xz inflow boundary
315    INTEGER(isp), DIMENSION(:,:), ALLOCATABLE ::  seq_rand_yz    !< initial random seeds at yz inflow boundary
316
[4022]317    REAL(wp) ::  blend                    !< value to create gradually and smooth blending of Reynolds stress and length
318                                          !< scales above the boundary layer
319    REAL(wp) ::  blend_coeff = -2.3_wp    !< coefficient used to ensure that blending functions decreases to 1/10 after
320                                          !< one length scale above ABL top
321    REAL(wp) ::  d_l                      !< blend_coeff/length_scale
322    REAL(wp) ::  length_scale             !< length scale, default is 8 x minimum grid spacing
[3347]323    REAL(wp) ::  dt_stg_adjust = 300.0_wp !< time interval for adjusting turbulence statistics
[4438]324    REAL(wp) ::  dt_stg_call = 0.0_wp     !< time interval for calling synthetic turbulence generator
[3347]325    REAL(wp) ::  scale_l                  !< scaling parameter used for turbulence parametrization - Obukhov length
326    REAL(wp) ::  scale_us                 !< scaling parameter used for turbulence parametrization - friction velocity
327    REAL(wp) ::  scale_wm                 !< scaling parameter used for turbulence parametrization - momentum scale 
328    REAL(wp) ::  time_stg_adjust = 0.0_wp !< time counter for adjusting turbulence information   
329    REAL(wp) ::  time_stg_call = 0.0_wp   !< time counter for calling generator   
330   
[4022]331    REAL(wp), DIMENSION(3) ::  mc_factor = 1.0_wp !< correction factor for the u,v,w-components to maintain original mass flux
[3347]332   
[4022]333   
[3347]334    REAL(wp),DIMENSION(:), ALLOCATABLE ::  r11              !< Reynolds parameter
335    REAL(wp),DIMENSION(:), ALLOCATABLE ::  r21              !< Reynolds parameter
336    REAL(wp),DIMENSION(:), ALLOCATABLE ::  r22              !< Reynolds parameter
337    REAL(wp),DIMENSION(:), ALLOCATABLE ::  r31              !< Reynolds parameter
338    REAL(wp),DIMENSION(:), ALLOCATABLE ::  r32              !< Reynolds parameter
339    REAL(wp),DIMENSION(:), ALLOCATABLE ::  r33              !< Reynolds parameter
340   
341    REAL(wp), DIMENSION(:), ALLOCATABLE ::  a11             !< coefficient for Lund rotation
342    REAL(wp), DIMENSION(:), ALLOCATABLE ::  a21             !< coefficient for Lund rotation
343    REAL(wp), DIMENSION(:), ALLOCATABLE ::  a22             !< coefficient for Lund rotation
344    REAL(wp), DIMENSION(:), ALLOCATABLE ::  a31             !< coefficient for Lund rotation
345    REAL(wp), DIMENSION(:), ALLOCATABLE ::  a32             !< coefficient for Lund rotation
346    REAL(wp), DIMENSION(:), ALLOCATABLE ::  a33             !< coefficient for Lund rotation
347    REAL(wp), DIMENSION(:), ALLOCATABLE ::  tu              !< Lagrangian time scale of u
348    REAL(wp), DIMENSION(:), ALLOCATABLE ::  tv              !< Lagrangian time scale of v
349    REAL(wp), DIMENSION(:), ALLOCATABLE ::  tw              !< Lagrangian time scale of w
[2259]350
[3347]351    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  bux           !< filter function for u in x direction
352    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  buy           !< filter function for u in y direction
353    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  buz           !< filter function for u in z direction
354    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  bvx           !< filter function for v in x direction
355    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  bvy           !< filter function for v in y direction
356    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  bvz           !< filter function for v in z direction
357    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  bwx           !< filter function for w in y direction
358    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  bwy           !< filter function for w in y direction
359    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  bwz           !< filter function for w in z direction
360    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fu_xz         !< velocity seed for u at xz plane
361    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fuo_xz        !< velocity seed for u at xz plane with new random number
362    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fu_yz         !< velocity seed for u at yz plane
363    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fuo_yz        !< velocity seed for u at yz plane with new random number
364    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fv_xz         !< velocity seed for v at xz plane
365    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fvo_xz        !< velocity seed for v at xz plane with new random number
366    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fv_yz         !< velocity seed for v at yz plane
367    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fvo_yz        !< velocity seed for v at yz plane with new random number
368    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fw_xz         !< velocity seed for w at xz plane
369    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fwo_xz        !< velocity seed for w at xz plane with new random number
370    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fw_yz         !< velocity seed for w at yz plane
371    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  fwo_yz        !< velocity seed for w at yz plane with new random number
372   
373    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  dist_xz     !< imposed disturbances at north/south boundary
374    REAL(wp), DIMENSION(:,:,:), ALLOCATABLE ::  dist_yz     !< imposed disturbances at north/south boundary
[2259]375
376!
377!-- PALM interfaces:
[3347]378!-- Adjust time and lenght scales, Reynolds stress, and filter functions
379    INTERFACE stg_adjust
380       MODULE PROCEDURE stg_adjust
381    END INTERFACE stg_adjust
382!
[2259]383!-- Input parameter checks to be done in check_parameters
384    INTERFACE stg_check_parameters
385       MODULE PROCEDURE stg_check_parameters
386    END INTERFACE stg_check_parameters
387
388!
389!-- Calculate filter functions
390    INTERFACE stg_filter_func
391       MODULE PROCEDURE stg_filter_func
392    END INTERFACE stg_filter_func
393
394!
[2938]395!-- Generate velocity seeds at south and north domain boundary
396    INTERFACE stg_generate_seed_xz
397       MODULE PROCEDURE stg_generate_seed_xz
398    END INTERFACE stg_generate_seed_xz
399!
400!-- Generate velocity seeds at left and/or right domain boundary
[2259]401    INTERFACE stg_generate_seed_yz
402       MODULE PROCEDURE stg_generate_seed_yz
403    END INTERFACE stg_generate_seed_yz
404
405!
406!-- Output of information to the header file
407    INTERFACE stg_header
408       MODULE PROCEDURE stg_header
409    END INTERFACE stg_header
410
411!
412!-- Initialization actions
413    INTERFACE stg_init
414       MODULE PROCEDURE stg_init
415    END INTERFACE stg_init
416
417!
418!-- Main procedure of synth. turb. gen.
419    INTERFACE stg_main
420       MODULE PROCEDURE stg_main
421    END INTERFACE stg_main
422
423!
424!-- Reading of NAMELIST parameters
425    INTERFACE stg_parin
426       MODULE PROCEDURE stg_parin
427    END INTERFACE stg_parin
428
429!
430!-- Reading of parameters for restart runs
[2894]431    INTERFACE stg_rrd_global
432       MODULE PROCEDURE stg_rrd_global
433    END INTERFACE stg_rrd_global
[2259]434
435!
436!-- Writing of binary output for restart runs
[2894]437    INTERFACE stg_wrd_global
438       MODULE PROCEDURE stg_wrd_global
439    END INTERFACE stg_wrd_global
[2259]440
441    SAVE
442
443    PRIVATE
444
445!
446!-- Public interfaces
[3347]447    PUBLIC  stg_adjust, stg_check_parameters, stg_header, stg_init, stg_main,  &
448            stg_parin, stg_rrd_global, stg_wrd_global
[2259]449
450!
451!-- Public variables
[3347]452    PUBLIC  dt_stg_call, dt_stg_adjust, id_stg_left, id_stg_north,             &
453            id_stg_right, id_stg_south, parametrize_inflow_turbulence,         &
454            time_stg_adjust, time_stg_call, use_syn_turb_gen
[2259]455
456
457 CONTAINS
458
459
460!------------------------------------------------------------------------------!
461! Description:
462! ------------
463!> Check parameters routine for synthetic turbulence generator
464!------------------------------------------------------------------------------!
465 SUBROUTINE stg_check_parameters
466
[3182]467    IF ( .NOT. use_syn_turb_gen  .AND.  .NOT. rans_mode  .AND.                 &
468          nesting_offline )  THEN
[3376]469       message_string = 'Synthetic turbulence generator is required ' //       &
470                        'if offline nesting is applied and PALM operates ' //  &
471                        'in LES mode.'
472       CALL message( 'stg_check_parameters', 'PA0520', 0, 0, 0, 6, 0 )
[2938]473    ENDIF
474
[3182]475    IF ( .NOT. use_syn_turb_gen  .AND.  child_domain                           &
[2938]476         .AND. rans_mode_parent  .AND.  .NOT. rans_mode )  THEN
[3376]477       message_string = 'Synthetic turbulence generator is required ' //       &
[2938]478                        'when nesting is applied and parent operates in '  //  &
479                        'RANS-mode but current child in LES mode.'
[3376]480       CALL message( 'stg_check_parameters', 'PA0524', 1, 2, 0, 6, 0 )
[2938]481    ENDIF
482
[2776]483    IF ( use_syn_turb_gen )  THEN
[2259]484
[3579]485       IF ( child_domain  .AND.  .NOT. rans_mode  .AND.                        &
486                                 .NOT. rans_mode_parent )  THEN
487          message_string = 'Using synthetic turbulence generator ' //          &
488                           'is not allowed in LES-LES nesting.'
489          CALL message( 'stg_check_parameters', 'PA0620', 1, 2, 0, 6, 0 )
490       
491       ENDIF
492       
493       IF ( child_domain  .AND.  rans_mode  .AND.                              &
494                                 rans_mode_parent )  THEN
495          message_string = 'Using synthetic turbulence generator ' //          &
496                           'is not allowed in RANS-RANS nesting.'
497          CALL message( 'stg_check_parameters', 'PA0621', 1, 2, 0, 6, 0 )
498       
499       ENDIF
500   
[3182]501       IF ( .NOT. nesting_offline  .AND.  .NOT. child_domain )  THEN
502       
[2938]503          IF ( INDEX( initializing_actions, 'set_constant_profiles' ) == 0     &
504        .AND.  INDEX( initializing_actions, 'read_restart_data' ) == 0 )  THEN
505             message_string = 'Using synthetic turbulence generator ' //       &
[3579]506                            'requires %initializing_actions = '         //     &
507                            '"set_constant_profiles" or "read_restart_data"' //&
508                            ', if not offline nesting is applied.'
[2938]509             CALL message( 'stg_check_parameters', 'PA0015', 1, 2, 0, 6, 0 )
510          ENDIF
511
512          IF ( bc_lr /= 'dirichlet/radiation' )  THEN
513             message_string = 'Using synthetic turbulence generator ' //       &
[3347]514                              'requires &bc_lr = "dirichlet/radiation", ' //   &
515                              'if not offline nesting is applied.'
[2938]516             CALL message( 'stg_check_parameters', 'PA0035', 1, 2, 0, 6, 0 )
517          ENDIF
518          IF ( bc_ns /= 'cyclic' )  THEN
519             message_string = 'Using synthetic turbulence generator ' //       &
[3579]520                              'requires &bc_ns = "cyclic", ' //                &
[3347]521                              'if not offline nesting is applied.'
[2938]522             CALL message( 'stg_check_parameters', 'PA0037', 1, 2, 0, 6, 0 )
523          ENDIF
524
[2259]525       ENDIF
526
527       IF ( turbulent_inflow )  THEN
528          message_string = 'Using synthetic turbulence generator ' //          &
[2938]529                           'in combination &with turbulent_inflow = .T. '//    &
530                              'is not allowed'
[2259]531          CALL message( 'stg_check_parameters', 'PA0039', 1, 2, 0, 6, 0 )
532       ENDIF
[4309]533!
534!--    Synthetic turbulence generator requires the parallel random generator
535       IF ( random_generator /= 'random-parallel' )  THEN
536          message_string = 'Using synthetic turbulence generator ' //          &
537                           'requires random_generator = random-parallel.'
538          CALL message( 'stg_check_parameters', 'PA0421', 1, 2, 0, 6, 0 )
539       ENDIF
[2259]540
541    ENDIF
542
543 END SUBROUTINE stg_check_parameters
544
545
546!------------------------------------------------------------------------------!
547! Description:
548! ------------
549!> Header output for synthetic turbulence generator
550!------------------------------------------------------------------------------!
551 SUBROUTINE stg_header ( io )
552
553    INTEGER(iwp), INTENT(IN) ::  io   !< Unit of the output file
554
555!
556!-- Write synthetic turbulence generator Header
557    WRITE( io, 1 )
[2776]558    IF ( use_syn_turb_gen )  THEN
[2259]559       WRITE( io, 2 )
560    ELSE
561       WRITE( io, 3 )
562    ENDIF
[3347]563   
564    IF ( parametrize_inflow_turbulence )  THEN
565       WRITE( io, 4 ) dt_stg_adjust
566    ELSE
567       WRITE( io, 5 )
568    ENDIF
[2259]569
5701   FORMAT (//' Synthetic turbulence generator information:'/                  &
571              ' ------------------------------------------'/)
[3347]5722   FORMAT ('    synthetic turbulence generator is switched on')
5733   FORMAT ('    synthetic turbulence generator is switched off')
[3348]5744   FORMAT ('    imposed turbulence statistics are parametrized and ajdusted to boundary-layer development each ', F8.2, ' s' )
[3347]5755   FORMAT ('    imposed turbulence is read from file' )
[2259]576
577 END SUBROUTINE stg_header
578
579
580!------------------------------------------------------------------------------!
581! Description:
582! ------------
583!> Initialization of the synthetic turbulence generator
584!------------------------------------------------------------------------------!
585 SUBROUTINE stg_init
586
[3347]587    LOGICAL ::  file_stg_exist = .FALSE. !< flag indicating whether parameter file for Reynolds stress and length scales exist
[2938]588
[2669]589#if defined( __parallel )
[2259]590    INTEGER(KIND=MPI_ADDRESS_KIND) :: extent !< extent of new MPI type
591    INTEGER(KIND=MPI_ADDRESS_KIND) :: tob=0  !< dummy variable
[2669]592#endif
[2259]593
[2938]594    INTEGER(iwp) :: i                        !> grid index in x-direction
[2259]595    INTEGER(iwp) :: j                        !> loop index
596    INTEGER(iwp) :: k                        !< index
597    INTEGER(iwp) :: newtype                  !< dummy MPI type
598    INTEGER(iwp) :: realsize                 !< size of REAL variables
[4309]599
[4022]600    INTEGER(iwp), DIMENSION(3) ::  nr_non_topo_xz_l = 0 !< number of non-topography grid points at xz-cross-section on subdomain
601    INTEGER(iwp), DIMENSION(3) ::  nr_non_topo_yz_l = 0 !< number of non-topography grid points at yz-cross-section on subdomain
[2259]602!
603!-- Dummy variables used for reading profiles
604    REAL(wp) :: d1      !< u profile
605    REAL(wp) :: d2      !< v profile
606    REAL(wp) :: d3      !< w profile
607    REAL(wp) :: d5      !< e profile
608    REAL(wp) :: luy     !< length scale for u in y direction
609    REAL(wp) :: luz     !< length scale for u in z direction
610    REAL(wp) :: lvy     !< length scale for v in y direction
611    REAL(wp) :: lvz     !< length scale for v in z direction
612    REAL(wp) :: lwy     !< length scale for w in y direction
613    REAL(wp) :: lwz     !< length scale for w in z direction
[3038]614    REAL(wp) :: nnz     !< increment used to determine processor decomposition of z-axis along x and y direction
[2259]615    REAL(wp) :: zz      !< height
616
[2938]617
[2259]618#if defined( __parallel )
619    CALL MPI_BARRIER( comm2d, ierr )
620#endif
[4438]621!
622!-- Create mpi-datatypes for exchange in case of non-local but distributed
623!-- computation of the velocity seeds. This option is useful in
624!-- case large turbulent length scales are presentm, where the computational
625!-- effort becomes large and need to be parallelized. For parametrized
626!-- turbulence the length scales are small and computing the velocity seeds
627!-- locally is faster (no overhead by communication).
628    IF ( .NOT. compute_velocity_seeds_local )  THEN
[2669]629#if defined( __parallel )
[4438]630!     
631!--    Determine processor decomposition of z-axis along x- and y-direction
632       nnz = nz / pdims(1)
633       nzb_x_stg = 1 + myidx * INT( nnz )
634       nzt_x_stg = ( myidx + 1 ) * INT( nnz )
635       
636       IF ( MOD( nz , pdims(1) ) /= 0  .AND.  myidx == id_stg_right )          &
637          nzt_x_stg = nzt_x_stg + myidx * ( nnz - INT( nnz ) )
638       
639       IF ( nesting_offline   .OR.  ( child_domain  .AND.  rans_mode_parent    &
640                               .AND.  .NOT.  rans_mode ) )  THEN
641          nnz = nz / pdims(2)
642          nzb_y_stg = 1 + myidy * INT( nnz )
643          nzt_y_stg = ( myidy + 1 ) * INT( nnz )
644       
645          IF ( MOD( nz , pdims(2) ) /= 0  .AND.  myidy == id_stg_north )       &
646             nzt_y_stg = nzt_y_stg + myidy * ( nnz - INT( nnz ) )
647       ENDIF
648       
649!     
650!--    Define MPI type used in stg_generate_seed_yz to gather vertical splitted
651!--    velocity seeds
652       CALL MPI_TYPE_SIZE( MPI_REAL, realsize, ierr )
653       extent = 1 * realsize
654!     
655!--    Set-up MPI datatyp to involve all cores for turbulence generation at yz
656!--    layer
657!--    stg_type_yz: yz-slice with vertical bounds nzb:nzt+1
658       CALL MPI_TYPE_CREATE_SUBARRAY( 2, [nzt-nzb+2,nyn-nys+1],                &
659               [1,nyn-nys+1], [0,0], MPI_ORDER_FORTRAN, MPI_REAL, newtype, ierr )
660       CALL MPI_TYPE_CREATE_RESIZED( newtype, tob, extent, stg_type_yz, ierr )
661       CALL MPI_TYPE_COMMIT( stg_type_yz, ierr )
[2938]662       CALL MPI_TYPE_FREE( newtype, ierr )
[4438]663       
664       ! stg_type_yz_small: yz-slice with vertical bounds nzb_x_stg:nzt_x_stg+1
665       CALL MPI_TYPE_CREATE_SUBARRAY( 2, [nzt_x_stg-nzb_x_stg+2,nyn-nys+1],    &
666               [1,nyn-nys+1], [0,0], MPI_ORDER_FORTRAN, MPI_REAL, newtype, ierr )
667       CALL MPI_TYPE_CREATE_RESIZED( newtype, tob, extent, stg_type_yz_small, ierr )
668       CALL MPI_TYPE_COMMIT( stg_type_yz_small, ierr )
[2938]669       CALL MPI_TYPE_FREE( newtype, ierr )
[4438]670       
[2938]671       ! receive count and displacement for MPI_GATHERV in stg_generate_seed_yz
[4438]672       ALLOCATE( recv_count_yz(pdims(1)), displs_yz(pdims(1)) )
673       
674       recv_count_yz           = nzt_x_stg-nzb_x_stg + 1
675       recv_count_yz(pdims(1)) = recv_count_yz(pdims(1)) + 1
676       
677       DO  j = 1, pdims(1)
678          displs_yz(j) = 0 + (nzt_x_stg-nzb_x_stg+1) * (j-1)
[2938]679       ENDDO
[4438]680!     
681!--    Set-up MPI datatyp to involve all cores for turbulence generation at xz
682!--    layer
683!--    stg_type_xz: xz-slice with vertical bounds nzb:nzt+1
684       IF ( nesting_offline  .OR.  ( child_domain .AND.  rans_mode_parent      &
685                              .AND.  .NOT.  rans_mode ) )  THEN
686          CALL MPI_TYPE_CREATE_SUBARRAY( 2, [nzt-nzb+2,nxr-nxl+1],             &
687                  [1,nxr-nxl+1], [0,0], MPI_ORDER_FORTRAN, MPI_REAL, newtype, ierr )
688          CALL MPI_TYPE_CREATE_RESIZED( newtype, tob, extent, stg_type_xz, ierr )
689          CALL MPI_TYPE_COMMIT( stg_type_xz, ierr )
690          CALL MPI_TYPE_FREE( newtype, ierr )
691       
692          ! stg_type_yz_small: xz-slice with vertical bounds nzb_x_stg:nzt_x_stg+1
693          CALL MPI_TYPE_CREATE_SUBARRAY( 2, [nzt_y_stg-nzb_y_stg+2,nxr-nxl+1], &
694                  [1,nxr-nxl+1], [0,0], MPI_ORDER_FORTRAN, MPI_REAL, newtype, ierr )
695          CALL MPI_TYPE_CREATE_RESIZED( newtype, tob, extent, stg_type_xz_small, ierr )
696          CALL MPI_TYPE_COMMIT( stg_type_xz_small, ierr )
697          CALL MPI_TYPE_FREE( newtype, ierr )
698       
699          ! receive count and displacement for MPI_GATHERV in stg_generate_seed_yz
700          ALLOCATE( recv_count_xz(pdims(2)), displs_xz(pdims(2)) )
701       
702          recv_count_xz           = nzt_y_stg-nzb_y_stg + 1
703          recv_count_xz(pdims(2)) = recv_count_xz(pdims(2)) + 1
704       
705          DO  j = 1, pdims(2)
706             displs_xz(j) = 0 + (nzt_y_stg-nzb_y_stg+1) * (j-1)
707          ENDDO
708       
709       ENDIF
[4440]710#endif
[2938]711    ENDIF
[2259]712!
[4071]713!-- Allocate required arrays.
714!-- In case no offline nesting or self nesting is used, the arrary
715!-- mean_inflow profiles is required. Check if it is already allocated, else
716!-- allocate and initialize it appropriately. Note, in case turbulence and
717!-- inflow information is read from file, mean_inflow_profiles is already
718!-- allocated and initialized appropriately.
[3347]719    IF ( .NOT. nesting_offline  .AND.  .NOT.  child_domain )  THEN
[4071]720       IF ( .NOT. ALLOCATED( mean_inflow_profiles ) )  THEN
[3347]721          ALLOCATE( mean_inflow_profiles(nzb:nzt+1,1:num_mean_inflow_profiles) )
[4071]722          mean_inflow_profiles = 0.0_wp
723          mean_inflow_profiles(:,1) = u_init
724          mean_inflow_profiles(:,2) = v_init
725!
726!--       Even though potential temperature and humidity are not perturbed,
727!--       they need to be initialized appropriately.
728          IF ( .NOT. neutral )                                                 &
729             mean_inflow_profiles(:,4) = pt_init
730          IF ( humidity )                                                      &
731             mean_inflow_profiles(:,6) = q_init       
732       ENDIF   
[3347]733    ENDIF
[2259]734
[3347]735    ALLOCATE ( a11(nzb:nzt+1), a21(nzb:nzt+1), a22(nzb:nzt+1),                 &
736               a31(nzb:nzt+1), a32(nzb:nzt+1), a33(nzb:nzt+1),                 &
737               nux(nzb:nzt+1), nuy(nzb:nzt+1), nuz(nzb:nzt+1),                 &
738               nvx(nzb:nzt+1), nvy(nzb:nzt+1), nvz(nzb:nzt+1),                 &
739               nwx(nzb:nzt+1), nwy(nzb:nzt+1), nwz(nzb:nzt+1),                 &
740               r11(nzb:nzt+1), r21(nzb:nzt+1), r22(nzb:nzt+1),                 &
741               r31(nzb:nzt+1), r32(nzb:nzt+1), r33(nzb:nzt+1),                 &
742               tu(nzb:nzt+1),  tv(nzb:nzt+1),  tw(nzb:nzt+1)   )
743               
[4438]744    ALLOCATE ( dist_xz(nzb:nzt+1,nxl:nxr,3) )
745    ALLOCATE ( dist_yz(nzb:nzt+1,nys:nyn,3) )
[3347]746    dist_xz = 0.0_wp
747    dist_yz = 0.0_wp
748!
[2259]749!-- Read inflow profile
750!-- Height levels of profiles in input profile is as follows:
751!-- zu: luy, luz, tu, lvy, lvz, tv, r11, r21, r22, d1, d2, d5
752!-- zw: lwy, lwz, tw, r31, r32, r33, d3
753!-- WARNING: zz is not used at the moment
[2938]754    INQUIRE( FILE = 'STG_PROFILES' // TRIM( coupling_char ),                   &
755             EXIST = file_stg_exist  )
[2259]756
[2938]757    IF ( file_stg_exist )  THEN
[2259]758
[2938]759       OPEN( 90, FILE='STG_PROFILES'//TRIM( coupling_char ), STATUS='OLD',     &
760                      FORM='FORMATTED')
761!
762!--    Skip header
763       READ( 90, * )
[2259]764
[3182]765       DO  k = nzb+1, nzt+1
[2938]766          READ( 90, * ) zz, luy, luz, tu(k), lvy, lvz, tv(k), lwy, lwz, tw(k), &
767                        r11(k), r21(k), r22(k), r31(k), r32(k), r33(k),        &
768                        d1, d2, d3, d5
769
[2259]770!
[3182]771!--       Convert length scales from meter to number of grid points.
[2938]772          nuy(k) = INT( luy * ddy )
[3182]773          nuz(k) = INT( luz * ddzw(k) )
[2938]774          nvy(k) = INT( lvy * ddy )
[3182]775          nvz(k) = INT( lvz * ddzw(k) )
[2938]776          nwy(k) = INT( lwy * ddy )
[3182]777          nwz(k) = INT( lwz * ddzw(k) )
[2938]778!
779!--       Workaround, assume isotropic turbulence
780          nwx(k) = nwy(k)
781          nvx(k) = nvy(k)
782          nux(k) = nuy(k)
783!
784!--       Save Mean inflow profiles
785          IF ( TRIM( initializing_actions ) /= 'read_restart_data' ) THEN
786             mean_inflow_profiles(k,1) = d1
787             mean_inflow_profiles(k,2) = d2
788            !  mean_inflow_profiles(k,4) = d4
789             mean_inflow_profiles(k,5) = d5
790          ENDIF
791       ENDDO
[3182]792!
793!--    Set lenght scales at surface grid point
794       nuy(nzb) = nuy(nzb+1) 
795       nuz(nzb) = nuz(nzb+1)
796       nvy(nzb) = nvy(nzb+1)
797       nvz(nzb) = nvz(nzb+1)
798       nwy(nzb) = nwy(nzb+1)
799       nwz(nzb) = nwz(nzb+1)
800       
[2938]801       CLOSE( 90 )
[3347]802!
803!--    Calculate coefficient matrix from Reynolds stress tensor 
804!--    (Lund rotation)
805       CALL calc_coeff_matrix
806!
807!-- No information about turbulence and its length scales are available.
808!-- Instead, parametrize turbulence which is imposed at the boundaries.
809!-- Set flag which indicates that turbulence is parametrized, which is done
810!-- later when energy-balance models are already initialized. This is
811!-- because the STG needs information about surface properties such as
812!-- roughness to build 'realistic' turbulence profiles.
[2938]813    ELSE
[2259]814!
[4022]815!--    Define length scale for the imposed turbulence, which is defined as
816!--    8 times the minimum grid spacing
[4441]817       length_scale = 8.0_wp * MIN( dx, dy, MINVAL( dzw ) )
[4022]818!
819!--    Define constant to gradually decrease length scales and Reynolds stress
820!--    above ABL top. Assure that no zero length scales are used.
821       d_l = blend_coeff / MAX( length_scale, dx, dy, MINVAL( dzw ) )
822!
[3347]823!--    Set flag indicating that turbulence is parametrized
824       parametrize_inflow_turbulence = .TRUE.
825!
[4022]826!--    In case of dirichlet inflow boundary conditions only at one lateral
827!--    boundary, i.e. in the case no offline or self nesting is applied but
828!--    synthetic turbulence shall be parametrized nevertheless, the
829!--    boundary-layer depth need to determined first.
830       IF ( .NOT. nesting_offline  .AND.  .NOT.  child_domain )                &
831          CALL nesting_offl_calc_zi
832!
[3347]833!--    Determine boundary-layer depth, which is used to initialize lenght
834!--    scales
835       CALL calc_scaling_variables
836!
837!--    Initialize lenght and time scales, which in turn are used
838!--    to initialize the filter functions.
839       CALL calc_length_and_time_scale
[3891]840!
841!--    Parametrize Reynolds-stress tensor, diagonal elements as well
842!--    as r21 (v'u'), r31 (w'u'), r32 (w'v'). Parametrization follows
843!--    Rotach et al. (1996) and is based on boundary-layer depth,
844!--    friction velocity and velocity scale.
845       CALL parametrize_reynolds_stress
846!     
847!--    Calculate coefficient matrix from Reynolds stress tensor 
848!--    (Lund rotation)
849       CALL calc_coeff_matrix
[3347]850           
[2938]851    ENDIF
852
[2259]853!
[3347]854!-- Assign initial profiles. Note, this is only required if turbulent
855!-- inflow from the left is desired, not in case of any of the
856!-- nesting (offline or self nesting) approaches.
[3182]857    IF ( .NOT. nesting_offline  .AND.  .NOT.  child_domain )  THEN
[2938]858       u_init = mean_inflow_profiles(:,1)
859       v_init = mean_inflow_profiles(:,2)
860      !pt_init = mean_inflow_profiles(:,4)
861       e_init = MAXVAL( mean_inflow_profiles(:,5) )
862    ENDIF
[3347]863   
[2938]864!
[2259]865!-- Define the size of the filter functions and allocate them.
[4438]866    mergp = 0
[2259]867
868    ! arrays must be large enough to cover the largest length scale
869    DO  k = nzb, nzt+1
[2938]870       j = MAX( ABS(nux(k)), ABS(nuy(k)), ABS(nuz(k)), &
871                ABS(nvx(k)), ABS(nvy(k)), ABS(nvz(k)), &
872                ABS(nwx(k)), ABS(nwy(k)), ABS(nwz(k))  )
[4438]873       IF ( j > mergp )  mergp = j
[2259]874    ENDDO
875
[4438]876!     mergp  = 2 * mergp
877!     mergp = mergp
[2259]878
[4438]879    ALLOCATE ( bux(-mergp:mergp,nzb:nzt+1),                                      &
880               buy(-mergp:mergp,nzb:nzt+1),                                      &
881               buz(-mergp:mergp,nzb:nzt+1),                                      &
882               bvx(-mergp:mergp,nzb:nzt+1),                                      &
883               bvy(-mergp:mergp,nzb:nzt+1),                                      &
884               bvz(-mergp:mergp,nzb:nzt+1),                                      &
885               bwx(-mergp:mergp,nzb:nzt+1),                                      &
886               bwy(-mergp:mergp,nzb:nzt+1),                                      &
887               bwz(-mergp:mergp,nzb:nzt+1)  )
[2259]888
889!
[2938]890!-- Allocate velocity seeds for turbulence at xz-layer
[4438]891    ALLOCATE ( fu_xz( nzb:nzt+1,nxl:nxr), fuo_xz(nzb:nzt+1,nxl:nxr),       &
892               fv_xz( nzb:nzt+1,nxl:nxr), fvo_xz(nzb:nzt+1,nxl:nxr),       &
893               fw_xz( nzb:nzt+1,nxl:nxr), fwo_xz(nzb:nzt+1,nxl:nxr)  )
[2259]894
[2938]895!
896!-- Allocate velocity seeds for turbulence at yz-layer
[4438]897    ALLOCATE ( fu_yz( nzb:nzt+1,nys:nyn), fuo_yz(nzb:nzt+1,nys:nyn),       &
898               fv_yz( nzb:nzt+1,nys:nyn), fvo_yz(nzb:nzt+1,nys:nyn),       &
899               fw_yz( nzb:nzt+1,nys:nyn), fwo_yz(nzb:nzt+1,nys:nyn)  )
[2259]900
[2938]901    fu_xz  = 0.0_wp
902    fuo_xz = 0.0_wp
903    fv_xz  = 0.0_wp
904    fvo_xz = 0.0_wp
905    fw_xz  = 0.0_wp
906    fwo_xz = 0.0_wp
907
908    fu_yz  = 0.0_wp
909    fuo_yz = 0.0_wp
910    fv_yz  = 0.0_wp
911    fvo_yz = 0.0_wp
912    fw_yz  = 0.0_wp
913    fwo_yz = 0.0_wp
914
[2259]915!
916!-- Create filter functions
[2938]917    CALL stg_filter_func( nux, bux ) !filter ux
[2259]918    CALL stg_filter_func( nuy, buy ) !filter uy
919    CALL stg_filter_func( nuz, buz ) !filter uz
[2938]920    CALL stg_filter_func( nvx, bvx ) !filter vx
[2259]921    CALL stg_filter_func( nvy, bvy ) !filter vy
922    CALL stg_filter_func( nvz, bvz ) !filter vz
[2938]923    CALL stg_filter_func( nwx, bwx ) !filter wx
[2259]924    CALL stg_filter_func( nwy, bwy ) !filter wy
925    CALL stg_filter_func( nwz, bwz ) !filter wz
926
927#if defined( __parallel )
928    CALL MPI_BARRIER( comm2d, ierr )
929#endif
930
931!
[2938]932!-- In case of restart, calculate velocity seeds fu, fv, fw from former
933!   time step.
934!   Bug: fu, fv, fw are different in those heights where a11, a22, a33
935!        are 0 compared to the prerun. This is mostly for k=nzt+1.
[2259]936    IF ( TRIM( initializing_actions ) == 'read_restart_data' )  THEN
[2938]937       IF ( myidx == id_stg_left  .OR.  myidx == id_stg_right )  THEN
938
939          IF ( myidx == id_stg_left  )  i = -1
940          IF ( myidx == id_stg_right )  i = nxr+1
941
[4438]942          DO  j = nys, nyn
[2259]943             DO  k = nzb, nzt+1
[4332]944                IF  ( a11(k) > 10E-8_wp )  THEN
[4022]945                   fu_yz(k,j) = ( u(k,j,i) - u_init(k) ) / a11(k)
[2259]946                ELSE
[4332]947                   fu_yz(k,j) = 10E-8_wp
[2259]948                ENDIF
949
[4332]950                IF  ( a22(k) > 10E-8_wp )  THEN
[4022]951                   fv_yz(k,j) = ( v(k,j,i) -                                  &
952                                  a21(k) * fu_yz(k,j) - v_init(k) ) / a22(k)
[2259]953                ELSE
[4332]954                   fv_yz(k,j) = 10E-8_wp
[2259]955                ENDIF
956
[4332]957                IF  ( a33(k) > 10E-8_wp )  THEN
[4022]958                   fw_yz(k,j) = ( w(k,j,i) -                                   &
959                                  a31(k) * fu_yz(k,j) - a32(k) *               &
960                                  fv_yz(k,j) ) / a33(k)
[2259]961                ELSE
[4332]962                   fw_yz(k,j) = 10E-8_wp
[2259]963                ENDIF
964             ENDDO
965          ENDDO
966       ENDIF
[3900]967       
968       IF ( myidy == id_stg_south  .OR.  myidy == id_stg_north )  THEN
969
970          IF ( myidy == id_stg_south )  j = -1
971          IF ( myidy == id_stg_north )  j = nyn+1
972
[4438]973          DO  i = nxl, nxr
[3900]974             DO  k = nzb, nzt+1
[4335]975!
976!--             In case the correlation coefficients are very small, the
977!--             velocity seeds may become very large finally creating
978!--             numerical instabilities in the synthetic turbulence generator.
979!--             Empirically, a value of 10E-8 seems to be sufficient.
[4332]980                IF  ( a11(k) > 10E-8_wp )  THEN
[4022]981                   fu_xz(k,i) = ( u(k,j,i) - u_init(k) ) / a11(k)
[3900]982                ELSE
[4332]983                   fu_xz(k,i) = 10E-8_wp
[3900]984                ENDIF
985
[4332]986                IF  ( a22(k) > 10E-8_wp )  THEN
[4022]987                   fv_xz(k,i) = ( v(k,j,i) -                                   &
988                                  a21(k) * fu_xz(k,i) - v_init(k) ) / a22(k)
[3900]989                ELSE
[4332]990                   fv_xz(k,i) = 10E-8_wp
[3900]991                ENDIF
992
[4332]993                IF  ( a33(k) > 10E-8_wp )  THEN
[4022]994                   fw_xz(k,i) = ( w(k,j,i) -                                   &
995                                  a31(k) * fu_xz(k,i) -                        &
996                                  a32(k) * fv_xz(k,i) ) / a33(k)
[3900]997                ELSE
[4332]998                   fw_xz(k,i) = 10E-8_wp
[3900]999                ENDIF
1000
1001             ENDDO
1002          ENDDO
1003       ENDIF
[2259]1004    ENDIF
[4022]1005!
1006!-- Count the number of non-topography grid points at the boundaries where
1007!-- perturbations are imposed. This number is later used for bias corrections
1008!-- of the perturbations, i.e. to force that their mean is zero. Please note,
1009!-- due to the asymetry of u and v along x and y direction, respectively,
1010!-- different cases must be distinguished.
1011    IF ( myidx == id_stg_left  .OR.  myidx == id_stg_right )  THEN
1012!
1013!--    Number of grid points where perturbations are imposed on u
1014       IF ( myidx == id_stg_left  )  i = nxl
1015       IF ( myidx == id_stg_right )  i = nxr+1
1016       
1017       nr_non_topo_yz_l(1) = SUM(                                              &
1018                          MERGE( 1, 0,                                         &
[4346]1019                          BTEST( wall_flags_total_0(nzb:nzt,nys:nyn,i), 1 ) ) )
[4022]1020!
1021!--    Number of grid points where perturbations are imposed on v and w                                   
1022       IF ( myidx == id_stg_left  )  i = nxl-1
1023       IF ( myidx == id_stg_right )  i = nxr+1
1024       
1025       nr_non_topo_yz_l(2) = SUM(                                              &
1026                          MERGE( 1, 0,                                         &
[4346]1027                          BTEST( wall_flags_total_0(nzb:nzt,nysv:nyn,i), 2 ) ) )
[4022]1028       nr_non_topo_yz_l(3) = SUM(                                              &
1029                          MERGE( 1, 0,                                         &
[4346]1030                          BTEST( wall_flags_total_0(nzb:nzt,nys:nyn,i), 3 ) ) )
[4022]1031                                   
1032#if defined( __parallel )
1033       CALL MPI_ALLREDUCE( nr_non_topo_yz_l, nr_non_topo_yz, 3, MPI_INTEGER,   &
1034                           MPI_SUM, comm1dy, ierr )
1035#else
1036       nr_non_topo_yz = nr_non_topo_yz_l
1037#endif 
1038    ENDIF
1039   
1040    IF ( myidy == id_stg_south  .OR.  myidy == id_stg_north )  THEN
1041!
1042!--    Number of grid points where perturbations are imposed on v
1043       IF ( myidy == id_stg_south )  j = nys
1044       IF ( myidy == id_stg_north )  j = nyn+1
1045       
1046       nr_non_topo_xz_l(2) = SUM(                                              &
1047                          MERGE( 1, 0,                                         &
[4346]1048                          BTEST( wall_flags_total_0(nzb:nzt,j,nxl:nxr), 2 ) ) )
[4022]1049!
1050!--    Number of grid points where perturbations are imposed on u and w
1051       IF ( myidy == id_stg_south )  j = nys-1
1052       IF ( myidy == id_stg_north )  j = nyn+1
1053       
1054       nr_non_topo_xz_l(1) = SUM(                                              &
1055                          MERGE( 1, 0,                                         &
[4346]1056                          BTEST( wall_flags_total_0(nzb:nzt,j,nxlu:nxr), 1 ) ) )
[4022]1057       nr_non_topo_xz_l(3) = SUM(                                              &
1058                          MERGE( 1, 0,                                         &
[4346]1059                          BTEST( wall_flags_total_0(nzb:nzt,j,nxl:nxr), 3 ) ) )
[4022]1060                                   
1061#if defined( __parallel )
1062       CALL MPI_ALLREDUCE( nr_non_topo_xz_l, nr_non_topo_xz, 3, MPI_INTEGER,   &
1063                           MPI_SUM, comm1dx, ierr )
1064#else
1065       nr_non_topo_xz = nr_non_topo_xz_l
1066#endif 
1067    ENDIF
[4438]1068!
1069!-- Initialize random number generator at xz- and yz-layers. Random numbers
1070!-- are initialized at each core. In case there is only inflow from the left,
1071!-- it is sufficient to generate only random numbers for the yz-layer, else
1072!-- random numbers for the xz-layer are also required.
1073    ALLOCATE ( id_rand_yz(-mergp+nys:nyn+mergp) )
1074    ALLOCATE ( seq_rand_yz(5,-mergp+nys:nyn+mergp) )
1075    id_rand_yz  = 0
1076    seq_rand_yz = 0
[2259]1077
[4438]1078    CALL init_parallel_random_generator( ny, -mergp+nys, nyn+mergp,            &
1079                                         id_rand_yz, seq_rand_yz )
[4022]1080
[4438]1081    IF ( nesting_offline  .OR.  ( child_domain .AND.  rans_mode_parent         &
1082                           .AND.  .NOT.  rans_mode ) )  THEN
1083       ALLOCATE ( id_rand_xz(-mergp+nxl:nxr+mergp) )
1084       ALLOCATE ( seq_rand_xz(5,-mergp+nxl:nxr+mergp) )
1085       id_rand_xz  = 0
1086       seq_rand_xz = 0
1087
1088       CALL init_parallel_random_generator( nx, -mergp+nxl, nxr+mergp,         &
1089                                            id_rand_xz, seq_rand_xz )
1090    ENDIF
1091
1092
1093
[2259]1094 END SUBROUTINE stg_init
1095
1096
1097!------------------------------------------------------------------------------!
1098! Description:
1099! ------------
1100!> Calculate filter function bxx from length scale nxx following Eg.9 and 10
1101!> (Xie and Castro, 2008)
1102!------------------------------------------------------------------------------!
1103 SUBROUTINE stg_filter_func( nxx, bxx )
1104
1105    INTEGER(iwp) :: k         !< loop index
1106    INTEGER(iwp) :: n_k       !< length scale nXX in height k
1107    INTEGER(iwp) :: nf        !< index for length scales
1108
1109    REAL(wp) :: bdenom        !< denominator for filter functions bXX
1110    REAL(wp) :: qsi = 1.0_wp  !< minimization factor
1111
[4438]1112    INTEGER(iwp), DIMENSION(nzb:nzt+1) ::  nxx         !< length scale (in gp)
[2259]1113
[4438]1114    REAL(wp), DIMENSION(-mergp:mergp,nzb:nzt+1) ::  bxx  !< filter function
[2259]1115
1116
1117    bxx = 0.0_wp
1118
1119    DO  k = nzb, nzt+1
1120       bdenom = 0.0_wp
1121       n_k    = nxx(k)
1122       IF ( n_k /= 0 )  THEN
1123
1124!
1125!--       ( Eq.10 )^2
[4438]1126          DO  nf = -n_k, n_k
[2259]1127             bdenom = bdenom + EXP( -qsi * pi * ABS(nf) / n_k )**2
1128          ENDDO
1129
1130!
1131!--       ( Eq.9 )
1132          bdenom = SQRT( bdenom )
[4438]1133          DO  nf = -n_k, n_k
[2259]1134             bxx(nf,k) = EXP( -qsi * pi * ABS(nf) / n_k ) / bdenom
1135          ENDDO
1136       ENDIF
1137    ENDDO
1138
[3347]1139 END SUBROUTINE stg_filter_func
[2259]1140
1141
1142!------------------------------------------------------------------------------!
1143! Description:
1144! ------------
1145!> Parin for &stg_par for synthetic turbulence generator
1146!------------------------------------------------------------------------------!
1147 SUBROUTINE stg_parin
1148
1149    CHARACTER (LEN=80) ::  line   !< dummy string that contains the current line of the parameter file
1150
1151
[4438]1152    NAMELIST /stg_par/  dt_stg_adjust,                                         &
1153                        dt_stg_call,                                           &
1154                        use_syn_turb_gen,                                      &
1155                        compute_velocity_seeds_local
[2259]1156
1157    line = ' '
1158!
1159!-- Try to find stg package
1160    REWIND ( 11 )
1161    line = ' '
1162    DO WHILE ( INDEX( line, '&stg_par' ) == 0 )
[3246]1163       READ ( 11, '(A)', END=20 )  line
[2259]1164    ENDDO
1165    BACKSPACE ( 11 )
1166
1167!
1168!-- Read namelist
[3246]1169    READ ( 11, stg_par, ERR = 10, END = 20 )
[2259]1170
1171!
1172!-- Set flag that indicates that the synthetic turbulence generator is switched
1173!-- on
[2776]1174    syn_turb_gen = .TRUE.
[3246]1175    GOTO 20
[2259]1176
[3246]1177 10 BACKSPACE( 11 )
[3248]1178    READ( 11 , '(A)') line
1179    CALL parin_fail_message( 'stg_par', line )
[2563]1180
[3246]1181 20 CONTINUE
[2259]1182
1183 END SUBROUTINE stg_parin
1184
1185
1186!------------------------------------------------------------------------------!
1187! Description:
1188! ------------
[2894]1189!> This routine reads the respective restart data.
[2576]1190!------------------------------------------------------------------------------!
[2894]1191 SUBROUTINE stg_rrd_global( found )
[2576]1192
[3044]1193    LOGICAL, INTENT(OUT)  ::  found !< flag indicating if variable was found
[2259]1194
[2894]1195    found = .TRUE.
[2259]1196
[3038]1197
[2894]1198    SELECT CASE ( restart_string(1:length) )
[4022]1199         
1200       CASE ( 'time_stg_adjust' )
1201          READ ( 13 )  time_stg_adjust
1202         
1203       CASE ( 'time_stg_call' )
1204          READ ( 13 )  time_stg_call
1205         
[2894]1206       CASE ( 'use_syn_turb_gen' )
1207          READ ( 13 )  use_syn_turb_gen
[2259]1208
[2894]1209       CASE DEFAULT
[2259]1210
[3038]1211          found = .FALSE.
[2259]1212
[2894]1213    END SELECT
[2259]1214
1215
[2894]1216 END SUBROUTINE stg_rrd_global
[2259]1217
1218
1219!------------------------------------------------------------------------------!
1220! Description:
1221! ------------
1222!> This routine writes the respective restart data.
1223!------------------------------------------------------------------------------!
[2894]1224 SUBROUTINE stg_wrd_global
[2259]1225
[4022]1226    CALL wrd_write_string( 'time_stg_adjust' )
1227    WRITE ( 14 )  time_stg_adjust
1228   
1229    CALL wrd_write_string( 'time_stg_call' )
1230    WRITE ( 14 )  time_stg_call
[2259]1231
[2894]1232    CALL wrd_write_string( 'use_syn_turb_gen' )
1233    WRITE ( 14 )  use_syn_turb_gen
[2259]1234
1235
[2894]1236 END SUBROUTINE stg_wrd_global
[2259]1237
[2894]1238
[2259]1239!------------------------------------------------------------------------------!
1240! Description:
1241! ------------
1242!> Create turbulent inflow fields for u, v, w with prescribed length scales and
1243!> Reynolds stress tensor after a method of Xie and Castro (2008), modified
1244!> following suggestions of Kim et al. (2013), and using a Lund rotation
1245!> (Lund, 1998).
1246!------------------------------------------------------------------------------!
1247 SUBROUTINE stg_main
1248
[2938]1249    INTEGER(iwp) :: i           !< grid index in x-direction
[2259]1250    INTEGER(iwp) :: j           !< loop index in y-direction
1251    INTEGER(iwp) :: k           !< loop index in z-direction
[4022]1252   
1253    LOGICAL  :: stg_call = .FALSE. !< control flag indicating whether turbulence was updated or only restored from last call
[2259]1254
1255    REAL(wp) :: dt_stg          !< wheighted subtimestep
[4022]1256   
1257    REAL(wp), DIMENSION(3) :: mc_factor_l   !< local mass flux correction factor
[2259]1258
[3987]1259    IF ( debug_output_timestep )  CALL debug_message( 'stg_main', 'start' )
[2259]1260!
1261!-- Calculate time step which is needed for filter functions
[3775]1262    dt_stg = MAX( dt_3d, dt_stg_call )
[2259]1263!
[4022]1264!-- Check if synthetic turbulence generator needs to be called and new
1265!-- perturbations need to be created or if old disturbances can be imposed
1266!-- again.
1267    IF ( time_stg_call >= dt_stg_call  .AND.                                  &
1268         intermediate_timestep_count == intermediate_timestep_count_max  )  THEN
1269       stg_call = .TRUE.
1270    ELSE
1271       stg_call = .FALSE.
1272    ENDIF
1273!
[2259]1274!-- Initial value of fu, fv, fw
[3646]1275    IF ( time_since_reference_point == 0.0_wp .AND. .NOT. velocity_seed_initialized )  THEN
[4309]1276!
1277!--    Generate turbulence at the left and right boundary. Random numbers
1278!--    for the yz-planes at the left/right boundary are generated by the
1279!--    left-sided mpi ranks only. After random numbers are calculated, they
1280!--    are distributed to all other mpi ranks in the model, so that the
1281!--    velocity seed matrices are available on all mpi ranks (i.e. also on the
1282!--    right-sided boundary mpi ranks). In case of offline nesting, this implies,
1283!--    that the left- and the right-sided lateral boundary have the same initial
1284!--    seeds.
1285!--    Note, in case of inflow from the right only, only turbulence at the left
1286!--    boundary is required.
1287       IF ( .NOT. ( nesting_offline  .OR.                                      &
1288                  ( child_domain .AND.  rans_mode_parent                       &
1289                                 .AND.  .NOT.  rans_mode ) ) )  THEN
1290          CALL stg_generate_seed_yz( nuy, nuz, buy, buz, fu_yz, id_stg_left )
1291          CALL stg_generate_seed_yz( nvy, nvz, bvy, bvz, fv_yz, id_stg_left )
1292          CALL stg_generate_seed_yz( nwy, nwz, bwy, bwz, fw_yz, id_stg_left )
1293       ELSE
1294          CALL stg_generate_seed_yz( nuy, nuz, buy, buz, fu_yz,               &
1295                                     id_stg_left, id_stg_right )
1296          CALL stg_generate_seed_yz( nvy, nvz, bvy, bvz, fv_yz,               &
1297                                     id_stg_left, id_stg_right )
1298          CALL stg_generate_seed_yz( nwy, nwz, bwy, bwz, fw_yz,               &
1299                                     id_stg_left, id_stg_right )
[2938]1300!
[4309]1301!--       Generate turbulence at the south and north boundary. Random numbers
1302!--       for the xz-planes at the south/north boundary are generated by the
1303!--       south-sided mpi ranks only. Please see also comment above.
1304          CALL stg_generate_seed_xz( nux, nuz, bux, buz, fu_xz,               &
1305                                     id_stg_south, id_stg_north )
1306          CALL stg_generate_seed_xz( nvx, nvz, bvx, bvz, fv_xz,               &
1307                                     id_stg_south, id_stg_north )
1308          CALL stg_generate_seed_xz( nwx, nwz, bwx, bwz, fw_xz,               &
1309                                     id_stg_south, id_stg_north )
[2938]1310       ENDIF
[2259]1311       velocity_seed_initialized = .TRUE.
1312    ENDIF
1313!
[4309]1314!-- New set of fu, fv, fw. Note, for inflow from the left side only, velocity
1315!-- seeds are only required at the left boundary, while in case of offline
1316!-- nesting or RANS-LES nesting velocity seeds are required also at the
1317!-- right, south and north boundaries.
[4022]1318    IF ( stg_call )  THEN
[4309]1319       IF ( .NOT. ( nesting_offline  .OR.                                      &
1320                  ( child_domain .AND.  rans_mode_parent                       &
1321                                 .AND.  .NOT.  rans_mode ) ) )  THEN
1322          CALL stg_generate_seed_yz( nuy, nuz, buy, buz, fuo_yz, id_stg_left )
1323          CALL stg_generate_seed_yz( nvy, nvz, bvy, bvz, fvo_yz, id_stg_left )
1324          CALL stg_generate_seed_yz( nwy, nwz, bwy, bwz, fwo_yz, id_stg_left )
1325
1326       ELSE
1327          CALL stg_generate_seed_yz( nuy, nuz, buy, buz, fuo_yz,               &
1328                                     id_stg_left, id_stg_right )
1329          CALL stg_generate_seed_yz( nvy, nvz, bvy, bvz, fvo_yz,               &
1330                                     id_stg_left, id_stg_right )
1331          CALL stg_generate_seed_yz( nwy, nwz, bwy, bwz, fwo_yz,               &
1332                                     id_stg_left, id_stg_right )
1333
1334          CALL stg_generate_seed_xz( nux, nuz, bux, buz, fuo_xz,               &
1335                                     id_stg_south, id_stg_north )
1336          CALL stg_generate_seed_xz( nvx, nvz, bvx, bvz, fvo_xz,               &
1337                                     id_stg_south, id_stg_north )
1338          CALL stg_generate_seed_xz( nwx, nwz, bwx, bwz, fwo_xz,               &
1339                                     id_stg_south, id_stg_north )
[4022]1340       ENDIF
[2938]1341    ENDIF
[3347]1342   
[2938]1343!
[4309]1344!-- Turbulence generation at left and/or right boundary
[2938]1345    IF ( myidx == id_stg_left  .OR.  myidx == id_stg_right )  THEN
[2259]1346!
[4022]1347!--    Calculate new set of perturbations. Do this only at last RK3-substep and
1348!--    when dt_stg_call is exceeded. Else the old set of perturbations is
1349!--    imposed
1350       IF ( stg_call )  THEN
1351       
[4438]1352          DO  j = nys, nyn
[4022]1353             DO  k = nzb, nzt + 1
1354!     
1355!--             Update fu, fv, fw following Eq. 14 of Xie and Castro (2008)
1356                IF ( tu(k) == 0.0_wp )  THEN
1357                   fu_yz(k,j) = fuo_yz(k,j)
1358                ELSE
1359                   fu_yz(k,j) = fu_yz(k,j) * EXP( -pi * dt_stg * 0.5_wp / tu(k) ) + &
1360                            fuo_yz(k,j) * SQRT( 1.0_wp - EXP( -pi * dt_stg / tu(k) ) )
1361                ENDIF
1362       
1363                IF ( tv(k) == 0.0_wp )  THEN
1364                   fv_yz(k,j) = fvo_yz(k,j)
1365                ELSE
1366                   fv_yz(k,j) = fv_yz(k,j) * EXP( -pi * dt_stg * 0.5_wp / tv(k) ) + &
1367                            fvo_yz(k,j) * SQRT( 1.0_wp - EXP( -pi * dt_stg / tv(k) ) )
1368                ENDIF
1369       
1370                IF ( tw(k) == 0.0_wp )  THEN
1371                   fw_yz(k,j) = fwo_yz(k,j)
1372                ELSE
1373                   fw_yz(k,j) = fw_yz(k,j) * EXP( -pi * dt_stg * 0.5_wp / tw(k) ) + &
1374                            fwo_yz(k,j) * SQRT( 1.0_wp - EXP( -pi * dt_stg / tw(k) ) )
1375                ENDIF
1376             ENDDO
1377          ENDDO
1378         
1379          dist_yz(nzb,:,1) = 0.0_wp
1380          dist_yz(nzb,:,2) = 0.0_wp
1381          dist_yz(nzb,:,3) = 0.0_wp
1382         
1383          IF ( myidx == id_stg_left  )  i = nxl
1384          IF ( myidx == id_stg_right )  i = nxr+1       
[4438]1385          DO  j = nys, nyn
[4022]1386             DO  k = nzb+1, nzt + 1
1387!     
1388!--             Lund rotation following Eq. 17 in Xie and Castro (2008).
1389!--             Additional factors are added to improve the variance of v and w
1390                dist_yz(k,j,1) = MIN( a11(k) * fu_yz(k,j), 3.0_wp ) *          &
1391                                    MERGE( 1.0_wp, 0.0_wp,                     &
[4346]1392                                    BTEST( wall_flags_total_0(k,j,i), 1 ) )
[4022]1393             ENDDO
1394          ENDDO
[4309]1395
[4022]1396          IF ( myidx == id_stg_left  )  i = nxl-1
1397          IF ( myidx == id_stg_right )  i = nxr+1
[4438]1398          DO  j = nys, nyn
[4022]1399             DO  k = nzb+1, nzt + 1
1400!     
1401!--             Lund rotation following Eq. 17 in Xie and Castro (2008).
1402!--             Additional factors are added to improve the variance of v and w
1403!--             experimental test of 1.2                                       
[3347]1404                dist_yz(k,j,2) = MIN( ( SQRT( a22(k) / MAXVAL(a22) )           &
1405                                      * 1.2_wp )                               &
1406                                     * (   a21(k) * fu_yz(k,j)                 &
[4022]1407                                         + a22(k) * fv_yz(k,j) ), 3.0_wp ) *   &
1408                                    MERGE( 1.0_wp, 0.0_wp,                     &
[4346]1409                                        BTEST( wall_flags_total_0(k,j,i), 2 ) )   
[3347]1410                dist_yz(k,j,3) = MIN( ( SQRT(a33(k) / MAXVAL(a33) )            &
1411                                      * 1.3_wp )                               &
1412                                    * (   a31(k) * fu_yz(k,j)                  &
1413                                        + a32(k) * fv_yz(k,j)                  &
[4022]1414                                        + a33(k) * fw_yz(k,j) ), 3.0_wp )  *   &
1415                                    MERGE( 1.0_wp, 0.0_wp,                     &
[4346]1416                                        BTEST( wall_flags_total_0(k,j,i), 3 ) )
[4022]1417             ENDDO
[2259]1418          ENDDO
[4022]1419       ENDIF
[2259]1420!
1421!--    Mass flux correction following Kim et al. (2013)
1422!--    This correction factor insures that the mass flux is preserved at the
[4022]1423!--    inflow boundary. First, calculate mean value of the imposed
1424!--    perturbations at yz boundary.
1425!--    Note, this needs to be done only after the last RK3-substep, else
1426!--    the boundary values won't be accessed.
1427       IF ( intermediate_timestep_count == intermediate_timestep_count_max )  THEN
1428          mc_factor_l   = 0.0_wp
1429          mc_factor     = 0.0_wp
1430!       
1431!--       Sum up the original volume flows (with and without perturbations).
1432!--       Note, for non-normal components (here v and w) it is actually no
1433!--       volume flow.
[2938]1434          IF ( myidx == id_stg_left  )  i = nxl
1435          IF ( myidx == id_stg_right )  i = nxr+1
[4022]1436         
1437          mc_factor_l(1) = SUM( dist_yz(nzb:nzt,nys:nyn,1)                     &
1438                         * MERGE( 1.0_wp, 0.0_wp,                              &
[4346]1439                           BTEST( wall_flags_total_0(nzb:nzt,nys:nyn,i), 1 ) ) )
[4022]1440       
1441          IF ( myidx == id_stg_left  )  i = nxl-1
1442          IF ( myidx == id_stg_right )  i = nxr+1
1443         
1444          mc_factor_l(2) = SUM( dist_yz(nzb:nzt,nysv:nyn,2)                    &
1445                          * MERGE( 1.0_wp, 0.0_wp,                             &
[4346]1446                            BTEST( wall_flags_total_0(nzb:nzt,nysv:nyn,i), 2 ) ) )
[4022]1447          mc_factor_l(3) = SUM( dist_yz(nzb:nzt,nys:nyn,3)                     &
1448                          * MERGE( 1.0_wp, 0.0_wp,                             &
[4346]1449                            BTEST( wall_flags_total_0(nzb:nzt,nys:nyn,i), 3 ) ) )
[4022]1450         
[2938]1451#if defined( __parallel )
1452          CALL MPI_ALLREDUCE( mc_factor_l, mc_factor,                          &
[4022]1453                              3, MPI_REAL, MPI_SUM, comm1dy, ierr )           
1454#else                                                                         
1455          mc_factor   = mc_factor_l                                           
[2938]1456#endif
[4022]1457!     
1458!--       Calculate correction factor and force zero mean perturbations.
1459          mc_factor = mc_factor / REAL( nr_non_topo_yz, KIND = wp )           
1460                                                                               
1461          IF ( myidx == id_stg_left  )  i = nxl                               
1462          IF ( myidx == id_stg_right )  i = nxr+1                             
1463                                                                               
[4438]1464          dist_yz(:,nys:nyn,1) = ( dist_yz(:,nys:nyn,1) - mc_factor(1) )                   &
[4022]1465                        * MERGE( 1.0_wp, 0.0_wp,                               &
[4438]1466                          BTEST( wall_flags_total_0(:,nys:nyn,i), 1 ) )             
[4022]1467                                                                               
1468                                                                               
1469          IF ( myidx == id_stg_left  )  i = nxl-1                             
1470          IF ( myidx == id_stg_right )  i = nxr+1                             
1471                                                                               
[4438]1472          dist_yz(:,nys:nyn,2) = ( dist_yz(:,nys:nyn,2) - mc_factor(2) )                   &
[4022]1473                        * MERGE( 1.0_wp, 0.0_wp,                               &
[4438]1474                          BTEST( wall_flags_total_0(:,nys:nyn,i), 2 ) )             
[4022]1475                                                                               
[4438]1476          dist_yz(:,nys:nyn,3) = ( dist_yz(:,nys:nyn,3) - mc_factor(3) )                   &
[4022]1477                        * MERGE( 1.0_wp, 0.0_wp,                               &
[4438]1478                          BTEST( wall_flags_total_0(:,nys:nyn,i), 3 ) )
[4022]1479!     
[2938]1480!--       Add disturbances
1481          IF ( myidx == id_stg_left  )  THEN
[4022]1482!     
1483!--          For the left boundary distinguish between mesoscale offline / self
1484!--          nesting and turbulent inflow at the left boundary only. In the latter
1485!--          case turbulence is imposed on the mean inflow profiles.
1486             IF ( .NOT. nesting_offline  .AND.  .NOT. child_domain )  THEN 
1487!           
1488!--             Add disturbance at the inflow
[4438]1489                DO  j = nys, nyn
[4022]1490                   DO  k = nzb, nzt+1
1491                      u(k,j,-nbgp+1:0) = ( mean_inflow_profiles(k,1) +         &
1492                                           dist_yz(k,j,1)             )        &
1493                                   * MERGE( 1.0_wp, 0.0_wp,                    &
[4346]1494                                     BTEST( wall_flags_total_0(k,j,0), 1 ) ) 
[4022]1495                      v(k,j,-nbgp:-1)  = ( mean_inflow_profiles(k,2) +         &
1496                                           dist_yz(k,j,2)             )        &
1497                                   * MERGE( 1.0_wp, 0.0_wp,                    &
[4346]1498                                     BTEST( wall_flags_total_0(k,j,-1), 2 ) ) 
[4022]1499                      w(k,j,-nbgp:-1)  =   dist_yz(k,j,3)                      &
1500                                   * MERGE( 1.0_wp, 0.0_wp,                    &
[4346]1501                                     BTEST( wall_flags_total_0(k,j,-1), 3 ) )
[4022]1502                   ENDDO
[2938]1503                ENDDO
[4022]1504             ELSE
1505             
1506                DO  j = nys, nyn
1507                   DO  k = nzb+1, nzt
1508                      u(k,j,0)   = ( u(k,j,0) + dist_yz(k,j,1) )               &
1509                                 * MERGE( 1.0_wp, 0.0_wp,                      &
[4346]1510                                   BTEST( wall_flags_total_0(k,j,0), 1 ) )
[4022]1511                      u(k,j,-1)  = u(k,j,0)
1512                      v(k,j,-1)  = ( v(k,j,-1)  + dist_yz(k,j,2)  )            &
1513                                 * MERGE( 1.0_wp, 0.0_wp,                      &
[4346]1514                                   BTEST( wall_flags_total_0(k,j,-1), 2 ) )
[4022]1515                      w(k,j,-1)  = ( w(k,j,-1)  + dist_yz(k,j,3) )             &
1516                                 * MERGE( 1.0_wp, 0.0_wp,                      &
[4346]1517                                   BTEST( wall_flags_total_0(k,j,-1), 3 ) )
[4022]1518                   ENDDO
1519                ENDDO
1520             ENDIF
[2938]1521          ENDIF
1522          IF ( myidx == id_stg_right  )  THEN
[3186]1523             DO  j = nys, nyn
[3347]1524                DO  k = nzb+1, nzt
[3186]1525                   u(k,j,nxr+1) = ( u(k,j,nxr+1) + dist_yz(k,j,1) )            &
[4022]1526                                  * MERGE( 1.0_wp, 0.0_wp,                     &
[4346]1527                                    BTEST( wall_flags_total_0(k,j,nxr+1), 1 ) ) 
[3186]1528                   v(k,j,nxr+1) = ( v(k,j,nxr+1) + dist_yz(k,j,2) )            &
[4022]1529                                  * MERGE( 1.0_wp, 0.0_wp,                     &
[4346]1530                                    BTEST( wall_flags_total_0(k,j,nxr+1), 2 ) )
[3186]1531                   w(k,j,nxr+1) = ( w(k,j,nxr+1) + dist_yz(k,j,3) )            &
[4022]1532                                  * MERGE( 1.0_wp, 0.0_wp,                     &
[4346]1533                                    BTEST( wall_flags_total_0(k,j,nxr+1), 3 ) )
[2938]1534                ENDDO
1535             ENDDO
1536          ENDIF
1537       ENDIF
1538    ENDIF
1539!
1540!-- Turbulence generation at north and south boundary
1541    IF ( myidy == id_stg_north  .OR.  myidy == id_stg_south )  THEN
1542!
[4022]1543!--    Calculate new set of perturbations. Do this only at last RK3-substep and
1544!--    when dt_stg_call is exceeded. Else the old set of perturbations is
1545!--    imposed
1546       IF ( stg_call )  THEN
[4438]1547          DO  i = nxl, nxr
[4022]1548             DO  k = nzb, nzt + 1
1549!         
1550!--             Update fu, fv, fw following Eq. 14 of Xie and Castro (2008)
1551                IF ( tu(k) == 0.0_wp )  THEN
1552                   fu_xz(k,i) = fuo_xz(k,i)
1553                ELSE
1554                   fu_xz(k,i) = fu_xz(k,i) * EXP( -pi * dt_stg * 0.5_wp / tu(k) ) +     &
1555                            fuo_xz(k,i) * SQRT( 1.0_wp - EXP( -pi * dt_stg / tu(k) ) )
1556                ENDIF
1557         
1558                IF ( tv(k) == 0.0_wp )  THEN
1559                   fv_xz(k,i) = fvo_xz(k,i)
1560                ELSE
1561                   fv_xz(k,i) = fv_xz(k,i) * EXP( -pi * dt_stg * 0.5_wp / tv(k) ) +     &
1562                         fvo_xz(k,i) * SQRT( 1.0_wp - EXP( -pi * dt_stg / tv(k) ) )
1563                ENDIF
1564               
1565                IF ( tw(k) == 0.0_wp )  THEN
1566                   fw_xz(k,i) = fwo_xz(k,i)
1567                ELSE
1568                   fw_xz(k,i) = fw_xz(k,i) * EXP( -pi * dt_stg * 0.5_wp / tw(k) ) +     &
1569                         fwo_xz(k,i) * SQRT( 1.0_wp - EXP( -pi * dt_stg / tw(k) ) )
1570                ENDIF
1571             ENDDO
1572          ENDDO
1573         
1574         
1575          dist_xz(nzb,:,1) = 0.0_wp
1576          dist_xz(nzb,:,2) = 0.0_wp
1577          dist_xz(nzb,:,3) = 0.0_wp
1578         
1579          IF ( myidy == id_stg_south  ) j = nys
1580          IF ( myidy == id_stg_north )  j = nyn+1
[4438]1581          DO  i = nxl, nxr
[4022]1582             DO  k = nzb+1, nzt + 1
1583!         
1584!--             Lund rotation following Eq. 17 in Xie and Castro (2008).
1585!--             Additional factors are added to improve the variance of v and w
1586                !experimental test of 1.2                                         
[3347]1587                dist_xz(k,i,2) = MIN( ( SQRT( a22(k) / MAXVAL(a22) )           &
1588                                      * 1.2_wp )                               &
1589                                     * (   a21(k) * fu_xz(k,i)                 &
[4022]1590                                         + a22(k) * fv_xz(k,i) ), 3.0_wp ) *   &
1591                                    MERGE( 1.0_wp, 0.0_wp,                     &
[4346]1592                                    BTEST( wall_flags_total_0(k,j,i), 2 ) )
[4022]1593             ENDDO
1594          ENDDO
1595         
1596          IF ( myidy == id_stg_south  ) j = nys-1
1597          IF ( myidy == id_stg_north )  j = nyn+1
[4438]1598          DO  i = nxl, nxr
[4022]1599             DO  k = nzb+1, nzt + 1
1600!         
1601!--             Lund rotation following Eq. 17 in Xie and Castro (2008).
1602!--             Additional factors are added to improve the variance of v and w
1603                dist_xz(k,i,1) = MIN( a11(k) * fu_xz(k,i), 3.0_wp ) *          &
1604                                    MERGE( 1.0_wp, 0.0_wp,                     &
[4346]1605                                    BTEST( wall_flags_total_0(k,j,i), 1 ) )   
[4022]1606         
[3347]1607                dist_xz(k,i,3) = MIN( ( SQRT(a33(k) / MAXVAL(a33) )            &
1608                                      * 1.3_wp )                               &
1609                                    * (   a31(k) * fu_xz(k,i)                  &
1610                                        + a32(k) * fv_xz(k,i)                  &
[4022]1611                                        + a33(k) * fw_xz(k,i) ), 3.0_wp )  *   &
1612                                    MERGE( 1.0_wp, 0.0_wp,                     &
[4346]1613                                    BTEST( wall_flags_total_0(k,j,i), 3 ) ) 
[4022]1614             ENDDO
[2938]1615          ENDDO
[4022]1616       ENDIF
[3347]1617
[2938]1618!
1619!--    Mass flux correction following Kim et al. (2013)
1620!--    This correction factor insures that the mass flux is preserved at the
[4022]1621!--    inflow boundary. First, calculate mean value of the imposed
1622!--    perturbations at yz boundary.
1623!--    Note, this needs to be done only after the last RK3-substep, else
1624!--    the boundary values won't be accessed.
1625       IF ( intermediate_timestep_count == intermediate_timestep_count_max )  THEN
1626          mc_factor_l   = 0.0_wp
1627          mc_factor     = 0.0_wp
1628         
1629          IF ( myidy == id_stg_south  ) j = nys
1630          IF ( myidy == id_stg_north )  j = nyn+1
1631         
1632          mc_factor_l(2) = SUM( dist_xz(nzb:nzt,nxl:nxr,2)                     &
1633                         * MERGE( 1.0_wp, 0.0_wp,                              &
[4346]1634                           BTEST( wall_flags_total_0(nzb:nzt,j,nxl:nxr), 2 ) ) )
[4022]1635         
1636          IF ( myidy == id_stg_south  ) j = nys-1
1637          IF ( myidy == id_stg_north )  j = nyn+1
1638         
1639          mc_factor_l(1) = SUM( dist_xz(nzb:nzt,nxlu:nxr,1)                    &
1640                         * MERGE( 1.0_wp, 0.0_wp,                              &
[4346]1641                           BTEST( wall_flags_total_0(nzb:nzt,j,nxlu:nxr), 1 ) ) )
[4022]1642          mc_factor_l(3) = SUM( dist_xz(nzb:nzt,nxl:nxr,3)                     &
1643                         * MERGE( 1.0_wp, 0.0_wp,                              &
[4346]1644                           BTEST( wall_flags_total_0(nzb:nzt,j,nxl:nxr), 3 ) ) )
[4022]1645         
[2938]1646#if defined( __parallel )
[4022]1647          CALL MPI_ALLREDUCE( mc_factor_l, mc_factor,                          &
1648                              3, MPI_REAL, MPI_SUM, comm1dx, ierr )
1649#else     
1650          mc_factor   = mc_factor_l
[2938]1651#endif
[4022]1652         
1653          mc_factor = mc_factor / REAL( nr_non_topo_xz, KIND = wp )
1654         
1655          IF ( myidy == id_stg_south  ) j = nys
1656          IF ( myidy == id_stg_north )  j = nyn+1
1657         
[4438]1658          dist_xz(:,nxl:nxr,2)   = ( dist_xz(:,nxl:nxr,2) - mc_factor(2) )                 &
[4022]1659                           * MERGE( 1.0_wp, 0.0_wp,                            &
[4438]1660                             BTEST( wall_flags_total_0(:,j,nxl:nxr), 2 ) )         
[4022]1661                                                                               
1662                                                                               
1663          IF ( myidy == id_stg_south  ) j = nys-1                             
1664          IF ( myidy == id_stg_north )  j = nyn+1                             
1665                                                                               
[4438]1666          dist_xz(:,nxl:nxr,1)   = ( dist_xz(:,nxl:nxr,1) - mc_factor(1) )                 &
[4022]1667                           * MERGE( 1.0_wp, 0.0_wp,                            &
[4438]1668                             BTEST( wall_flags_total_0(:,j,nxl:nxr), 1 ) )         
[4022]1669                                                                               
[4438]1670          dist_xz(:,nxl:nxr,3)   = ( dist_xz(:,nxl:nxr,3) - mc_factor(3) )                 &
[4022]1671                           * MERGE( 1.0_wp, 0.0_wp,                            &
[4438]1672                             BTEST( wall_flags_total_0(:,j,nxl:nxr), 3 ) )     
[4022]1673!         
1674!--       Add disturbances
1675          IF ( myidy == id_stg_south  )  THEN
1676             DO  i = nxl, nxr
1677                DO  k = nzb+1, nzt
1678                   u(k,-1,i) = ( u(k,-1,i) + dist_xz(k,i,1) )                  &
1679                                        * MERGE( 1.0_wp, 0.0_wp,               &
[4346]1680                                          BTEST( wall_flags_total_0(k,-1,i), 1 ) )
[4022]1681                   v(k,0,i)  = ( v(k,0,i)  + dist_xz(k,i,2)  )                 &
1682                                        * MERGE( 1.0_wp, 0.0_wp,               &
[4346]1683                                          BTEST( wall_flags_total_0(k,0,i), 2 ) )
[4022]1684                   v(k,-1,i) = v(k,0,i)
1685                   w(k,-1,i) = ( w(k,-1,i) + dist_xz(k,i,3)  )                 &
1686                                        * MERGE( 1.0_wp, 0.0_wp,               &
[4346]1687                                          BTEST( wall_flags_total_0(k,-1,i), 3 ) )
[4022]1688                ENDDO
[2938]1689             ENDDO
[4022]1690          ENDIF
1691          IF ( myidy == id_stg_north  )  THEN
1692         
1693             DO  i = nxl, nxr
1694                DO  k = nzb+1, nzt
1695                   u(k,nyn+1,i) = ( u(k,nyn+1,i) + dist_xz(k,i,1) )            &
1696                                     * MERGE( 1.0_wp, 0.0_wp,                  &
[4346]1697                                       BTEST( wall_flags_total_0(k,nyn+1,i), 1 ) )
[4022]1698                   v(k,nyn+1,i) = ( v(k,nyn+1,i) + dist_xz(k,i,2) )            &
1699                                     * MERGE( 1.0_wp, 0.0_wp,                  &
[4346]1700                                       BTEST( wall_flags_total_0(k,nyn+1,i), 2 ) )
[4022]1701                   w(k,nyn+1,i) = ( w(k,nyn+1,i) + dist_xz(k,i,3) )            &
1702                                     * MERGE( 1.0_wp, 0.0_wp,                  &
[4346]1703                                       BTEST( wall_flags_total_0(k,nyn+1,i), 3 ) )
[4022]1704                ENDDO
[2938]1705             ENDDO
[4022]1706          ENDIF
[2938]1707       ENDIF
[2259]1708    ENDIF
[3347]1709!
[4438]1710!-- Exchange ghost points.
1711    CALL exchange_horiz( u, nbgp )
1712    CALL exchange_horiz( v, nbgp )
1713    CALL exchange_horiz( w, nbgp )
1714!
[3347]1715!-- Finally, set time counter for calling STG to zero
[4022]1716    IF ( stg_call )  time_stg_call = 0.0_wp
[2259]1717
[3987]1718    IF ( debug_output_timestep )  CALL debug_message( 'stg_main', 'end' )
1719
[2259]1720 END SUBROUTINE stg_main
1721
1722!------------------------------------------------------------------------------!
1723! Description:
1724! ------------
1725!> Generate a set of random number rand_it wich is equal on each PE
1726!> and calculate the velocity seed f_n.
1727!> f_n is splitted in vertical direction by the number of PEs in x-direction and
1728!> and each PE calculates a vertical subsection of f_n. At the the end, all
1729!> parts are collected to form the full array.
1730!------------------------------------------------------------------------------!
[4309]1731 SUBROUTINE stg_generate_seed_yz( n_y, n_z, b_y, b_z, f_n, id_left, id_right )
[2259]1732
[4309]1733    INTEGER(iwp)           :: id_left     !< core ids at respective boundaries
1734    INTEGER(iwp), OPTIONAL :: id_right    !< core ids at respective boundaries
1735    INTEGER(iwp)           :: j           !< loop index in y-direction
1736    INTEGER(iwp)           :: jj          !< loop index in y-direction
1737    INTEGER(iwp)           :: k           !< loop index in z-direction
1738    INTEGER(iwp)           :: kk          !< loop index in z-direction
1739    INTEGER(iwp)           :: send_count  !< send count for MPI_GATHERV
[2259]1740
1741    INTEGER(iwp), DIMENSION(nzb:nzt+1) :: n_y    !< length scale in y-direction
1742    INTEGER(iwp), DIMENSION(nzb:nzt+1) :: n_z    !< length scale in z-direction
1743
1744    REAL(wp) :: nyz_inv         !< inverse of number of grid points in yz-slice
1745    REAL(wp) :: rand_av         !< average of random number
1746    REAL(wp) :: rand_sigma_inv  !< inverse of stdev of random number
1747
[4438]1748    REAL(wp), DIMENSION(-mergp:mergp,nzb:nzt+1)    :: b_y     !< filter function in y-direction
1749    REAL(wp), DIMENSION(-mergp:mergp,nzb:nzt+1)    :: b_z     !< filter function in z-direction
[4309]1750   
[4438]1751    REAL(wp), DIMENSION(nzb_x_stg:nzt_x_stg+1,nys:nyn) :: f_n_l   !<  local velocity seed
1752    REAL(wp), DIMENSION(nzb:nzt+1,nys:nyn)             :: f_n     !<  velocity seed
[4309]1753   
1754    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rand_it   !< global array of random numbers
[2259]1755!
[4309]1756!-- Generate random numbers using the parallel random generator.
[2259]1757!-- The set of random numbers are modified to have an average of 0 and
[4309]1758!-- unit variance. Note, at the end the random number array must be defined
1759!-- globally in order to compute the correlation matrices. However,
1760!-- the calculation and normalization of random numbers is done locally,
1761!-- while the result is later distributed to all processes. Further,
1762!-- please note, a set of random numbers is only calculated for the
1763!-- left boundary, while the right boundary uses the same random numbers
1764!-- and thus also computes the same correlation matrix.
[4438]1765    ALLOCATE( rand_it(nzb-mergp:nzt+1+mergp,-mergp+nys:nyn+mergp) )
1766    rand_it = 0.0_wp
[2259]1767
1768    rand_av        = 0.0_wp
1769    rand_sigma_inv = 0.0_wp
[4438]1770    nyz_inv        = 1.0_wp / REAL( ( nzt + 1 + mergp - ( nzb - mergp ) + 1 )  &
1771                                  * ( ny + mergp - ( 0 - mergp ) + 1 ),        &
1772                                    KIND=wp )
[4309]1773!
[4438]1774!-- Compute and normalize random numbers.
1775    DO  j = nys - mergp, nyn + mergp
[4309]1776!
[4438]1777!--    Put the random seeds at grid point j
1778       CALL random_seed_parallel( put=seq_rand_yz(:,j) )
1779       DO  k = nzb - mergp, nzt + 1 + mergp
1780          CALL random_number_parallel( random_dummy )
1781          rand_it(k,j) = random_dummy
1782       ENDDO
[4309]1783!
[4438]1784!--    Get the new random seeds from last call at grid point j
1785       CALL random_seed_parallel( get=seq_rand_yz(:,j) )
1786    ENDDO
[4309]1787!
[4438]1788!-- For normalization to zero mean, sum-up the global random numers.
1789!-- To normalize the global set of random numbers,
1790!-- the inner ghost layers mergp must not be summed-up, else
1791!-- the random numbers on the ghost layers will be stronger weighted as they
1792!-- also occur on the inner subdomains.
1793    DO  j = MERGE( nys, nys - mergp, nys /= 0 ),                              &
1794            MERGE( nyn, nyn + mergp, nyn /= ny )
1795       DO  k = nzb - mergp, nzt + 1 + mergp
1796          rand_av = rand_av + rand_it(k,j)
[2259]1797       ENDDO
[4438]1798    ENDDO
1799   
[4309]1800#if defined( __parallel )
1801!
[4438]1802!-- Sum-up the local averages of the random numbers
1803    CALL MPI_ALLREDUCE( MPI_IN_PLACE, rand_av, 1, MPI_REAL,                    &
1804                        MPI_SUM, comm1dy, ierr )
[4309]1805#endif
[4438]1806    rand_av = rand_av * nyz_inv
[4309]1807!
[4438]1808!-- Obtain zero mean
1809    rand_it= rand_it - rand_av
[4309]1810!
[4438]1811!-- Now, compute the variance
1812    DO  j = MERGE( nys, nys - mergp, nys /= 0 ),                               &
1813            MERGE( nyn, nyn + mergp, nyn /= ny )
1814       DO  k = nzb - mergp, nzt + 1 + mergp
1815          rand_sigma_inv = rand_sigma_inv + rand_it(k,j)**2
[2259]1816       ENDDO
[4438]1817    ENDDO
[2259]1818
[4309]1819#if defined( __parallel )
[2259]1820!
[4438]1821!-- Sum-up the local quadratic averages of the random numbers
1822    CALL MPI_ALLREDUCE( MPI_IN_PLACE, rand_sigma_inv, 1, MPI_REAL,          &
1823                        MPI_SUM, comm1dy, ierr )
[4309]1824#endif
1825!
[4438]1826!-- Compute standard deviation
1827    IF ( rand_sigma_inv /= 0.0_wp )  THEN
1828       rand_sigma_inv = 1.0_wp / SQRT( rand_sigma_inv * nyz_inv )
1829    ELSE
1830       rand_sigma_inv = 1.0_wp
[4309]1831    ENDIF
1832!
[4438]1833!-- Normalize with standard deviation to obtain unit variance
1834    rand_it = rand_it * rand_sigma_inv
1835
1836    CALL cpu_log( log_point_s(31), 'STG f_n factors', 'start' )
[4309]1837!
[4438]1838!-- Generate velocity seed following Eq.6 of Xie and Castro (2008). There
1839!-- are two options. In the first one, the computation of the seeds is
1840!-- distributed to all processes along the communicator comm1dy and
1841!-- gathered on the leftmost and, if necessary, on the rightmost process.
1842!-- For huge length scales the computational effort can become quite huge
1843!-- (it scales with the turbulent length scales), so that gain by parallelization
1844!-- exceeds the costs by the subsequent communication.
1845!-- In the second option, which performs better when the turbulent length scales
1846!-- are parametrized and thus the loops are smaller, the seeds are computed
1847!-- locally and no communication is necessary.
1848    IF ( compute_velocity_seeds_local )  THEN
1849
1850       f_n  = 0.0_wp
1851       DO  j = nys, nyn
1852          DO  k = nzb, nzt+1
1853             DO  jj = -n_y(k), n_y(k)
1854                DO  kk = -n_z(k), n_z(k)
1855                   f_n(k,j) = f_n(k,j) + b_y(jj,k) * b_z(kk,k) * rand_it(k+kk,j+jj)
1856                ENDDO
1857             ENDDO
1858          ENDDO
[2259]1859       ENDDO
1860
[4438]1861    ELSE
[2259]1862
[4438]1863       f_n_l  = 0.0_wp
1864       DO  j = nys, nyn
1865          DO  k = nzb_x_stg, nzt_x_stg+1
1866             DO  jj = -n_y(k), n_y(k)
1867                DO  kk = -n_z(k), n_z(k)
1868                   f_n_l(k,j) = f_n_l(k,j) + b_y(jj,k) * b_z(kk,k) * rand_it(k+kk,j+jj)
1869                ENDDO
[2259]1870             ENDDO
1871          ENDDO
1872       ENDDO
1873!
[4438]1874!--    Gather velocity seeds of full subdomain
1875       send_count = nzt_x_stg - nzb_x_stg + 1
1876       IF ( nzt_x_stg == nzt )  send_count = send_count + 1
[2259]1877
1878#if defined( __parallel )
[4309]1879!
[4438]1880!--    Gather the velocity seed matrix on left boundary mpi ranks.
1881       CALL MPI_GATHERV( f_n_l(nzb_x_stg,nys), send_count, stg_type_yz_small,  &
1882                         f_n(nzb+1,nys), recv_count_yz, displs_yz, stg_type_yz,&
1883                         id_left, comm1dx, ierr )
[4309]1884!
[4438]1885!--    If required, gather the same velocity seed matrix on right boundary
1886!--    mpi ranks (in offline nesting for example).
1887       IF ( PRESENT( id_right ) )  THEN
1888          CALL MPI_GATHERV( f_n_l(nzb_x_stg,nys), send_count, stg_type_yz_small,  &
1889                            f_n(nzb+1,nys), recv_count_yz, displs_yz, stg_type_yz,&
1890                            id_right, comm1dx, ierr )
1891       ENDIF
[2259]1892#else
[4438]1893       f_n(nzb+1:nzt+1,nys:nyn) = f_n_l(nzb_x_stg:nzt_x_stg+1,nys:nyn)
[2259]1894#endif
1895
[4438]1896    ENDIF
[2259]1897
[4438]1898    DEALLOCATE( rand_it )
1899
1900    CALL cpu_log( log_point_s(31), 'STG f_n factors', 'stop' )
1901
[2259]1902 END SUBROUTINE stg_generate_seed_yz
1903
[2938]1904
1905!------------------------------------------------------------------------------!
1906! Description:
1907! ------------
1908!> Generate a set of random number rand_it wich is equal on each PE
1909!> and calculate the velocity seed f_n.
1910!> f_n is splitted in vertical direction by the number of PEs in y-direction and
1911!> and each PE calculates a vertical subsection of f_n. At the the end, all
1912!> parts are collected to form the full array.
1913!------------------------------------------------------------------------------!
[4309]1914 SUBROUTINE stg_generate_seed_xz( n_x, n_z, b_x, b_z, f_n, id_south, id_north )
[2938]1915
1916    INTEGER(iwp) :: i           !< loop index in x-direction
[4309]1917    INTEGER(iwp) :: id_north    !< core ids at respective boundaries
1918    INTEGER(iwp) :: id_south    !< core ids at respective boundaries
[2938]1919    INTEGER(iwp) :: ii          !< loop index in x-direction
1920    INTEGER(iwp) :: k           !< loop index in z-direction
1921    INTEGER(iwp) :: kk          !< loop index in z-direction
1922    INTEGER(iwp) :: send_count  !< send count for MPI_GATHERV
1923
1924    INTEGER(iwp), DIMENSION(nzb:nzt+1) :: n_x    !< length scale in x-direction
1925    INTEGER(iwp), DIMENSION(nzb:nzt+1) :: n_z    !< length scale in z-direction
1926
1927    REAL(wp) :: nxz_inv         !< inverse of number of grid points in xz-slice
1928    REAL(wp) :: rand_av         !< average of random number
1929    REAL(wp) :: rand_sigma_inv  !< inverse of stdev of random number
1930
[4438]1931    REAL(wp), DIMENSION(-mergp:mergp,nzb:nzt+1)    :: b_x     !< filter function in x-direction
1932    REAL(wp), DIMENSION(-mergp:mergp,nzb:nzt+1)    :: b_z     !< filter function in z-direction
[4309]1933   
[4438]1934    REAL(wp), DIMENSION(nzb_y_stg:nzt_y_stg+1,nxl:nxr) :: f_n_l   !<  local velocity seed
1935    REAL(wp), DIMENSION(nzb:nzt+1,nxl:nxr)             :: f_n     !<  velocity seed
[2938]1936
[4309]1937    REAL(wp), DIMENSION(:,:), ALLOCATABLE ::  rand_it   !< global array of random numbers
[2938]1938
1939!
[4309]1940!-- Generate random numbers using the parallel random generator.
[2938]1941!-- The set of random numbers are modified to have an average of 0 and
[4309]1942!-- unit variance. Note, at the end the random number array must be defined
1943!-- globally in order to compute the correlation matrices. However,
1944!-- the calculation and normalization of random numbers is done locally,
1945!-- while the result is later distributed to all processes. Further,
1946!-- please note, a set of random numbers is only calculated for the
1947!-- left boundary, while the right boundary uses the same random numbers
1948!-- and thus also computes the same correlation matrix.
[4438]1949    ALLOCATE( rand_it(nzb-mergp:nzt+1+mergp,-mergp+nxl:nxr+mergp) )
1950    rand_it = 0.0_wp
[2938]1951
1952    rand_av        = 0.0_wp
1953    rand_sigma_inv = 0.0_wp
[4438]1954    nxz_inv        = 1.0_wp / REAL( ( nzt + 1 + mergp - ( nzb - mergp ) + 1 )  &
1955                                  * ( nx + mergp - ( 0 - mergp ) +1 ),         &
1956                                    KIND=wp )
[4309]1957!
[4438]1958!-- Compute and normalize random numbers.
1959    DO  i = nxl - mergp, nxr + mergp
[4309]1960!
[4438]1961!--    Put the random seeds at grid point ii
1962       CALL random_seed_parallel( put=seq_rand_xz(:,i) )
1963       DO  k = nzb - mergp, nzt + 1 + mergp
1964          CALL random_number_parallel( random_dummy )
1965          rand_it(k,i) = random_dummy
1966       ENDDO
[4309]1967!
[4438]1968!--    Get the new random seeds from last call at grid point ii
1969       CALL random_seed_parallel( get=seq_rand_xz(:,i) )
1970    ENDDO
[4309]1971!
[4438]1972!-- For normalization to zero mean, sum-up the global random numers.
1973!-- To normalize the global set of random numbers,
1974!-- the inner ghost layers mergp must not be summed-up, else
1975!-- the random numbers on the ghost layers will be stronger weighted as they
1976!-- also occur on the inner subdomains.
1977    DO  i = MERGE( nxl, nxl - mergp, nxl /= 0 ),                              &
1978            MERGE( nxr, nxr + mergp, nxr /= nx )
1979       DO  k = nzb - mergp, nzt + 1 + mergp
1980          rand_av = rand_av + rand_it(k,i)
[2938]1981       ENDDO
[4438]1982    ENDDO
1983   
[4309]1984#if defined( __parallel )
[4438]1985!
1986!-- Sum-up the local averages of the random numbers
1987    CALL MPI_ALLREDUCE( MPI_IN_PLACE, rand_av, 1, MPI_REAL,                    &
1988                        MPI_SUM, comm1dx, ierr )
[4309]1989#endif
[4438]1990    rand_av = rand_av * nxz_inv
[4309]1991!
[4438]1992!-- Obtain zero mean
1993    rand_it= rand_it - rand_av
[4309]1994!
[4438]1995!-- Now, compute the variance
1996    DO  i = MERGE( nxl, nxl - mergp, nxl /= 0 ),                               &
1997            MERGE( nxr, nxr + mergp, nxr /= nx )
1998       DO  k = nzb - mergp, nzt + 1 + mergp
1999          rand_sigma_inv = rand_sigma_inv + rand_it(k,i)**2
[2938]2000       ENDDO
[4438]2001    ENDDO
[2938]2002
[4309]2003#if defined( __parallel )
[4438]2004!
2005!-- Sum-up the local quadratic averages of the random numbers
2006    CALL MPI_ALLREDUCE( MPI_IN_PLACE, rand_sigma_inv, 1, MPI_REAL,          &
2007                        MPI_SUM, comm1dx, ierr )
[4309]2008#endif
[2938]2009!
[4438]2010!-- Compute standard deviation
2011    IF ( rand_sigma_inv /= 0.0_wp )  THEN
2012       rand_sigma_inv = 1.0_wp / SQRT( rand_sigma_inv * nxz_inv )
2013    ELSE
2014       rand_sigma_inv = 1.0_wp
[4309]2015    ENDIF
2016!
[4438]2017!-- Normalize with standard deviation to obtain unit variance
2018    rand_it = rand_it * rand_sigma_inv
2019
2020    CALL cpu_log( log_point_s(31), 'STG f_n factors', 'start' )
[4309]2021!
[4438]2022!-- Generate velocity seed following Eq.6 of Xie and Castro (2008). There
2023!-- are two options. In the first one, the computation of the seeds is
2024!-- distributed to all processes along the communicator comm1dx and
2025!-- gathered on the southmost and, if necessary, on the northmost process.
2026!-- For huge length scales the computational effort can become quite huge
2027!-- (it scales with the turbulent length scales), so that gain by parallelization
2028!-- exceeds the costs by the subsequent communication.
2029!-- In the second option, which performs better when the turbulent length scales
2030!-- are parametrized and thus the loops are smaller, the seeds are computed
2031!-- locally and no communication is necessary.
2032    IF ( compute_velocity_seeds_local )  THEN
[2938]2033
[4438]2034       f_n  = 0.0_wp
2035       DO  i = nxl, nxr
2036          DO  k = nzb, nzt+1
2037             DO  ii = -n_x(k), n_x(k)
2038                DO  kk = -n_z(k), n_z(k)
2039                   f_n(k,i) = f_n(k,i) + b_x(ii,k) * b_z(kk,k) * rand_it(k+kk,i+ii)
2040                ENDDO
[2938]2041             ENDDO
2042          ENDDO
2043       ENDDO
2044
[4438]2045    ELSE
[2938]2046
[4438]2047       f_n_l  = 0.0_wp
2048       DO  i = nxl, nxr
2049          DO  k = nzb_y_stg, nzt_y_stg+1
2050             DO  ii = -n_x(k), n_x(k)
2051                DO  kk = -n_z(k), n_z(k)
2052                   f_n_l(k,i) = f_n_l(k,i) + b_x(ii,k) * b_z(kk,k) * rand_it(k+kk,i+ii)
2053                ENDDO
2054             ENDDO
2055          ENDDO
2056       ENDDO
[2938]2057!
[4438]2058!--    Gather velocity seeds of full subdomain
2059       send_count = nzt_y_stg - nzb_y_stg + 1
2060       IF ( nzt_y_stg == nzt )  send_count = send_count + 1
[2938]2061
2062#if defined( __parallel )
[4309]2063!
[4438]2064!--    Gather the processed velocity seed on south boundary mpi ranks.
2065       CALL MPI_GATHERV( f_n_l(nzb_y_stg,nxl), send_count, stg_type_xz_small,   &
2066                         f_n(nzb+1,nxl), recv_count_xz, displs_xz, stg_type_xz, &
2067                         id_south, comm1dy, ierr )
[4309]2068!
[4438]2069!--    Gather the processed velocity seed on north boundary mpi ranks.
2070       CALL MPI_GATHERV( f_n_l(nzb_y_stg,nxl), send_count, stg_type_xz_small,   &
2071                         f_n(nzb+1,nxl), recv_count_xz, displs_xz, stg_type_xz, &
2072                         id_north, comm1dy, ierr )
[2938]2073#else
[4438]2074       f_n(nzb+1:nzt+1,nxl:nxr) = f_n_l(nzb_y_stg:nzt_y_stg+1,nxl:nxr)
[2938]2075#endif
2076
[4438]2077    ENDIF
2078
2079    DEALLOCATE( rand_it )
2080
2081    CALL cpu_log( log_point_s(31), 'STG f_n factors', 'stop' )
2082
[2938]2083 END SUBROUTINE stg_generate_seed_xz
2084
[3347]2085!------------------------------------------------------------------------------!
2086! Description:
2087! ------------
2088!> Parametrization of the Reynolds stress tensor, following the parametrization
2089!> described in Rotach et al. (1996), which is applied in state-of-the-art
2090!> dispserion modelling. Please note, the parametrization does not distinguish
2091!> between along-wind and cross-wind turbulence.
2092!------------------------------------------------------------------------------!
2093 SUBROUTINE parametrize_reynolds_stress
2094
2095    INTEGER(iwp) :: k            !< loop index in z-direction
2096   
2097    REAL(wp)     ::  zzi         !< ratio of z/zi
2098   
2099    DO  k = nzb+1, nzt+1
2100!
[4022]2101!--    Calculate function to gradually decrease Reynolds stress above ABL top.
2102!--    The function decreases to 1/10 after one length scale above the
2103!--    ABL top.
2104       blend = MIN( 1.0_wp, EXP( d_l * zu(k) - d_l * zi_ribulk ) )
[3347]2105!
[4022]2106!--    Determine normalized height coordinate
2107       zzi = zu(k) / zi_ribulk
[3347]2108!
[4022]2109!--    u'u' and v'v'. Assume isotropy. Note, add a small negative number
[4438]2110!--    to the denominator, else the mergpe-function can crash if scale_l is
[4022]2111!--    zero.
2112       r11(k) = scale_us**2 * (                                                &
2113                   MERGE( 0.35_wp * ABS(                                       &
2114                        - zi_ribulk / ( kappa * scale_l - 10E-4_wp )           &
2115                                       )**( 2.0_wp / 3.0_wp ),                 &
2116                          0.0_wp,                                              &
2117                          scale_l < 0.0_wp )                                   &
2118                 + 5.0_wp - 4.0_wp * zzi                                       &
2119                              ) * blend                                       
2120                                                                               
2121       r22(k) = r11(k)                                                         
2122!                                                                             
2123!--    w'w'                                                                   
2124       r33(k) = scale_wm**2 * (                                                &
2125                   1.5_wp * zzi**( 2.0_wp / 3.0_wp ) * EXP( -2.0_wp * zzi )    &
2126                 + ( 1.7_wp - zzi ) * ( scale_us / scale_wm )**2               &                     
2127                              )  * blend                                       
2128!                                                                             
2129!--    u'w' and v'w'. Assume isotropy.                                         
2130       r31(k) = - scale_us**2 * ( 1.01_wp - MIN( zzi, 1.0_wp ) ) * blend
2131       r32(k) = r31(k)
[3347]2132!
[4022]2133!--    For u'v' no parametrization exist so far - ?. For simplicity assume
2134!--    a similar profile as for u'w'.
2135       r21(k) = r31(k)
[3347]2136    ENDDO
2137
2138!
2139!-- Set bottom boundary condition   
2140    r11(nzb) = r11(nzb+1)
2141    r22(nzb) = r22(nzb+1)
2142    r33(nzb) = r33(nzb+1)
2143
2144    r21(nzb) = r11(nzb+1)
2145    r31(nzb) = r31(nzb+1)
2146    r32(nzb) = r32(nzb+1)
2147   
2148
2149 END SUBROUTINE parametrize_reynolds_stress 
2150 
2151!------------------------------------------------------------------------------!
2152! Description:
2153! ------------
2154!> Calculate the coefficient matrix from the Lund rotation.
2155!------------------------------------------------------------------------------!
2156 SUBROUTINE calc_coeff_matrix
2157
2158    INTEGER(iwp) :: k   !< loop index in z-direction
2159   
2160!
2161!-- Calculate coefficient matrix. Split loops to allow for loop vectorization.
2162    DO  k = nzb+1, nzt+1
[4022]2163       IF ( r11(k) > 10E-6_wp )  THEN
[3347]2164          a11(k) = SQRT( r11(k) ) 
2165          a21(k) = r21(k) / a11(k)
2166          a31(k) = r31(k) / a11(k)
2167       ELSE
2168          a11(k) = 10E-8_wp
2169          a21(k) = 10E-8_wp
2170          a31(k) = 10E-8_wp
2171       ENDIF
2172    ENDDO
2173    DO  k = nzb+1, nzt+1
2174       a22(k) = r22(k) - a21(k)**2 
[4022]2175       IF ( a22(k) > 10E-6_wp )  THEN
[3347]2176          a22(k) = SQRT( a22(k) )
2177          a32(k) = r32(k) - a21(k) * a31(k) / a22(k)
2178       ELSE
2179          a22(k) = 10E-8_wp
2180          a32(k) = 10E-8_wp
2181       ENDIF
2182    ENDDO
2183    DO  k = nzb+1, nzt+1
2184       a33(k) = r33(k) - a31(k)**2 - a32(k)**2
[4022]2185       IF ( a33(k) > 10E-6_wp )  THEN
[3347]2186          a33(k) =  SQRT( a33(k) )
2187       ELSE
2188          a33(k) = 10E-8_wp
2189       ENDIF
2190    ENDDO   
2191!
2192!-- Set bottom boundary condition
2193    a11(nzb) = a11(nzb+1)
2194    a22(nzb) = a22(nzb+1)
2195    a21(nzb) = a21(nzb+1)
2196    a33(nzb) = a33(nzb+1)   
2197    a31(nzb) = a31(nzb+1)
2198    a32(nzb) = a32(nzb+1)   
2199
2200 END SUBROUTINE calc_coeff_matrix
2201 
2202!------------------------------------------------------------------------------!
2203! Description:
2204! ------------
2205!> This routine controls the re-adjustment of the turbulence statistics used
2206!> for generating turbulence at the lateral boundaries. 
2207!------------------------------------------------------------------------------!
2208 SUBROUTINE stg_adjust
2209
[3987]2210    IF ( debug_output_timestep )  CALL debug_message( 'stg_adjust', 'start' )
[3347]2211!
[4022]2212!-- In case of dirichlet inflow boundary conditions only at one lateral
2213!-- boundary, i.e. in the case no offline or self nesting is applied but
2214!-- synthetic turbulence shall be parametrized nevertheless, the
2215!-- boundary-layer depth need to determined first.
2216    IF ( .NOT. nesting_offline  .AND.  .NOT.  child_domain )                   &
2217       CALL nesting_offl_calc_zi   
2218!
2219!-- Compute scaling parameters (domain-averaged), such as friction velocity
2220!-- are calculated.
[3347]2221    CALL calc_scaling_variables
2222!
2223!-- Set length and time scales depending on boundary-layer height
2224    CALL calc_length_and_time_scale
2225!
2226!-- Parametrize Reynolds-stress tensor, diagonal elements as well
2227!-- as r21 (v'u'), r31 (w'u'), r32 (w'v'). Parametrization follows
2228!-- Rotach et al. (1996) and is based on boundary-layer depth,
2229!-- friction velocity and velocity scale.
2230    CALL parametrize_reynolds_stress
2231!
2232!-- Calculate coefficient matrix from Reynolds stress tensor 
2233!-- (Lund rotation)
2234    CALL calc_coeff_matrix
2235!
2236!-- Determine filter functions on basis of updated length scales
2237    CALL stg_filter_func( nux, bux ) !filter ux
2238    CALL stg_filter_func( nuy, buy ) !filter uy
2239    CALL stg_filter_func( nuz, buz ) !filter uz
2240    CALL stg_filter_func( nvx, bvx ) !filter vx
2241    CALL stg_filter_func( nvy, bvy ) !filter vy
2242    CALL stg_filter_func( nvz, bvz ) !filter vz
2243    CALL stg_filter_func( nwx, bwx ) !filter wx
2244    CALL stg_filter_func( nwy, bwy ) !filter wy
2245    CALL stg_filter_func( nwz, bwz ) !filter wz
2246!
2247!-- Reset time counter for controlling next adjustment to zero
2248    time_stg_adjust = 0.0_wp
[3987]2249
2250    IF ( debug_output_timestep )  CALL debug_message( 'stg_adjust', 'end' )
[3347]2251   
2252 END SUBROUTINE stg_adjust 
2253 
2254 
2255!------------------------------------------------------------------------------!
2256! Description:
2257! ------------
2258!> Calculates turbuluent length and time scales if these are not available
2259!> from measurements.
2260!------------------------------------------------------------------------------!
2261 SUBROUTINE calc_length_and_time_scale
2262
[4022]2263    INTEGER(iwp) ::  k !< loop index in z-direction
[3347]2264   
[4022]2265    REAL(wp) ::  length_scale_dum     !< effectively used length scale
2266   
[3347]2267!
2268!-- In initial call the boundary-layer depth can be zero. This case, set
2269!-- minimum value for boundary-layer depth, to setup length scales correctly.
2270    zi_ribulk = MAX( zi_ribulk, zw(nzb+2) )
2271!
2272!-- Set-up default turbulent length scales. From the numerical point of
2273!-- view the imposed perturbations should not be immediately dissipated
2274!-- by the numerics. The numerical dissipation, however, acts on scales
2275!-- up to 8 x the grid spacing. For this reason, set the turbulence
2276!-- length scale to 8 time the grid spacing. Further, above the boundary
2277!-- layer height, set turbulence lenght scales to zero (equivalent to not
2278!-- imposing any perturbations) in order to save computational costs.
2279!-- Typical time scales are derived by assuming Taylors's hypothesis,
2280!-- using the length scales and the mean profiles of u- and v-component.
2281    DO  k = nzb+1, nzt+1
2282!
[4022]2283!--    Determine blending parameter. Within the boundary layer length scales
2284!--    are constant, while above lengths scales approach gradully zero,
2285!--    i.e. imposed turbulence is not correlated in space and time,
2286!--    just white noise, which saves computations power as the loops for the
2287!--    computation of the filter functions depend on the length scales.
2288!--    The value decreases to 1/10 after one length scale above the
2289!--    ABL top.
2290       blend = MIN( 1.0_wp, EXP( d_l * zu(k) - d_l * zi_ribulk ) )
[3347]2291!
[4022]2292!--    Assume isotropic turbulence length scales
2293       nux(k) = MAX( INT( length_scale * ddx     ), 1 ) * blend
[4438]2294       nuy(k) = MAX( INT( length_scale * ddy     ), 1 ) * blend
[4022]2295       nvx(k) = MAX( INT( length_scale * ddx     ), 1 ) * blend
[4438]2296       nvy(k) = MAX( INT( length_scale * ddy     ), 1 ) * blend
[4022]2297       nwx(k) = MAX( INT( length_scale * ddx     ), 1 ) * blend
[4438]2298       nwy(k) = MAX( INT( length_scale * ddy     ), 1 ) * blend
[3347]2299!
[4022]2300!--    Along the vertical direction limit the length scale further by the
2301!--    boundary-layer depth to assure that no length scales larger than
2302!--    the boundary-layer depth are used
2303       length_scale_dum = MIN( length_scale, zi_ribulk )
2304       
2305       nuz(k) = MAX( INT( length_scale_dum * ddzw(k) ), 1 ) * blend
2306       nvz(k) = MAX( INT( length_scale_dum * ddzw(k) ), 1 ) * blend
2307       nwz(k) = MAX( INT( length_scale_dum * ddzw(k) ), 1 ) * blend
[3347]2308!
[4022]2309!--    Limit time scales, else they become very larger for low wind speed,
2310!--    imposing long-living inflow perturbations which in turn propagate
2311!--    further into the model domain. Use u_init and v_init to calculate
2312!--    the time scales, which will be equal to the inflow profiles, both,
2313!--    in offline nesting mode or in dirichlet/radiation mode.
2314       tu(k)  = MIN( dt_stg_adjust, length_scale /                          &
2315                               ( ABS( u_init(k) ) + 0.1_wp ) ) * blend 
2316       tv(k)  = MIN( dt_stg_adjust, length_scale /                          &
2317                               ( ABS( v_init(k) ) + 0.1_wp ) ) * blend
2318!
2319!--    Time scale of w-component is a mixture from u- and v-component.
2320       tw(k)  = SQRT( tu(k)**2 + tv(k)**2 ) * blend
2321     
[3347]2322    ENDDO
2323!
2324!-- Set bottom boundary condition for the length and time scales
2325    nux(nzb) = nux(nzb+1)
2326    nuy(nzb) = nuy(nzb+1)
2327    nuz(nzb) = nuz(nzb+1)
2328    nvx(nzb) = nvx(nzb+1)
2329    nvy(nzb) = nvy(nzb+1)
2330    nvz(nzb) = nvz(nzb+1)
2331    nwx(nzb) = nwx(nzb+1)
2332    nwy(nzb) = nwy(nzb+1)
2333    nwz(nzb) = nwz(nzb+1)
2334
2335    tu(nzb)  = tu(nzb+1)
2336    tv(nzb)  = tv(nzb+1)
2337    tw(nzb)  = tw(nzb+1)
2338
2339
2340 END SUBROUTINE calc_length_and_time_scale 
2341
2342!------------------------------------------------------------------------------!
2343! Description:
2344! ------------
2345!> Calculate scaling variables which are used for turbulence parametrization
2346!> according to Rotach et al. (1996). Scaling variables are: friction velocity,
2347!> boundary-layer depth, momentum velocity scale, and Obukhov length.
2348!------------------------------------------------------------------------------!
2349 SUBROUTINE calc_scaling_variables
2350
2351    INTEGER(iwp) :: i            !< loop index in x-direction
2352    INTEGER(iwp) :: j            !< loop index in y-direction
2353    INTEGER(iwp) :: k            !< loop index in z-direction
2354    INTEGER(iwp) :: m            !< surface element index
2355
2356    REAL(wp) ::  friction_vel_l         !< mean friction veloctiy on subdomain
[3937]2357    REAL(wp) ::  pt_surf_mean           !< mean near surface temperature (at 1st grid point)
2358    REAL(wp) ::  pt_surf_mean_l         !< mean near surface temperature (at 1st grid point) on subdomain
2359    REAL(wp) ::  scale_l_l              !< mean Obukhov lenght on subdomain
[3347]2360    REAL(wp) ::  shf_mean               !< mean surface sensible heat flux
2361    REAL(wp) ::  shf_mean_l             !< mean surface sensible heat flux on subdomain
2362    REAL(wp) ::  w_convective           !< convective velocity scale
2363   
2364!
[3937]2365!-- Calculate mean friction velocity, velocity scale, heat flux and
2366!-- near-surface temperature in the model domain. 
2367    pt_surf_mean_l = 0.0_wp
2368    shf_mean_l     = 0.0_wp
2369    scale_l_l      = 0.0_wp
2370    friction_vel_l = 0.0_wp
[3347]2371    DO  m = 1, surf_def_h(0)%ns
[3937]2372       i = surf_def_h(0)%i(m)
2373       j = surf_def_h(0)%j(m)
2374       k = surf_def_h(0)%k(m)
2375       friction_vel_l = friction_vel_l  + surf_def_h(0)%us(m)
2376       shf_mean_l     = shf_mean_l      + surf_def_h(0)%shf(m) * drho_air(k)
2377       scale_l_l      = scale_l_l       + surf_def_h(0)%ol(m)
2378       pt_surf_mean_l = pt_surf_mean_l  + pt(k,j,i)
[3347]2379    ENDDO   
2380    DO  m = 1, surf_lsm_h%ns
[3937]2381       i = surf_lsm_h%i(m)
2382       j = surf_lsm_h%j(m)
2383       k = surf_lsm_h%k(m)
2384       friction_vel_l = friction_vel_l  + surf_lsm_h%us(m)
2385       shf_mean_l     = shf_mean_l      + surf_lsm_h%shf(m) * drho_air(k)
2386       scale_l_l      = scale_l_l       + surf_lsm_h%ol(m)
2387       pt_surf_mean_l = pt_surf_mean_l  + pt(k,j,i)
[3347]2388    ENDDO
2389    DO  m = 1, surf_usm_h%ns
[3937]2390       i = surf_usm_h%i(m)
2391       j = surf_usm_h%j(m)
2392       k = surf_usm_h%k(m)
2393       friction_vel_l = friction_vel_l  + surf_usm_h%us(m)
2394       shf_mean_l     = shf_mean_l      + surf_usm_h%shf(m) * drho_air(k)
2395       scale_l_l      = scale_l_l       + surf_usm_h%ol(m)
2396       pt_surf_mean_l = pt_surf_mean_l  + pt(k,j,i)
[3347]2397    ENDDO
2398   
2399#if defined( __parallel )
[3937]2400    CALL MPI_ALLREDUCE( friction_vel_l, scale_us,     1, MPI_REAL, MPI_SUM,    &
[3347]2401                        comm2d, ierr )
[3937]2402    CALL MPI_ALLREDUCE( shf_mean_l, shf_mean,         1, MPI_REAL, MPI_SUM,    &
[3347]2403                        comm2d, ierr )
[3937]2404    CALL MPI_ALLREDUCE( scale_l_l, scale_l,           1, MPI_REAL, MPI_SUM,    &
2405                        comm2d, ierr )
2406    CALL MPI_ALLREDUCE( pt_surf_mean_l, pt_surf_mean, 1, MPI_REAL, MPI_SUM,    &
2407                        comm2d, ierr )
[3347]2408#else
[3937]2409    scale_us     = friction_vel_l
2410    shf_mean     = shf_mean_l
2411    scale_l      = scale_l_l
2412    pt_surf_mean = pt_surf_mean_l
[3347]2413#endif
2414
[3937]2415    scale_us     = scale_us     / REAL( ( nx + 1 ) * ( ny + 1 ), KIND = wp )
2416    shf_mean     = shf_mean     / REAL( ( nx + 1 ) * ( ny + 1 ), KIND = wp )
2417    scale_l      = scale_l      / REAL( ( nx + 1 ) * ( ny + 1 ), KIND = wp )
2418    pt_surf_mean = pt_surf_mean / REAL( ( nx + 1 ) * ( ny + 1 ), KIND = wp )   
[3347]2419!
2420!-- Compute mean convective velocity scale. Note, in case the mean heat flux
2421!-- is negative, set convective velocity scale to zero.
2422    IF ( shf_mean > 0.0_wp )  THEN
[3937]2423       w_convective = ( g * shf_mean * zi_ribulk / pt_surf_mean )**( 1.0_wp / 3.0_wp )
[3347]2424    ELSE
2425       w_convective = 0.0_wp
2426    ENDIF
2427!
2428!-- Finally, in order to consider also neutral or stable stratification,
2429!-- compute momentum velocity scale from u* and convective velocity scale,
2430!-- according to Rotach et al. (1996).
2431    scale_wm = ( scale_us**3 + 0.6_wp * w_convective**3 )**( 1.0_wp / 3.0_wp )
2432   
2433 END SUBROUTINE calc_scaling_variables
2434
[2259]2435 END MODULE synthetic_turbulence_generator_mod
Note: See TracBrowser for help on using the repository browser.