source: palm/trunk/SOURCE/prandtl_fluxes.f90 @ 1683

Last change on this file since 1683 was 1683, checked in by knoop, 9 years ago

last commit documented

  • Property svn:keywords set to Id
File size: 19.6 KB
Line 
1!> @file prandtl_fluxes.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 terms
6! of the GNU General Public License as published by the Free Software Foundation,
7! either version 3 of the License, or (at your option) any later version.
8!
9! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
10! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
12!
13! You should have received a copy of the GNU General Public License along with
14! PALM. If not, see <http://www.gnu.org/licenses/>.
15!
16! Copyright 1997-2014 Leibniz Universitaet Hannover
17!--------------------------------------------------------------------------------!
18!
19! Current revisions:
20! -----------------
21!
22!
23! Former revisions:
24! -----------------
25! $Id: prandtl_fluxes.f90 1683 2015-10-07 23:57:51Z knoop $
26!
27! 1682 2015-10-07 23:56:08Z knoop
28! Code annotations made doxygen readable
29!
30! 1551 2015-03-03 14:18:16Z maronga
31! Removed land surface model part. The surface fluxes are now always calculated
32! within prandtl_fluxes, based on the given surface temperature/humidity (which
33! is either provided by the land surface model, by large scale forcing data, or
34! directly prescribed by the user.
35!
36! 1496 2014-12-02 17:25:50Z maronga
37! Adapted for land surface model
38!
39! 1494 2014-11-21 17:14:03Z maronga
40! Bugfixes: qs is now calculated before calculation of Rif. Ccalculation of
41! buoyancy flux in Rif corrected (added missing humidity term), allow use of
42! topography for coupled runs (not tested)
43!
44! 1361 2014-04-16 15:17:48Z hoffmann
45! Bugfix: calculation of turbulent fluxes of rain water content (qrsws) and rain
46! drop concentration (nrsws) added
47!
48! 1340 2014-03-25 19:45:13Z kanani
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! old module precision_kind is removed,
56! revision history before 2012 removed,
57! comment fields (!:) to be used for variable explanations added to
58! all variable declaration statements
59!
60! 1276 2014-01-15 13:40:41Z heinze
61! Use LSF_DATA also in case of Dirichlet bottom boundary condition for scalars
62!
63! 1257 2013-11-08 15:18:40Z raasch
64! openACC "kernels do" replaced by "kernels loop", "loop independent" added
65!
66! 1036 2012-10-22 13:43:42Z raasch
67! code put under GPL (PALM 3.9)
68!
69! 1015 2012-09-27 09:23:24Z raasch
70! OpenACC statements added
71!
72! 978 2012-08-09 08:28:32Z fricke
73! roughness length for scalar quantities z0h added
74!
75! Revision 1.1  1998/01/23 10:06:06  raasch
76! Initial revision
77!
78!
79! Description:
80! ------------
81!> Diagnostic computation of vertical fluxes in the Prandtl layer from the
82!> values of the variables at grid point k=1
83!------------------------------------------------------------------------------!
84 SUBROUTINE prandtl_fluxes
85 
86
87    USE arrays_3d,                                                             &
88        ONLY:  e, nr, nrs, nrsws, pt, q, qr, qrs, qrsws, qs, qsws, rif, shf,   &
89               ts, u, us, usws, v, vpt, vsws, zu, zw, z0, z0h
90
91    USE control_parameters,                                                    &
92        ONLY:  cloud_physics, constant_heatflux, constant_waterflux,           &
93               coupling_mode, g, humidity, ibc_e_b, icloud_scheme, kappa,      &
94               large_scale_forcing, lsf_surf, passive_scalar, precipitation,   &
95               pt_surface, q_surface, rif_max, rif_min, run_coupled,           &
96               surface_pressure
97
98    USE indices,                                                               &
99        ONLY:  nxl, nxlg, nxr, nxrg, nys, nysg, nyn, nyng, nzb_s_inner,        &
100               nzb_u_inner, nzb_v_inner
101
102    USE kinds
103
104    IMPLICIT NONE
105
106    INTEGER(iwp) ::  i            !<
107    INTEGER(iwp) ::  j            !<
108    INTEGER(iwp) ::  k            !<
109
110    LOGICAL      ::  coupled_run  !<
111
112    REAL(wp)     ::  a            !<
113    REAL(wp)     ::  b            !<
114    REAL(wp)     ::  e_q          !<
115    REAL(wp)     ::  rifm         !<
116    REAL(wp)     ::  uv_total     !<
117    REAL(wp)     ::  z_p          !<
118
119!
120!-- Data information for accelerators
121    !$acc data present( e, nrsws, nzb_u_inner, nzb_v_inner, nzb_s_inner, pt )  &
122    !$acc      present( q, qs, qsws, qrsws, rif, shf, ts, u, us, usws, v )     &
123    !$acc      present( vpt, vsws, zu, zw, z0, z0h )
124!
125!-- Compute theta*
126    IF ( constant_heatflux )  THEN
127
128!
129!--    For a given heat flux in the Prandtl layer:
130!--    for u* use the value from the previous time step
131       !$OMP PARALLEL DO
132       !$acc kernels loop
133       DO  i = nxlg, nxrg
134          DO  j = nysg, nyng
135             ts(j,i) = -shf(j,i) / ( us(j,i) + 1E-30_wp )
136!
137!--          ts must be limited, because otherwise overflow may occur in case of
138!--          us=0 when computing rif further below
139             IF ( ts(j,i) < -1.05E5_wp )  ts(j,i) = -1.0E5_wp
140             IF ( ts(j,i) >   1.0E5_wp )  ts(j,i) =  1.0E5_wp
141          ENDDO
142       ENDDO
143
144    ELSE
145!
146!--    For a given surface temperature:
147!--    (the Richardson number is still the one from the previous time step)
148       IF ( large_scale_forcing .AND. lsf_surf )  THEN
149          !$OMP PARALLEL DO
150          !$acc kernels loop
151          DO  i = nxlg, nxrg
152             DO  j = nysg, nyng
153                k = nzb_s_inner(j,i)
154                pt(k,j,i) = pt_surface
155             ENDDO
156          ENDDO
157       ENDIF
158
159       !$OMP PARALLEL DO PRIVATE( a, b, k, z_p )
160       !$acc kernels loop
161       DO  i = nxlg, nxrg
162          DO  j = nysg, nyng
163
164             k   = nzb_s_inner(j,i)
165             z_p = zu(k+1) - zw(k)
166
167             IF ( rif(j,i) >= 0.0_wp )  THEN
168!
169!--             Stable stratification
170                ts(j,i) = kappa * ( pt(k+1,j,i) - pt(k,j,i) ) / (           &
171                                  LOG( z_p / z0h(j,i) ) +                   &
172                                  5.0_wp * rif(j,i) * ( z_p - z0h(j,i) ) / z_p &
173                                                                )
174             ELSE
175!
176!--             Unstable stratification
177                a = SQRT( 1.0_wp - 16.0_wp * rif(j,i) )
178                b = SQRT( 1.0_wp - 16.0_wp * rif(j,i) * z0h(j,i) / z_p )
179
180                ts(j,i) = kappa * ( pt(k+1,j,i) - pt(k,j,i) ) /  (             &
181                          LOG( z_p / z0h(j,i) ) -                              &
182                          2.0_wp * LOG( ( 1.0_wp + a ) / ( 1.0_wp + b ) ) )
183             ENDIF
184
185          ENDDO
186       ENDDO
187    ENDIF
188
189!
190!-- If required compute q*
191    IF ( humidity  .OR.  passive_scalar )  THEN
192       IF ( constant_waterflux )  THEN
193!
194!--       For a given water flux in the Prandtl layer:
195          !$OMP PARALLEL DO
196          !$acc kernels loop
197          DO  i = nxlg, nxrg
198             DO  j = nysg, nyng
199                qs(j,i) = -qsws(j,i) / ( us(j,i) + 1E-30_wp )
200             ENDDO
201          ENDDO
202         
203       ELSE
204          coupled_run = ( coupling_mode == 'atmosphere_to_ocean' .AND. run_coupled )
205
206           IF ( large_scale_forcing .AND. lsf_surf )  THEN
207                !$OMP PARALLEL DO
208                !$acc kernels loop
209                 DO  i = nxlg, nxrg
210                    DO  j = nysg, nyng
211                       k = nzb_s_inner(j,i)
212                       q(k,j,i) = q_surface
213                    ENDDO
214                 ENDDO
215           ENDIF
216
217          !$OMP PARALLEL DO PRIVATE( a, b, k, z_p )
218          !$acc kernels loop independent
219          DO  i = nxlg, nxrg
220             !$acc loop independent
221             DO  j = nysg, nyng
222
223                k   = nzb_s_inner(j,i)
224                z_p = zu(k+1) - zw(k)
225
226!
227!--             Assume saturation for atmosphere coupled to ocean (but not
228!--             in case of precursor runs)
229                IF ( coupled_run )  THEN
230                   e_q = 6.1_wp * &
231                           EXP( 0.07_wp * ( MIN(pt(k,j,i),pt(k+1,j,i)) - 273.15_wp ) )
232                   q(k,j,i) = 0.622_wp * e_q / ( surface_pressure - e_q )
233                ENDIF
234                IF ( rif(j,i) >= 0.0_wp )  THEN
235!
236!--                Stable stratification
237                   qs(j,i) = kappa * ( q(k+1,j,i) - q(k,j,i) ) / (             &
238                                  LOG( z_p / z0h(j,i) ) +                      &
239                                  5.0_wp * rif(j,i) * ( z_p - z0h(j,i) ) / z_p &
240                                                                 )
241                ELSE
242!
243!--                Unstable stratification
244                   a = SQRT( 1.0_wp - 16.0_wp * rif(j,i) ) 
245                   b = SQRT( 1.0_wp - 16.0_wp * rif(j,i) * z0h(j,i) / z_p ) 
246 
247                   qs(j,i) = kappa * ( q(k+1,j,i) - q(k,j,i) ) /   (           &
248                             LOG( z_p / z0h(j,i) ) -                           &
249                              2.0_wp * LOG( (1.0_wp + a ) / ( 1.0_wp + b ) ) )
250                ENDIF
251
252             ENDDO
253          ENDDO
254       ENDIF
255    ENDIF
256
257!
258!-- Compute z_p/L (corresponds to the Richardson-flux number)
259    IF ( .NOT. humidity )  THEN
260       !$OMP PARALLEL DO PRIVATE( k, z_p )
261       !$acc kernels loop
262       DO  i = nxlg, nxrg
263          DO  j = nysg, nyng
264             k   = nzb_s_inner(j,i)
265             z_p = zu(k+1) - zw(k)
266             rif(j,i) = z_p * kappa * g * ts(j,i) / &
267                        ( pt(k+1,j,i) * ( us(j,i)**2 + 1E-30_wp ) )
268!
269!--          Limit the value range of the Richardson numbers.
270!--          This is necessary for very small velocities (u,v --> 0), because
271!--          the absolute value of rif can then become very large, which in
272!--          consequence would result in very large shear stresses and very
273!--          small momentum fluxes (both are generally unrealistic).
274             IF ( rif(j,i) < rif_min )  rif(j,i) = rif_min
275             IF ( rif(j,i) > rif_max )  rif(j,i) = rif_max
276          ENDDO
277       ENDDO
278    ELSE
279       !$OMP PARALLEL DO PRIVATE( k, z_p )
280       !$acc kernels loop
281       DO  i = nxlg, nxrg
282          DO  j = nysg, nyng
283             k   = nzb_s_inner(j,i)
284             z_p = zu(k+1) - zw(k)
285             rif(j,i) = z_p * kappa * g *                                      &
286                        ( ts(j,i) + 0.61_wp * pt(k+1,j,i) * qs(j,i) + 0.61_wp  &
287                          * q(k+1,j,i) * ts(j,i)) /                            &
288                        ( vpt(k+1,j,i) * ( us(j,i)**2 + 1E-30_wp ) )
289!
290!--          Limit the value range of the Richardson numbers.
291!--          This is necessary for very small velocities (u,v --> 0), because
292!--          the absolute value of rif can then become very large, which in
293!--          consequence would result in very large shear stresses and very
294!--          small momentum fluxes (both are generally unrealistic).
295             IF ( rif(j,i) < rif_min )  rif(j,i) = rif_min
296             IF ( rif(j,i) > rif_max )  rif(j,i) = rif_max
297          ENDDO
298       ENDDO       
299    ENDIF
300
301!
302!-- Compute u* at the scalars' grid points
303    !$OMP PARALLEL DO PRIVATE( a, b, k, uv_total, z_p )
304    !$acc kernels loop
305    DO  i = nxl, nxr
306       DO  j = nys, nyn
307
308          k   = nzb_s_inner(j,i)
309          z_p = zu(k+1) - zw(k)
310
311!
312!--       Compute the absolute value of the horizontal velocity
313!--       (relative to the surface)
314          uv_total = SQRT( ( 0.5_wp * ( u(k+1,j,i) + u(k+1,j,i+1)              &
315                                      - u(k,j,i)   - u(k,j,i+1) ) )**2 +       &
316                           ( 0.5_wp * ( v(k+1,j,i) + v(k+1,j+1,i)              &
317                                      - v(k,j,i)   - v(k,j+1,i) ) )**2 )   
318
319
320          IF ( rif(j,i) >= 0.0_wp )  THEN
321!
322!--          Stable stratification
323             us(j,i) = kappa * uv_total / (                                    &
324                                  LOG( z_p / z0(j,i) ) +                       &
325                                  5.0_wp * rif(j,i) * ( z_p - z0(j,i) ) / z_p  &
326                                          )
327          ELSE
328!
329!--          Unstable stratification
330             a = SQRT( SQRT( 1.0_wp - 16.0_wp * rif(j,i) ) )
331             b = SQRT( SQRT( 1.0_wp - 16.0_wp * rif(j,i) / z_p * z0(j,i) ) )
332
333             us(j,i) = kappa * uv_total / (                                    &
334                       LOG( z_p / z0(j,i) ) -                                  &
335                       LOG( ( 1.0_wp + a )**2 * ( 1.0_wp + a**2 ) / (          &
336                            ( 1.0_wp + b )**2 * ( 1.0_wp + b**2 )   ) ) +      &
337                               2.0_wp * ( ATAN( a ) - ATAN( b ) )              &
338                                           )
339          ENDIF
340       ENDDO
341    ENDDO
342
343!
344!-- Values of us at ghost point locations are needed for the evaluation of usws
345!-- and vsws.
346    !$acc update host( us )
347    CALL exchange_horiz_2d( us )
348    !$acc update device( us )
349
350!
351!-- Compute u'w' for the total model domain.
352!-- First compute the corresponding component of u* and square it.
353    !$OMP PARALLEL DO PRIVATE( a, b, k, rifm, z_p )
354    !$acc kernels loop
355    DO  i = nxl, nxr
356       DO  j = nys, nyn
357
358          k   = nzb_u_inner(j,i)
359          z_p = zu(k+1) - zw(k)
360
361!
362!--       Compute Richardson-flux number for this point
363          rifm = 0.5_wp * ( rif(j,i-1) + rif(j,i) )
364          IF ( rifm >= 0.0_wp )  THEN
365!
366!--          Stable stratification
367             usws(j,i) = kappa * ( u(k+1,j,i) - u(k,j,i) )/ (                  &
368                                     LOG( z_p / z0(j,i) ) +                    &
369                                     5.0_wp * rifm * ( z_p - z0(j,i) ) / z_p   &
370                                                            )
371          ELSE
372!
373!--          Unstable stratification
374             a = SQRT( SQRT( 1.0_wp - 16.0_wp * rifm ) )
375             b = SQRT( SQRT( 1.0_wp - 16.0_wp * rifm / z_p * z0(j,i) ) )
376
377             usws(j,i) = kappa * ( u(k+1,j,i) - u(k,j,i) ) / (                 &
378                         LOG( z_p / z0(j,i) ) -                                &
379                         LOG( (1.0_wp + a )**2 * ( 1.0_wp + a**2 ) / (         &
380                              (1.0_wp + b )**2 * ( 1.0_wp + b**2 )   ) ) +     &
381                                 2.0_wp * ( ATAN( a ) - ATAN( b ) )            &
382                                                 )
383          ENDIF
384          usws(j,i) = -usws(j,i) * 0.5_wp * ( us(j,i-1) + us(j,i) )
385       ENDDO
386    ENDDO
387
388!
389!-- Compute v'w' for the total model domain.
390!-- First compute the corresponding component of u* and square it.
391    !$OMP PARALLEL DO PRIVATE( a, b, k, rifm, z_p )
392    !$acc kernels loop
393    DO  i = nxl, nxr
394       DO  j = nys, nyn
395
396          k   = nzb_v_inner(j,i)
397          z_p = zu(k+1) - zw(k)
398
399!
400!--       Compute Richardson-flux number for this point
401          rifm = 0.5_wp * ( rif(j-1,i) + rif(j,i) )
402          IF ( rifm >= 0.0_wp )  THEN
403!
404!--          Stable stratification
405             vsws(j,i) = kappa * ( v(k+1,j,i) -  v(k,j,i) ) / (                &
406                                     LOG( z_p / z0(j,i) ) +                    &
407                                     5.0_wp * rifm * ( z_p - z0(j,i) ) / z_p   &
408                                                              )
409          ELSE
410!
411!--          Unstable stratification
412             a = SQRT( SQRT( 1.0_wp - 16.0_wp * rifm ) )
413             b = SQRT( SQRT( 1.0_wp - 16.0_wp * rifm / z_p * z0(j,i) ) )
414
415             vsws(j,i) = kappa * ( v(k+1,j,i) - v(k,j,i) ) / (                 &
416                         LOG( z_p / z0(j,i) ) -                                &
417                         LOG( (1.0_wp + a )**2 * ( 1.0_wp + a**2 ) / (         &
418                              (1.0_wp + b )**2 * ( 1.0_wp + b**2 )   ) ) +     &
419                                 2.0_wp * ( ATAN( a ) - ATAN( b ) )            &
420                                                 )
421          ENDIF
422          vsws(j,i) = -vsws(j,i) * 0.5_wp * ( us(j-1,i) + us(j,i) )
423       ENDDO
424    ENDDO
425
426!
427!-- If required compute qr* and nr*
428    IF ( cloud_physics .AND. icloud_scheme == 0 .AND. precipitation )  THEN
429
430       !$OMP PARALLEL DO PRIVATE( a, b, k, z_p )
431       !$acc kernels loop independent
432       DO  i = nxlg, nxrg
433          !$acc loop independent
434          DO  j = nysg, nyng
435
436             k   = nzb_s_inner(j,i)
437             z_p = zu(k+1) - zw(k)
438
439             IF ( rif(j,i) >= 0.0 )  THEN
440!
441!--             Stable stratification
442                qrs(j,i) = kappa * ( qr(k+1,j,i) - qr(k,j,i) ) / (             &
443                               LOG( z_p / z0h(j,i) ) +                         &
444                               5.0 * rif(j,i) * ( z_p - z0h(j,i) ) / z_p )
445                nrs(j,i) = kappa * ( nr(k+1,j,i) - nr(k,j,i) ) / (             &
446                               LOG( z_p / z0h(j,i) ) +                         &
447                               5.0 * rif(j,i) * ( z_p - z0h(j,i) ) / z_p )
448
449             ELSE
450!
451!--             Unstable stratification
452                a = SQRT( 1.0 - 16.0 * rif(j,i) ) 
453                b = SQRT( 1.0 - 16.0 * rif(j,i) * z0h(j,i) / z_p ) 
454 
455                qrs(j,i) = kappa * ( qr(k+1,j,i) - qr(k,j,i) ) /   (           &
456                          LOG( z_p / z0h(j,i) ) -                              &
457                          2.0 * LOG( (1.0 + a ) / ( 1.0 + b ) ) )
458                nrs(j,i) = kappa * ( nr(k+1,j,i) - nr(k,j,i) ) /   (           &
459                          LOG( z_p / z0h(j,i) ) -                              &
460                          2.0 * LOG( (1.0 + a ) / ( 1.0 + b ) ) )
461
462             ENDIF
463
464          ENDDO
465       ENDDO
466
467    ENDIF
468
469!
470!-- Exchange the boundaries for the momentum fluxes (only for sake of
471!-- completeness)
472    !$acc update host( usws, vsws )
473    CALL exchange_horiz_2d( usws )
474    CALL exchange_horiz_2d( vsws )
475    !$acc update device( usws, vsws )
476    IF ( humidity  .OR.  passive_scalar )  THEN
477       !$acc update host( qsws )
478       CALL exchange_horiz_2d( qsws )
479       !$acc update device( qsws )
480       IF ( cloud_physics  .AND.  icloud_scheme == 0  .AND.  &
481            precipitation )  THEN
482          !$acc update host( qrsws, nrsws )
483          CALL exchange_horiz_2d( qrsws )
484          CALL exchange_horiz_2d( nrsws )
485          !$acc update device( qrsws, nrsws )
486       ENDIF
487    ENDIF
488
489!
490!-- Compute the vertical kinematic heat flux
491    IF ( .NOT. constant_heatflux  )  THEN
492       !$OMP PARALLEL DO
493       !$acc kernels loop independent
494       DO  i = nxlg, nxrg
495          !$acc loop independent
496          DO  j = nysg, nyng
497             shf(j,i) = -ts(j,i) * us(j,i)
498          ENDDO
499       ENDDO
500    ENDIF
501
502!
503!-- Compute the vertical water/scalar flux
504    IF ( .NOT. constant_waterflux .AND. ( humidity .OR. passive_scalar ) )  THEN
505       !$OMP PARALLEL DO
506       !$acc kernels loop independent
507       DO  i = nxlg, nxrg
508          !$acc loop independent
509          DO  j = nysg, nyng
510             qsws(j,i) = -qs(j,i) * us(j,i)
511          ENDDO
512       ENDDO
513    ENDIF
514
515!
516!-- Compute (turbulent) fluxes of rain water content and rain drop concentartion
517    IF ( cloud_physics  .AND.  icloud_scheme == 0  .AND.  precipitation )  THEN
518       !$OMP PARALLEL DO
519       !$acc kernels loop independent
520       DO  i = nxlg, nxrg
521          !$acc loop independent
522          DO  j = nysg, nyng
523             qrsws(j,i) = -qrs(j,i) * us(j,i)
524             nrsws(j,i) = -nrs(j,i) * us(j,i)
525          ENDDO
526       ENDDO
527    ENDIF
528
529!
530!-- Bottom boundary condition for the TKE
531    IF ( ibc_e_b == 2 )  THEN
532       !$OMP PARALLEL DO
533       !$acc kernels loop independent
534       DO  i = nxlg, nxrg
535          !$acc loop independent
536          DO  j = nysg, nyng
537             e(nzb_s_inner(j,i)+1,j,i) = ( us(j,i) / 0.1_wp )**2
538!
539!--          As a test: cm = 0.4
540!            e(nzb_s_inner(j,i)+1,j,i) = ( us(j,i) / 0.4_wp )**2
541             e(nzb_s_inner(j,i),j,i)   = e(nzb_s_inner(j,i)+1,j,i)
542          ENDDO
543       ENDDO
544    ENDIF
545
546    !$acc end data
547
548 END SUBROUTINE prandtl_fluxes
Note: See TracBrowser for help on using the repository browser.