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

Last change on this file since 1267 was 1258, checked in by raasch, 11 years ago

last commit documented

  • Property svn:keywords set to Id
File size: 15.0 KB
RevLine 
[1]1 SUBROUTINE prandtl_fluxes
2
[1036]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-2012  Leibniz University Hannover
18!--------------------------------------------------------------------------------!
19!
[484]20! Current revisions:
[1]21! -----------------
22!
[1258]23!
[668]24! Former revisions:
25! -----------------
26! $Id: prandtl_fluxes.f90 1258 2013-11-08 16:09:09Z heinze $
27!
[1258]28! 1257 2013-11-08 15:18:40Z raasch
29! openACC "kernels do" replaced by "kernels loop", "loop independent" added
30!
[1037]31! 1036 2012-10-22 13:43:42Z raasch
32! code put under GPL (PALM 3.9)
33!
[1017]34! 1015 2012-09-27 09:23:24Z raasch
35! OpenACC statements added
36!
[979]37! 978 2012-08-09 08:28:32Z fricke
38! roughness length for scalar quantities z0h added
39!
[760]40! 759 2011-09-15 13:58:31Z raasch
41! Bugfix for ts limitation
42!
[710]43! 709 2011-03-30 09:31:40Z raasch
44! formatting adjustments
45!
[668]46! 667 2010-12-23 12:06:00Z suehring/gryschka
[709]47! Changed surface boundary conditions for u and v from mirror to Dirichlet.
48! Therefore u(uzb,:,:) and v(nzb,:,:) are now representative for height z0.
[667]49! nxl-1, nxr+1, nys-1, nyn+1 replaced by nxlg, nxrg, nysg, nyng
50!
[392]51! 315 2009-05-13 10:57:59Z raasch
52! Saturation condition at (sea) surface is not used in precursor runs (only
53! in the following coupled runs)
54! Bugfix: qsws was calculated in case of constant heatflux = .FALSE.
55!
[198]56! 187 2008-08-06 16:25:09Z letzel
57! Bugfix: modification of the calculation of the vertical turbulent momentum
58! fluxes u'w' and v'w'
59! Bugfix: change definition of us_wall from 1D to 2D
60! Change: modification of the integrated version of the profile function for
61! momentum for unstable stratification (does not effect results)
62!
[110]63! 108 2007-08-24 15:10:38Z letzel
64! assume saturation at k=nzb_s_inner(j,i) for atmosphere coupled to ocean
65!
[77]66! 75 2007-03-22 09:54:05Z raasch
67! moisture renamed humidity
68!
[3]69! RCS Log replace by Id keyword, revision history cleaned up
70!
[1]71! Revision 1.19  2006/04/26 12:24:35  raasch
72! +OpenMP directives and optimization (array assignments replaced by DO loops)
73!
74! Revision 1.1  1998/01/23 10:06:06  raasch
75! Initial revision
76!
77!
78! Description:
79! ------------
80! Diagnostic computation of vertical fluxes in the Prandtl layer from the
81! values of the variables at grid point k=1
82!------------------------------------------------------------------------------!
83
84    USE arrays_3d
85    USE control_parameters
86    USE grid_variables
87    USE indices
88
89    IMPLICIT NONE
90
91    INTEGER ::  i, j, k
[1015]92    LOGICAL ::  coupled_run
[108]93    REAL    ::  a, b, e_q, rifm, uv_total, z_p
[1]94
[1015]95!
96!-- Data information for accelerators
97    !$acc data present( e, nzb_u_inner, nzb_v_inner, nzb_s_inner, pt, q, qs ) &
98    !$acc      present( qsws, rif, shf, ts, u, us, usws, v, vpt, vsws, zu, zw, z0, z0h )
[667]99!
[1]100!-- Compute theta*
101    IF ( constant_heatflux )  THEN
102!
103!--    For a given heat flux in the Prandtl layer:
104!--    for u* use the value from the previous time step
105       !$OMP PARALLEL DO
[1257]106       !$acc kernels loop
[667]107       DO  i = nxlg, nxrg
108          DO  j = nysg, nyng
[1]109             ts(j,i) = -shf(j,i) / ( us(j,i) + 1E-30 )
110!
111!--          ts must be limited, because otherwise overflow may occur in case of
112!--          us=0 when computing rif further below
[759]113             IF ( ts(j,i) < -1.05E5 )  ts(j,i) = -1.0E5
114             IF ( ts(j,i) >   1.0E5 )  ts(j,i) =  1.0E5
[1]115          ENDDO
116       ENDDO
117
118    ELSE
119!
120!--    For a given surface temperature:
121!--    (the Richardson number is still the one from the previous time step)
122       !$OMP PARALLEL DO PRIVATE( a, b, k, z_p )
[1257]123       !$acc kernels loop
[667]124       DO  i = nxlg, nxrg
125          DO  j = nysg, nyng
[1]126
127             k   = nzb_s_inner(j,i)
128             z_p = zu(k+1) - zw(k)
129
130             IF ( rif(j,i) >= 0.0 )  THEN
131!
132!--             Stable stratification
[978]133                ts(j,i) = kappa * ( pt(k+1,j,i) - pt(k,j,i) ) / (           &
134                                  LOG( z_p / z0h(j,i) ) +                   &
135                                  5.0 * rif(j,i) * ( z_p - z0h(j,i) ) / z_p &
[1]136                                                                )
137             ELSE
138!
139!--             Unstable stratification
140                a = SQRT( 1.0 - 16.0 * rif(j,i) )
[978]141                b = SQRT( 1.0 - 16.0 * rif(j,i) * z0h(j,i) / z_p )
[187]142
[978]143                ts(j,i) = kappa * ( pt(k+1,j,i) - pt(k,j,i) ) /  (          &
144                          LOG( z_p / z0h(j,i) ) -                           &
[187]145                          2.0 * LOG( ( 1.0 + a ) / ( 1.0 + b ) ) )
[1]146             ENDIF
147
148          ENDDO
149       ENDDO
150    ENDIF
151
152!
153!-- Compute z_p/L (corresponds to the Richardson-flux number)
[75]154    IF ( .NOT. humidity )  THEN
[1]155       !$OMP PARALLEL DO PRIVATE( k, z_p )
[1257]156       !$acc kernels loop
[667]157       DO  i = nxlg, nxrg
158          DO  j = nysg, nyng
[1]159             k   = nzb_s_inner(j,i)
160             z_p = zu(k+1) - zw(k)
161             rif(j,i) = z_p * kappa * g * ts(j,i) / &
162                        ( pt(k+1,j,i) * ( us(j,i)**2 + 1E-30 ) )
163!
164!--          Limit the value range of the Richardson numbers.
165!--          This is necessary for very small velocities (u,v --> 0), because
166!--          the absolute value of rif can then become very large, which in
167!--          consequence would result in very large shear stresses and very
168!--          small momentum fluxes (both are generally unrealistic).
169             IF ( rif(j,i) < rif_min )  rif(j,i) = rif_min
170             IF ( rif(j,i) > rif_max )  rif(j,i) = rif_max
171          ENDDO
172       ENDDO
173    ELSE
174       !$OMP PARALLEL DO PRIVATE( k, z_p )
[1257]175       !$acc kernels loop
[667]176       DO  i = nxlg, nxrg
177          DO  j = nysg, nyng
[1]178             k   = nzb_s_inner(j,i)
179             z_p = zu(k+1) - zw(k)
180             rif(j,i) = z_p * kappa * g *                            &
181                        ( ts(j,i) + 0.61 * pt(k+1,j,i) * qs(j,i) ) / &
182                        ( vpt(k+1,j,i) * ( us(j,i)**2 + 1E-30 ) )
183!
184!--          Limit the value range of the Richardson numbers.
185!--          This is necessary for very small velocities (u,v --> 0), because
186!--          the absolute value of rif can then become very large, which in
187!--          consequence would result in very large shear stresses and very
188!--          small momentum fluxes (both are generally unrealistic).
189             IF ( rif(j,i) < rif_min )  rif(j,i) = rif_min
190             IF ( rif(j,i) > rif_max )  rif(j,i) = rif_max
191          ENDDO
192       ENDDO       
193    ENDIF
194
195!
196!-- Compute u* at the scalars' grid points
197    !$OMP PARALLEL DO PRIVATE( a, b, k, uv_total, z_p )
[1257]198    !$acc kernels loop
[1]199    DO  i = nxl, nxr
200       DO  j = nys, nyn
201
202          k   = nzb_s_inner(j,i)
203          z_p = zu(k+1) - zw(k)
204
205!
[667]206!--       Compute the absolute value of the horizontal velocity
207!--       (relative to the surface)
208          uv_total = SQRT( ( 0.5 * ( u(k+1,j,i) + u(k+1,j,i+1)        &
209                                   - u(k,j,i)   - u(k,j,i+1) ) )**2 + &
210                           ( 0.5 * ( v(k+1,j,i) + v(k+1,j+1,i)        &
211                                   - v(k,j,i)   - v(k,j+1,i) ) )**2 )   
[1]212
[667]213
[1]214          IF ( rif(j,i) >= 0.0 )  THEN
215!
216!--          Stable stratification
217             us(j,i) = kappa * uv_total / (                                &
218                                  LOG( z_p / z0(j,i) ) +                   &
219                                  5.0 * rif(j,i) * ( z_p - z0(j,i) ) / z_p &
220                                          )
221          ELSE
222!
223!--          Unstable stratification
[187]224             a = SQRT( SQRT( 1.0 - 16.0 * rif(j,i) ) )
225             b = SQRT( SQRT( 1.0 - 16.0 * rif(j,i) / z_p * z0(j,i) ) )
226
227             us(j,i) = kappa * uv_total / (                                  &
228                       LOG( z_p / z0(j,i) ) -                                &
229                       LOG( ( 1.0 + a )**2 * ( 1.0 + a**2 ) / (              &
230                            ( 1.0 + b )**2 * ( 1.0 + b**2 )   ) ) +          &
231                            2.0 * ( ATAN( a ) - ATAN( b ) )                  &
232                                           )
[1]233          ENDIF
234       ENDDO
235    ENDDO
236
237!
[187]238!-- Values of us at ghost point locations are needed for the evaluation of usws
239!-- and vsws.
[1015]240    !$acc update host( us )
[187]241    CALL exchange_horiz_2d( us )
[1015]242    !$acc update device( us )
243
[187]244!
[1]245!-- Compute u'w' for the total model domain.
246!-- First compute the corresponding component of u* and square it.
247    !$OMP PARALLEL DO PRIVATE( a, b, k, rifm, z_p )
[1257]248    !$acc kernels loop
[1]249    DO  i = nxl, nxr
250       DO  j = nys, nyn
251
252          k   = nzb_u_inner(j,i)
253          z_p = zu(k+1) - zw(k)
254
255!
256!--       Compute Richardson-flux number for this point
257          rifm = 0.5 * ( rif(j,i-1) + rif(j,i) )
258          IF ( rifm >= 0.0 )  THEN
259!
260!--          Stable stratification
[667]261             usws(j,i) = kappa * ( u(k+1,j,i) - u(k,j,i) )/ (              &
[1]262                                     LOG( z_p / z0(j,i) ) +               &
263                                     5.0 * rifm * ( z_p - z0(j,i) ) / z_p &
264                                              )
265          ELSE
266!
267!--          Unstable stratification
[187]268             a = SQRT( SQRT( 1.0 - 16.0 * rifm ) )
269             b = SQRT( SQRT( 1.0 - 16.0 * rifm / z_p * z0(j,i) ) )
270
[667]271             usws(j,i) = kappa * ( u(k+1,j,i) - u(k,j,i) ) / (            &
[187]272                         LOG( z_p / z0(j,i) ) -                           &
273                         LOG( (1.0 + a )**2 * ( 1.0 + a**2 ) / (          &
274                              (1.0 + b )**2 * ( 1.0 + b**2 )   ) ) +      &
275                              2.0 * ( ATAN( a ) - ATAN( b ) )             &
[1]276                                                 )
277          ENDIF
[187]278          usws(j,i) = -usws(j,i) * 0.5 * ( us(j,i-1) + us(j,i) )
[1]279       ENDDO
280    ENDDO
281
282!
283!-- Compute v'w' for the total model domain.
284!-- First compute the corresponding component of u* and square it.
285    !$OMP PARALLEL DO PRIVATE( a, b, k, rifm, z_p )
[1257]286    !$acc kernels loop
[1]287    DO  i = nxl, nxr
288       DO  j = nys, nyn
289
290          k   = nzb_v_inner(j,i)
291          z_p = zu(k+1) - zw(k)
292
293!
294!--       Compute Richardson-flux number for this point
295          rifm = 0.5 * ( rif(j-1,i) + rif(j,i) )
296          IF ( rifm >= 0.0 )  THEN
297!
298!--          Stable stratification
[667]299             vsws(j,i) = kappa * ( v(k+1,j,i) -  v(k,j,i) ) / (           &
[1]300                                     LOG( z_p / z0(j,i) ) +               &
301                                     5.0 * rifm * ( z_p - z0(j,i) ) / z_p &
302                                              )
303          ELSE
304!
305!--          Unstable stratification
[187]306             a = SQRT( SQRT( 1.0 - 16.0 * rifm ) )
307             b = SQRT( SQRT( 1.0 - 16.0 * rifm / z_p * z0(j,i) ) )
308
[667]309             vsws(j,i) = kappa * ( v(k+1,j,i) - v(k,j,i) ) / (            &
[187]310                         LOG( z_p / z0(j,i) ) -                           &
311                         LOG( (1.0 + a )**2 * ( 1.0 + a**2 ) / (          &
312                              (1.0 + b )**2 * ( 1.0 + b**2 )   ) ) +      &
313                              2.0 * ( ATAN( a ) - ATAN( b ) )             &
[1]314                                                 )
315          ENDIF
[187]316          vsws(j,i) = -vsws(j,i) * 0.5 * ( us(j-1,i) + us(j,i) )
[1]317       ENDDO
318    ENDDO
319
320!
321!-- If required compute q*
[75]322    IF ( humidity  .OR.  passive_scalar )  THEN
[1]323       IF ( constant_waterflux )  THEN
324!
325!--       For a given water flux in the Prandtl layer:
326          !$OMP PARALLEL DO
[1257]327          !$acc kernels loop
[667]328          DO  i = nxlg, nxrg
329             DO  j = nysg, nyng
[1]330                qs(j,i) = -qsws(j,i) / ( us(j,i) + 1E-30 )
331             ENDDO
332          ENDDO
333         
[1015]334       ELSE
335          coupled_run = ( coupling_mode == 'atmosphere_to_ocean' .AND. run_coupled )
[1]336          !$OMP PARALLEL DO PRIVATE( a, b, k, z_p )
[1257]337          !$acc kernels loop independent
[667]338          DO  i = nxlg, nxrg
[1257]339             !$acc loop independent
[667]340             DO  j = nysg, nyng
[1]341
342                k   = nzb_s_inner(j,i)
343                z_p = zu(k+1) - zw(k)
344
[108]345!
[291]346!--             Assume saturation for atmosphere coupled to ocean (but not
347!--             in case of precursor runs)
[1015]348                IF ( coupled_run )  THEN
[108]349                   e_q = 6.1 * &
350                        EXP( 0.07 * ( MIN(pt(0,j,i),pt(1,j,i)) - 273.15 ) )
351                   q(k,j,i) = 0.622 * e_q / ( surface_pressure - e_q )
352                ENDIF
[1]353                IF ( rif(j,i) >= 0.0 )  THEN
354!
355!--                Stable stratification
[978]356                   qs(j,i) = kappa * ( q(k+1,j,i) - q(k,j,i) ) / (          &
357                                  LOG( z_p / z0h(j,i) ) +                   &
358                                  5.0 * rif(j,i) * ( z_p - z0h(j,i) ) / z_p &
[1]359                                                                 )
360                ELSE
361!
362!--                Unstable stratification
[187]363                   a = SQRT( 1.0 - 16.0 * rif(j,i) ) 
[978]364                   b = SQRT( 1.0 - 16.0 * rif(j,i) * z0h(j,i) / z_p ) 
[187]365 
[978]366                   qs(j,i) = kappa * ( q(k+1,j,i) - q(k,j,i) ) /   (        &
367                             LOG( z_p / z0h(j,i) ) -                        &
[187]368                              2.0 * LOG( (1.0 + a ) / ( 1.0 + b ) ) )
[1]369                ENDIF
370
371             ENDDO
372          ENDDO
373       ENDIF
374    ENDIF
375
376!
[187]377!-- Exchange the boundaries for the momentum fluxes (only for sake of
378!-- completeness)
[1015]379    !$acc update host( usws, vsws )
[1]380    CALL exchange_horiz_2d( usws )
381    CALL exchange_horiz_2d( vsws )
[1015]382    !$acc update device( usws, vsws )
383    IF ( humidity  .OR.  passive_scalar )  THEN
384       !$acc update host( qsws )
385       CALL exchange_horiz_2d( qsws )
386       !$acc update device( qsws )
387    ENDIF
[1]388
389!
390!-- Compute the vertical kinematic heat flux
391    IF ( .NOT. constant_heatflux )  THEN
392       !$OMP PARALLEL DO
[1257]393       !$acc kernels loop independent
[667]394       DO  i = nxlg, nxrg
[1257]395          !$acc loop independent
[667]396          DO  j = nysg, nyng
[1]397             shf(j,i) = -ts(j,i) * us(j,i)
398          ENDDO
399       ENDDO
400    ENDIF
401
402!
403!-- Compute the vertical water/scalar flux
[315]404    IF ( .NOT. constant_waterflux .AND. ( humidity .OR. passive_scalar ) ) THEN
[1]405       !$OMP PARALLEL DO
[1257]406       !$acc kernels loop independent
[667]407       DO  i = nxlg, nxrg
[1257]408          !$acc loop independent
[667]409          DO  j = nysg, nyng
[1]410             qsws(j,i) = -qs(j,i) * us(j,i)
411          ENDDO
412       ENDDO
413    ENDIF
414
415!
416!-- Bottom boundary condition for the TKE
417    IF ( ibc_e_b == 2 )  THEN
418       !$OMP PARALLEL DO
[1257]419       !$acc kernels loop independent
[667]420       DO  i = nxlg, nxrg
[1257]421          !$acc loop independent
[667]422          DO  j = nysg, nyng
[1]423             e(nzb_s_inner(j,i)+1,j,i) = ( us(j,i) / 0.1 )**2
424!
425!--          As a test: cm = 0.4
426!            e(nzb_s_inner(j,i)+1,j,i) = ( us(j,i) / 0.4 )**2
427             e(nzb_s_inner(j,i),j,i)   = e(nzb_s_inner(j,i)+1,j,i)
428          ENDDO
429       ENDDO
430    ENDIF
431
[1015]432    !$acc end data
[1]433
434 END SUBROUTINE prandtl_fluxes
Note: See TracBrowser for help on using the repository browser.