source: palm/trunk/SOURCE/lpm_droplet_collision.f90 @ 2000

Last change on this file since 2000 was 2000, checked in by knoop, 5 years ago

Forced header and separation lines into 80 columns

  • Property svn:keywords set to Id
File size: 22.8 KB
Line 
1!> @file lpm_droplet_collision.f90
2!------------------------------------------------------------------------------!
3! This file is part of PALM.
4!
5! PALM is free software: you can redistribute it and/or modify it under the
6! terms of the GNU General Public License as published by the Free Software
7! Foundation, either version 3 of the License, or (at your option) any later
8! version.
9!
10! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13!
14! You should have received a copy of the GNU General Public License along with
15! PALM. If not, see <http://www.gnu.org/licenses/>.
16!
17! Copyright 1997-2016 Leibniz Universitaet Hannover
18!------------------------------------------------------------------------------!
19!
20! Current revisions:
21! ------------------
22! Forced header and separation lines into 80 columns
23!
24! Former revisions:
25! -----------------
26! $Id: lpm_droplet_collision.f90 2000 2016-08-20 18:09:15Z knoop $
27!
28! 1884 2016-04-21 11:11:40Z hoffmann
29! Conservation of mass should only be checked if collisions took place.
30!
31! 1860 2016-04-13 13:21:28Z hoffmann
32! Interpolation of dissipation rate adjusted to more reasonable values.
33!
34! 1822 2016-04-07 07:49:42Z hoffmann
35! Integration of a new collision algortithm based on Shima et al. (2009) and
36! Soelch and Kaercher (2010) called all_or_nothing. The previous implemented
37! collision algorithm is called average_impact. Moreover, both algorithms are
38! now positive definit due to their construction, i.e., no negative weighting
39! factors should occur.
40!
41! 1682 2015-10-07 23:56:08Z knoop
42! Code annotations made doxygen readable
43!
44! 1359 2014-04-11 17:15:14Z hoffmann
45! New particle structure integrated.
46! Kind definition added to all floating point numbers.
47!
48! 1322 2014-03-20 16:38:49Z raasch
49! REAL constants defined as wp_kind
50!
51! 1320 2014-03-20 08:40:49Z raasch
52! ONLY-attribute added to USE-statements,
53! kind-parameters added to all INTEGER and REAL declaration statements,
54! kinds are defined in new module kinds,
55! revision history before 2012 removed,
56! comment fields (!:) to be used for variable explanations added to
57! all variable declaration statements
58!
59! 1092 2013-02-02 11:24:22Z raasch
60! unused variables removed
61!
62! 1071 2012-11-29 16:54:55Z franke
63! Calculation of Hall and Wang kernel now uses collision-coalescence formulation
64! proposed by Wang instead of the continuous collection equation (for more
65! information about new method see PALM documentation)
66! Bugfix: message identifiers added
67!
68! 1036 2012-10-22 13:43:42Z raasch
69! code put under GPL (PALM 3.9)
70!
71! 849 2012-03-15 10:35:09Z raasch
72! initial revision (former part of advec_particles)
73!
74!
75! Description:
76! ------------
77!> Calculates change in droplet radius by collision. Droplet collision is
78!> calculated for each grid box seperately. Collision is parameterized by
79!> using collision kernels. Two different kernels are available:
80!> Hall kernel: Kernel from Hall (1980, J. Atmos. Sci., 2486-2507), which
81!>              considers collision due to pure gravitational effects.
82!> Wang kernel: Beside gravitational effects (treated with the Hall-kernel) also
83!>              the effects of turbulence on the collision are considered using
84!>              parameterizations of Ayala et al. (2008, New J. Phys., 10,
85!>              075015) and Wang and Grabowski (2009, Atmos. Sci. Lett., 10,
86!>              1-8). This kernel includes three possible effects of turbulence:
87!>              the modification of the relative velocity between the droplets,
88!>              the effect of preferential concentration, and the enhancement of
89!>              collision efficiencies.
90!------------------------------------------------------------------------------!
91 SUBROUTINE lpm_droplet_collision (i,j,k)
92 
93
94
95    USE arrays_3d,                                                             &
96        ONLY:  diss, ql_v, ql_vp
97
98    USE cloud_parameters,                                                      &
99        ONLY:  rho_l
100
101    USE constants,                                                             &
102        ONLY:  pi
103
104    USE control_parameters,                                                    &
105        ONLY:  dt_3d, message_string, dz
106
107    USE cpulog,                                                                &
108        ONLY:  cpu_log, log_point_s
109
110    USE grid_variables,                                                        &
111        ONLY:  dx, dy
112
113    USE kinds
114
115    USE lpm_collision_kernels_mod,                                             &
116        ONLY:  ckernel, recalculate_kernel
117
118    USE particle_attributes,                                                   &
119        ONLY:  all_or_nothing, average_impact, dissipation_classes,            &
120               hall_kernel, iran_part, number_of_particles, particles,         &
121               particle_type, prt_count, use_kernel_tables, wang_kernel
122
123    USE random_function_mod,                                                   &
124        ONLY:  random_function
125
126    USE pegrid
127
128    IMPLICIT NONE
129
130    INTEGER(iwp) ::  eclass   !<
131    INTEGER(iwp) ::  i        !<
132    INTEGER(iwp) ::  j        !<
133    INTEGER(iwp) ::  k        !<
134    INTEGER(iwp) ::  n        !<
135    INTEGER(iwp) ::  m        !<
136    INTEGER(iwp) ::  rclass_l !<
137    INTEGER(iwp) ::  rclass_s !<
138
139    REAL(wp) ::  collection_probability  !< probability for collection
140    REAL(wp) ::  ddV                     !< inverse grid box volume
141    REAL(wp) ::  epsilon                 !< dissipation rate
142    REAL(wp) ::  factor_volume_to_mass   !< 4.0 / 3.0 * pi * rho_l
143    REAL(wp) ::  xm                      !< mean mass of droplet m
144    REAL(wp) ::  xn                      !< mean mass of droplet n
145
146    REAL(wp), DIMENSION(:), ALLOCATABLE ::  weight  !< weighting factor
147    REAL(wp), DIMENSION(:), ALLOCATABLE ::  mass    !< total mass of super droplet
148
149    CALL cpu_log( log_point_s(43), 'lpm_droplet_coll', 'start' )
150
151    number_of_particles   = prt_count(k,j,i)
152    factor_volume_to_mass = 4.0_wp / 3.0_wp * pi * rho_l
153    ddV                   = 1 / ( dx * dy * dz )
154!
155!-- Collision requires at least one super droplet inside the box
156    IF ( number_of_particles > 0 )  THEN
157
158!
159!--    Now apply the different kernels
160       IF ( use_kernel_tables )  THEN
161!
162!--       Fast method with pre-calculated collection kernels for
163!--       discrete radius- and dissipation-classes.
164!--
165!--       Determine dissipation class index of this gridbox
166          IF ( wang_kernel )  THEN
167             eclass = INT( diss(k,j,i) * 1.0E4_wp / 600.0_wp * &
168                           dissipation_classes ) + 1
169             epsilon = diss(k,j,i)
170          ELSE
171             epsilon = 0.0_wp
172          ENDIF
173          IF ( hall_kernel  .OR.  epsilon * 1.0E4_wp < 0.001_wp )  THEN
174             eclass = 0   ! Hall kernel is used
175          ELSE
176             eclass = MIN( dissipation_classes, eclass )
177          ENDIF
178
179!
180!--       Droplet collision are calculated using collision-coalescence
181!--       formulation proposed by Wang (see PALM documentation)
182!--       Temporary fields for total mass of super-droplet and weighting factors
183!--       are allocated.
184          ALLOCATE(mass(1:number_of_particles), weight(1:number_of_particles))
185
186          mass(1:number_of_particles)   = particles(1:number_of_particles)%weight_factor * &
187                                          particles(1:number_of_particles)%radius**3     * &
188                                          factor_volume_to_mass
189          weight(1:number_of_particles) = particles(1:number_of_particles)%weight_factor
190
191          IF ( average_impact )  THEN  ! select collision algorithm
192
193             DO  n = 1, number_of_particles
194
195                rclass_l = particles(n)%class
196                xn       = mass(n) / weight(n)
197
198                DO  m = n, number_of_particles
199
200                   rclass_s = particles(m)%class
201                   xm       = mass(m) / weight(m)
202
203                   IF ( xm .LT. xn )  THEN
204                     
205!
206!--                   Particle n collects smaller particle m
207                      collection_probability = ckernel(rclass_l,rclass_s,eclass) * &
208                                               weight(n) * ddV * dt_3d
209
210                      mass(n)   = mass(n)   + mass(m)   * collection_probability
211                      weight(m) = weight(m) - weight(m) * collection_probability
212                      mass(m)   = mass(m)   - mass(m)   * collection_probability
213                   ELSEIF ( xm .GT. xn )  THEN 
214!
215!--                   Particle m collects smaller particle n
216                      collection_probability = ckernel(rclass_l,rclass_s,eclass) * &
217                                               weight(m) * ddV * dt_3d
218
219                      mass(m)   = mass(m)   + mass(n)   * collection_probability
220                      weight(n) = weight(n) - weight(n) * collection_probability
221                      mass(n)   = mass(n)   - mass(n)   * collection_probability
222                   ELSE
223!
224!--                   Same-size collections. If n = m, weight is reduced by the
225!--                   number of possible same-size collections; the total mass
226!--                   is not changed during same-size collection.
227!--                   Same-size collections of different
228!--                   particles ( n /= m ) are treated as same-size collections
229!--                   of ONE partilce with weight = weight(n) + weight(m) and
230!--                   mass = mass(n) + mass(m).
231!--                   Accordingly, each particle loses the same number of
232!--                   droplets to the other particle, but this has no effect on
233!--                   total mass mass, since the exchanged droplets have the
234!--                   same radius.
235
236!--                   Note: For m = n this equation is an approximation only
237!--                   valid for weight >> 1 (which is usually the case). The
238!--                   approximation is weight(n)-1 = weight(n).
239                      weight(n) = weight(n) - 0.5_wp * weight(n) *                &
240                                              ckernel(rclass_l,rclass_s,eclass) * &
241                                              weight(m) * ddV * dt_3d
242                      IF ( n .NE. m )  THEN
243                         weight(m) = weight(m) - 0.5_wp * weight(m) *                &
244                                                 ckernel(rclass_l,rclass_s,eclass) * &
245                                                 weight(n) * ddV * dt_3d
246                      ENDIF
247                   ENDIF
248
249                ENDDO
250
251                ql_vp(k,j,i) = ql_vp(k,j,i) + mass(n) / factor_volume_to_mass
252
253             ENDDO
254
255          ELSEIF ( all_or_nothing )  THEN  ! select collision algorithm
256
257             DO  n = 1, number_of_particles
258
259                rclass_l = particles(n)%class
260                xn       = mass(n) / weight(n) ! mean mass of droplet n
261
262                DO  m = n, number_of_particles
263
264                   rclass_s = particles(m)%class
265                   xm = mass(m) / weight(m) ! mean mass of droplet m
266
267                   IF ( weight(n) .LT. weight(m) )  THEN
268!
269!--                   Particle n collects weight(n) droplets of particle m 
270                      collection_probability = ckernel(rclass_l,rclass_s,eclass) * &
271                                               weight(m) * ddV * dt_3d
272
273                      IF ( collection_probability .GT. random_function( iran_part ) )  THEN
274                         mass(n)   = mass(n)   + weight(n) * xm
275                         weight(m) = weight(m) - weight(n)
276                         mass(m)   = mass(m)   - weight(n) * xm
277                      ENDIF
278
279                   ELSEIF ( weight(m) .LT. weight(n) )  THEN 
280!
281!--                   Particle m collects weight(m) droplets of particle n 
282                      collection_probability = ckernel(rclass_l,rclass_s,eclass) * &
283                                               weight(n) * ddV * dt_3d
284
285                      IF ( collection_probability .GT. random_function( iran_part ) )  THEN
286                         mass(m)   = mass(m)   + weight(m) * xn
287                         weight(n) = weight(n) - weight(m)
288                         mass(n)   = mass(n)   - weight(m) * xn
289                      ENDIF
290                   ELSE
291!
292!--                   Collisions of particles of the same weighting factor.
293!--                   Particle n collects 1/2 weight(n) droplets of particle m,
294!--                   particle m collects 1/2 weight(m) droplets of particle n.
295!--                   The total mass mass changes accordingly.
296!--                   If n = m, the first half of the droplets coalesces with the
297!--                   second half of the droplets; mass is unchanged because
298!--                   xm = xn for n = m.
299
300!--                   Note: For m = n this equation is an approximation only
301!--                   valid for weight >> 1 (which is usually the case). The
302!--                   approximation is weight(n)-1 = weight(n).
303                      collection_probability = ckernel(rclass_l,rclass_s,eclass) * &
304                                               weight(n) * ddV * dt_3d
305
306                      IF ( collection_probability .GT. random_function( iran_part ) )  THEN
307                         mass(n)   = mass(n)   + 0.5_wp * weight(n) * ( xm - xn )
308                         mass(m)   = mass(m)   + 0.5_wp * weight(m) * ( xn - xm )
309                         weight(n) = weight(n) - 0.5_wp * weight(m)
310                         weight(m) = weight(n)
311                      ENDIF
312                   ENDIF
313
314                ENDDO
315
316                ql_vp(k,j,i) = ql_vp(k,j,i) + mass(n) / factor_volume_to_mass
317
318             ENDDO
319
320          ENDIF
321
322
323
324
325          IF ( ANY(weight < 0.0_wp) )  THEN
326                WRITE( message_string, * ) 'negative weighting'
327                CALL message( 'lpm_droplet_collision', 'PA0028',      &
328                               2, 2, -1, 6, 1 )
329          ENDIF
330
331          particles(1:number_of_particles)%radius = ( mass(1:number_of_particles) /   &
332                                                      ( weight(1:number_of_particles) &
333                                                        * factor_volume_to_mass       &
334                                                      )                               &
335                                                    )**0.33333333333333_wp
336
337          particles(1:number_of_particles)%weight_factor = weight(1:number_of_particles)
338
339          DEALLOCATE(weight, mass)
340
341       ELSEIF ( .NOT. use_kernel_tables )  THEN
342!
343!--       Collection kernels are calculated for every new
344!--       grid box. First, allocate memory for kernel table.
345!--       Third dimension is 1, because table is re-calculated for
346!--       every new dissipation value.
347          ALLOCATE( ckernel(1:number_of_particles,1:number_of_particles,1:1) )
348!
349!--       Now calculate collection kernel for this box. Note that
350!--       the kernel is based on the previous time step
351          CALL recalculate_kernel( i, j, k )
352!
353!--       Droplet collision are calculated using collision-coalescence
354!--       formulation proposed by Wang (see PALM documentation)
355!--       Temporary fields for total mass of super-droplet and weighting factors
356!--       are allocated.
357          ALLOCATE(mass(1:number_of_particles), weight(1:number_of_particles))
358
359          mass(1:number_of_particles) = particles(1:number_of_particles)%weight_factor * &
360                                        particles(1:number_of_particles)%radius**3     * &
361                                        factor_volume_to_mass
362
363          weight(1:number_of_particles) = particles(1:number_of_particles)%weight_factor
364
365          IF ( average_impact )  THEN  ! select collision algorithm
366
367             DO  n = 1, number_of_particles
368
369                xn = mass(n) / weight(n) ! mean mass of droplet n
370
371                DO  m = n, number_of_particles
372
373                   xm = mass(m) / weight(m) !mean mass of droplet m
374
375                   IF ( xm .LT. xn )  THEN
376!
377!--                   Particle n collects smaller particle m
378                      collection_probability = ckernel(n,m,1) * weight(n) *    &
379                                               ddV * dt_3d
380
381                      mass(n)   = mass(n)   + mass(m)   * collection_probability
382                      weight(m) = weight(m) - weight(m) * collection_probability
383                      mass(m)   = mass(m)   - mass(m)   * collection_probability
384                   ELSEIF ( xm .GT. xn )  THEN 
385!
386!--                   Particle m collects smaller particle n
387                      collection_probability = ckernel(n,m,1) * weight(m) *    &
388                                               ddV * dt_3d
389
390                      mass(m)   = mass(m)   + mass(n)   * collection_probability
391                      weight(n) = weight(n) - weight(n) * collection_probability
392                      mass(n)   = mass(n)   - mass(n)   * collection_probability
393                   ELSE
394!
395!--                   Same-size collections. If n = m, weight is reduced by the
396!--                   number of possible same-size collections; the total mass
397!--                   mass is not changed during same-size collection.
398!--                   Same-size collections of different
399!--                   particles ( n /= m ) are treated as same-size collections
400!--                   of ONE partilce with weight = weight(n) + weight(m) and
401!--                   mass = mass(n) + mass(m).
402!--                   Accordingly, each particle loses the same number of
403!--                   droplets to the other particle, but this has no effect on
404!--                   total mass mass, since the exchanged droplets have the
405!--                   same radius.
406!--
407!--                   Note: For m = n this equation is an approximation only
408!--                   valid for weight >> 1 (which is usually the case). The
409!--                   approximation is weight(n)-1 = weight(n).
410                      weight(n) = weight(n) - 0.5_wp * weight(n) *             &
411                                              ckernel(n,m,1) * weight(m) *     &
412                                              ddV * dt_3d
413                      IF ( n .NE. m )  THEN
414                         weight(m) = weight(m) - 0.5_wp * weight(m) *          &
415                                                 ckernel(n,m,1) * weight(n) *  &
416                                                 ddV * dt_3d
417                      ENDIF
418                   ENDIF
419
420
421                ENDDO
422
423                ql_vp(k,j,i) = ql_vp(k,j,i) + mass(n) / factor_volume_to_mass
424
425             ENDDO
426
427          ELSEIF ( all_or_nothing )  THEN  ! select collision algorithm
428
429             DO  n = 1, number_of_particles
430
431                xn = mass(n) / weight(n) ! mean mass of droplet n
432
433                DO  m = n, number_of_particles
434
435                   xm = mass(m) / weight(m) !mean mass of droplet m
436
437                   IF ( weight(n) .LT. weight(m) )  THEN
438!
439!--                   Particle n collects smaller particle m
440                      collection_probability = ckernel(n,m,1) * weight(m) *    &
441                                               ddV * dt_3d
442
443                      IF ( collection_probability .GT. random_function( iran_part ) )  THEN
444                         mass(n) = mass(n) + weight(n) * xm 
445                         weight(m)    = weight(m)    - weight(n)
446                         mass(m) = mass(m) - weight(n) * xm
447                      ENDIF
448
449                   ELSEIF ( weight(m) .LT. weight(n) )  THEN
450!
451!--                   Particle m collects smaller particle n
452                      collection_probability = ckernel(n,m,1) * weight(n) *    &
453                                               ddV * dt_3d
454
455                      IF ( collection_probability .GT. random_function( iran_part ) )  THEN
456                         mass(m) = mass(m) + weight(m) * xn
457                         weight(n)    = weight(n)    - weight(m)
458                         mass(n) = mass(n) - weight(m) * xn
459                      ENDIF
460                   ELSE
461!
462!--                   Collisions of particles of the same weighting factor.
463!--                   Particle n collects 1/2 weight(n) droplets of particle m,
464!--                   particle m collects 1/2 weight(m) droplets of particle n.
465!--                   The total mass mass changes accordingly.
466!--                   If n = m, the first half of the droplets coalesces with the
467!--                   second half of the droplets; mass is unchanged because
468!--                   xm = xn for n = m.
469!--
470!--                   Note: For m = n this equation is an approximation only
471!--                   valid for weight >> 1 (which is usually the case). The
472!--                   approximation is weight(n)-1 = weight(n).
473                      collection_probability = ckernel(n,m,1) * weight(n) *    &
474                                               ddV * dt_3d
475
476                      IF ( collection_probability .GT. random_function( iran_part ) )  THEN
477                         mass(n)   = mass(n)   + 0.5_wp * weight(n) * ( xm - xn )
478                         mass(m)   = mass(m)   + 0.5_wp * weight(m) * ( xn - xm )
479                         weight(n) = weight(n) - 0.5_wp * weight(m)
480                         weight(m) = weight(n)
481                      ENDIF
482                   ENDIF
483
484
485                ENDDO
486
487                ql_vp(k,j,i) = ql_vp(k,j,i) + mass(n) / factor_volume_to_mass
488
489             ENDDO
490
491          ENDIF
492
493          IF ( ANY(weight < 0.0_wp) )  THEN
494                WRITE( message_string, * ) 'negative weighting'
495                CALL message( 'lpm_droplet_collision', 'PA0028',      &
496                               2, 2, -1, 6, 1 )
497          ENDIF
498
499          particles(1:number_of_particles)%radius = ( mass(1:number_of_particles) /   &
500                                                      ( weight(1:number_of_particles) &
501                                                        * factor_volume_to_mass       &
502                                                      )                               &
503                                                    )**0.33333333333333_wp
504
505          particles(1:number_of_particles)%weight_factor = weight(1:number_of_particles)
506
507          DEALLOCATE( weight, mass, ckernel )
508
509       ENDIF
510 
511!
512!--    Check if LWC is conserved during collision process
513       IF ( ql_v(k,j,i) /= 0.0_wp )  THEN
514          IF ( ql_vp(k,j,i) / ql_v(k,j,i) >= 1.0001_wp  .OR.                      &
515               ql_vp(k,j,i) / ql_v(k,j,i) <= 0.9999_wp )  THEN
516             WRITE( message_string, * ) ' LWC is not conserved during',           &
517                                        ' collision! ',                           &
518                                        ' LWC after condensation: ', ql_v(k,j,i), &
519                                        ' LWC after collision: ', ql_vp(k,j,i)
520             CALL message( 'lpm_droplet_collision', 'PA0040', 2, 2, -1, 6, 1 )
521          ENDIF
522       ENDIF
523
524    ENDIF
525 
526    CALL cpu_log( log_point_s(43), 'lpm_droplet_coll', 'stop' )
527
528 END SUBROUTINE lpm_droplet_collision
Note: See TracBrowser for help on using the repository browser.