!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_SPLIT2d                ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


SUBROUTINE wrf_split2d(globvar,nx,ny,fzone,var),4

!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Split the global array and scatter to each processor.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2002/08/20
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    globvar  Global array passed in from processor 0.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!
!  OUTPUT:
!
!    var      Subdomain variable in each process.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, INTENT(IN)  :: nx,ny       ! Number of grid points in x and y
  INTEGER, INTENT(IN)  :: fzone       ! number of fake zone
                                      ! 1 for wrf
                                      ! 3 for arps
  REAL,    INTENT(IN)  ::                                               &
           globvar((nx-fzone)*nproc_x+fzone,(ny-fzone)*nproc_y+fzone)

  REAL,    INTENT(OUT) :: var(nx,ny)


!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: target
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  DO jc=1,nproc_y
    DO ic=1,nproc_x

      !  storage section

      IF(myproc == 0)THEN  ! store data into var

        DO j=1,ny
          ja = j + (jc-1)*(ny-fzone)
          DO i=1,nx
            ia = i + (ic-1)*(nx-fzone)
            var(i,j) = globvar(ia,ja)
          END DO          
        END DO      

      END IF

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  receive data from processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == 0)THEN          ! send data

          target = ic+(jc-1)*nproc_x-1

          CALL mpi_send (var,nx*ny,MPI_REAL,target,               &
                         mytag, MPI_COMM_WORLD,imstat)
        END IF

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_recv (var,nx*ny,MPI_REAL,master,               &
                         mytag,MPI_COMM_WORLD,stat,imstat) 

        END IF

      END IF

      CALL mpbarrier
 
    END DO      
  END DO      

!At the end, make sure processor 0 contains correct varlue (ic=1,jc=1)
  IF(myproc == 0) var(:,:) = globvar(1:nx,1:ny)     

  RETURN
END SUBROUTINE wrf_split2d
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_SPLIT2DI               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


SUBROUTINE wrf_split2di(globvar,nx,ny,fzone,var),4

!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Split the global array and scatter to each processor.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2002/08/20
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    globvar  Global array passed in from processor 0.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!
!  OUTPUT:
!
!    var      Subdomain variable in each process.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, INTENT(IN)  :: nx,ny       ! Number of grid points in x and y
  INTEGER, INTENT(IN)  :: fzone       ! number of fake zone
                                      ! 1 for wrf
                                      ! 3 for arps
  INTEGER, INTENT(IN)  ::                                               &
           globvar((nx-fzone)*nproc_x+fzone,(ny-fzone)*nproc_y+fzone)

  INTEGER, INTENT(OUT) :: var(nx,ny)


!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: target
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  DO jc=1,nproc_y
    DO ic=1,nproc_x

      !  storage section

      IF(myproc == 0)THEN  ! store data into tem

        DO j=1,ny
          ja = j + (jc-1)*(ny-fzone)
          DO i=1,nx
            ia = i + (ic-1)*(nx-fzone)
            var(i,j) = globvar(ia,ja)
          END DO          
        END DO      

      END IF

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  receive data from processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == 0)THEN          ! send data

          target = ic+(jc-1)*nproc_x-1

          CALL mpi_send (var,nx*ny,MPI_INTEGER,target,               &
                         mytag, MPI_COMM_WORLD,imstat)
        END IF

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_recv (var,nx*ny,MPI_INTEGER,master,               &
                         mytag,MPI_COMM_WORLD,stat,imstat) 

        END IF

      END IF

      CALL mpbarrier
 
    END DO      
  END DO      

!At the end, make sure processor 0 contains correct varlue (ic=1,jc=1)
  IF(myproc == 0) var(:,:) = globvar(1:nx,1:ny)     

  RETURN
END SUBROUTINE wrf_split2di
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_SPLIT3d                ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!


SUBROUTINE wrf_split3d(globvar,nx,ny,nz,fzone,var),4

!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Split the global array and scatter to each processor.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2002/08/20
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    globvar  Global array passed in from processor 0.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       3rd dimension of the subdomain array, possible value are
!             vertical grid points (nz in other subroutines), nzsoil,
!             nstyps+1, or 4 (prcrate) or 1 (for 2D arrays)
!
!  OUTPUT:
!
!    var      Subdomain variable in each process.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, INTENT(IN)  :: nx,ny,nz    ! Number of grid points in x, y and z
  INTEGER, INTENT(IN)  :: fzone       ! number of fake zone
                                      ! 1 for wrf
                                      ! 3 for arps
  REAL,    INTENT(IN)  ::                                               &
           globvar((nx-fzone)*nproc_x+fzone,(ny-fzone)*nproc_y+fzone,nz)

  REAL, INTENT(OUT) :: var(nx,ny,nz)


!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: target
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  DO jc=1,nproc_y
    DO ic=1,nproc_x

      !  storage section

      IF(myproc == 0)THEN  ! store data into tem

        DO k=1,nz
          DO j=1,ny
            ja = j + (jc-1)*(ny-fzone)
            DO i=1,nx
              ia = i + (ic-1)*(nx-fzone)
              var(i,j,k) = globvar(ia,ja,k)
            END DO          
          END DO      
        END DO      

      END IF

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  receive data from processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == 0)THEN          ! send data

          target = ic+(jc-1)*nproc_x-1

          CALL mpi_send (var,nx*ny*nz,MPI_REAL,target,               &
                         mytag, MPI_COMM_WORLD,imstat)
        END IF

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_recv (var,nx*ny*nz,MPI_REAL,master,               &
                         mytag,MPI_COMM_WORLD,stat,imstat) 

        END IF

      END IF

      CALL mpbarrier
 
    END DO      
  END DO      

!At the end, make sure processor 0 contains correct varlue (ic=1,jc=1)
  IF(myproc == 0) var(:,:,:) = globvar(1:nx,1:ny,1:nz)     

  RETURN
END SUBROUTINE wrf_split3d
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_merge3dt               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_merge3dt(locvar,nx,ny,nz,fzone,globvar),2
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Generate global array from a multiprocessor run for variable at 
!  mass grid points  
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/09/29
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    localvar Variable to be written.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!  OUTPUT:
!
!    globvar  global variable to be output
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny,nz          
                            ! Number of stagger grid points in x, y and z
  INTEGER, INTENT(IN) :: fzone
  REAL,    INTENT(IN) :: locvar(nx,ny,nz)

  REAL,    INTENT(OUT)::  & ! Output array in global domain, defined on mass points
     globvar((nx-fzone)*nproc_x+fzone-1,(ny-fzone)*nproc_y+fzone-1,nz-1)
!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0
  REAL    :: tem(nx,ny,nz)

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  tem(:,:,:) = locvar(:,:,:) ! each processor stores the locvar into tem
 
  DO jc=1,nproc_y
    DO ic=1,nproc_x

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  pass data to processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_send (locvar,nx*ny*nz,MPI_REAL,master,               &
                         mytag,MPI_COMM_WORLD,imstat) 

        END IF

        IF(myproc == 0)THEN          ! receive data

          source = ic+(jc-1)*nproc_x-1

          CALL mpi_recv (tem,nx*ny*nz,MPI_REAL,source,               &
                         mytag, MPI_COMM_WORLD,stat,imstat)
        END IF

      END IF

      !  storage section

      IF(myproc == 0)THEN  ! store data into globvar

        DO k=1,nz-1
          DO j=1,ny-1
            ja = j + (jc-1)*(ny-fzone)
            DO i=1,nx-1
              ia = i + (ic-1)*(nx-fzone)
              globvar(ia,ja,k) = tem(i,j,k)
            END DO          
          END DO      
        END DO      

      END IF

      CALL mpbarrier

    END DO      
  END DO      

  RETURN
END SUBROUTINE wrf_merge3dt
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_merge3du               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_merge3du(locvar,nx,ny,nz,fzone,globvar),2
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Generate global array from a multiprocessor run for variable at 
!  U grid points  
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/09/29
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    localvar Variable to be written.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!  OUTPUT:
!
!    globvar  global variable to be output
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny,nz          
                            ! Number of stagger grid points in x, y and z
  INTEGER, INTENT(IN) :: fzone
  REAL,    INTENT(IN) :: locvar(nx,ny,nz)

  REAL,    INTENT(OUT)::  & ! Output array in global domain, defined on mass points
     globvar((nx-fzone)*nproc_x+fzone,(ny-fzone)*nproc_y+fzone-1,nz-1)
!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0
  REAL    :: tem(nx,ny,nz)

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k
  INTEGER :: i0

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  tem(:,:,:) = locvar(:,:,:) ! each processor stores the locvar into tem
 
  DO jc=1,nproc_y
    DO ic=1,nproc_x

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  pass data to processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_send (locvar,nx*ny*nz,MPI_REAL,master,               &
                         mytag,MPI_COMM_WORLD,imstat) 

        END IF

        IF(myproc == 0)THEN          ! receive data

          source = ic+(jc-1)*nproc_x-1

          CALL mpi_recv (tem,nx*ny*nz,MPI_REAL,source,               &
                         mytag, MPI_COMM_WORLD,stat,imstat)
        END IF

      END IF

      !  storage section

      IF(myproc == 0)THEN  ! store data into globvar

        i0 = 1
        IF (ic > 1) i0 = 2
        DO k=1,nz-1
          DO j=1,ny-1
            ja = j + (jc-1)*(ny-fzone)
            DO i=i0,nx
              ia = i + (ic-1)*(nx-fzone)
              globvar(ia,ja,k) = tem(i,j,k)
            END DO          
          END DO      
        END DO      

      END IF

      CALL mpbarrier

    END DO      
  END DO      

  RETURN
END SUBROUTINE wrf_merge3du
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_merge3dv               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_merge3dv(locvar,nx,ny,nz,fzone,globvar),2
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Generate global array from a multiprocessor run for variable at 
!  mass grid points  
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/09/29
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    localvar Variable to be written.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!  OUTPUT:
!
!    globvar  global variable to be output
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny,nz          
                            ! Number of stagger grid points in x, y and z
  INTEGER, INTENT(IN) :: fzone
  REAL,    INTENT(IN) :: locvar(nx,ny,nz)

  REAL,    INTENT(OUT)::  & ! Output array in global domain, defined on mass points
     globvar((nx-fzone)*nproc_x+fzone-1,(ny-fzone)*nproc_y+fzone,nz-1)
!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0
  REAL    :: tem(nx,ny,nz)

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k
  INTEGER :: j0

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  tem(:,:,:) = locvar(:,:,:) ! each processor stores the locvar into tem
 
  DO jc=1,nproc_y
    DO ic=1,nproc_x

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  pass data to processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_send (locvar,nx*ny*nz,MPI_REAL,master,               &
                         mytag,MPI_COMM_WORLD,imstat) 

        END IF

        IF(myproc == 0)THEN          ! receive data

          source = ic+(jc-1)*nproc_x-1

          CALL mpi_recv (tem,nx*ny*nz,MPI_REAL,source,               &
                         mytag, MPI_COMM_WORLD,stat,imstat)
        END IF

      END IF

      !  storage section

      IF(myproc == 0)THEN  ! store data into globvar

        j0 = 1
        IF (jc > 1) j0 = 2

        DO k=1,nz-1
          DO j=j0,ny
            ja = j + (jc-1)*(ny-fzone)
            DO i=1,nx-1
              ia = i + (ic-1)*(nx-fzone)
              globvar(ia,ja,k) = tem(i,j,k)
            END DO          
          END DO      
        END DO      

      END IF

      CALL mpbarrier

    END DO      
  END DO      

  RETURN
END SUBROUTINE wrf_merge3dv
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_merge3dw               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_merge3dw(locvar,nx,ny,nz,fzone,globvar),2
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Generate global array from a multiprocessor run for variable at 
!  W grid points  
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/09/29
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    localvar Variable to be written.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!  OUTPUT:
!
!    globvar  global variable to be output
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny,nz          
                            ! Number of stagger grid points in x, y and z
  INTEGER, INTENT(IN) :: fzone
  REAL,    INTENT(IN) :: locvar(nx,ny,nz)

  REAL,    INTENT(OUT)::  & ! Output array in global domain, defined on mass points
     globvar((nx-fzone)*nproc_x+fzone-1,(ny-fzone)*nproc_y+fzone-1,nz)
!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0
  REAL    :: tem(nx,ny,nz)

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  tem(:,:,:) = locvar(:,:,:) ! each processor stores the locvar into tem
 
  DO jc=1,nproc_y
    DO ic=1,nproc_x

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  pass data to processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_send (locvar,nx*ny*nz,MPI_REAL,master,               &
                         mytag,MPI_COMM_WORLD,imstat) 

        END IF

        IF(myproc == 0)THEN          ! receive data

          source = ic+(jc-1)*nproc_x-1

          CALL mpi_recv (tem,nx*ny*nz,MPI_REAL,source,               &
                         mytag, MPI_COMM_WORLD,stat,imstat)
        END IF

      END IF

      !  storage section

      IF(myproc == 0)THEN  ! store data into globvar

        DO k=1,nz
          DO j=1,ny-1
            ja = j + (jc-1)*(ny-fzone)
            DO i=1,nx-1
              ia = i + (ic-1)*(nx-fzone)
              globvar(ia,ja,k) = tem(i,j,k)
            END DO          
          END DO      
        END DO      

      END IF

      CALL mpbarrier

    END DO      
  END DO      

  RETURN
END SUBROUTINE wrf_merge3dw
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_merge2dt               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_merge2dt(locvar,nx,ny,fzone,globvar),2
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Generate global array from a multiprocessor run for variable at 
!  mass grid points  
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/10/04
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    localvar Variable to be written.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!  OUTPUT:
!
!    globvar  global variable to be output
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny ! Number of stagger grid points in x, y
  INTEGER, INTENT(IN) :: fzone
  REAL,    INTENT(IN) :: locvar(nx,ny)

  REAL,    INTENT(OUT):: globvar((nx-fzone)*nproc_x+fzone-1,(ny-fzone)*nproc_y+fzone-1)
                    ! Output array in global domain, defined on mass points
!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0
  REAL    :: tem(nx,ny)

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  tem(:,:) = locvar(:,:) ! each processor stores the locvar into tem
 
  DO jc=1,nproc_y
    DO ic=1,nproc_x

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  pass data to processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_send (locvar,nx*ny,MPI_REAL,master,                  &
                         mytag,MPI_COMM_WORLD,imstat) 

        END IF

        IF(myproc == 0)THEN          ! receive data

          source = ic+(jc-1)*nproc_x-1

          CALL mpi_recv (tem,nx*ny,MPI_REAL,source,                     &
                         mytag, MPI_COMM_WORLD,stat,imstat)
        END IF

      END IF

      !  storage section

      IF(myproc == 0)THEN  ! store data into globvar

        DO j=1,ny-1
          ja = j + (jc-1)*(ny-fzone)
          DO i=1,nx-1
            ia = i + (ic-1)*(nx-fzone)
            globvar(ia,ja) = tem(i,j)
          END DO      
        END DO      

      END IF

      CALL mpbarrier

    END DO      
  END DO      

  RETURN
END SUBROUTINE wrf_merge2dt
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_merge2du               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_merge2du(locvar,nx,ny,fzone,globvar),2
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Generate global array from a multiprocessor run for variable at 
!  U grid points  
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/10/04
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    localvar Variable to be written.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!
!  OUTPUT:
!
!    globvar  global variable to be output
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny ! Number of stagger grid points in x, y
  INTEGER, INTENT(IN) :: fzone
  REAL,    INTENT(IN) :: locvar(nx,ny)

  REAL,    INTENT(OUT):: globvar((nx-fzone)*nproc_x+fzone,(ny-fzone)*nproc_y+fzone-1)
                    ! Output array in global domain, defined on U points
!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0
  REAL    :: tem(nx,ny)

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  tem(:,:) = locvar(:,:) ! each processor stores the locvar into tem
 
  DO jc=1,nproc_y
    DO ic=1,nproc_x

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  pass data to processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_send (locvar,nx*ny,MPI_REAL,master,                  &
                         mytag,MPI_COMM_WORLD,imstat) 

        END IF

        IF(myproc == 0)THEN          ! receive data

          source = ic+(jc-1)*nproc_x-1

          CALL mpi_recv (tem,nx*ny,MPI_REAL,source,                     &
                         mytag, MPI_COMM_WORLD,stat,imstat)
        END IF

      END IF

      !  storage section

      IF(myproc == 0)THEN  ! store data into globvar

        DO j=1,ny-1
          ja = j + (jc-1)*(ny-fzone)
          DO i=1,nx
            ia = i + (ic-1)*(nx-fzone)
            globvar(ia,ja) = tem(i,j)
          END DO      
        END DO      

      END IF

      CALL mpbarrier

    END DO      
  END DO      

  RETURN
END SUBROUTINE wrf_merge2du
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_merge2dv               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_merge2dv(locvar,nx,ny,fzone,globvar),2
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Generate global array from a multiprocessor run for variable at 
!  V grid points  
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/10/04
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    localvar Variable to be written.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!
!  OUTPUT:
!
!    globvar  global variable to be output
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny ! Number of stagger grid points in x, y
  INTEGER, INTENT(IN) :: fzone
  REAL,    INTENT(IN) :: locvar(nx,ny)

  REAL,    INTENT(OUT):: globvar((nx-fzone)*nproc_x+fzone-1,(ny-fzone)*nproc_y+fzone)
                    ! Output array in global domain, defined on mass points
!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0
  REAL    :: tem(nx,ny)

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  tem(:,:) = locvar(:,:) ! each processor stores the locvar into tem
 
  DO jc=1,nproc_y
    DO ic=1,nproc_x

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  pass data to processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_send (locvar,nx*ny,MPI_REAL,master,                  &
                         mytag,MPI_COMM_WORLD,imstat) 

        END IF

        IF(myproc == 0)THEN          ! receive data

          source = ic+(jc-1)*nproc_x-1

          CALL mpi_recv (tem,nx*ny,MPI_REAL,source,                     &
                         mytag, MPI_COMM_WORLD,stat,imstat)
        END IF

      END IF

      !  storage section

      IF(myproc == 0)THEN  ! store data into globvar

        DO j=1,ny
          ja = j + (jc-1)*(ny-fzone)
          DO i=1,nx-1
            ia = i + (ic-1)*(nx-fzone)
            globvar(ia,ja) = tem(i,j)
          END DO      
        END DO      

      END IF

      CALL mpbarrier

    END DO      
  END DO      

  RETURN
END SUBROUTINE wrf_merge2dv
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_merge2di               ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_merge2di(locvar,nx,ny,fzone,globvar),2
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Generate global array from a multiprocessor run for variable at 
!  mass grid points  
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/10/04
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    localvar Variable to be written.
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the vertical
!
!  OUTPUT:
!
!    globvar  global variable to be output
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny ! Number of stagger grid points in x, y
  INTEGER, INTENT(IN) :: fzone
  INTEGER, INTENT(IN) :: locvar(nx,ny)

  INTEGER, INTENT(OUT):: globvar((nx-fzone)*nproc_x+fzone-1,(ny-fzone)*nproc_y+fzone-1)
                    ! Output array in global domain, defined on mass points
!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0
  INTEGER :: tem(nx,ny)

  INTEGER :: mptag        ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  fill the globvar array
!
!-----------------------------------------------------------------------

  tem(:,:) = locvar(:,:) ! each processor stores the locvar into tem
 
  DO jc=1,nproc_y
    DO ic=1,nproc_x

      ! message passing section...

      IF(ic /=1 .OR. jc /=1)THEN     !  pass data to processor 0

        mytag = mptag + 100 + ic + jc

        IF(myproc == (ic+(jc-1)*nproc_x-1))THEN
       
          CALL mpi_send (locvar,nx*ny,MPI_INTEGER,master,              &
                         mytag,MPI_COMM_WORLD,imstat) 

        END IF

        IF(myproc == 0)THEN          ! receive data

          source = ic+(jc-1)*nproc_x-1

          CALL mpi_recv (tem,nx*ny,MPI_INTEGER,source,                 &
                         mytag, MPI_COMM_WORLD,stat,imstat)
        END IF

      END IF

      !  storage section

      IF(myproc == 0)THEN  ! store data into globvar

        DO j=1,ny-1
          ja = j + (jc-1)*(ny-fzone)
          DO i=1,nx-1
            ia = i + (ic-1)*(nx-fzone)
            globvar(ia,ja) = tem(i,j)
          END DO      
        END DO      

      END IF

      CALL mpbarrier

    END DO      
  END DO      

  RETURN
END SUBROUTINE wrf_merge2di
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_mergebdyu              ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_mergebdyu(bdyw,bdye,bdys,bdyn,nx,ny,nz,bdyzone,          &,5
                         fzone,globwt,globet,globsu,globnu,tem1,tem2)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Merge lateral boundary arrays to U staggered grids.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/10/08
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    bdyw     West boundary array without stagger (local)
!    bdye     East boundary array without stagger (local)
!    bdys     South boundary array without stagger (local)
!    bdyn     North boundary array without stagger (local)
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the z-direction (botthom/top)
!             Note: All are local staggered size, i.e. scalar 
!                   grid size plus 1.
!
!    bdyzone  Number of lateral boundary zone
!    fzone    Message passing overlay (fake) zone. It should be 1 for WRF
!             and 3 for ARPS
!
!  OUTPUT:
!
!    globwt   West lateral boundary array staggered at global Mass points
!    globet   East lateral boundary array staggered at global Mass points
!    globsu   South lateral boundary array staggered at global U points
!    globnu   North lateral boundary array staggered at global U points
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny,nz
  INTEGER, INTENT(IN) :: bdyzone
  INTEGER, INTENT(IN) :: fzone

  REAL,   INTENT(IN)  :: bdyw(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdye(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdys(nx,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdyn(nx,nz,bdyzone)

  REAL,   INTENT(OUT) :: globwt((ny-fzone)*nproc_y+fzone-1,nz-1,bdyzone)
  REAL,   INTENT(OUT) :: globet((ny-fzone)*nproc_y+fzone-1,nz-1,bdyzone)
  REAL,   INTENT(OUT) :: globsu((nx-fzone)*nproc_x+fzone,  nz-1,bdyzone)
  REAL,   INTENT(OUT) :: globnu((nx-fzone)*nproc_x+fzone,  nz-1,bdyzone)
                    ! Output array in global domain, defined on U points

  REAL,   INTENT(OUT) :: tem1(nx,nz,bdyzone)
  REAL,   INTENT(OUT) :: tem2(ny,nz,bdyzone)

!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0  ! NetCDF is not parallel I/O, So 
                         ! only one processor can access the opened file
  INTEGER :: mptag       ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc, i0
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k, bdy

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  West/south boundary, no-stagger, processor 0 do merge
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO k = 1,nz
      DO j = 1,ny
        tem2(j,k,bdy) = bdyw(j,k,bdy)
      END DO

      DO i = 1,nx
        tem1(i,k,bdy) = bdys(i,k,bdy)
      END DO
    END DO
  END DO

  !
  ! West boudnary
  !
  ic = 1
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 100 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO j = 1,ny-1
            ja = j + (jc-1)*(ny-fzone)
            globwt(ja,k,bdy) = tem2(j,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! South boudnary
  !
  jc = 1
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 200 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      i0 = 1
      IF (ic > 1) i0 = 2

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO i = i0,nx
            ia = i + (ic-1)*(nx-fzone)
            globsu(ia,k,bdy) = tem1(i,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

!-----------------------------------------------------------------------
!
!  East/North boundary, U-stagger
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO k = 1,nz
      DO j = 1,ny
        tem2(j,k,bdy) = bdye(j,k,bdy)
      END DO

      DO i = 1,nx
        tem1(i,k,bdy) = bdyn(i,k,bdy)
      END DO
    END DO
  END DO

  !
  ! East boudnary
  !
  ic = nproc_x
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 300 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO j = 1,ny-1
            ja = j + (jc-1)*(ny-fzone)
            globet(ja,k,bdy) = tem2(j,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! North boudnary
  !
  jc = nproc_y
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 400 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      i0 = 1
      IF (ic > 1) i0 = 2

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO i = i0,nx
            ia = i + (ic-1)*(nx-fzone)
            globnu(ia,k,bdy) = tem1(i,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

  RETURN
END SUBROUTINE wrf_mergebdyu
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_mergebdyv              ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_mergebdyv(bdyw,bdye,bdys,bdyn,nx,ny,nz,bdyzone,          &,5
                         fzone,globwv,globev,globst,globnt,tem1,tem2)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Merge lateral boundary arrays to V staggered grids.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/10/08
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    bdyw     West boundary array without stagger (local)
!    bdye     East boundary array without stagger (local)
!    bdys     South boundary array without stagger (local)
!    bdyn     North boundary array without stagger (local)
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the z-direction (botthom/top)
!             Note: All are local staggered size, i.e. scalar 
!                   grid size plus 1.
!
!    bdyzone  Number of lateral boundary zone
!    fzone    Message passing overlay (fake) zone. It should be 1 for WRF
!             and 3 for ARPS
!
!  OUTPUT:
!
!    globwv   West lateral boundary array staggered at global V points
!    globev   East lateral boundary array staggered at global V points
!    globst   South lateral boundary array staggered at global mass points
!    globnt   North lateral boundary array staggered at global mass points
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny,nz
  INTEGER, INTENT(IN) :: bdyzone
  INTEGER, INTENT(IN) :: fzone

  REAL,   INTENT(IN)  :: bdyw(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdye(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdys(nx,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdyn(nx,nz,bdyzone)

  REAL,   INTENT(OUT) :: globwv((ny-fzone)*nproc_y+fzone,  nz-1,bdyzone)
  REAL,   INTENT(OUT) :: globev((ny-fzone)*nproc_y+fzone,  nz-1,bdyzone)
  REAL,   INTENT(OUT) :: globst((nx-fzone)*nproc_x+fzone-1,nz-1,bdyzone)
  REAL,   INTENT(OUT) :: globnt((nx-fzone)*nproc_x+fzone-1,nz-1,bdyzone)
                    ! Output array in global domain, defined on U points

  REAL,   INTENT(OUT) :: tem1(nx,nz,bdyzone)
  REAL,   INTENT(OUT) :: tem2(ny,nz,bdyzone)

!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0  ! NetCDF is not parallel I/O, So 
                         ! only one processor can access the opened file
  INTEGER :: mptag       ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc, j0
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k, bdy

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  West/south boundary 
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO k = 1,nz
      DO j = 1,ny
        tem2(j,k,bdy) = bdyw(j,k,bdy)
      END DO

      DO i = 1,nx
        tem1(i,k,bdy) = bdys(i,k,bdy)
      END DO
    END DO
  END DO

  !
  ! West boudnary, V- staggered
  !
  ic = 1
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 100 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      j0 = 1
      IF (jc > 1) j0 = 2
      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO j = j0,ny
            ja = j + (jc-1)*(ny-fzone)
            globwv(ja,k,bdy) = tem2(j,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! South boudnary, mass grid
  !
  jc = 1
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 200 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO i = 1,nx-1
            ia = i + (ic-1)*(nx-fzone)
            globst(ia,k,bdy) = tem1(i,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

!-----------------------------------------------------------------------
!
!  East/North boundary, U-stagger
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO k = 1,nz
      DO j = 1,ny
        tem2(j,k,bdy) = bdye(j,k,bdy)
      END DO

      DO i = 1,nx
        tem1(i,k,bdy) = bdyn(i,k,bdy)
      END DO
    END DO
  END DO

  !
  ! East boudnary
  !
  ic = nproc_x
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 300 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      j0 = 1
      IF (jc > 1) j0 = 2
      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO j = j0,ny
            ja = j + (jc-1)*(ny-fzone)
            globev(ja,k,bdy) = tem2(j,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! North boudnary
  !
  jc = nproc_y
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 400 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO i = 1,nx-1
            ia = i + (ic-1)*(nx-fzone)
            globnt(ia,k,bdy) = tem1(i,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

  RETURN
END SUBROUTINE wrf_mergebdyv
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_mergebdyt              ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_mergebdyt(bdyw,bdye,bdys,bdyn,nx,ny,nz,bdyzone,          &,5
                         fzone,globwt,globet,globst,globnt,tem1,tem2)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Merge lateral boundary arrays to mass grids.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/10/08
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    bdyw     West boundary array without stagger (local)
!    bdye     East boundary array without stagger (local)
!    bdys     South boundary array without stagger (local)
!    bdyn     North boundary array without stagger (local)
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the z-direction (botthom/top)
!             Note: All are local staggered size, i.e. scalar 
!                   grid size plus 1.
!
!    bdyzone  Number of lateral boundary zone
!    fzone    Message passing overlay (fake) zone. It should be 1 for WRF
!             and 3 for ARPS
!
!  OUTPUT:
!
!    globwt   West lateral boundary array staggered at global Mass points
!    globet   East lateral boundary array staggered at global Mass points
!    globst   South lateral boundary array staggered at global Mass points
!    globnt   North lateral boundary array staggered at global Mass points
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE   'mpif.h'
  INCLUDE   'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny,nz
  INTEGER, INTENT(IN) :: bdyzone
  INTEGER, INTENT(IN) :: fzone

  REAL,   INTENT(IN)  :: bdyw(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdye(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdys(nx,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdyn(nx,nz,bdyzone)

  REAL,   INTENT(OUT) :: globwt((ny-fzone)*nproc_y+fzone-1,nz-1,bdyzone)
  REAL,   INTENT(OUT) :: globet((ny-fzone)*nproc_y+fzone-1,nz-1,bdyzone)
  REAL,   INTENT(OUT) :: globst((nx-fzone)*nproc_x+fzone-1,nz-1,bdyzone)
  REAL,   INTENT(OUT) :: globnt((nx-fzone)*nproc_x+fzone-1,nz-1,bdyzone)
                    ! Output array in global domain, defined on U points

  REAL,   INTENT(OUT) :: tem1(nx,nz,bdyzone)
  REAL,   INTENT(OUT) :: tem2(ny,nz,bdyzone)

!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0  ! NetCDF is not parallel I/O, So 
                         ! only one processor can access the opened file
  INTEGER :: mptag       ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k, bdy

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  West/south boundary, no-stagger, processor 0 do merge
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO k = 1,nz
      DO j = 1,ny
        tem2(j,k,bdy) = bdyw(j,k,bdy)
      END DO

      DO i = 1,nx
        tem1(i,k,bdy) = bdys(i,k,bdy)
      END DO
    END DO
  END DO

  !
  ! West boudnary
  !
  ic = 1
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 100 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO j = 1,ny-1
            ja = j + (jc-1)*(ny-fzone)
            globwt(ja,k,bdy) = tem2(j,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! South boudnary
  !
  jc = 1
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 200 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO i = 1,nx-1
            ia = i + (ic-1)*(nx-fzone)
            globst(ia,k,bdy) = tem1(i,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

!-----------------------------------------------------------------------
!
!  East/North boundary, U-stagger
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO k = 1,nz
      DO j = 1,ny
        tem2(j,k,bdy) = bdye(j,k,bdy)
      END DO

      DO i = 1,nx
        tem1(i,k,bdy) = bdyn(i,k,bdy)
      END DO
    END DO
  END DO

  !
  ! East boudnary
  !
  ic = nproc_x
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 300 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO j = 1,ny-1
            ja = j + (jc-1)*(ny-fzone)
            globet(ja,k,bdy) = tem2(j,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! North boudnary
  !
  jc = nproc_y
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 400 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz-1
          DO i = 1,nx-1
            ia = i + (ic-1)*(nx-fzone)
            globnt(ia,k,bdy) = tem1(i,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

  RETURN
END SUBROUTINE wrf_mergebdyt
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_mergebdyw              ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_mergebdyw(bdyw,bdye,bdys,bdyn,nx,ny,nz,bdyzone,          &,5
                         fzone,globww,globew,globsw,globnw,tem1,tem2)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Merge lateral boundary arrays to W staggered grids.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/10/08
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    bdyw     West boundary array without stagger (local)
!    bdye     East boundary array without stagger (local)
!    bdys     South boundary array without stagger (local)
!    bdyn     North boundary array without stagger (local)
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the z-direction (botthom/top)
!             Note: All are local staggered size, i.e. scalar 
!                   grid size plus 1.
!
!    bdyzone  Number of lateral boundary zone
!    fzone    Message passing overlay (fake) zone. It should be 1 for WRF
!             and 3 for ARPS
!
!  OUTPUT:
!
!    globww   West lateral boundary array staggered at global W points
!    globew   East lateral boundary array staggered at global W points
!    globsw   South lateral boundary array staggered at global W points
!    globnw   North lateral boundary array staggered at global W points
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny,nz
  INTEGER, INTENT(IN) :: bdyzone
  INTEGER, INTENT(IN) :: fzone

  REAL,   INTENT(IN)  :: bdyw(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdye(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdys(nx,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdyn(nx,nz,bdyzone)

  REAL,   INTENT(OUT) :: globww((ny-fzone)*nproc_y+fzone-1,nz,bdyzone)
  REAL,   INTENT(OUT) :: globew((ny-fzone)*nproc_y+fzone-1,nz,bdyzone)
  REAL,   INTENT(OUT) :: globsw((nx-fzone)*nproc_x+fzone-1,nz,bdyzone)
  REAL,   INTENT(OUT) :: globnw((nx-fzone)*nproc_x+fzone-1,nz,bdyzone)
                    ! Output array in global domain, defined on U points

  REAL,   INTENT(OUT) :: tem1(nx,nz,bdyzone)
  REAL,   INTENT(OUT) :: tem2(ny,nz,bdyzone)

!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0  ! NetCDF is not parallel I/O, So 
                         ! only one processor can access the opened file
  INTEGER :: mptag       ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k, bdy

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  West/south boundary, no-stagger, processor 0 do merge
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO k = 1,nz
      DO j = 1,ny
        tem2(j,k,bdy) = bdyw(j,k,bdy)
      END DO

      DO i = 1,nx
        tem1(i,k,bdy) = bdys(i,k,bdy)
      END DO
    END DO
  END DO

  !
  ! West boudnary
  !
  ic = 1
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 100 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz
          DO j = 1,ny-1
            ja = j + (jc-1)*(ny-fzone)
            globww(ja,k,bdy) = tem2(j,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! South boudnary
  !
  jc = 1
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 200 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz
          DO i = 1,nx-1
            ia = i + (ic-1)*(nx-fzone)
            globsw(ia,k,bdy) = tem1(i,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

!-----------------------------------------------------------------------
!
!  East/North boundary, U-stagger
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO k = 1,nz
      DO j = 1,ny
        tem2(j,k,bdy) = bdye(j,k,bdy)
      END DO

      DO i = 1,nx
        tem1(i,k,bdy) = bdyn(i,k,bdy)
      END DO
    END DO
  END DO

  !
  ! East boudnary
  !
  ic = nproc_x
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 300 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz
          DO j = 1,ny-1
            ja = j + (jc-1)*(ny-fzone)
            globew(ja,k,bdy) = tem2(j,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! North boudnary
  !
  jc = nproc_y
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 400 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*nz*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*nz*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO k = 1,nz
          DO i = 1,nx-1
            ia = i + (ic-1)*(nx-fzone)
            globnw(ia,k,bdy) = tem1(i,k,bdy)
          END DO      
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

  RETURN
END SUBROUTINE wrf_mergebdyw
!
!##################################################################
!##################################################################
!######                                                      ######
!######                SUBROUTINE WRF_mergebdy2d             ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_mergebdy2d(bdyw,bdye,bdys,bdyn,nx,ny,nz,bdyzone,          &,5
                         fzone,globw2d,globe2d,globs2d,globn2d,tem1,tem2)
!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Merge lateral boundary arrays to scalar staggered grids for 2D arrays.
!
!  NOTE: the input unstaggered arrays have already been packed to be
!        3D arrays to be compatible with WRF version 1.3. This may be
!        changed later if WRFV1.3 support is not needed any more.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  2004/10/11
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    bdyw     West boundary array without stagger (local)
!    bdye     East boundary array without stagger (local)
!    bdys     South boundary array without stagger (local)
!    bdyn     North boundary array without stagger (local)
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!    nz       Number of grid points in the z-direction (botthom/top)
!             Note: All are local staggered size, i.e. scalar 
!                   grid size plus 1.
!
!    bdyzone  Number of lateral boundary zone
!    fzone    Message passing overlay (fake) zone. It should be 1 for WRF
!             and 3 for ARPS
!
!  OUTPUT:
!
!    globw2d   West lateral boundary array
!    globe2d   East lateral boundary array
!    globs2d   South lateral boundary array
!    globn2d   North lateral boundary array
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

  INTEGER, INTENT(IN) :: nx,ny,nz
  INTEGER, INTENT(IN) :: bdyzone
  INTEGER, INTENT(IN) :: fzone

  REAL,   INTENT(IN)  :: bdyw(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdye(ny,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdys(nx,nz,bdyzone)
  REAL,   INTENT(IN)  :: bdyn(nx,nz,bdyzone)

  REAL,   INTENT(OUT) :: globw2d((ny-fzone)*nproc_y+fzone-1,bdyzone)
  REAL,   INTENT(OUT) :: globe2d((ny-fzone)*nproc_y+fzone-1,bdyzone)
  REAL,   INTENT(OUT) :: globs2d((nx-fzone)*nproc_x+fzone-1,bdyzone)
  REAL,   INTENT(OUT) :: globn2d((nx-fzone)*nproc_x+fzone-1,bdyzone)
                    ! Output array in global domain, defined on U points

  REAL,   INTENT(OUT) :: tem1(nx,bdyzone)
  REAL,   INTENT(OUT) :: tem2(ny,bdyzone)

!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER, PARAMETER :: master = 0  ! NetCDF is not parallel I/O, So 
                         ! only one processor can access the opened file
  INTEGER :: mptag       ! Unique MPI id.
  INTEGER :: mytag
  INTEGER :: source
  INTEGER :: ia,ja, ic,jc
  INTEGER :: stat(mpi_status_size)
  INTEGER :: imstat
  INTEGER :: i, j, k, bdy

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  West/south boundary, no-stagger, processor 0 do merge
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO j = 1,ny
      tem2(j,bdy) = bdyw(j,1,bdy)
    END DO

    DO i = 1,nx
      tem1(i,bdy) = bdys(i,1,bdy)
    END DO
  END DO

  !
  ! West boudnary
  !
  ic = 1
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 100 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO j = 1,ny-1
          ja = j + (jc-1)*(ny-fzone)
          globw2d(ja,bdy) = tem2(j,bdy)
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! South boudnary
  !
  jc = 1
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 200 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO i = 1,nx-1
          ia = i + (ic-1)*(nx-fzone)
          globs2d(ia,bdy) = tem1(i,bdy)
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

!-----------------------------------------------------------------------
!
!  East/North boundary, U-stagger
!
!-----------------------------------------------------------------------

  DO bdy = 1,bdyzone
    DO j = 1,ny
      tem2(j,bdy) = bdye(j,1,bdy)
    END DO

    DO i = 1,nx
      tem1(i,bdy) = bdyn(i,1,bdy)
    END DO
  END DO

  !
  ! East boudnary
  !
  ic = nproc_x
  DO jc=1,nproc_y

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 300 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem2,ny*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem2,ny*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO j = 1,ny-1
          ja = j + (jc-1)*(ny-fzone)
          globe2d(ja,bdy) = tem2(j,bdy)
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! jc
  CALL mpbarrier

  !
  ! North boudnary
  !
  jc = nproc_y
  DO ic=1,nproc_x

    source = ic+(jc-1)*nproc_x-1

    IF (source /= master) THEN        ! message passing and receiving section...

      mytag = mptag + 400 + ic + jc

      IF(myproc == (ic+(jc-1)*nproc_x-1))THEN  ! pass data to processor 0
       
        CALL mpi_send(tem1,nx*bdyzone,MPI_REAL,master,mytag,         &
                      MPI_COMM_WORLD,imstat) 

      END If

      IF (myproc == master) THEN               ! receive data

        CALL mpi_recv(tem1,nx*bdyzone,MPI_REAL,source,mytag,         &
                      MPI_COMM_WORLD,stat,imstat)
      END IF

    END IF

    IF (myproc == master) THEN  ! store data into global arrays

      DO bdy = 1,bdyzone
        DO i = 1,nx-1
          ia = i + (ic-1)*(nx-fzone)
          globn2d(ia,bdy) = tem1(i,bdy)
        END DO      
      END DO

    END IF                      ! End of storing section

  END DO     ! ic
  CALL mpbarrier

  RETURN
END SUBROUTINE wrf_mergebdy2d
!
!##################################################################
!##################################################################
!######                                                      ######
!######              SUBROUTINE WRF_MPSENDRECV1DE            ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_mpsendrecv1de(var,nx,ny,tem),1

!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Send & receive east boundary 1D data between processors to 
!  update the fake zones.
!
!  NOTE: After this updating, the scalar array with have one extra 
!        valid row, i.e. var(nx,:) is valid now for scalar array.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  10/11/2004
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!
!
!  INPUT & OUTPUT
!
!    var      Variable for which boundaries need updating.
!
!  WORK array
!
!    tem      Work array (with a size at least ny x 2).
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

  INTEGER, INTENT(IN) :: nx,ny         ! Number of grid points in 
                                       ! x and y directions
  REAL, INTENT(INOUT) :: var(nx,ny)
  REAL, INTENT(INOUT) :: tem(ny,2)   ! Work array.


!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

!-----------------------------------------------------------------------
!
!  Local variable declarations.
!!
!-----------------------------------------------------------------------
!
  INTEGER :: mpi_status(MPI_STATUS_SIZE)
  INTEGER :: imstat
  INTEGER :: j

  INTEGER :: source, dest
  INTEGER :: mptag           ! Unique MPI id used for this BC update.
                             ! mptag + tag_w for west boundary
                             ! mptag + tag_e for east boundary

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  Set the east boundary conditions
!
!-----------------------------------------------------------------------

  !
  ! send destination
  !
  IF(loc_x == 1) THEN             ! First processor in a row
    dest = MPI_PROC_NULL
  ELSE
    dest = proc(loc_x-1+nproc_x*(loc_y-1))
  END IF

  ! 
  ! receive from
  !
  IF(loc_x == nproc_x) THEN        ! Last processor in a row
    source = MPI_PROC_NULL
  ELSE
    source = proc(loc_x+1+nproc_x*(loc_y-1))
  END IF

  !
  ! Pack send buffer, the first valid slice
  !
  DO j=1,ny
    tem(j,1) = var(1,j)
  END DO

  CALL mpi_sendrecv(tem(:,1),ny,MPI_REAL,dest,  mptag+tag_e,       &
                    tem(:,2),ny,MPI_REAL,source,mptag+tag_e,       &
                    MPI_COMM_WORLD,mpi_status,imstat)

  !
  ! Unpack receive buffer, update the last row
  !
  IF ( loc_x /= nproc_x )  THEN
    DO j=1,ny
      var(nx,j) = tem(j,2)
    END DO
  ELSE                   ! just copy slice
    DO j = 1,ny
      var(nx,j) = var(nx-1,j)
    END DO
  END IF

  RETURN
END SUBROUTINE wrf_mpsendrecv1de
!
!##################################################################
!##################################################################
!######                                                      ######
!######              SUBROUTINE WRF_MPSENDRECV1DN            ######
!######                                                      ######
!######                     Developed by                     ######
!######     Center for Analysis and Prediction of Storms     ######
!######                University of Oklahoma                ######
!######                                                      ######
!##################################################################
!##################################################################
!

SUBROUTINE wrf_mpsendrecv1dn(var,nx,ny,tem),1

!
!-----------------------------------------------------------------------
!
!  PURPOSE:
!
!  Send & receive north boundary data between processors to 
!  update the fake zones.
!
!  NOTE: After this updating, the scalar array with have one extra 
!        valid row, i.e. var(:,ny is valid now for scalar array.
!
!-----------------------------------------------------------------------
!
!
!  AUTHOR: Yunheng Wang
!  10/11/2004
!
!  MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
!  INPUT :
!
!    nx       Number of grid points in the x-direction (east/west)
!    ny       Number of grid points in the y-direction (north/south)
!
!  INPUT & OUTPUT:
!
!    var      Variable for which boundaries need updating.
!
!    tem      Work array (with a size at least nx X 2).
!
!-----------------------------------------------------------------------
!
!  Variable declarations.
!
!-----------------------------------------------------------------------

  IMPLICIT NONE

  INTEGER, INTENT(IN) :: nx,ny         ! Number of grid points in 
                                       ! x, and y directions
  REAL, INTENT(INOUT) :: var(nx,ny)
  REAL, INTENT(INOUT) :: tem(nx,2)     ! Work array.

!-----------------------------------------------------------------------
!
!  Include files.
!
!-----------------------------------------------------------------------

  INCLUDE 'mpif.h'
  INCLUDE 'mp.inc'

!-----------------------------------------------------------------------
!
!  Local variable declarations.
!
!-----------------------------------------------------------------------

  INTEGER :: mpi_status(MPI_STATUS_SIZE)
  INTEGER :: imstat
  INTEGER :: i

  INTEGER :: source, dest
  INTEGER :: mptag           ! Unique MPI id used for this BC update.
                             ! mptag + tag_n for north boundary
                             ! mptag + tag_s for south boundary

!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!  Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

  CALL inctag
  mptag = gentag

!-----------------------------------------------------------------------
!
!  Set the north boundary conditions
!
!-----------------------------------------------------------------------

  !
  ! send destination
  !
  IF(loc_y == 1) THEN             ! the south most processor in a column
    dest = MPI_PROC_NULL
  ELSE
    dest = proc(loc_x+nproc_x*(loc_y-2))
  END IF

  ! 
  ! receive from
  !
  IF(loc_y == nproc_y) THEN       ! The north most processor in a column
    source = MPI_PROC_NULL
  ELSE
    source = proc(loc_x+nproc_x*loc_y)
  END IF

  !
  ! Pack send buffer, send south slice to update north boundary of 
  ! the south neighbor
  !
  DO i=1,nx
    tem(i,1) = var(i,1)
  END DO

  CALL mpi_sendrecv(tem(:,1),nx,MPI_REAL,dest,  mptag+tag_n,       &
                    tem(:,2),nx,MPI_REAL,source,mptag+tag_n,       &
                    MPI_COMM_WORLD,mpi_status,imstat)

  !
  ! Unpack receive buffer, update north boundary data
  !
  IF ( loc_y /= nproc_y )  THEN
    DO i=1,nx
      var(i,ny) = tem(i,2)
    END DO
  ELSE
    DO i = 1,nx
      var(i,ny) = var(i,ny-1)
    END DO
  END IF

  RETURN
END SUBROUTINE wrf_mpsendrecv1dn