source: palm/trunk/SOURCE/pres.f90 @ 2232

Last change on this file since 2232 was 2232, checked in by suehring, 7 years ago

Adjustments according new topography and surface-modelling concept implemented

  • Property svn:keywords set to Id
File size: 30.5 KB
RevLine 
[1682]1!> @file pres.f90
[2000]2!------------------------------------------------------------------------------!
[1036]3! This file is part of PALM.
4!
[2000]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.
[1036]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!
[2101]17! Copyright 1997-2017 Leibniz Universitaet Hannover
[2000]18!------------------------------------------------------------------------------!
[1036]19!
[484]20! Current revisions:
[1212]21! ------------------
[2232]22! Adjustments to new topography and surface concept
[1932]23!
[1919]24! Former revisions:
25! -----------------
26! $Id: pres.f90 2232 2017-05-30 17:47:52Z suehring $
27!
[2119]28! 2118 2017-01-17 16:38:49Z raasch
29! OpenACC directives and related code removed
30!
[2074]31! 2073 2016-11-30 14:34:05Z raasch
32! openmp bugfix for calculation of new divergence
33!
[2038]34! 2037 2016-10-26 11:15:40Z knoop
35! Anelastic approximation implemented
36!
[2001]37! 2000 2016-08-20 18:09:15Z knoop
38! Forced header and separation lines into 80 columns
39!
[1933]40! 1932 2016-06-10 12:09:21Z suehring
41! Initial version of purely vertical nesting introduced.
42!
[1932]43! 1931 2016-06-10 12:06:59Z suehring
44! Rename multigrid into multigrid_noopt and multigrid_fast into multigrid
45!
[1930]46! 1929 2016-06-09 16:25:25Z suehring
47! Bugfix: weight_substep for initial call, replace by local variable
48!
[1919]49! 1918 2016-05-27 14:35:57Z raasch
[1918]50! sum of divergence is also calculated when pres is called before the initial
51! first time step,
52! stearing is modified by using intermediate_timestep_count = 0 in order to
53! determine if pres is called before the first initial timestep,
54! bugfix: in case of Neumann conditions for pressure both at bottom and top,
55!         mean vertical velocity is also removed for the first time step
56! bugfix for calculating divergences
[1321]57!
[1909]58! 1908 2016-05-25 17:22:32Z suehring
59! New divergence for output into RUN_CONTROL file is calculated only at last
60! Runge-Kutta step
61!
[1846]62! 1845 2016-04-08 08:29:13Z raasch
63! nzb_2d replace by nzb_u|v_inner
64!
[1800]65! 1799 2016-04-05 08:35:55Z gronemeier
66! Bugfix: excluded third dimension from horizontal volume flow calculation
67!
[1763]68! 1762 2016-02-25 12:31:13Z hellstea
69! Introduction of nested domain feature
70!
[1683]71! 1682 2015-10-07 23:56:08Z knoop
72! Code annotations made doxygen readable
73!
[1576]74! 1575 2015-03-27 09:56:27Z raasch
75! poismg_fast + respective module added, adjustments for psolver-queries
76!
[1343]77! 1342 2014-03-26 17:04:47Z kanani
78! REAL constants defined as wp-kind
79!
[1321]80! 1320 2014-03-20 08:40:49Z raasch
[1320]81! ONLY-attribute added to USE-statements,
82! kind-parameters added to all INTEGER and REAL declaration statements,
83! kinds are defined in new module kinds,
84! old module precision_kind is removed,
85! revision history before 2012 removed,
86! comment fields (!:) to be used for variable explanations added to
87! all variable declaration statements
[708]88!
[1319]89! 1318 2014-03-17 13:35:16Z raasch
90! module interfaces removed
91!
[1307]92! 1306 2014-03-13 14:30:59Z raasch
93! second argument removed from routine poisfft
94!
[1258]95! 1257 2013-11-08 15:18:40Z raasch
96! openacc loop and loop vector clauses removed, independent clauses added,
97! end parallel replaced by end parallel loop
98!
[1222]99! 1221 2013-09-10 08:59:13Z raasch
100! openACC porting of reduction operations, loops for calculating d are
101! using the rflags_s_inner multiply flag instead of the nzb_s_inner loop index
102!
[1213]103! 1212 2013-08-15 08:46:27Z raasch
104! call of poisfft_hybrid removed
105!
[1118]106! 1117 2013-03-27 11:15:36Z suehring
107! Bugfix in OpenMP parallelization.
108!
[1114]109! 1113 2013-03-10 02:48:14Z raasch
110! GPU-porting of several loops, some loops rearranged
111!
[1112]112! 1111 2013-03-08 23:54:10Z
113! openACC statements added,
114! ibc_p_b = 2 removed
115!
[1093]116! 1092 2013-02-02 11:24:22Z raasch
117! unused variables removed
118!
[1037]119! 1036 2012-10-22 13:43:42Z raasch
120! code put under GPL (PALM 3.9)
121!
[1004]122! 1003 2012-09-14 14:35:53Z raasch
123! adjustment of array tend for cases with unequal subdomain sizes removed
124!
[1]125! Revision 1.1  1997/07/24 11:24:44  raasch
126! Initial revision
127!
128!
129! Description:
130! ------------
[1682]131!> Compute the divergence of the provisional velocity field. Solve the Poisson
132!> equation for the perturbation pressure. Compute the final velocities using
133!> this perturbation pressure. Compute the remaining divergence.
[1]134!------------------------------------------------------------------------------!
[1682]135 SUBROUTINE pres
136 
[1]137
[1320]138    USE arrays_3d,                                                             &
[2037]139        ONLY:  d, ddzu, ddzu_pres, ddzw, dzw, p, p_loc, rho_air, rho_air_zw,   &
140               tend, u, v, w
[1320]141
142    USE control_parameters,                                                    &
143        ONLY:  bc_lr_cyc, bc_ns_cyc, conserve_volume_flow, dt_3d,              &
144               gathered_size, ibc_p_b, ibc_p_t, intermediate_timestep_count,   &
[1908]145               intermediate_timestep_count_max, mg_switch_to_pe0_level,        &
[2118]146               nest_domain, outflow_l, outflow_n, outflow_r,                   &
[1918]147               outflow_s, psolver, subdomain_size, topography, volume_flow,    &
148               volume_flow_area, volume_flow_initial
[1320]149
150    USE cpulog,                                                                &
151        ONLY:  cpu_log, log_point, log_point_s
152
153    USE grid_variables,                                                        &
154        ONLY:  ddx, ddy
155
156    USE indices,                                                               &
157        ONLY:  nbgp, ngp_2dh_outer, nx, nxl, nxlg, nxl_mg, nxr, nxrg, nxr_mg,  &
[2232]158               ny, nys, nysg, nys_mg, nyn, nyng, nyn_mg, nzb, nzt, nzt_mg,     &
159               wall_flags_0
[1320]160
161    USE kinds
162
[1]163    USE pegrid
[1933]164   
165    USE pmc_interface,                                                         &
166        ONLY:  nesting_mode 
[1]167
[1320]168    USE poisfft_mod,                                                           &
169        ONLY:  poisfft
170
[1575]171    USE poismg_mod
172
[1320]173    USE statistics,                                                            &
174        ONLY:  statistic_regions, sums_divnew_l, sums_divold_l, weight_pres,   &
175               weight_substep
176
[2232]177    USE surface_mod,                                                           &
178        ONLY :  bc_h
179
[1]180    IMPLICIT NONE
181
[1682]182    INTEGER(iwp) ::  i              !<
183    INTEGER(iwp) ::  j              !<
184    INTEGER(iwp) ::  k              !<
[2232]185    INTEGER(iwp) ::  m              !<
[1]186
[1682]187    REAL(wp)     ::  ddt_3d         !<
[1918]188    REAL(wp)     ::  d_weight_pres  !<
[1682]189    REAL(wp)     ::  localsum       !<
190    REAL(wp)     ::  threadsum      !<
[1918]191    REAL(wp)     ::  weight_pres_l  !<
[1929]192    REAL(wp)     ::  weight_substep_l !<
[1]193
[1762]194    REAL(wp), DIMENSION(1:3)   ::  volume_flow_l       !<
195    REAL(wp), DIMENSION(1:3)   ::  volume_flow_offset  !<
[1682]196    REAL(wp), DIMENSION(1:nzt) ::  w_l                 !<
197    REAL(wp), DIMENSION(1:nzt) ::  w_l_l               !<
[1]198
[1933]199    LOGICAL :: nest_domain_nvn      !<
[1]200
[1933]201
[1]202    CALL cpu_log( log_point(8), 'pres', 'start' )
203
[85]204
[1918]205!
206!-- Calculate quantities to be used locally
[1342]207    ddt_3d = 1.0_wp / dt_3d
[1918]208    IF ( intermediate_timestep_count == 0 )  THEN
209!
210!--    If pres is called before initial time step
[1929]211       weight_pres_l    = 1.0_wp
212       d_weight_pres    = 1.0_wp
213       weight_substep_l = 1.0_wp
[1918]214    ELSE
[1929]215       weight_pres_l    = weight_pres(intermediate_timestep_count)
216       d_weight_pres    = 1.0_wp / weight_pres(intermediate_timestep_count)
217       weight_substep_l = weight_substep(intermediate_timestep_count)
[1918]218    ENDIF
[85]219
[1]220!
[707]221!-- Multigrid method expects array d to have one ghost layer.
222!--
[1575]223    IF ( psolver(1:9) == 'multigrid' )  THEN
[667]224     
[1]225       DEALLOCATE( d )
[667]226       ALLOCATE( d(nzb:nzt+1,nys-1:nyn+1,nxl-1:nxr+1) ) 
[707]227
228!
229!--    Since p is later used to hold the weighted average of the substeps, it
230!--    cannot be used in the iterative solver. Therefore, its initial value is
231!--    stored on p_loc, which is then iteratively advanced in every substep.
[1762]232       IF ( intermediate_timestep_count <= 1 )  THEN
[707]233          DO  i = nxl-1, nxr+1
234             DO  j = nys-1, nyn+1
235                DO  k = nzb, nzt+1
236                   p_loc(k,j,i) = p(k,j,i)
237                ENDDO
238             ENDDO
239          ENDDO
[667]240       ENDIF
241       
[1918]242    ELSEIF ( psolver == 'sor'  .AND.  intermediate_timestep_count <= 1 )  THEN
[707]243
244!
245!--    Since p is later used to hold the weighted average of the substeps, it
246!--    cannot be used in the iterative solver. Therefore, its initial value is
247!--    stored on p_loc, which is then iteratively advanced in every substep.
248       p_loc = p
249
[1]250    ENDIF
251
252!
[75]253!-- Conserve the volume flow at the outflow in case of non-cyclic lateral
254!-- boundary conditions
[106]255!-- WARNING: so far, this conservation does not work at the left/south
256!--          boundary if the topography at the inflow differs from that at the
257!--          outflow! For this case, volume_flow_area needs adjustment!
258!
259!-- Left/right
[709]260    IF ( conserve_volume_flow  .AND.  ( outflow_l .OR. outflow_r ) )  THEN
[680]261
[1342]262       volume_flow(1)   = 0.0_wp
263       volume_flow_l(1) = 0.0_wp
[106]264
265       IF ( outflow_l )  THEN
266          i = 0
267       ELSEIF ( outflow_r )  THEN
268          i = nx+1
269       ENDIF
270
271       DO  j = nys, nyn
272!
273!--       Sum up the volume flow through the south/north boundary
[2232]274          DO  k = nzb+1, nzt
275             volume_flow_l(1) = volume_flow_l(1) + u(k,j,i) * dzw(k)           &
276                                     * MERGE( 1.0_wp, 0.0_wp,                  &
277                                              BTEST( wall_flags_0(k,j,i), 1 )  &
278                                            )
[106]279          ENDDO
280       ENDDO
281
282#if defined( __parallel )   
[680]283       IF ( collective_wait )  CALL MPI_BARRIER( comm1dy, ierr )
[106]284       CALL MPI_ALLREDUCE( volume_flow_l(1), volume_flow(1), 1, MPI_REAL, &
285                           MPI_SUM, comm1dy, ierr )   
286#else
287       volume_flow = volume_flow_l 
288#endif
[709]289       volume_flow_offset(1) = ( volume_flow_initial(1) - volume_flow(1) ) &
[106]290                               / volume_flow_area(1)
291
[667]292       DO  j = nysg, nyng
[2232]293          DO  k = nzb+1, nzt
294             u(k,j,i) = u(k,j,i) + volume_flow_offset(1)                       &
295                                     * MERGE( 1.0_wp, 0.0_wp,                  &
296                                              BTEST( wall_flags_0(k,j,i), 1 )  &
297                                            )
[106]298          ENDDO
299       ENDDO
300
301    ENDIF
302
303!
304!-- South/north
[709]305    IF ( conserve_volume_flow  .AND.  ( outflow_n .OR. outflow_s ) )  THEN
[106]306
[1342]307       volume_flow(2)   = 0.0_wp
308       volume_flow_l(2) = 0.0_wp
[75]309
[106]310       IF ( outflow_s )  THEN
311          j = 0
312       ELSEIF ( outflow_n )  THEN
[75]313          j = ny+1
[106]314       ENDIF
315
316       DO  i = nxl, nxr
[75]317!
[106]318!--       Sum up the volume flow through the south/north boundary
[2232]319          DO  k = nzb+1, nzt
320             volume_flow_l(2) = volume_flow_l(2) + v(k,j,i) * dzw(k)           &
321                                     * MERGE( 1.0_wp, 0.0_wp,                  &
322                                              BTEST( wall_flags_0(k,j,i), 2 )  &
323                                            )
[75]324          ENDDO
[106]325       ENDDO
326
[75]327#if defined( __parallel )   
[680]328       IF ( collective_wait )  CALL MPI_BARRIER( comm1dx, ierr )
[75]329       CALL MPI_ALLREDUCE( volume_flow_l(2), volume_flow(2), 1, MPI_REAL, &
330                           MPI_SUM, comm1dx, ierr )   
331#else
332       volume_flow = volume_flow_l 
333#endif
334       volume_flow_offset(2) = ( volume_flow_initial(2) - volume_flow(2) )    &
[106]335                               / volume_flow_area(2)
[75]336
[667]337       DO  i = nxlg, nxrg
[2232]338          DO  k = nzb+1, nzt
339             v(k,j,i) = v(k,j,i) + volume_flow_offset(2)                       &
340                                     * MERGE( 1.0_wp, 0.0_wp,                  &
341                                              BTEST( wall_flags_0(k,j,i), 2 )  &
342                                            )
[75]343          ENDDO
[106]344       ENDDO
[75]345
346    ENDIF
347
[76]348!
[1762]349!-- Remove mean vertical velocity in case that Neumann conditions are
[1933]350!-- used both at bottom and top boundary, and if not a nested domain in a
351!-- normal nesting run. In case of vertical nesting, this must be done.
352!-- Therefore an auxiliary logical variable nest_domain_nvn is used here, and
353!-- nvn stands for non-vertical nesting.
[1918]354!-- This cannot be done before the first initial time step because ngp_2dh_outer
355!-- is not yet known then.
[1933]356    nest_domain_nvn = nest_domain
357    IF ( nest_domain .AND. nesting_mode == 'vertical' )  THEN
358       nest_domain_nvn = .FALSE.
359    ENDIF
360
361    IF ( ibc_p_b == 1  .AND.  ibc_p_t == 1  .AND.                               &
362         .NOT. nest_domain_nvn  .AND. intermediate_timestep_count /= 0 )        &
[1918]363    THEN
364       w_l = 0.0_wp;  w_l_l = 0.0_wp
365       DO  i = nxl, nxr
366          DO  j = nys, nyn
[2232]367             DO  k = nzb+1, nzt
368                w_l_l(k) = w_l_l(k) + w(k,j,i)                                 &
369                                     * MERGE( 1.0_wp, 0.0_wp,                  &
370                                              BTEST( wall_flags_0(k,j,i), 3 )  &
371                                            )
[76]372             ENDDO
373          ENDDO
[1918]374       ENDDO
[76]375#if defined( __parallel )   
[1918]376       IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
377       CALL MPI_ALLREDUCE( w_l_l(1), w_l(1), nzt, MPI_REAL, MPI_SUM, &
378                           comm2d, ierr )
[76]379#else
[1918]380       w_l = w_l_l
[76]381#endif
[1918]382       DO  k = 1, nzt
383          w_l(k) = w_l(k) / ngp_2dh_outer(k,0)
384       ENDDO
385       DO  i = nxlg, nxrg
386          DO  j = nysg, nyng
[2232]387             DO  k = nzb+1, nzt
388                w(k,j,i) = w(k,j,i) - w_l(k)                                   &
389                                     * MERGE( 1.0_wp, 0.0_wp,                  &
390                                              BTEST( wall_flags_0(k,j,i), 3 )  &
391                                            )
[76]392             ENDDO
393          ENDDO
[1918]394       ENDDO
[76]395    ENDIF
[75]396
397!
[1]398!-- Compute the divergence of the provisional velocity field.
399    CALL cpu_log( log_point_s(1), 'divergence', 'start' )
400
[1575]401    IF ( psolver(1:9) == 'multigrid' )  THEN
[2232]402       !$OMP PARALLEL DO SCHEDULE( STATIC ) PRIVATE (i,j,k)
[1]403       DO  i = nxl-1, nxr+1
404          DO  j = nys-1, nyn+1
405             DO  k = nzb, nzt+1
[1342]406                d(k,j,i) = 0.0_wp
[1]407             ENDDO
408          ENDDO
409       ENDDO
410    ELSE
[2232]411       !$OMP PARALLEL DO SCHEDULE( STATIC ) PRIVATE (i,j,k)
[1003]412       DO  i = nxl, nxr
413          DO  j = nys, nyn
414             DO  k = nzb+1, nzt
[1342]415                d(k,j,i) = 0.0_wp
[1]416             ENDDO
417          ENDDO
418       ENDDO
419    ENDIF
420
[1342]421    localsum  = 0.0_wp
422    threadsum = 0.0_wp
[1]423
424#if defined( __ibm )
425    !$OMP PARALLEL PRIVATE (i,j,k) FIRSTPRIVATE(threadsum) REDUCTION(+:localsum)
426    !$OMP DO SCHEDULE( STATIC )
427    DO  i = nxl, nxr
428       DO  j = nys, nyn
[2232]429          DO  k = nzb+1, nzt
[2037]430             d(k,j,i) = ( ( u(k,j,i+1) - u(k,j,i) ) * rho_air(k) * ddx +       &
431                          ( v(k,j+1,i) - v(k,j,i) ) * rho_air(k) * ddy +       &
432                          ( w(k,j,i)   * rho_air_zw(k) -                       &
433                            w(k-1,j,i) * rho_air_zw(k-1) ) * ddzw(k)           &
[2232]434                        ) * ddt_3d * d_weight_pres                             &
435                                   * MERGE( 1.0_wp, 0.0_wp,                    &
436                                            BTEST( wall_flags_0(k,j,i), 0 )    &
437                                          )
[1]438          ENDDO
439!
440!--       Compute possible PE-sum of divergences for flow_statistics
[2232]441          DO  k = nzb+1, nzt
442             threadsum = threadsum + ABS( d(k,j,i) )                           &
443                                   * MERGE( 1.0_wp, 0.0_wp,                    &
444                                            BTEST( wall_flags_0(k,j,i), 0 )    &
445                                          )
[1]446          ENDDO
447
448       ENDDO
449    ENDDO
450
[1918]451    IF ( intermediate_timestep_count == intermediate_timestep_count_max  .OR.  &
452         intermediate_timestep_count == 0 )  THEN
453       localsum = localsum + threadsum * dt_3d * weight_pres_l
[1908]454    ENDIF
[1]455    !$OMP END PARALLEL
456#else
457
[1111]458    !$OMP PARALLEL PRIVATE (i,j,k)
459    !$OMP DO SCHEDULE( STATIC )
460    DO  i = nxl, nxr
461       DO  j = nys, nyn
462          DO  k = 1, nzt
[2037]463             d(k,j,i) = ( ( u(k,j,i+1) - u(k,j,i) ) * rho_air(k) * ddx +       &
464                          ( v(k,j+1,i) - v(k,j,i) ) * rho_air(k) * ddy +       &
465                          ( w(k,j,i)   * rho_air_zw(k) -                       &
466                            w(k-1,j,i) * rho_air_zw(k-1) ) * ddzw(k)           &
[2232]467                        ) * ddt_3d * d_weight_pres                             &
468                                   * MERGE( 1.0_wp, 0.0_wp,                    &
469                                            BTEST( wall_flags_0(k,j,i), 0 )    &
470                                          )     
[1]471          ENDDO
472       ENDDO
[1111]473    ENDDO
474    !$OMP END PARALLEL
[1]475
476!
[1908]477!-- Compute possible PE-sum of divergences for flow_statistics. Carry out
478!-- computation only at last Runge-Kutta substep.
[1918]479    IF ( intermediate_timestep_count == intermediate_timestep_count_max  .OR.  &
480         intermediate_timestep_count == 0 )  THEN
[1908]481       !$OMP PARALLEL PRIVATE (i,j,k) FIRSTPRIVATE(threadsum) REDUCTION(+:localsum)
482       !$OMP DO SCHEDULE( STATIC )
483       DO  i = nxl, nxr
484          DO  j = nys, nyn
485             DO  k = nzb+1, nzt
486                threadsum = threadsum + ABS( d(k,j,i) )
487             ENDDO
[1]488          ENDDO
489       ENDDO
[1918]490       localsum = localsum + threadsum * dt_3d * weight_pres_l
[1908]491       !$OMP END PARALLEL
492    ENDIF
[1]493#endif
494
495!
496!-- For completeness, set the divergence sum of all statistic regions to those
497!-- of the total domain
[1918]498    IF ( intermediate_timestep_count == intermediate_timestep_count_max  .OR.  &
499         intermediate_timestep_count == 0 )  THEN
[1908]500       sums_divold_l(0:statistic_regions) = localsum
[1918]501    ENDIF
[1]502
503    CALL cpu_log( log_point_s(1), 'divergence', 'stop' )
504
505!
506!-- Compute the pressure perturbation solving the Poisson equation
[1575]507    IF ( psolver == 'poisfft' )  THEN
[1]508
509!
510!--    Solve Poisson equation via FFT and solution of tridiagonal matrices
[1575]511       CALL poisfft( d )
[1212]512
[1]513!
514!--    Store computed perturbation pressure and set boundary condition in
515!--    z-direction
[2232]516       !$OMP PARALLEL DO PRIVATE (i,j,k)
[1]517       DO  i = nxl, nxr
518          DO  j = nys, nyn
519             DO  k = nzb+1, nzt
520                tend(k,j,i) = d(k,j,i)
521             ENDDO
522          ENDDO
523       ENDDO
524
525!
526!--    Bottom boundary:
527!--    This condition is only required for internal output. The pressure
528!--    gradient (dp(nzb+1)-dp(nzb))/dz is not used anywhere else.
529       IF ( ibc_p_b == 1 )  THEN
530!
[2232]531!--       Neumann (dp/dz = 0). Using surfae data type, first for non-natural
532!--       surfaces, then for natural and urban surfaces
533!--       Upward facing
534          !$OMP PARALLEL DO PRIVATE( i, j, k )
535          DO  m = 1, bc_h(0)%ns
536             i             = bc_h(0)%i(m)           
537             j             = bc_h(0)%j(m)
538             k             = bc_h(0)%k(m)
539             tend(k-1,j,i) = tend(k,j,i)
[1]540          ENDDO
[2232]541!
542!--       Downward facing
543          !$OMP PARALLEL DO PRIVATE( i, j, k )
544          DO  m = 1, bc_h(1)%ns
545             i             = bc_h(1)%i(m)           
546             j             = bc_h(1)%j(m)
547             k             = bc_h(1)%k(m)
548             tend(k+1,j,i) = tend(k,j,i)
549          ENDDO
[1]550
551       ELSE
552!
[2232]553!--       Dirichlet. Using surface data type, first for non-natural
554!--       surfaces, then for natural and urban surfaces
555!--       Upward facing
556          !$OMP PARALLEL DO PRIVATE( i, j, k )
557          DO  m = 1, bc_h(0)%ns
558             i             = bc_h(0)%i(m)           
559             j             = bc_h(0)%j(m)
560             k             = bc_h(0)%k(m)
561             tend(k-1,j,i) = 0.0_wp
[1]562          ENDDO
[2232]563!
564!--       Downward facing
565          !$OMP PARALLEL DO PRIVATE( i, j, k )
566          DO  m = 1, bc_h(1)%ns
567             i             = bc_h(1)%i(m)           
568             j             = bc_h(1)%j(m)
569             k             = bc_h(1)%k(m)
570             tend(k+1,j,i) = 0.0_wp
571          ENDDO
[1]572
573       ENDIF
574
575!
576!--    Top boundary
577       IF ( ibc_p_t == 1 )  THEN
578!
579!--       Neumann
[2232]580          !$OMP PARALLEL DO PRIVATE (i,j,k)
[667]581          DO  i = nxlg, nxrg
582             DO  j = nysg, nyng
[1]583                tend(nzt+1,j,i) = tend(nzt,j,i)
584             ENDDO
585          ENDDO
586
587       ELSE
588!
589!--       Dirichlet
[2232]590          !$OMP PARALLEL DO PRIVATE (i,j,k)
[667]591          DO  i = nxlg, nxrg
592             DO  j = nysg, nyng
[1342]593                tend(nzt+1,j,i) = 0.0_wp
[1]594             ENDDO
595          ENDDO
596
597       ENDIF
598
599!
600!--    Exchange boundaries for p
[667]601       CALL exchange_horiz( tend, nbgp )
[1]602     
603    ELSEIF ( psolver == 'sor' )  THEN
604
605!
606!--    Solve Poisson equation for perturbation pressure using SOR-Red/Black
607!--    scheme
[707]608       CALL sor( d, ddzu_pres, ddzw, p_loc )
609       tend = p_loc
[1]610
[1575]611    ELSEIF ( psolver(1:9) == 'multigrid' )  THEN
[1]612
613!
614!--    Solve Poisson equation for perturbation pressure using Multigrid scheme,
[667]615!--    array tend is used to store the residuals, logical exchange_mg is used
616!--    to discern data exchange in multigrid ( 1 ghostpoint ) and normal grid
617!--    ( nbgp ghost points ).
[778]618
619!--    If the number of grid points of the gathered grid, which is collected
620!--    on PE0, is larger than the number of grid points of an PE, than array
621!--    tend will be enlarged.
622       IF ( gathered_size > subdomain_size )  THEN
623          DEALLOCATE( tend )
624          ALLOCATE( tend(nzb:nzt_mg(mg_switch_to_pe0_level)+1,nys_mg(          &
625                    mg_switch_to_pe0_level)-1:nyn_mg(mg_switch_to_pe0_level)+1,&
626                    nxl_mg(mg_switch_to_pe0_level)-1:nxr_mg(                   &
627                    mg_switch_to_pe0_level)+1) )
628       ENDIF
629
[1575]630       IF ( psolver == 'multigrid' )  THEN
631          CALL poismg( tend )
632       ELSE
[1931]633          CALL poismg_noopt( tend )
[1575]634       ENDIF
[707]635
[778]636       IF ( gathered_size > subdomain_size )  THEN
637          DEALLOCATE( tend )
638          ALLOCATE( tend(nzb:nzt+1,nysg:nyng,nxlg:nxrg) )
639       ENDIF
640
[1]641!
642!--    Restore perturbation pressure on tend because this array is used
643!--    further below to correct the velocity fields
[707]644       DO  i = nxl-1, nxr+1
645          DO  j = nys-1, nyn+1
646             DO  k = nzb, nzt+1
647                tend(k,j,i) = p_loc(k,j,i)
648             ENDDO
649          ENDDO
650       ENDDO
[667]651
[1]652    ENDIF
653
654!
[707]655!-- Store perturbation pressure on array p, used for pressure data output.
656!-- Ghost layers are added in the output routines (except sor-method: see below)
[1918]657    IF ( intermediate_timestep_count <= 1 )  THEN
[707]658       !$OMP PARALLEL PRIVATE (i,j,k)
659       !$OMP DO
660       DO  i = nxl-1, nxr+1
661          DO  j = nys-1, nyn+1
662             DO  k = nzb, nzt+1
663                p(k,j,i) = tend(k,j,i) * &
[1929]664                           weight_substep_l
[673]665             ENDDO
[1]666          ENDDO
[707]667       ENDDO
668       !$OMP END PARALLEL
669
[1762]670    ELSEIF ( intermediate_timestep_count > 1 )  THEN
[707]671       !$OMP PARALLEL PRIVATE (i,j,k)
672       !$OMP DO
673       DO  i = nxl-1, nxr+1
674          DO  j = nys-1, nyn+1
675             DO  k = nzb, nzt+1
676                p(k,j,i) = p(k,j,i) + tend(k,j,i) * &
[1929]677                           weight_substep_l
[673]678             ENDDO
679          ENDDO
[707]680       ENDDO
681       !$OMP END PARALLEL
682
683    ENDIF
[673]684       
[707]685!
686!-- SOR-method needs ghost layers for the next timestep
687    IF ( psolver == 'sor' )  CALL exchange_horiz( p, nbgp )
[682]688
[1]689!
690!-- Correction of the provisional velocities with the current perturbation
691!-- pressure just computed
[709]692    IF ( conserve_volume_flow  .AND.  ( bc_lr_cyc .OR. bc_ns_cyc ) )  THEN
[1342]693       volume_flow_l(1) = 0.0_wp
694       volume_flow_l(2) = 0.0_wp
[1]695    ENDIF
[707]696
[1]697    !$OMP PARALLEL PRIVATE (i,j,k)
698    !$OMP DO
[673]699    DO  i = nxl, nxr   
[1]700       DO  j = nys, nyn
[2118]701
[2232]702          DO  k = nzb+1, nzt
703             w(k,j,i) = w(k,j,i) - dt_3d *                                     &
704                           ( tend(k+1,j,i) - tend(k,j,i) ) * ddzu(k+1)         &
705                                     * weight_pres_l                           &
706                                     * MERGE( 1.0_wp, 0.0_wp,                  &
707                                              BTEST( wall_flags_0(k,j,i), 3 )  &
708                                            )
[1]709          ENDDO
[2118]710
[2232]711          DO  k = nzb+1, nzt
712             u(k,j,i) = u(k,j,i) - dt_3d *                                     &
713                           ( tend(k,j,i) - tend(k,j,i-1) ) * ddx               &
714                                     * weight_pres_l                           &
715                                     * MERGE( 1.0_wp, 0.0_wp,                  &
716                                              BTEST( wall_flags_0(k,j,i), 1 )  &
717                                            )
[1]718          ENDDO
[2118]719
[2232]720          DO  k = nzb+1, nzt
721             v(k,j,i) = v(k,j,i) - dt_3d *                                     &
722                           ( tend(k,j,i) - tend(k,j-1,i) ) * ddy               &
723                                     * weight_pres_l                           &
724                                     * MERGE( 1.0_wp, 0.0_wp,                  &
725                                              BTEST( wall_flags_0(k,j,i), 2 )  &
726                                            )
[673]727          ENDDO                                                         
[1]728
729       ENDDO
730    ENDDO
731    !$OMP END PARALLEL
[1113]732
733!
734!-- Sum up the volume flow through the right and north boundary
[2232]735    IF ( conserve_volume_flow  .AND.  bc_lr_cyc  .AND.  bc_ns_cyc  .AND.       &
[1113]736         nxr == nx )  THEN
737
738       !$OMP PARALLEL PRIVATE (j,k)
739       !$OMP DO
740       DO  j = nys, nyn
741          !$OMP CRITICAL
[2232]742          DO  k = nzb+1, nzt
743             volume_flow_l(1) = volume_flow_l(1) + u(k,j,nxr) * dzw(k)         &
744                                     * MERGE( 1.0_wp, 0.0_wp,                  &
745                                              BTEST( wall_flags_0(k,j,nxr), 1 )&
746                                            )
[1113]747          ENDDO
748          !$OMP END CRITICAL
749       ENDDO
750       !$OMP END PARALLEL
751
752    ENDIF
753
[2232]754    IF ( conserve_volume_flow  .AND.  bc_ns_cyc  .AND.  bc_lr_cyc  .AND.       &
[1113]755         nyn == ny )  THEN
756
757       !$OMP PARALLEL PRIVATE (i,k)
758       !$OMP DO
759       DO  i = nxl, nxr
760          !$OMP CRITICAL
[2232]761          DO  k = nzb+1, nzt
762             volume_flow_l(2) = volume_flow_l(2) + v(k,nyn,i) * dzw(k)         &
763                                     * MERGE( 1.0_wp, 0.0_wp,                  &
764                                              BTEST( wall_flags_0(k,nyn,i), 2 )&
765                                            )
[1113]766           ENDDO
767          !$OMP END CRITICAL
768       ENDDO
769       !$OMP END PARALLEL
770
771    ENDIF
[673]772   
[1]773!
774!-- Conserve the volume flow
[707]775    IF ( conserve_volume_flow  .AND.  ( bc_lr_cyc  .AND.  bc_ns_cyc ) )  THEN
[1]776
777#if defined( __parallel )   
[622]778       IF ( collective_wait )  CALL MPI_BARRIER( comm2d, ierr )
[1]779       CALL MPI_ALLREDUCE( volume_flow_l(1), volume_flow(1), 2, MPI_REAL, &
780                           MPI_SUM, comm2d, ierr ) 
781#else
782       volume_flow = volume_flow_l 
783#endif   
784
[1799]785       volume_flow_offset(1:2) = ( volume_flow_initial(1:2) - volume_flow(1:2) ) / &
786                            volume_flow_area(1:2)
[1]787
788       !$OMP PARALLEL PRIVATE (i,j,k)
789       !$OMP DO
790       DO  i = nxl, nxr
791          DO  j = nys, nyn
[2232]792             DO  k = nzb+1, nzt
793                u(k,j,i) = u(k,j,i) + volume_flow_offset(1)                    &
794                                     * MERGE( 1.0_wp, 0.0_wp,                  &
795                                              BTEST( wall_flags_0(k,j,i), 1 )  &
796                                            )
[719]797             ENDDO
[2232]798             DO  k = nzb+1, nzt
799                v(k,j,i) = v(k,j,i) + volume_flow_offset(2)                    &
800                                     * MERGE( 1.0_wp, 0.0_wp,                  &
801                                              BTEST( wall_flags_0(k,j,i), 2 )  &
802                                            )
[667]803             ENDDO
[1]804          ENDDO
805       ENDDO
[667]806
[1]807       !$OMP END PARALLEL
808
809    ENDIF
810
811!
812!-- Exchange of boundaries for the velocities
[667]813    CALL exchange_horiz( u, nbgp )
814    CALL exchange_horiz( v, nbgp )
815    CALL exchange_horiz( w, nbgp )
[1]816
817!
818!-- Compute the divergence of the corrected velocity field,
[1908]819!-- A possible PE-sum is computed in flow_statistics. Carry out computation
820!-- only at last Runge-Kutta step.
[1918]821    IF ( intermediate_timestep_count == intermediate_timestep_count_max  .OR.  &
822         intermediate_timestep_count == 0 )  THEN
[1908]823       CALL cpu_log( log_point_s(1), 'divergence', 'start' )
824       sums_divnew_l = 0.0_wp
[1]825
826!
[1908]827!--    d must be reset to zero because it can contain nonzero values below the
828!--    topography
829       IF ( topography /= 'flat' )  d = 0.0_wp
[1]830
[1908]831       localsum  = 0.0_wp
832       threadsum = 0.0_wp
[1]833
[1908]834       !$OMP PARALLEL PRIVATE (i,j,k) FIRSTPRIVATE(threadsum) REDUCTION(+:localsum)
[2073]835#if defined( __ibm )
[1908]836       !$OMP DO SCHEDULE( STATIC )
837       DO  i = nxl, nxr
838          DO  j = nys, nyn
[2232]839             DO  k = nzb+1, nzt
840             d(k,j,i) = ( ( u(k,j,i+1) - u(k,j,i) ) * rho_air(k) * ddx +       &
841                          ( v(k,j+1,i) - v(k,j,i) ) * rho_air(k) * ddy +       &
842                          ( w(k,j,i)   * rho_air_zw(k) -                       &
843                            w(k-1,j,i) * rho_air_zw(k-1) ) * ddzw(k)           &
844                        ) * MERGE( 1.0_wp, 0.0_wp,                             &
845                                   BTEST( wall_flags_0(k,j,i), 0 )             &
846                                 )
[1908]847             ENDDO
848             DO  k = nzb+1, nzt
849                threadsum = threadsum + ABS( d(k,j,i) )
850             ENDDO
[1]851          ENDDO
852       ENDDO
853#else
[2073]854       !$OMP DO SCHEDULE( STATIC )
[1908]855       DO  i = nxl, nxr
856          DO  j = nys, nyn
[2232]857             DO  k = nzb+1, nzt
[2037]858                d(k,j,i) = ( ( u(k,j,i+1) - u(k,j,i) ) * rho_air(k) * ddx +    &
859                             ( v(k,j+1,i) - v(k,j,i) ) * rho_air(k) * ddy +    &
860                             ( w(k,j,i)   * rho_air_zw(k) -                    &
861                               w(k-1,j,i) * rho_air_zw(k-1) ) * ddzw(k)        &
[2232]862                           ) * MERGE( 1.0_wp, 0.0_wp,                          &
863                                   BTEST( wall_flags_0(k,j,i), 0 )             &
864                                    )
[1908]865             ENDDO
[1113]866          ENDDO
867       ENDDO
868!
[1908]869!--    Compute possible PE-sum of divergences for flow_statistics
[2073]870       !$OMP DO SCHEDULE( STATIC )
[1908]871       DO  i = nxl, nxr
872          DO  j = nys, nyn
873             DO  k = nzb+1, nzt
874                threadsum = threadsum + ABS( d(k,j,i) )
875             ENDDO
[1]876          ENDDO
877       ENDDO
878#endif
[667]879
[1908]880       localsum = localsum + threadsum
881       !$OMP END PARALLEL
[1]882
883!
[1908]884!--    For completeness, set the divergence sum of all statistic regions to those
885!--    of the total domain
886       sums_divnew_l(0:statistic_regions) = localsum
[1]887
[1908]888       CALL cpu_log( log_point_s(1), 'divergence', 'stop' )
[1]889
[1908]890    ENDIF
891
[1]892    CALL cpu_log( log_point(8), 'pres', 'stop' )
893
894
895 END SUBROUTINE pres
Note: See TracBrowser for help on using the repository browser.