source: palm/trunk/SOURCE/lpm_droplet_condensation.f90 @ 1319

Last change on this file since 1319 was 1319, checked in by raasch, 10 years ago

last commit documented

  • Property svn:keywords set to Id
File size: 17.7 KB
Line 
1 SUBROUTINE lpm_droplet_condensation
2
3!--------------------------------------------------------------------------------!
4! This file is part of PALM.
5!
6! PALM is free software: you can redistribute it and/or modify it under the terms
7! of the GNU General Public License as published by the Free Software Foundation,
8! either version 3 of the License, or (at your option) any later 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-2014 Leibniz Universitaet Hannover
18!--------------------------------------------------------------------------------!
19!
20! Current revisions:
21! ------------------
22!
23!
24! Former revisions:
25! -----------------
26! $Id: lpm_droplet_condensation.f90 1319 2014-03-17 15:08:44Z raasch $
27!
28! 1318 2014-03-17 13:35:16Z raasch
29! module interfaces removed
30!
31! 1092 2013-02-02 11:24:22Z raasch
32! unused variables removed
33!
34! 1071 2012-11-29 16:54:55Z franke
35! Ventilation effect for evaporation of large droplets included
36! Check for unreasonable results included in calculation of Rosenbrock method
37! since physically unlikely results were observed and for the same
38! reason the first internal time step in Rosenbrock method should be < 1.0E02 in
39! case of evaporation
40! Unnecessary calculation of ql_int removed
41! Unnecessary calculations in Rosenbrock method (d2rdt2, drdt_m, dt_ros_last)
42! removed
43! Bugfix: factor in calculation of surface tension changed from 0.00155 to
44! 0.000155
45!
46! 1036 2012-10-22 13:43:42Z raasch
47! code put under GPL (PALM 3.9)
48!
49! 849 2012-03-15 10:35:09Z raasch
50! initial revision (former part of advec_particles)
51!
52!
53! Description:
54! ------------
55! Calculates change in droplet radius by condensation/evaporation, using
56! either an analytic formula or by numerically integrating the radius growth
57! equation including curvature and solution effects using Rosenbrocks method
58! (see Numerical recipes in FORTRAN, 2nd edition, p. 731).
59! The analytical formula and growth equation follow those given in
60! Rogers and Yau (A short course in cloud physics, 3rd edition, p. 102/103).
61!------------------------------------------------------------------------------!
62
63    USE arrays_3d
64    USE cloud_parameters
65    USE constants
66    USE control_parameters
67    USE cpulog
68    USE grid_variables
69    USE lpm_collision_kernels_mod
70    USE particle_attributes
71
72    IMPLICIT NONE
73
74    INTEGER ::  i, internal_timestep_count, j, jtry, k, n, ros_count
75
76    INTEGER, PARAMETER ::  maxtry = 40
77
78    LOGICAL ::  repeat
79
80    REAL ::  aa, afactor, arg, bb, cc, dd, ddenom, delta_r, drdt, drdt_ini,    &
81             dt_ros, dt_ros_next, dt_ros_sum, dt_ros_sum_ini, d2rdtdr, errmax, &
82             err_ros, g1, g2, g3, g4, e_a, e_s, gg, new_r, p_int, pt_int,      &
83             pt_int_l, pt_int_u, q_int, q_int_l, q_int_u, r_ros, r_ros_ini,    &
84             sigma, t_int, x, y, re_p
85
86!
87!-- Parameters for Rosenbrock method
88    REAL, PARAMETER ::  a21 = 2.0, a31 = 48.0/25.0, a32 = 6.0/25.0,        &
89                        b1 = 19.0/9.0, b2 = 0.5, b3 = 25.0/108.0,          &
90                        b4 = 125.0/108.0, c21 = -8.0, c31 = 372.0/25.0,    &
91                        c32 = 12.0/5.0, c41 = -112.0/125.0,                &
92                        c42 = -54.0/125.0, c43 = -2.0/5.0,                 &
93                        errcon = 0.1296, e1 = 17.0/54.0, e2 = 7.0/36.0,    &
94                        e3 = 0.0, e4 = 125.0/108.0, gam = 0.5, grow = 1.5, &
95                        pgrow = -0.25, pshrnk = -1.0/3.0, shrnk = 0.5
96
97
98    CALL cpu_log( log_point_s(42), 'lpm_droplet_condens', 'start' )
99
100    DO  n = 1, number_of_particles
101!
102!--    Interpolate temperature and humidity.
103!--    First determine left, south, and bottom index of the arrays.
104       i = particles(n)%x * ddx
105       j = particles(n)%y * ddy
106       k = ( particles(n)%z + 0.5 * dz * atmos_ocean_sign ) / dz  &
107           + offset_ocean_nzt                     ! only exact if equidistant
108
109       x  = particles(n)%x - i * dx
110       y  = particles(n)%y - j * dy
111       aa = x**2          + y**2
112       bb = ( dx - x )**2 + y**2
113       cc = x**2          + ( dy - y )**2
114       dd = ( dx - x )**2 + ( dy - y )**2
115       gg = aa + bb + cc + dd
116
117       pt_int_l = ( ( gg - aa ) * pt(k,j,i)   + ( gg - bb ) * pt(k,j,i+1)   &
118                  + ( gg - cc ) * pt(k,j+1,i) + ( gg - dd ) * pt(k,j+1,i+1) &
119                  ) / ( 3.0 * gg )
120
121       pt_int_u = ( ( gg-aa ) * pt(k+1,j,i)   + ( gg-bb ) * pt(k+1,j,i+1)   &
122                  + ( gg-cc ) * pt(k+1,j+1,i) + ( gg-dd ) * pt(k+1,j+1,i+1) &
123                  ) / ( 3.0 * gg )
124
125       pt_int = pt_int_l + ( particles(n)%z - zu(k) ) / dz * &
126                           ( pt_int_u - pt_int_l )
127
128       q_int_l = ( ( gg - aa ) * q(k,j,i)   + ( gg - bb ) * q(k,j,i+1)   &
129                 + ( gg - cc ) * q(k,j+1,i) + ( gg - dd ) * q(k,j+1,i+1) &
130                 ) / ( 3.0 * gg )
131
132       q_int_u = ( ( gg-aa ) * q(k+1,j,i)   + ( gg-bb ) * q(k+1,j,i+1)   &
133                 + ( gg-cc ) * q(k+1,j+1,i) + ( gg-dd ) * q(k+1,j+1,i+1) &
134                 ) / ( 3.0 * gg )
135
136       q_int = q_int_l + ( particles(n)%z - zu(k) ) / dz * &
137                           ( q_int_u - q_int_l )
138
139!
140!--    Calculate real temperature and saturation vapor pressure
141       p_int = hyp(k) + ( particles(n)%z - zu(k) ) / dz * ( hyp(k+1)-hyp(k) )
142       t_int = pt_int * ( p_int / 100000.0 )**0.286
143
144       e_s = 611.0 * EXP( l_d_rv * ( 3.6609E-3 - 1.0 / t_int ) )
145
146!
147!--    Current vapor pressure
148       e_a = q_int * p_int / ( 0.378 * q_int + 0.622 )
149
150!
151!--    Thermal conductivity for water (from Rogers and Yau, Table 7.1),
152!--    diffusivity for water vapor (after Hall und Pruppacher, 1976)
153       thermal_conductivity_l = 7.94048E-05 * t_int + 0.00227011 
154       diff_coeff_l           = 0.211E-4 * ( t_int / 273.15 )**1.94 * &
155                                ( 101325.0 / p_int)
156!
157!--    Change in radius by condensation/evaporation
158       IF ( particles(n)%radius >= 4.0E-5  .AND.  e_a/e_s < 1.0 )  THEN
159!
160!--       Approximation for large radii, where curvature and solution effects
161!--       can be neglected but ventilation effect has to be included in case of
162!--       evaporation.
163!--       First calculate the droplet's Reynolds number
164          re_p = 2.0 * particles(n)%radius * ABS( particles(n)%speed_z ) / &
165                 molecular_viscosity
166!
167!--       Ventilation coefficient after Rogers and Yau, 1989
168          IF ( re_p > 2.5 )  THEN
169             afactor = 0.78 + 0.28 * SQRT( re_p )
170          ELSE
171             afactor = 1.0 + 0.09 * re_p
172          ENDIF
173
174          arg = particles(n)%radius**2 + 2.0 * dt_3d * afactor *              &
175                           ( e_a / e_s - 1.0 ) /                              &
176                           ( ( l_d_rv / t_int - 1.0 ) * l_v * rho_l / t_int / &
177                             thermal_conductivity_l +                         &
178                             rho_l * r_v * t_int / diff_coeff_l / e_s )
179
180          new_r = SQRT( arg )
181
182       ELSEIF ( particles(n)%radius >= 1.0E-6  .OR.  &
183                .NOT. curvature_solution_effects )  THEN
184!
185!--       Approximation for larger radii in case that curvature and solution
186!--       effects are neglected and ventilation effects does not play a role
187          arg = particles(n)%radius**2 + 2.0 * dt_3d *                        &
188                           ( e_a / e_s - 1.0 ) /                              &
189                           ( ( l_d_rv / t_int - 1.0 ) * l_v * rho_l / t_int / &
190                             thermal_conductivity_l +                         &
191                             rho_l * r_v * t_int / diff_coeff_l / e_s )
192          IF ( arg < 1.0E-16 )  THEN
193             new_r = 1.0E-8
194          ELSE
195             new_r = SQRT( arg )
196          ENDIF
197       ENDIF
198
199       IF ( curvature_solution_effects  .AND.                              &
200            ( ( particles(n)%radius < 1.0E-6 ) .OR. ( new_r < 1.0E-6 ) ) ) &
201       THEN
202!
203!--       Curvature and solutions effects are included in growth equation.
204!--       Change in Radius is calculated with 4th-order Rosenbrock method
205!--       for stiff o.d.e's with monitoring local truncation error to adjust
206!--       stepsize (see Numerical recipes in FORTRAN, 2nd edition, p. 731).
207!--       For larger radii the simple analytic method (see ELSE) gives
208!--       almost the same results.
209
210          ros_count = 0
211          repeat = .TRUE.
212!
213!--       Carry out the Rosenbrock algorithm. In case of unreasonable results
214!--       the switch "repeat" will be set true and the algorithm will be carried
215!--       out again with the internal time step set to its initial (small) value.
216!--       Unreasonable results may occur if the external conditions, especially the
217!--       supersaturation, has significantly changed compared to the last PALM
218!--       timestep.
219          DO WHILE ( repeat )
220
221             repeat = .FALSE.
222!
223!--          Surface tension after (Straka, 2009)
224             sigma = 0.0761 - 0.000155 * ( t_int - 273.15 )
225
226             r_ros = particles(n)%radius
227             dt_ros_sum  = 0.0      ! internal integrated time (s)
228             internal_timestep_count = 0
229
230             ddenom  = 1.0 / ( rho_l * r_v * t_int / ( e_s * diff_coeff_l ) +  &
231                               ( l_v / ( r_v * t_int ) - 1.0 ) *               &
232                               rho_l * l_v / ( thermal_conductivity_l * t_int )&
233                             )
234
235             afactor = 2.0 * sigma / ( rho_l * r_v * t_int )
236
237!
238!--          Take internal time step values from the end of last PALM time step
239             dt_ros_next = particles(n)%rvar1
240
241!
242!--          Internal time step should not be > 1.0E-2 in case of evaporation
243!--          because larger values may lead to secondary solutions which are
244!--          physically unlikely
245             IF ( dt_ros_next > 1.0E-2  .AND.  e_a/e_s < 1.0 )  THEN
246                dt_ros_next = 1.0E-3
247             ENDIF
248!
249!--          If calculation of Rosenbrock method is repeated due to unreasonalble
250!--          results during previous try the initial internal time step has to be
251!--          reduced
252             IF ( ros_count > 1 )  THEN
253                dt_ros_next = dt_ros_next - ( 0.2 * dt_ros_next )
254             ELSEIF ( ros_count > 5 )  THEN
255!
256!--             Prevent creation of infinite loop
257                message_string = 'ros_count > 5 in Rosenbrock method'
258                CALL message( 'lpm_droplet_condensation', 'PA0018', 2, 2, &
259                               0, 6, 0 )
260             ENDIF
261
262!
263!--          Internal time step must not be larger than PALM time step
264             dt_ros = MIN( dt_ros_next, dt_3d )
265!
266!--          Integrate growth equation in time unless PALM time step is reached
267             DO WHILE ( dt_ros_sum < dt_3d )
268
269                internal_timestep_count = internal_timestep_count + 1
270
271!
272!--             Derivative at starting value
273                drdt = ddenom / r_ros * ( e_a / e_s - 1.0 - afactor / r_ros + &
274                                          bfactor / r_ros**3 )
275                drdt_ini       = drdt
276                dt_ros_sum_ini = dt_ros_sum
277                r_ros_ini      = r_ros
278
279!
280!--             Calculate radial derivative of dr/dt
281                d2rdtdr = ddenom * ( ( 1.0 - e_a/e_s ) / r_ros**2 + &
282                                     2.0 * afactor / r_ros**3 -     &
283                                     4.0 * bfactor / r_ros**5 )
284!
285!--             Adjust stepsize unless required accuracy is reached
286                DO  jtry = 1, maxtry+1
287
288                   IF ( jtry == maxtry+1 )  THEN
289                      message_string = 'maxtry > 40 in Rosenbrock method'
290                      CALL message( 'lpm_droplet_condensation', 'PA0347', 2, 2, &
291                                    0, 6, 0 )
292                   ENDIF
293
294                   aa    = 1.0 / ( gam * dt_ros ) - d2rdtdr
295                   g1    = drdt_ini / aa
296                   r_ros = r_ros_ini + a21 * g1
297                   drdt  = ddenom / r_ros * ( e_a / e_s - 1.0 - &
298                                              afactor / r_ros + &
299                                              bfactor / r_ros**3 )
300
301                   g2    = ( drdt + c21 * g1 / dt_ros )&
302                           / aa
303                   r_ros = r_ros_ini + a31 * g1 + a32 * g2
304                   drdt  = ddenom / r_ros * ( e_a / e_s - 1.0 - &
305                                              afactor / r_ros + &
306                                              bfactor / r_ros**3 )
307
308                   g3    = ( drdt +  &
309                             ( c31 * g1 + c32 * g2 ) / dt_ros ) / aa
310                   g4    = ( drdt +  &
311                             ( c41 * g1 + c42 * g2 + c43 * g3 ) / dt_ros ) / aa
312                   r_ros = r_ros_ini + b1 * g1 + b2 * g2 + b3 * g3 + b4 * g4
313
314                   dt_ros_sum = dt_ros_sum_ini + dt_ros
315
316                   IF ( dt_ros_sum == dt_ros_sum_ini )  THEN
317                      message_string = 'zero stepsize in Rosenbrock method'
318                      CALL message( 'lpm_droplet_condensation', 'PA0348', 2, 2, &
319                                    0, 6, 0 )
320                   ENDIF
321!
322!--                Calculate error
323                   err_ros = e1*g1 + e2*g2 + e3*g3 + e4*g4
324                   errmax  = 0.0
325                   errmax  = MAX( errmax, ABS( err_ros / r_ros_ini ) ) / eps_ros
326!
327!--                Leave loop if accuracy is sufficient, otherwise try again
328!--                with a reduced stepsize
329                   IF ( errmax <= 1.0 )  THEN
330                      EXIT
331                   ELSE
332                      dt_ros = SIGN( MAX( ABS( 0.9 * dt_ros * errmax**pshrnk ), &
333                                          shrnk * ABS( dt_ros ) ), dt_ros )
334                   ENDIF
335
336                ENDDO  ! loop for stepsize adjustment
337
338!
339!--             Calculate next internal time step
340                IF ( errmax > errcon )  THEN
341                   dt_ros_next = 0.9 * dt_ros * errmax**pgrow
342                ELSE
343                   dt_ros_next = grow * dt_ros
344                ENDIF
345
346!
347!--             Estimated time step is reduced if the PALM time step is exceeded
348                IF ( ( dt_ros_next + dt_ros_sum ) >= dt_3d )  THEN
349                   dt_ros = dt_3d - dt_ros_sum
350                ELSE
351                   dt_ros = dt_ros_next
352                ENDIF
353
354             ENDDO
355!
356!--          Store internal time step value for next PALM step
357             particles(n)%rvar1 = dt_ros_next
358
359             new_r = r_ros
360!
361!--          Radius should not fall below 1E-8 because Rosenbrock method may
362!--          lead to errors otherwise
363             new_r = MAX( new_r, 1.0E-8 )
364!
365!--          Check if calculated droplet radius change is reasonable since in
366!--          case of droplet evaporation the Rosenbrock method may lead to
367!--          secondary solutions which are physically unlikely.
368!--          Due to the solution effect the droplets may grow for relative
369!--          humidities below 100%, but change of radius should not be too large.
370!--          In case of unreasonable droplet growth the Rosenbrock method is
371!--          recalculated using a smaller initial time step.
372!--          Limiting values are tested for droplets down to 1.0E-7
373             IF ( new_r - particles(n)%radius >= 3.0E-7  .AND.  &
374                  e_a/e_s < 0.97 )  THEN
375                ros_count = ros_count + 1
376                repeat = .TRUE.
377             ENDIF
378
379          ENDDO    ! Rosenbrock method
380
381       ENDIF
382
383       delta_r = new_r - particles(n)%radius
384
385!
386!--    Sum up the change in volume of liquid water for the respective grid
387!--    volume (this is needed later in lpm_calc_liquid_water_content for
388!--    calculating the release of latent heat)
389       i = ( particles(n)%x + 0.5 * dx ) * ddx
390       j = ( particles(n)%y + 0.5 * dy ) * ddy
391       k = particles(n)%z / dz + 1 + offset_ocean_nzt_m1
392           ! only exact if equidistant
393
394       ql_c(k,j,i) = ql_c(k,j,i) + particles(n)%weight_factor *            &
395                                   rho_l * 1.33333333 * pi *               &
396                                   ( new_r**3 - particles(n)%radius**3 ) / &
397                                   ( rho_surface * dx * dy * dz )
398       IF ( ql_c(k,j,i) > 100.0 )  THEN
399          WRITE( message_string, * ) 'k=',k,' j=',j,' i=',i,      &
400                       ' ql_c=',ql_c(k,j,i), ' &part(',n,')%wf=', &
401                       particles(n)%weight_factor,' delta_r=',delta_r
402          CALL message( 'lpm_droplet_condensation', 'PA0143', 2, 2, -1, 6, 1 )
403       ENDIF
404
405!
406!--    Change the droplet radius
407       IF ( ( new_r - particles(n)%radius ) < 0.0  .AND.  new_r < 0.0 ) &
408       THEN
409          WRITE( message_string, * ) '#1 k=',k,' j=',j,' i=',i,   &
410                       ' e_s=',e_s, ' e_a=',e_a,' t_int=',t_int,  &
411                       ' &delta_r=',delta_r,                      &
412                       ' particle_radius=',particles(n)%radius
413          CALL message( 'lpm_droplet_condensation', 'PA0144', 2, 2, -1, 6, 1 )
414       ENDIF
415
416!
417!--    Sum up the total volume of liquid water (needed below for
418!--    re-calculating the weighting factors)
419       ql_v(k,j,i) = ql_v(k,j,i) + particles(n)%weight_factor * new_r**3
420
421       particles(n)%radius = new_r
422
423!
424!--    Determine radius class of the particle needed for collision
425       IF ( ( hall_kernel  .OR.  wang_kernel )  .AND.  use_kernel_tables ) &
426       THEN
427          particles(n)%class = ( LOG( new_r ) - rclass_lbound ) /  &
428                               ( rclass_ubound - rclass_lbound ) * &
429                               radius_classes
430          particles(n)%class = MIN( particles(n)%class, radius_classes )
431          particles(n)%class = MAX( particles(n)%class, 1 )
432       ENDIF
433
434    ENDDO
435
436    CALL cpu_log( log_point_s(42), 'lpm_droplet_condens', 'stop' )
437
438
439 END SUBROUTINE lpm_droplet_condensation
Note: See TracBrowser for help on using the repository browser.