Index: palm/trunk/SOURCE/exchange_horiz_mod.f90
===================================================================
--- palm/trunk/SOURCE/exchange_horiz.f90	(revision 4429)
+++ palm/trunk/SOURCE/exchange_horiz_mod.f90	(revision 4457)
@@ -25,4 +25,7 @@
 ! -----------------
 ! $Id$
+! routine has been modularized, file exchange_horiz_2d has been merged
+! 
+! 4429 2020-02-27 15:24:30Z raasch
 ! bugfix: cpp-directives added for serial mode
 ! 
@@ -45,6 +48,41 @@
 !> lateral boundary conditions, respectively.
 !------------------------------------------------------------------------------!
+ MODULE exchange_horiz_mod
+
+    USE kinds
+
+    USE pegrid
+
+    IMPLICIT NONE
+
+    PRIVATE
+    PUBLIC exchange_horiz, exchange_horiz_int, exchange_horiz_2d, exchange_horiz_2d_byte,          &
+           exchange_horiz_2d_int
+
+    INTERFACE exchange_horiz
+       MODULE PROCEDURE exchange_horiz
+    END INTERFACE exchange_horiz
+
+    INTERFACE exchange_horiz_int
+       MODULE PROCEDURE exchange_horiz_int
+    END INTERFACE exchange_horiz_int
+
+    INTERFACE exchange_horiz_2d
+       MODULE PROCEDURE exchange_horiz_2d
+    END INTERFACE exchange_horiz_2d
+
+    INTERFACE exchange_horiz_2d_byte
+       MODULE PROCEDURE exchange_horiz_2d_byte
+    END INTERFACE exchange_horiz_2d_byte
+
+    INTERFACE exchange_horiz_2d_int
+       MODULE PROCEDURE exchange_horiz_2d_int
+    END INTERFACE exchange_horiz_2d_int
+
+
+ CONTAINS
+
+
  SUBROUTINE exchange_horiz( ar, nbgp_local)
- 
 
     USE control_parameters,                                                    &
@@ -62,10 +100,4 @@
         ONLY:  nxl, nxr, nyn, nys, nzb, nzt
         
-    USE kinds
-    
-    USE pegrid
-
-    IMPLICIT NONE
-
 
 #if defined( _OPENACC )
@@ -293,10 +325,4 @@
     USE indices,                                                               &
         ONLY:  nzb
-        
-    USE kinds
-    
-    USE pegrid
-
-    IMPLICIT NONE
 
     INTEGER(iwp) ::  nxl_l       !< local index bound at current grid level, left side
@@ -379,4 +405,403 @@
 #endif
 
-
  END SUBROUTINE exchange_horiz_int
+
+! Description:
+! ------------
+!> Exchange of lateral (ghost) boundaries (parallel computers) and cyclic
+!> boundary conditions, respectively, for 2D-arrays.
+!------------------------------------------------------------------------------!
+ SUBROUTINE exchange_horiz_2d( ar )
+
+    USE control_parameters,                                                    &
+        ONLY :  bc_dirichlet_l, bc_dirichlet_n, bc_dirichlet_r,                &
+                bc_dirichlet_s, bc_radiation_l,                                &
+                bc_radiation_n, bc_radiation_r, bc_radiation_s
+
+    USE cpulog,                                                                &
+        ONLY :  cpu_log, log_point_s
+
+    USE indices,                                                               &
+        ONLY :  nbgp, nxl, nxlg, nxr, nxrg, nyn, nyng, nys, nysg
+
+#if ! defined( __parallel )
+    USE control_parameters,                                                    &
+        ONLY:  bc_lr_cyc, bc_ns_cyc
+#endif
+
+
+    INTEGER(iwp) :: i  !<
+
+    REAL(wp) ::  ar(nysg:nyng,nxlg:nxrg)  !<
+
+
+    CALL cpu_log( log_point_s(13), 'exchange_horiz_2d', 'start' )
+
+#if defined( __parallel )
+
+!
+!-- Exchange of lateral boundary values for parallel computers
+    IF ( pdims(1) == 1 )  THEN
+
+!
+!--    One-dimensional decomposition along y, boundary values can be exchanged
+!--    within the PE memory
+       ar(:,nxlg:nxl-1) = ar(:,nxr-nbgp+1:nxr)
+       ar(:,nxr+1:nxrg) = ar(:,nxl:nxl+nbgp-1)
+
+    ELSE
+!
+!--    Send left boundary, receive right one
+
+       CALL MPI_SENDRECV( ar(nysg,nxl), 1, type_y, pleft,  0,                 &
+                          ar(nysg,nxr+1), 1, type_y, pright, 0,               &
+                          comm2d, status, ierr )
+!
+!--    Send right boundary, receive left one
+       CALL MPI_SENDRECV( ar(nysg,nxr+1-nbgp), 1, type_y, pright,  1,         &
+                          ar(nysg,nxlg), 1, type_y, pleft,   1,               &
+                          comm2d, status, ierr )
+
+
+    ENDIF
+
+    IF ( pdims(2) == 1 )  THEN
+!
+!--    One-dimensional decomposition along x, boundary values can be exchanged
+!--    within the PE memory
+       ar(nysg:nys-1,:) = ar(nyn-nbgp+1:nyn,:)
+       ar(nyn+1:nyng,:) = ar(nys:nys+nbgp-1,:)
+
+    ELSE
+!
+!--    Send front boundary, receive rear one
+
+       CALL MPI_SENDRECV( ar(nys,nxlg), 1, type_x, psouth, 0,                 &
+                          ar(nyn+1,nxlg), 1, type_x, pnorth, 0,               &
+                          comm2d, status, ierr )
+!
+!--    Send rear boundary, receive front one
+       CALL MPI_SENDRECV( ar(nyn+1-nbgp,nxlg), 1, type_x, pnorth, 1,          &
+                          ar(nysg,nxlg), 1, type_x, psouth, 1,                &
+                          comm2d, status, ierr )
+
+    ENDIF
+
+#else
+
+!
+!-- Lateral boundary conditions in the non-parallel case
+    IF ( bc_lr_cyc )  THEN
+       ar(:,nxlg:nxl-1) = ar(:,nxr-nbgp+1:nxr)
+       ar(:,nxr+1:nxrg) = ar(:,nxl:nxl+nbgp-1)
+    ENDIF
+
+    IF ( bc_ns_cyc )  THEN
+       ar(nysg:nys-1,:) = ar(nyn-nbgp+1:nyn,:)
+       ar(nyn+1:nyng,:) = ar(nys:nys+nbgp-1,:)
+    ENDIF
+
+#endif
+
+!
+!-- Neumann-conditions at inflow/outflow/nested boundaries
+    IF ( bc_dirichlet_l  .OR.  bc_radiation_l )  THEN
+       DO  i = nbgp, 1, -1
+          ar(:,nxl-i) = ar(:,nxl)
+       ENDDO
+    ENDIF
+    IF ( bc_dirichlet_r  .OR.  bc_radiation_r )  THEN
+       DO  i = 1, nbgp
+          ar(:,nxr+i) = ar(:,nxr)
+       ENDDO
+    ENDIF
+    IF ( bc_dirichlet_s  .OR.  bc_radiation_s )  THEN
+       DO  i = nbgp, 1, -1
+          ar(nys-i,:) = ar(nys,:)
+       ENDDO
+    ENDIF
+    IF ( bc_dirichlet_n  .OR.  bc_radiation_n )  THEN
+       DO  i = 1, nbgp
+          ar(nyn+i,:) = ar(nyn,:)
+       ENDDO
+    ENDIF
+
+    CALL cpu_log( log_point_s(13), 'exchange_horiz_2d', 'stop' )
+
+ END SUBROUTINE exchange_horiz_2d
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Exchange of lateral (ghost) boundaries (parallel computers) and cyclic
+!> boundary conditions, respectively, for 2D 8-bit integer arrays.
+!------------------------------------------------------------------------------!
+ SUBROUTINE exchange_horiz_2d_byte( ar, nys_l, nyn_l, nxl_l, nxr_l, nbgp_local )
+
+
+    USE control_parameters,                                                    &
+        ONLY:  bc_dirichlet_l, bc_dirichlet_n, bc_dirichlet_r, bc_dirichlet_s, &
+               bc_radiation_l, bc_radiation_n, bc_radiation_r, bc_radiation_s, &
+               bc_radiation_l, bc_radiation_n, bc_radiation_r, bc_radiation_s
+
+    USE cpulog,                                                                &
+        ONLY:  cpu_log, log_point_s
+
+#if ! defined( __parallel )
+    USE control_parameters,                                                    &
+        ONLY:  bc_lr_cyc, bc_ns_cyc
+#endif
+
+    INTEGER(iwp) ::  i           !< dummy index to zero-gradient conditions at in/outflow boundaries
+    INTEGER(iwp) ::  nxl_l       !< local index bound at current grid level, left side
+    INTEGER(iwp) ::  nxr_l       !< local index bound at current grid level, right side
+    INTEGER(iwp) ::  nyn_l       !< local index bound at current grid level, north side
+    INTEGER(iwp) ::  nys_l       !< local index bound at current grid level, south side
+    INTEGER(iwp) ::  nbgp_local  !< number of ghost layers to be exchanged
+
+    INTEGER(KIND=1), DIMENSION(nys_l-nbgp_local:nyn_l+nbgp_local,              &
+                               nxl_l-nbgp_local:nxr_l+nbgp_local) ::  ar  !< treated array
+
+    CALL cpu_log( log_point_s(13), 'exchange_horiz_2d', 'start' )
+
+#if defined( __parallel )
+
+!
+!-- Exchange of lateral boundary values for parallel computers
+    IF ( pdims(1) == 1 )  THEN
+
+!
+!--    One-dimensional decomposition along y, boundary values can be exchanged
+!--    within the PE memory
+       ar(:,nxl_l-nbgp_local:nxl_l-1) = ar(:,nxr_l-nbgp_local+1:nxr_l)
+       ar(:,nxr_l+1:nxr_l+nbgp_local) = ar(:,nxl_l:nxl_l+nbgp_local-1)
+
+    ELSE
+!
+!--    Send left boundary, receive right one
+       CALL MPI_SENDRECV( ar(nys_l-nbgp_local,nxl_l),   1,                     &
+                          type_y_byte, pleft,  0,                              &
+                          ar(nys_l-nbgp_local,nxr_l+1), 1,                     &
+                          type_y_byte, pright, 0,                              &
+                          comm2d, status, ierr )
+!
+!--    Send right boundary, receive left one
+       CALL MPI_SENDRECV( ar(nys_l-nbgp_local,nxr_l+1-nbgp_local), 1,          &
+                          type_y_byte, pright, 1,                              &
+                          ar(nys_l-nbgp_local,nxl_l-nbgp_local),   1,          &
+                          type_y_byte, pleft,  1,                              &
+                          comm2d, status, ierr )
+
+    ENDIF
+
+    IF ( pdims(2) == 1 )  THEN
+!
+!--    One-dimensional decomposition along x, boundary values can be exchanged
+!--    within the PE memory
+       ar(nys_l-nbgp_local:nys_l-1,:) = ar(nyn_l+1-nbgp_local:nyn_l,:)
+       ar(nyn_l+1:nyn_l+nbgp_local,:) = ar(nys_l:nys_l-1+nbgp_local,:)
+
+
+    ELSE
+!
+!--    Send front boundary, receive rear one
+       CALL MPI_SENDRECV( ar(nys_l,nxl_l-nbgp_local),   1,                    &
+                          type_x_byte, psouth, 0,                             &
+                          ar(nyn_l+1,nxl_l-nbgp_local), 1,                    &
+                          type_x_byte, pnorth, 0,                             &
+                          comm2d, status, ierr )
+
+!
+!--    Send rear boundary, receive front one
+       CALL MPI_SENDRECV( ar(nyn_l+1-nbgp_local,nxl_l-nbgp_local), 1,         &
+                          type_x_byte, pnorth, 1,                             &
+                          ar(nys_l-nbgp_local,nxl_l-nbgp_local),   1,         &
+                          type_x_byte, psouth, 1,                             &
+                          comm2d, status, ierr )
+
+    ENDIF
+
+#else
+
+!
+!-- Lateral boundary conditions in the non-parallel case
+    IF ( bc_lr_cyc )  THEN
+       ar(:,nxl_l-nbgp_local:nxl_l-1) = ar(:,nxr_l-nbgp_local+1:nxr_l)
+       ar(:,nxr_l+1:nxr_l+nbgp_local) = ar(:,nxl_l:nxl_l+nbgp_local-1)
+    ENDIF
+
+    IF ( bc_ns_cyc )  THEN
+       ar(nys_l-nbgp_local:nys_l-1,:) = ar(nyn_l+1-nbgp_local:nyn_l,:)
+       ar(nyn_l+1:nyn_l+nbgp_local,:) = ar(nys_l:nys_l-1+nbgp_local,:)
+    ENDIF
+
+#endif
+!
+!-- Neumann-conditions at inflow/outflow/nested boundaries
+    IF ( bc_dirichlet_l  .OR.  bc_radiation_l )  THEN
+       DO  i = nbgp_local, 1, -1
+         ar(:,nxl_l-i) = ar(:,nxl_l)
+       ENDDO
+    ENDIF
+    IF ( bc_dirichlet_r  .OR.  bc_radiation_r  )  THEN
+       DO  i = 1, nbgp_local
+          ar(:,nxr_l+i) = ar(:,nxr_l)
+       ENDDO
+    ENDIF
+    IF ( bc_dirichlet_s  .OR.  bc_radiation_s  )  THEN
+       DO  i = nbgp_local, 1, -1
+         ar(nys_l-i,:) = ar(nys_l,:)
+       ENDDO
+    ENDIF
+    IF ( bc_dirichlet_n  .OR.  bc_radiation_n  )  THEN
+       DO  i = 1, nbgp_local
+         ar(nyn_l+i,:) = ar(nyn_l,:)
+       ENDDO
+    ENDIF
+
+    CALL cpu_log( log_point_s(13), 'exchange_horiz_2d', 'stop' )
+
+ END SUBROUTINE exchange_horiz_2d_byte
+
+
+!------------------------------------------------------------------------------!
+! Description:
+! ------------
+!> Exchange of lateral (ghost) boundaries (parallel computers) and cyclic
+!> boundary conditions, respectively, for 2D 32-bit integer arrays.
+!------------------------------------------------------------------------------!
+ SUBROUTINE exchange_horiz_2d_int( ar, nys_l, nyn_l, nxl_l, nxr_l, nbgp_local )
+
+
+    USE control_parameters,                                                    &
+        ONLY:  bc_dirichlet_l, bc_dirichlet_n, bc_dirichlet_r, bc_dirichlet_s, &
+               bc_radiation_l, bc_radiation_n, bc_radiation_r, bc_radiation_s, &
+               bc_radiation_l, bc_radiation_n, bc_radiation_r, bc_radiation_s
+
+#if defined( __parallel )
+    USE control_parameters,                                                    &
+        ONLY:  grid_level
+#endif
+
+    USE cpulog,                                                                &
+        ONLY:  cpu_log, log_point_s
+
+#if ! defined( __parallel )
+    USE control_parameters,                                                    &
+        ONLY:  bc_lr_cyc, bc_ns_cyc
+#endif
+
+    INTEGER(iwp) ::  i           !< dummy index to zero-gradient conditions at in/outflow boundaries
+    INTEGER(iwp) ::  nxl_l       !< local index bound at current grid level, left side
+    INTEGER(iwp) ::  nxr_l       !< local index bound at current grid level, right side
+    INTEGER(iwp) ::  nyn_l       !< local index bound at current grid level, north side
+    INTEGER(iwp) ::  nys_l       !< local index bound at current grid level, south side
+    INTEGER(iwp) ::  nbgp_local  !< number of ghost layers to be exchanged
+
+    INTEGER(iwp), DIMENSION(nys_l-nbgp_local:nyn_l+nbgp_local,                 &
+                            nxl_l-nbgp_local:nxr_l+nbgp_local) ::  ar  !< treated array
+
+    CALL cpu_log( log_point_s(13), 'exchange_horiz_2d', 'start' )
+
+#if defined( __parallel )
+
+!
+!-- Exchange of lateral boundary values for parallel computers
+    IF ( pdims(1) == 1 )  THEN
+
+!
+!--    One-dimensional decomposition along y, boundary values can be exchanged
+!--    within the PE memory
+       ar(:,nxl_l-nbgp_local:nxl_l-1) = ar(:,nxr_l-nbgp_local+1:nxr_l)
+       ar(:,nxr_l+1:nxr_l+nbgp_local) = ar(:,nxl_l:nxl_l+nbgp_local-1)
+
+    ELSE
+!
+!--    Send left boundary, receive right one
+       CALL MPI_SENDRECV( ar(nys_l-nbgp_local,nxl_l),   1,                     &
+                          type_y_int(grid_level), pleft,  0,                   &
+                          ar(nys_l-nbgp_local,nxr_l+1), 1,                     &
+                          type_y_int(grid_level), pright, 0,                   &
+                          comm2d, status, ierr )
+!
+!--    Send right boundary, receive left one
+       CALL MPI_SENDRECV( ar(nys_l-nbgp_local,nxr_l+1-nbgp_local), 1,          &
+                          type_y_int(grid_level), pright, 1,                   &
+                          ar(nys_l-nbgp_local,nxl_l-nbgp_local),   1,          &
+                          type_y_int(grid_level), pleft,  1,                   &
+                          comm2d, status, ierr )
+
+    ENDIF
+
+    IF ( pdims(2) == 1 )  THEN
+!
+!--    One-dimensional decomposition along x, boundary values can be exchanged
+!--    within the PE memory
+       ar(nys_l-nbgp_local:nys_l-1,:) = ar(nyn_l+1-nbgp_local:nyn_l,:)
+       ar(nyn_l+1:nyn_l+nbgp_local,:) = ar(nys_l:nys_l-1+nbgp_local,:)
+
+
+    ELSE
+!
+!--    Send front boundary, receive rear one
+       CALL MPI_SENDRECV( ar(nys_l,nxl_l-nbgp_local),   1,                    &
+                          type_x_int(grid_level), psouth, 0,                  &
+                          ar(nyn_l+1,nxl_l-nbgp_local), 1,                    &
+                          type_x_int(grid_level), pnorth, 0,                  &
+                          comm2d, status, ierr )
+
+!
+!--    Send rear boundary, receive front one
+       CALL MPI_SENDRECV( ar(nyn_l+1-nbgp_local,nxl_l-nbgp_local), 1,         &
+                          type_x_int(grid_level), pnorth, 1,                  &
+                          ar(nys_l-nbgp_local,nxl_l-nbgp_local),   1,         &
+                          type_x_int(grid_level), psouth, 1,                  &
+                          comm2d, status, ierr )
+
+    ENDIF
+
+#else
+
+!
+!-- Lateral boundary conditions in the non-parallel case
+    IF ( bc_lr_cyc )  THEN
+       ar(:,nxl_l-nbgp_local:nxl_l-1) = ar(:,nxr_l-nbgp_local+1:nxr_l)
+       ar(:,nxr_l+1:nxr_l+nbgp_local) = ar(:,nxl_l:nxl_l+nbgp_local-1)
+    ENDIF
+
+    IF ( bc_ns_cyc )  THEN
+       ar(nys_l-nbgp_local:nys_l-1,:) = ar(nyn_l+1-nbgp_local:nyn_l,:)
+       ar(nyn_l+1:nyn_l+nbgp_local,:) = ar(nys_l:nys_l-1+nbgp_local,:)
+    ENDIF
+
+#endif
+!
+!-- Neumann-conditions at inflow/outflow/nested boundaries
+    IF ( bc_dirichlet_l  .OR.  bc_radiation_l )  THEN
+       DO  i = nbgp_local, 1, -1
+         ar(:,nxl_l-i) = ar(:,nxl_l)
+       ENDDO
+    ENDIF
+    IF ( bc_dirichlet_r  .OR.  bc_radiation_r  )  THEN
+       DO  i = 1, nbgp_local
+          ar(:,nxr_l+i) = ar(:,nxr_l)
+       ENDDO
+    ENDIF
+    IF ( bc_dirichlet_s  .OR.  bc_radiation_s  )  THEN
+       DO  i = nbgp_local, 1, -1
+         ar(nys_l-i,:) = ar(nys_l,:)
+       ENDDO
+    ENDIF
+    IF ( bc_dirichlet_n  .OR.  bc_radiation_n  )  THEN
+       DO  i = 1, nbgp_local
+         ar(nyn_l+i,:) = ar(nyn_l,:)
+       ENDDO
+    ENDIF
+
+    CALL cpu_log( log_point_s(13), 'exchange_horiz_2d', 'stop' )
+
+ END SUBROUTINE exchange_horiz_2d_int
+
+
+ END MODULE exchange_horiz_mod
