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

Last change on this file since 2064 was 2001, checked in by knoop, 8 years ago

last commit documented

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