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

Last change on this file since 2338 was 2312, checked in by hoffmann, 7 years ago

various improvements of the LCM

  • Property svn:keywords set to Id
File size: 15.0 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-2017 Leibniz Universitaet Hannover
18!------------------------------------------------------------------------------!
19!
20! Current revisions:
21! ------------------
22!
23!
24! Former revisions:
25! -----------------
26! $Id: lpm_droplet_collision.f90 2312 2017-07-14 20:26:51Z gronemeier $
27! Consideration of aerosol mass during collision. Average impact algorithm has
28! been removed.
29!
30! 2274 2017-06-09 13:27:48Z Giersch
31! Changed error messages
32!
33! 2123 2017-01-18 12:34:59Z hoffmann
34!
35! 2122 2017-01-18 12:22:54Z hoffmann
36! Some reformatting of the code.
37!
38! 2000 2016-08-20 18:09:15Z knoop
39! Forced header and separation lines into 80 columns
40!
41! 1884 2016-04-21 11:11:40Z hoffmann
42! Conservation of mass should only be checked if collisions took place.
43!
44! 1860 2016-04-13 13:21:28Z hoffmann
45! Interpolation of dissipation rate adjusted to more reasonable values.
46!
47! 1822 2016-04-07 07:49:42Z hoffmann
48! Integration of a new collision algortithm based on Shima et al. (2009) and
49! Soelch and Kaercher (2010) called all_or_nothing. The previous implemented
50! collision algorithm is called average_impact. Moreover, both algorithms are
51! now positive definit due to their construction, i.e., no negative weighting
52! factors should occur.
53!
54! 1682 2015-10-07 23:56:08Z knoop
55! Code annotations made doxygen readable
56!
57! 1359 2014-04-11 17:15:14Z hoffmann
58! New particle structure integrated.
59! Kind definition added to all floating point numbers.
60!
61! 1322 2014-03-20 16:38:49Z raasch
62! REAL constants defined as wp_kind
63!
64! 1320 2014-03-20 08:40:49Z raasch
65! ONLY-attribute added to USE-statements,
66! kind-parameters added to all INTEGER and REAL declaration statements,
67! kinds are defined in new module kinds,
68! revision history before 2012 removed,
69! comment fields (!:) to be used for variable explanations added to
70! all variable declaration statements
71!
72! 1092 2013-02-02 11:24:22Z raasch
73! unused variables removed
74!
75! 1071 2012-11-29 16:54:55Z franke
76! Calculation of Hall and Wang kernel now uses collision-coalescence formulation
77! proposed by Wang instead of the continuous collection equation (for more
78! information about new method see PALM documentation)
79! Bugfix: message identifiers added
80!
81! 1036 2012-10-22 13:43:42Z raasch
82! code put under GPL (PALM 3.9)
83!
84! 849 2012-03-15 10:35:09Z raasch
85! initial revision (former part of advec_particles)
86!
87!
88! Description:
89! ------------
90!> Calculates change in droplet radius by collision. Droplet collision is
91!> calculated for each grid box seperately. Collision is parameterized by
92!> using collision kernels. Two different kernels are available:
93!> Hall kernel: Kernel from Hall (1980, J. Atmos. Sci., 2486-2507), which
94!>              considers collision due to pure gravitational effects.
95!> Wang kernel: Beside gravitational effects (treated with the Hall-kernel) also
96!>              the effects of turbulence on the collision are considered using
97!>              parameterizations of Ayala et al. (2008, New J. Phys., 10,
98!>              075015) and Wang and Grabowski (2009, Atmos. Sci. Lett., 10,
99!>              1-8). This kernel includes three possible effects of turbulence:
100!>              the modification of the relative velocity between the droplets,
101!>              the effect of preferential concentration, and the enhancement of
102!>              collision efficiencies.
103!------------------------------------------------------------------------------!
104 SUBROUTINE lpm_droplet_collision (i,j,k)
105
106    USE arrays_3d,                                                             &
107        ONLY:  diss, ql_v, ql_vp
108
109    USE cloud_parameters,                                                      &
110        ONLY:  rho_l
111
112    USE constants,                                                             &
113        ONLY:  pi
114
115    USE control_parameters,                                                    &
116        ONLY:  dt_3d, message_string, dz
117
118    USE cpulog,                                                                &
119        ONLY:  cpu_log, log_point_s
120
121    USE grid_variables,                                                        &
122        ONLY:  dx, dy
123
124    USE kinds
125
126    USE lpm_collision_kernels_mod,                                             &
127        ONLY:  ckernel, recalculate_kernel
128
129    USE particle_attributes,                                                   &
130        ONLY:  curvature_solution_effects, dissipation_classes, hall_kernel,   &
131               iran_part, number_of_particles, particles, particle_type,       &
132               prt_count, rho_s, use_kernel_tables, wang_kernel
133
134    USE random_function_mod,                                                   &
135        ONLY:  random_function
136
137    USE pegrid
138
139    IMPLICIT NONE
140
141    INTEGER(iwp) ::  eclass   !<
142    INTEGER(iwp) ::  i        !<
143    INTEGER(iwp) ::  j        !<
144    INTEGER(iwp) ::  k        !<
145    INTEGER(iwp) ::  n        !<
146    INTEGER(iwp) ::  m        !<
147    INTEGER(iwp) ::  rclass_l !<
148    INTEGER(iwp) ::  rclass_s !<
149
150    REAL(wp) ::  collection_probability  !< probability for collection
151    REAL(wp) ::  ddV                     !< inverse grid box volume
152    REAL(wp) ::  epsilon                 !< dissipation rate
153    REAL(wp) ::  factor_volume_to_mass   !< 4.0 / 3.0 * pi * rho_l
154    REAL(wp) ::  xm                      !< droplet mass of super-droplet m
155    REAL(wp) ::  xn                      !< droplet mass of super-droplet n
156    REAL(wp) ::  xsm                     !< aerosol mass of super-droplet m
157    REAL(wp) ::  xsn                     !< aerosol mass of super-droplet n
158
159    REAL(wp), DIMENSION(:), ALLOCATABLE ::  weight    !< weighting factor
160    REAL(wp), DIMENSION(:), ALLOCATABLE ::  mass      !< total mass of super droplet
161    REAL(wp), DIMENSION(:), ALLOCATABLE ::  aero_mass !< total aerosol mass of super droplet
162
163    CALL cpu_log( log_point_s(43), 'lpm_droplet_coll', 'start' )
164
165    number_of_particles   = prt_count(k,j,i)
166    factor_volume_to_mass = 4.0_wp / 3.0_wp * pi * rho_l
167    ddV                   = 1.0_wp / ( dx * dy * dz )
168!
169!-- Collision requires at least one super droplet inside the box
170    IF ( number_of_particles > 0 )  THEN
171
172       IF ( use_kernel_tables )  THEN
173!
174!--       Fast method with pre-calculated collection kernels for
175!--       discrete radius- and dissipation-classes.
176          IF ( wang_kernel )  THEN
177             eclass = INT( diss(k,j,i) * 1.0E4_wp / 600.0_wp * &
178                           dissipation_classes ) + 1
179             epsilon = diss(k,j,i)
180          ELSE
181             epsilon = 0.0_wp
182          ENDIF
183
184          IF ( hall_kernel  .OR.  epsilon * 1.0E4_wp < 0.001_wp )  THEN
185             eclass = 0   ! Hall kernel is used
186          ELSE
187             eclass = MIN( dissipation_classes, eclass )
188          ENDIF
189
190       ELSE
191!
192!--       Collection kernels are re-calculated for every new
193!--       grid box. First, allocate memory for kernel table.
194!--       Third dimension is 1, because table is re-calculated for
195!--       every new dissipation value.
196          ALLOCATE( ckernel(1:number_of_particles,1:number_of_particles,1:1) )
197!
198!--       Now calculate collection kernel for this box. Note that
199!--       the kernel is based on the previous time step
200          CALL recalculate_kernel( i, j, k )
201
202       ENDIF
203!
204!--    Temporary fields for total mass of super-droplet, aerosol mass, and
205!--    weighting factor are allocated.
206       ALLOCATE(mass(1:number_of_particles), weight(1:number_of_particles))
207       IF ( curvature_solution_effects )  ALLOCATE(aero_mass(1:number_of_particles))
208
209       mass(1:number_of_particles)   = particles(1:number_of_particles)%weight_factor * &
210                                       particles(1:number_of_particles)%radius**3     * &
211                                       factor_volume_to_mass
212
213       weight(1:number_of_particles) = particles(1:number_of_particles)%weight_factor
214
215       IF ( curvature_solution_effects )  THEN
216          aero_mass(1:number_of_particles) = particles(1:number_of_particles)%weight_factor * &
217                                             particles(1:number_of_particles)%aux1**3       * &
218                                             4.0 / 3.0 * pi * rho_s
219       ENDIF
220!
221!--    Calculate collision/coalescence
222       DO  n = 1, number_of_particles
223
224          DO  m = n, number_of_particles
225!
226!--          For collisions, the weighting factor of at least one super-droplet
227!--          needs to be larger or equal to one.
228             IF ( MIN( weight(n), weight(m) ) .LT. 1.0 )  CYCLE
229!
230!--          Get mass of individual droplets (aerosols)
231             xn = mass(n) / weight(n)
232             xm = mass(m) / weight(m)
233             IF ( curvature_solution_effects )  THEN
234                xsn = aero_mass(n) / weight(n)
235                xsm = aero_mass(m) / weight(m)
236             ENDIF
237!
238!--          Probability that the necessary collisions take place
239             IF ( use_kernel_tables )  THEN
240                rclass_l = particles(n)%class
241                rclass_s = particles(m)%class
242
243                collection_probability  = MAX( weight(n), weight(m) ) *     &
244                                          ckernel(rclass_l,rclass_s,eclass) * ddV * dt_3d
245             ELSE
246                collection_probability  = MAX( weight(n), weight(m) ) *     &
247                                          ckernel(n,m,1) * ddV * dt_3d
248             ENDIF
249!
250!--          Calculate the number of collections and consider multiple collections.
251!--          (Accordingly, p_crit will be 0.0, 1.0, 2.0, ...)
252             IF ( collection_probability - FLOOR(collection_probability)    &
253                  .GT. random_function( iran_part ) )  THEN
254                collection_probability = FLOOR(collection_probability) + 1.0_wp
255             ELSE
256                collection_probability = FLOOR(collection_probability)
257             ENDIF
258
259             IF ( collection_probability .GT. 0.0 )  THEN
260!
261!--             Super-droplet n collects droplets of super-droplet m
262                IF ( weight(n) .LT. weight(m) )  THEN
263
264                   mass(n)   = mass(n)   + weight(n) * xm * collection_probability
265                   weight(m) = weight(m) - weight(n)      * collection_probability
266                   mass(m)   = mass(m)   - weight(n) * xm * collection_probability
267                   IF ( curvature_solution_effects )  THEN
268                      aero_mass(n) = aero_mass(n) + weight(n) * xsm * collection_probability
269                      aero_mass(m) = aero_mass(m) - weight(n) * xsm * collection_probability
270                   ENDIF
271
272                ELSEIF ( weight(m) .LT. weight(n) )  THEN
273
274                   mass(m)   = mass(m)   + weight(m) * xn * collection_probability
275                   weight(n) = weight(n) - weight(m)      * collection_probability
276                   mass(n)   = mass(n)   - weight(m) * xn * collection_probability
277                   IF ( curvature_solution_effects )  THEN
278                      aero_mass(m) = aero_mass(m) + weight(m) * xsn * collection_probability
279                      aero_mass(n) = aero_mass(n) - weight(m) * xsn * collection_probability
280                   ENDIF
281
282                ELSE
283!
284!--                Collisions of particles of the same weighting factor.
285!--                Particle n collects 1/2 weight(n) droplets of particle m,
286!--                particle m collects 1/2 weight(m) droplets of particle n.
287!--                The total mass mass changes accordingly.
288!--                If n = m, the first half of the droplets coalesces with the
289!--                second half of the droplets; mass is unchanged because
290!--                xm = xn for n = m.
291!--
292!--                Note: For m = n this equation is an approximation only
293!--                valid for weight >> 1 (which is usually the case). The
294!--                approximation is weight(n)-1 = weight(n).
295                   mass(n)   = mass(n)   + 0.5_wp * weight(n) * ( xm - xn )
296                   mass(m)   = mass(m)   + 0.5_wp * weight(m) * ( xn - xm )
297                   IF ( curvature_solution_effects )  THEN
298                      aero_mass(n) = aero_mass(n) + 0.5_wp * weight(n) * ( xsm - xsn )
299                      aero_mass(m) = aero_mass(m) + 0.5_wp * weight(m) * ( xsn - xsm )
300                   ENDIF
301                   weight(n) = weight(n) - 0.5_wp * weight(m)
302                   weight(m) = weight(n)
303
304                ENDIF
305
306             ENDIF
307
308          ENDDO
309
310          ql_vp(k,j,i) = ql_vp(k,j,i) + mass(n) / factor_volume_to_mass
311
312       ENDDO
313
314       IF ( ANY(weight < 0.0_wp) )  THEN
315             WRITE( message_string, * ) 'negative weighting factor'
316             CALL message( 'lpm_droplet_collision', 'PA0028',      &
317                            2, 2, -1, 6, 1 )
318       ENDIF
319
320       particles(1:number_of_particles)%radius = ( mass(1:number_of_particles) /   &
321                                                   ( weight(1:number_of_particles) &
322                                                     * factor_volume_to_mass       &
323                                                   )                               &
324                                                 )**0.33333333333333_wp
325
326       IF ( curvature_solution_effects )  THEN
327          particles(1:number_of_particles)%aux1 = ( aero_mass(1:number_of_particles) / &
328                                                    ( weight(1:number_of_particles)    &
329                                                      * 4.0_wp / 3.0_wp * pi * rho_s   &
330                                                    )                                  &
331                                                  )**0.33333333333333_wp
332       ENDIF
333
334       particles(1:number_of_particles)%weight_factor = weight(1:number_of_particles)
335
336       DEALLOCATE( weight, mass )
337       IF ( curvature_solution_effects )  DEALLOCATE( aero_mass )
338       IF ( .NOT. use_kernel_tables )  DEALLOCATE( ckernel )
339
340!
341!--    Check if LWC is conserved during collision process
342       IF ( ql_v(k,j,i) /= 0.0_wp )  THEN
343          IF ( ql_vp(k,j,i) / ql_v(k,j,i) >= 1.0001_wp  .OR.                      &
344               ql_vp(k,j,i) / ql_v(k,j,i) <= 0.9999_wp )  THEN
345             WRITE( message_string, * ) ' LWC is not conserved during',           &
346                                        ' collision! ',                           &
347                                        ' LWC after condensation: ', ql_v(k,j,i), &
348                                        ' LWC after collision: ', ql_vp(k,j,i)
349             CALL message( 'lpm_droplet_collision', 'PA0040', 2, 2, -1, 6, 1 )
350          ENDIF
351       ENDIF
352
353    ENDIF
354
355    CALL cpu_log( log_point_s(43), 'lpm_droplet_coll', 'stop' )
356
357 END SUBROUTINE lpm_droplet_collision
Note: See TracBrowser for help on using the repository browser.