source: palm/trunk/SOURCE/init_particles.f90 @ 275

Last change on this file since 275 was 274, checked in by heinze, 16 years ago

Indentation of the message calls corrected

  • Property svn:keywords set to Id
File size: 21.5 KB
Line 
1 SUBROUTINE init_particles
2
3!------------------------------------------------------------------------------!
4! Current revisions:
5! -----------------
6! Output of messages replaced by message handling routine
7! Bugfix: arrays for tails are allocated with a minimum size of 10 tails if
8! there is no tail initially
9!
10! Former revisions:
11! -----------------
12! $Id: init_particles.f90 274 2009-03-26 15:11:21Z raasch $
13!
14! 150 2008-02-29 08:19:58Z raasch
15! Setting offset_ocean_* needed for calculating vertical indices within ocean
16! runs
17!
18! 117 2007-10-11 03:27:59Z raasch
19! Sorting of particles only in case of cloud droplets
20!
21! 106 2007-08-16 14:30:26Z raasch
22! variable iran replaced by iran_part
23!
24! 82 2007-04-16 15:40:52Z raasch
25! Preprocessor directives for old systems removed
26!
27! 70 2007-03-18 23:46:30Z raasch
28! displacements for mpi_particle_type changed, age_m initialized,
29! particles-package is now part of the default code
30!
31! 16 2007-02-15 13:16:47Z raasch
32! Bugfix: MPI_REAL in MPI_ALLREDUCE replaced by MPI_INTEGER
33!
34! r4 | raasch | 2007-02-13 12:33:16 +0100 (Tue, 13 Feb 2007)
35! RCS Log replace by Id keyword, revision history cleaned up
36!
37! Revision 1.24  2007/02/11 13:00:17  raasch
38! Bugfix: allocation of tail_mask and new_tail_id in case of restart-runs
39! Bugfix: __ was missing in a cpp-directive
40!
41! Revision 1.1  1999/11/25 16:22:38  raasch
42! Initial revision
43!
44!
45! Description:
46! ------------
47! This routine initializes a set of particles and their attributes (position,
48! radius, ..). Advection of these particles is carried out by advec_particles,
49! plotting is done in data_output_dvrp.
50!------------------------------------------------------------------------------!
51
52    USE arrays_3d
53    USE control_parameters
54    USE grid_variables
55    USE indices
56    USE particle_attributes
57    USE pegrid
58    USE random_function_mod
59
60
61    IMPLICIT NONE
62
63    CHARACTER (LEN=10) ::  particle_binary_version, version_on_file
64
65    INTEGER ::  i, j, n, nn
66#if defined( __parallel )
67    INTEGER, DIMENSION(3) ::  blocklengths, displacements, types
68#endif
69    LOGICAL ::  uniform_particles_l
70    REAL    ::  factor, pos_x, pos_y, pos_z, value
71
72
73#if defined( __parallel )
74!
75!-- Define MPI derived datatype for FORTRAN datatype particle_type (see module
76!-- particle_attributes). Integer length is 4 byte, Real is 8 byte
77    blocklengths(1)  = 19;  blocklengths(2)  =   4;  blocklengths(3)  =   1
78    displacements(1) =  0;  displacements(2) = 152;  displacements(3) = 168
79
80    types(1) = MPI_REAL
81    types(2) = MPI_INTEGER
82    types(3) = MPI_UB
83    CALL MPI_TYPE_STRUCT( 3, blocklengths, displacements, types, &
84                          mpi_particle_type, ierr )
85    CALL MPI_TYPE_COMMIT( mpi_particle_type, ierr )
86#endif
87
88!
89!-- In case of oceans runs, the vertical index calculations need an offset,
90!-- because otherwise the k indices will become negative
91    IF ( ocean )  THEN
92       offset_ocean_nzt    = nzt
93       offset_ocean_nzt_m1 = nzt - 1
94    ENDIF
95
96
97!
98!-- Check the number of particle groups.
99    IF ( number_of_particle_groups > max_number_of_particle_groups )  THEN
100       WRITE( message_string, * ) 'max_number_of_particle_groups =',      &
101                                  max_number_of_particle_groups ,         &
102                                  '&number_of_particle_groups reset to ', &
103                                  max_number_of_particle_groups
104       CALL message( 'init_particles', 'PA0213', 0, 1, 0, 6, 0 )
105       number_of_particle_groups = max_number_of_particle_groups
106    ENDIF
107
108!
109!-- Set default start positions, if necessary
110    IF ( psl(1) == 9999999.9 )  psl(1) = -0.5 * dx
111    IF ( psr(1) == 9999999.9 )  psr(1) = ( nx + 0.5 ) * dx
112    IF ( pss(1) == 9999999.9 )  pss(1) = -0.5 * dy
113    IF ( psn(1) == 9999999.9 )  psn(1) = ( ny + 0.5 ) * dy
114    IF ( psb(1) == 9999999.9 )  psb(1) = zu(nz/2)
115    IF ( pst(1) == 9999999.9 )  pst(1) = psb(1)
116
117    IF ( pdx(1) == 9999999.9  .OR.  pdx(1) == 0.0 )  pdx(1) = dx
118    IF ( pdy(1) == 9999999.9  .OR.  pdy(1) == 0.0 )  pdy(1) = dy
119    IF ( pdz(1) == 9999999.9  .OR.  pdz(1) == 0.0 )  pdz(1) = zu(2) - zu(1)
120
121    DO  j = 2, number_of_particle_groups
122       IF ( psl(j) == 9999999.9 )  psl(j) = psl(j-1)
123       IF ( psr(j) == 9999999.9 )  psr(j) = psr(j-1)
124       IF ( pss(j) == 9999999.9 )  pss(j) = pss(j-1)
125       IF ( psn(j) == 9999999.9 )  psn(j) = psn(j-1)
126       IF ( psb(j) == 9999999.9 )  psb(j) = psb(j-1)
127       IF ( pst(j) == 9999999.9 )  pst(j) = pst(j-1)
128       IF ( pdx(j) == 9999999.9  .OR.  pdx(j) == 0.0 )  pdx(j) = pdx(j-1)
129       IF ( pdy(j) == 9999999.9  .OR.  pdy(j) == 0.0 )  pdy(j) = pdy(j-1)
130       IF ( pdz(j) == 9999999.9  .OR.  pdz(j) == 0.0 )  pdz(j) = pdz(j-1)
131    ENDDO
132
133!
134!-- For the first model run of a possible job chain initialize the
135!-- particles, otherwise read the particle data from file.
136    IF ( TRIM( initializing_actions ) == 'read_restart_data'  &
137         .AND.  read_particles_from_restartfile )  THEN
138
139!
140!--    Read particle data from previous model run.
141!--    First open the input unit.
142       IF ( myid_char == '' )  THEN
143          OPEN ( 90, FILE='PARTICLE_RESTART_DATA_IN'//myid_char, &
144                     FORM='UNFORMATTED' )
145       ELSE
146          OPEN ( 90, FILE='PARTICLE_RESTART_DATA_IN/'//myid_char, &
147                     FORM='UNFORMATTED' )
148       ENDIF
149
150!
151!--    First compare the version numbers
152       READ ( 90 )  version_on_file
153       particle_binary_version = '3.0'
154       IF ( TRIM( version_on_file ) /= TRIM( particle_binary_version ) )  THEN
155          message_string = 'version mismatch concerning data from prior ' // &
156                           'run &version on file    = "' //                  &
157                                         TRIM( version_on_file ) //          &
158                           '&version in program = "' //                      &
159                                         TRIM( particle_binary_version ) // '"'
160          CALL message( 'init_particles', 'PA0214', 1, 2, 0, 6, 0 )
161       ENDIF
162
163!
164!--    Read some particle parameters and the size of the particle arrays,
165!--    allocate them and read their contents.
166       READ ( 90 )  bc_par_b, bc_par_lr, bc_par_ns, bc_par_t,                  &
167                    maximum_number_of_particles, maximum_number_of_tailpoints, &
168                    maximum_number_of_tails, number_of_initial_particles,      &
169                    number_of_particles, number_of_particle_groups,            &
170                    number_of_tails, particle_groups, time_prel,               &
171                    time_write_particle_data, uniform_particles
172
173       IF ( number_of_initial_particles /= 0 )  THEN
174          ALLOCATE( initial_particles(1:number_of_initial_particles) )
175          READ ( 90 )  initial_particles
176       ENDIF
177
178       ALLOCATE( prt_count(nzb:nzt+1,nys-1:nyn+1,nxl-1:nxr+1),       &
179                 prt_start_index(nzb:nzt+1,nys-1:nyn+1,nxl-1:nxr+1), &
180                 particle_mask(maximum_number_of_particles),         &
181                 particles(maximum_number_of_particles) )
182
183       READ ( 90 )  prt_count, prt_start_index
184       READ ( 90 )  particles
185
186       IF ( use_particle_tails )  THEN
187          ALLOCATE( particle_tail_coordinates(maximum_number_of_tailpoints,5, &
188                    maximum_number_of_tails),                                 &
189                    new_tail_id(maximum_number_of_tails),                     &
190                    tail_mask(maximum_number_of_tails) )
191          READ ( 90 )  particle_tail_coordinates
192       ENDIF
193
194       CLOSE ( 90 )
195
196    ELSE
197
198!
199!--    Allocate particle arrays and set attributes of the initial set of
200!--    particles, which can be also periodically released at later times.
201!--    Also allocate array for particle tail coordinates, if needed.
202       ALLOCATE( prt_count(nzb:nzt+1,nys-1:nyn+1,nxl-1:nxr+1),       &
203                 prt_start_index(nzb:nzt+1,nys-1:nyn+1,nxl-1:nxr+1), &
204                 particle_mask(maximum_number_of_particles),         &
205                 particles(maximum_number_of_particles) )
206
207!
208!--    Initialize all particles with dummy values (otherwise errors may
209!--    occur within restart runs). The reason for this is still not clear
210!--    and may be presumably caused by errors in the respective user-interface.
211       particles = particle_type( 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, &
212                                  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, &
213                                  0.0, 0, 0, 0, 0 )
214       particle_groups = particle_groups_type( 0.0, 0.0, 0.0, 0.0 )
215
216!
217!--    Set the default particle size used for dvrp plots
218       IF ( dvrp_psize == 9999999.9 )  dvrp_psize = 0.2 * dx
219
220!
221!--    Set values for the density ratio and radius for all particle
222!--    groups, if necessary
223       IF ( density_ratio(1) == 9999999.9 )  density_ratio(1) = 0.0
224       IF ( radius(1)        == 9999999.9 )  radius(1) = 0.0
225       DO  i = 2, number_of_particle_groups
226          IF ( density_ratio(i) == 9999999.9 )  THEN
227             density_ratio(i) = density_ratio(i-1)
228          ENDIF
229          IF ( radius(i) == 9999999.9 )  radius(i) = radius(i-1)
230       ENDDO
231
232       DO  i = 1, number_of_particle_groups
233          IF ( density_ratio(i) /= 0.0  .AND.  radius(i) == 0 )  THEN
234             WRITE( message_string, * ) 'particle group #', i, 'has a', &
235                                        'density ratio /= 0 but radius = 0'
236             CALL message( 'init_particles', 'PA0215', 1, 2, 0, 6, 0 )
237          ENDIF
238          particle_groups(i)%density_ratio = density_ratio(i)
239          particle_groups(i)%radius        = radius(i)
240       ENDDO
241
242!
243!--    Calculate particle positions and store particle attributes, if
244!--    particle is situated on this PE
245       n = 0
246
247       DO  i = 1, number_of_particle_groups
248
249          pos_z = psb(i)
250
251          DO WHILE ( pos_z <= pst(i) )
252
253             pos_y = pss(i)
254
255             DO WHILE ( pos_y <= psn(i) )
256
257                IF ( pos_y >= ( nys - 0.5 ) * dy  .AND.  &
258                     pos_y <  ( nyn + 0.5 ) * dy )  THEN
259
260                   pos_x = psl(i)
261
262                   DO WHILE ( pos_x <= psr(i) )
263
264                      IF ( pos_x >= ( nxl - 0.5 ) * dx  .AND.  &
265                           pos_x <  ( nxr + 0.5 ) * dx )  THEN
266
267                         DO  j = 1, particles_per_point
268
269                            n = n + 1
270                            IF ( n > maximum_number_of_particles )  THEN
271                               WRITE( message_string, * ) 'number of initial', &
272                                      'particles (', n, ') exceeds',           &
273                                      '&maximum_number_of_particles (',        &
274                                      maximum_number_of_particles, ') on PE ', &
275                                             myid
276                               CALL message( 'init_particles', 'PA0216', &
277                                                                 2, 2, 0, 6, 0 )
278                            ENDIF
279                            particles(n)%x             = pos_x
280                            particles(n)%y             = pos_y
281                            particles(n)%z             = pos_z
282                            particles(n)%age           = 0.0
283                            particles(n)%age_m         = 0.0
284                            particles(n)%dt_sum        = 0.0
285                            particles(n)%dvrp_psize    = dvrp_psize
286                            particles(n)%e_m           = 0.0
287                            particles(n)%speed_x       = 0.0
288                            particles(n)%speed_x_sgs   = 0.0
289                            particles(n)%speed_y       = 0.0
290                            particles(n)%speed_y_sgs   = 0.0
291                            particles(n)%speed_z       = 0.0
292                            particles(n)%speed_z_sgs   = 0.0
293                            particles(n)%origin_x      = pos_x
294                            particles(n)%origin_y      = pos_y
295                            particles(n)%origin_z      = pos_z
296                            particles(n)%radius      = particle_groups(i)%radius
297                            particles(n)%weight_factor =initial_weighting_factor
298                            particles(n)%color         = 1
299                            particles(n)%group         = i
300                            particles(n)%tailpoints    = 0
301                            IF ( use_particle_tails  .AND. &
302                                 MOD( n, skip_particles_for_tail ) == 0 )  THEN
303                               number_of_tails         = number_of_tails + 1
304!
305!--                            This is a temporary provisional setting (see
306!--                            further below!)
307                               particles(n)%tail_id    = number_of_tails
308                            ELSE
309                               particles(n)%tail_id    = 0
310                            ENDIF
311
312                         ENDDO
313
314                      ENDIF
315
316                      pos_x = pos_x + pdx(i)
317
318                   ENDDO
319
320                ENDIF
321
322                pos_y = pos_y + pdy(i)
323
324             ENDDO
325
326             pos_z = pos_z + pdz(i)
327
328          ENDDO
329
330       ENDDO
331
332       number_of_initial_particles = n
333       number_of_particles         = n
334
335!
336!--    Calculate the number of particles and tails of the total domain
337#if defined( __parallel )
338       CALL MPI_ALLREDUCE( number_of_particles, total_number_of_particles, 1, &
339                           MPI_INTEGER, MPI_SUM, comm2d, ierr )
340       CALL MPI_ALLREDUCE( number_of_tails, total_number_of_tails, 1, &
341                           MPI_INTEGER, MPI_SUM, comm2d, ierr )
342#else
343       total_number_of_particles = number_of_particles
344       total_number_of_tails     = number_of_tails
345#endif
346
347!
348!--    Set a seed value for the random number generator to be exclusively
349!--    used for the particle code. The generated random numbers should be
350!--    different on the different PEs.
351       iran_part = iran_part + myid
352
353!
354!--    User modification of initial particles
355       CALL user_init_particles
356
357!
358!--    Store the initial set of particles for release at later times
359       IF ( number_of_initial_particles /= 0 )  THEN
360          ALLOCATE( initial_particles(1:number_of_initial_particles) )
361          initial_particles(1:number_of_initial_particles) = &
362                                        particles(1:number_of_initial_particles)
363       ENDIF
364
365!
366!--    Add random fluctuation to particle positions
367       IF ( random_start_position )  THEN
368
369          DO  n = 1, number_of_initial_particles
370             IF ( psl(particles(n)%group) /= psr(particles(n)%group) )  THEN
371                particles(n)%x = particles(n)%x + &
372                                 ( random_function( iran_part ) - 0.5 ) * &
373                                 pdx(particles(n)%group)
374                IF ( particles(n)%x  <=  ( nxl - 0.5 ) * dx )  THEN
375                   particles(n)%x = ( nxl - 0.4999999999 ) * dx
376                ELSEIF ( particles(n)%x  >=  ( nxr + 0.5 ) * dx )  THEN
377                   particles(n)%x = ( nxr + 0.4999999999 ) * dx
378                ENDIF
379             ENDIF
380             IF ( pss(particles(n)%group) /= psn(particles(n)%group) )  THEN
381                particles(n)%y = particles(n)%y + &
382                                 ( random_function( iran_part ) - 0.5 ) * &
383                                 pdy(particles(n)%group)
384                IF ( particles(n)%y  <=  ( nys - 0.5 ) * dy )  THEN
385                   particles(n)%y = ( nys - 0.4999999999 ) * dy
386                ELSEIF ( particles(n)%y  >=  ( nyn + 0.5 ) * dy )  THEN
387                   particles(n)%y = ( nyn + 0.4999999999 ) * dy
388                ENDIF
389             ENDIF
390             IF ( psb(particles(n)%group) /= pst(particles(n)%group) )  THEN
391                particles(n)%z = particles(n)%z + &
392                                 ( random_function( iran_part ) - 0.5 ) * &
393                                 pdz(particles(n)%group)
394             ENDIF
395          ENDDO
396       ENDIF
397
398!
399!--    Sort particles in the sequence the gridboxes are stored in the memory.
400!--    Only required if cloud droplets are used.
401       IF ( cloud_droplets )  CALL sort_particles
402
403!
404!--    Open file for statistical informations about particle conditions
405       IF ( write_particle_statistics )  THEN
406          CALL check_open( 80 )
407          WRITE ( 80, 8000 )  current_timestep_number, simulated_time, &
408                              number_of_initial_particles,             &
409                              maximum_number_of_particles
410          CALL close_file( 80 )
411       ENDIF
412
413!
414!--    Check if particles are really uniform in color and radius (dvrp_size)
415!--    (uniform_particles is preset TRUE)
416       IF ( uniform_particles )  THEN
417          IF ( number_of_initial_particles == 0 )  THEN
418             uniform_particles_l = .TRUE.
419          ELSE
420             n = number_of_initial_particles
421             IF ( MINVAL( particles(1:n)%dvrp_psize  ) ==     &
422                  MAXVAL( particles(1:n)%dvrp_psize  )  .AND. &
423                  MINVAL( particles(1:n)%color ) ==     &
424                  MAXVAL( particles(1:n)%color ) )  THEN
425                uniform_particles_l = .TRUE.
426             ELSE
427                uniform_particles_l = .FALSE.
428             ENDIF
429          ENDIF
430
431#if defined( __parallel )
432          CALL MPI_ALLREDUCE( uniform_particles_l, uniform_particles, 1, &
433                              MPI_LOGICAL, MPI_LAND, comm2d, ierr )
434#else
435          uniform_particles = uniform_particles_l
436#endif
437
438       ENDIF
439
440!
441!--    Set the beginning of the particle tails and their age
442       IF ( use_particle_tails )  THEN
443!
444!--       Choose the maximum number of tails significantly larger than the
445!--       one initially required
446          factor = 10.0
447          value  = number_of_tails
448          DO WHILE ( value / 10.0 >= 1.0 )
449             factor = factor * 10.0
450             value  = value / 10.0
451          ENDDO
452          maximum_number_of_tails = factor * INT( value )
453!
454!--       Create a minimum number of tails in case that there is no tail
455!--       initially (otherwise, index errors will occur when adressing the
456!--       arrays below)
457          IF ( maximum_number_of_tails == 0 )  maximum_number_of_tails = 10
458
459          ALLOCATE( particle_tail_coordinates(maximum_number_of_tailpoints,5, &
460                    maximum_number_of_tails),                                 &
461                    new_tail_id(maximum_number_of_tails),                     &
462                    tail_mask(maximum_number_of_tails) )
463
464          particle_tail_coordinates  = 0.0
465          minimum_tailpoint_distance = minimum_tailpoint_distance**2
466          number_of_initial_tails    = number_of_tails
467
468          nn = 0
469          DO  n = 1, number_of_particles
470!
471!--          Only for those particles marked above with a provisional tail_id
472!--          tails will be created. Particles now get their final tail_id.
473             IF ( particles(n)%tail_id /= 0 )  THEN
474
475                nn = nn + 1
476                particles(n)%tail_id = nn
477
478                particle_tail_coordinates(1,1,nn) = particles(n)%x
479                particle_tail_coordinates(1,2,nn) = particles(n)%y
480                particle_tail_coordinates(1,3,nn) = particles(n)%z
481                particle_tail_coordinates(1,4,nn) = particles(n)%color
482                particles(n)%tailpoints = 1
483                IF ( minimum_tailpoint_distance /= 0.0 )  THEN
484                   particle_tail_coordinates(2,1,nn) = particles(n)%x
485                   particle_tail_coordinates(2,2,nn) = particles(n)%y
486                   particle_tail_coordinates(2,3,nn) = particles(n)%z
487                   particle_tail_coordinates(2,4,nn) = particles(n)%color
488                   particle_tail_coordinates(1:2,5,nn) = 0.0
489                   particles(n)%tailpoints = 2
490                ENDIF
491
492             ENDIF
493          ENDDO
494       ENDIF
495
496!
497!--    Plot initial positions of particles (only if particle advection is
498!--    switched on from the beginning of the simulation (t=0))
499       IF ( particle_advection_start == 0.0 )  CALL data_output_dvrp
500
501    ENDIF
502
503!
504!-- Check boundary condition and set internal variables
505    SELECT CASE ( bc_par_b )
506   
507       CASE ( 'absorb' )
508          ibc_par_b = 1
509
510       CASE ( 'reflect' )
511          ibc_par_b = 2
512         
513       CASE DEFAULT
514          WRITE( message_string, * )  'unknown boundary condition ',   &
515                                       'bc_par_b = "', TRIM( bc_par_b ), '"'
516          CALL message( 'init_particles', 'PA0217', 1, 2, 0, 6, 0 )
517         
518    END SELECT
519    SELECT CASE ( bc_par_t )
520   
521       CASE ( 'absorb' )
522          ibc_par_t = 1
523
524       CASE ( 'reflect' )
525          ibc_par_t = 2
526         
527       CASE DEFAULT
528          WRITE( message_string, * ) 'unknown boundary condition ',   &
529                                     'bc_par_t = "', TRIM( bc_par_t ), '"'
530          CALL message( 'init_particles', 'PA0218', 1, 2, 0, 6, 0 )
531         
532    END SELECT
533    SELECT CASE ( bc_par_lr )
534
535       CASE ( 'cyclic' )
536          ibc_par_lr = 0
537
538       CASE ( 'absorb' )
539          ibc_par_lr = 1
540
541       CASE ( 'reflect' )
542          ibc_par_lr = 2
543         
544       CASE DEFAULT
545          WRITE( message_string, * ) 'unknown boundary condition ',   &
546                                     'bc_par_lr = "', TRIM( bc_par_lr ), '"'
547          CALL message( 'init_particles', 'PA0219', 1, 2, 0, 6, 0 )
548         
549    END SELECT
550    SELECT CASE ( bc_par_ns )
551
552       CASE ( 'cyclic' )
553          ibc_par_ns = 0
554
555       CASE ( 'absorb' )
556          ibc_par_ns = 1
557
558       CASE ( 'reflect' )
559          ibc_par_ns = 2
560         
561       CASE DEFAULT
562          WRITE( message_string, * ) 'unknown boundary condition ',   &
563                                     'bc_par_ns = "', TRIM( bc_par_ns ), '"'
564          CALL message( 'init_particles', 'PA0220', 1, 2, 0, 6, 0 )
565         
566    END SELECT
567!
568!-- Formats
5698000 FORMAT (I6,1X,F7.2,4X,I6,71X,I6)
570
571 END SUBROUTINE init_particles
Note: See TracBrowser for help on using the repository browser.