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

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

Code annotations made doxygen readable

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