      MODULE bc_2d_mod
!
!svn $Id: bc_2d.F 294 2009-01-09 21:37:26Z arango $
!================================================== Hernan G. Arango ===
!  Copyright (c) 2002-2009 The ROMS/TOMS Group                         !
!    Licensed under a MIT/X style license                              !
!    See License_ROMS.txt                                              !
!=======================================================================
!                                                                      !
!  This package applies gradient or periodic boundary conditions for   !
!  generic 2D fields.                                                  !
!                                                                      !
!  Routines:                                                           !
!                                                                      !
!    bc_r2d_tile        Boundary conditions for field at RHO-points    !
!    bc_u2d_tile        Boundary conditions for field at U-points      !
!    bc_v2d_tile        Boundary conditions for field at V-points      !
!                                                                      !
!=======================================================================
!
      implicit none
      CONTAINS
! 
!***********************************************************************
      SUBROUTINE bc_r2d_tile (ng, tile,                                 &
     &                        LBi, UBi, LBj, UBj,                       &
     &                        A)
!***********************************************************************
!
      USE mod_param
!
!  Imported variable declarations.
!
      integer, intent(in) :: ng, tile
      integer, intent(in) :: LBi, UBi, LBj, UBj
      real(r8), intent(inout) :: A(LBi:,LBj:)
!
!  Local variable declarations.
!
      integer :: i, j
!
!-----------------------------------------------------------------------
!  Set lower and upper tile bounds and staggered variables bounds for
!  this horizontal domain partition.  Notice that if tile=-1, it will
!  set the values for the global grid.
!-----------------------------------------------------------------------
!
      integer :: Istr, IstrR, IstrT, IstrU, Iend, IendR, IendT
      integer :: Jstr, JstrR, JstrT, JstrV, Jend, JendR, JendT
!
      Istr =BOUNDS(ng)%Istr (tile)
      IstrR=BOUNDS(ng)%IstrR(tile)
      IstrT=BOUNDS(ng)%IstrT(tile)
      IstrU=BOUNDS(ng)%IstrU(tile)
      Iend =BOUNDS(ng)%Iend (tile)
      IendR=BOUNDS(ng)%IendR(tile)
      IendT=BOUNDS(ng)%IendT(tile)
      Jstr =BOUNDS(ng)%Jstr (tile)
      JstrR=BOUNDS(ng)%JstrR(tile)
      JstrT=BOUNDS(ng)%JstrT(tile)
      JstrV=BOUNDS(ng)%JstrV(tile)
      Jend =BOUNDS(ng)%Jend (tile)
      JendR=BOUNDS(ng)%JendR(tile)
      JendT=BOUNDS(ng)%JendT(tile)
!
!-----------------------------------------------------------------------
!  East-West gradient boundary conditions.
!-----------------------------------------------------------------------
!
      IF (Iend.eq.Lm(ng)) THEN
        DO j=Jstr,Jend
          A(Iend+1,j)=A(Iend,j)
        END DO
      END IF
      IF (Istr.eq.1) THEN
        DO j=Jstr,Jend
          A(Istr-1,j)=A(Istr,j)
        END DO
      END IF
!
!-----------------------------------------------------------------------
!  North-South gradient boundary conditions.
!-----------------------------------------------------------------------
!
      IF (Jend.eq.Mm(ng)) THEN
        DO i=Istr,Iend
          A(i,Jend+1)=A(i,Jend)
        END DO
      END IF
      IF (Jstr.eq.1) THEN
        DO i=Istr,Iend
          A(i,Jstr-1)=A(i,Jstr)
        END DO
      END IF
!
!-----------------------------------------------------------------------
!  Boundary corners.
!-----------------------------------------------------------------------
!
      IF ((Jstr.eq.1).and.(Istr.eq.1)) THEN
        A(Istr-1,Jstr-1)=0.5_r8*(A(Istr  ,Jstr-1)+                      &
     &                           A(Istr-1,Jstr  ))
      END IF
      IF ((Jstr.eq.1).and.(Iend.eq.Lm(ng))) THEN
        A(Iend+1,Jstr-1)=0.5_r8*(A(Iend  ,Jstr-1)+                      &
     &                           A(Iend+1,Jstr  ))
      END IF
      IF ((Jend.eq.Mm(ng)).and.(Istr.eq.1)) THEN
        A(Istr-1,Jend+1)=0.5_r8*(A(Istr-1,Jend  )+                      &
     &                           A(Istr  ,Jend+1))
      END IF
      IF ((Jend.eq.Mm(ng)).and.(Iend.eq.Lm(ng))) THEN
        A(Iend+1,Jend+1)=0.5_r8*(A(Iend+1,Jend  )+                      &
     &                           A(Iend  ,Jend+1))
      END IF
      RETURN
      END SUBROUTINE bc_r2d_tile
!
!***********************************************************************
      SUBROUTINE bc_u2d_tile (ng, tile,                                 &
     &                        LBi, UBi, LBj, UBj,                       &
     &                        A)
!***********************************************************************
!
      USE mod_param
      USE mod_grid
      USE mod_scalars
!
!  Imported variable declarations.
!
      integer, intent(in) :: ng, tile
      integer, intent(in) :: LBi, UBi, LBj, UBj
      real(r8), intent(inout) :: A(LBi:,LBj:)
!
!  Local variable declarations.
!
      integer :: i, j
!
!-----------------------------------------------------------------------
!  Set lower and upper tile bounds and staggered variables bounds for
!  this horizontal domain partition.  Notice that if tile=-1, it will
!  set the values for the global grid.
!-----------------------------------------------------------------------
!
      integer :: Istr, IstrR, IstrT, IstrU, Iend, IendR, IendT
      integer :: Jstr, JstrR, JstrT, JstrV, Jend, JendR, JendT
!
      Istr =BOUNDS(ng)%Istr (tile)
      IstrR=BOUNDS(ng)%IstrR(tile)
      IstrT=BOUNDS(ng)%IstrT(tile)
      IstrU=BOUNDS(ng)%IstrU(tile)
      Iend =BOUNDS(ng)%Iend (tile)
      IendR=BOUNDS(ng)%IendR(tile)
      IendT=BOUNDS(ng)%IendT(tile)
      Jstr =BOUNDS(ng)%Jstr (tile)
      JstrR=BOUNDS(ng)%JstrR(tile)
      JstrT=BOUNDS(ng)%JstrT(tile)
      JstrV=BOUNDS(ng)%JstrV(tile)
      Jend =BOUNDS(ng)%Jend (tile)
      JendR=BOUNDS(ng)%JendR(tile)
      JendT=BOUNDS(ng)%JendT(tile)
!
!-----------------------------------------------------------------------
!  East-West boundary conditions: Closed or gradient 
!-----------------------------------------------------------------------
!
      IF (Iend.eq.Lm(ng)) THEN
        DO j=Jstr,Jend
          A(Iend+1,j)=A(Iend,j)
        END DO
      END IF
      IF (Istr.eq.1) THEN
        DO j=Jstr,Jend
          A(Istr,j)=0.0_r8
        END DO
      END IF
!
!-----------------------------------------------------------------------
!  North-South boundary conditions: Closed (free-slip/no-slip) or
!  gradient.
!-----------------------------------------------------------------------
!
      IF (Jend.eq.Mm(ng)) THEN
        DO i=Istr,IendR
          A(i,Jend+1)=gamma2(ng)*A(i,Jend)
          A(i,Jend+1)=A(i,Jend+1)*GRID(ng)%umask(i,Jend+1)
        END DO
      END IF
      IF (Jstr.eq.1) THEN
        DO i=Istr,IendR
          A(i,Jstr-1)=gamma2(ng)*A(i,Jstr)
          A(i,Jstr-1)=A(i,Jstr-1)*GRID(ng)%umask(i,Jstr-1)
        END DO
      END IF
!
!-----------------------------------------------------------------------
!  Boundary corners.
!-----------------------------------------------------------------------
!
      IF ((Jstr.eq.1).and.(Istr.eq.1)) THEN
        A(Istr  ,Jstr-1)=0.5_r8*(A(Istr+1,Jstr-1)+                      &
     &                           A(Istr  ,Jstr  ))
      END IF
      IF ((Jstr.eq.1).and.(Iend.eq.Lm(ng))) THEN
        A(Iend+1,Jstr-1)=0.5_r8*(A(Iend  ,Jstr-1)+                      &
     &                           A(Iend+1,Jstr  ))
      END IF
      IF ((Jend.eq.Mm(ng)).and.(Istr.eq.1)) THEN
        A(Istr  ,Jend+1)=0.5_r8*(A(Istr  ,Jend  )+                      &
     &                           A(Istr+1,Jend+1)) 
      END IF
      IF ((Jend.eq.Mm(ng)).and.(Iend.eq.Lm(ng))) THEN
        A(Iend+1,Jend+1)=0.5_r8*(A(Iend+1,Jend  )+                      &
     &                           A(Iend  ,Jend+1))
      END IF
      RETURN
      END SUBROUTINE bc_u2d_tile
!
!***********************************************************************
      SUBROUTINE bc_v2d_tile (ng, tile,                                 &
     &                        LBi, UBi, LBj, UBj,                       &
     &                        A)
!***********************************************************************
!
      USE mod_param
      USE mod_grid
      USE mod_scalars
!
!  Imported variable declarations.
!
      integer, intent(in) :: ng, tile
      integer, intent(in) :: LBi, UBi, LBj, UBj
      real(r8), intent(inout) :: A(LBi:,LBj:)
!
!  Local variable declarations.
!
      integer :: i, j
!
!-----------------------------------------------------------------------
!  Set lower and upper tile bounds and staggered variables bounds for
!  this horizontal domain partition.  Notice that if tile=-1, it will
!  set the values for the global grid.
!-----------------------------------------------------------------------
!
      integer :: Istr, IstrR, IstrT, IstrU, Iend, IendR, IendT
      integer :: Jstr, JstrR, JstrT, JstrV, Jend, JendR, JendT
!
      Istr =BOUNDS(ng)%Istr (tile)
      IstrR=BOUNDS(ng)%IstrR(tile)
      IstrT=BOUNDS(ng)%IstrT(tile)
      IstrU=BOUNDS(ng)%IstrU(tile)
      Iend =BOUNDS(ng)%Iend (tile)
      IendR=BOUNDS(ng)%IendR(tile)
      IendT=BOUNDS(ng)%IendT(tile)
      Jstr =BOUNDS(ng)%Jstr (tile)
      JstrR=BOUNDS(ng)%JstrR(tile)
      JstrT=BOUNDS(ng)%JstrT(tile)
      JstrV=BOUNDS(ng)%JstrV(tile)
      Jend =BOUNDS(ng)%Jend (tile)
      JendR=BOUNDS(ng)%JendR(tile)
      JendT=BOUNDS(ng)%JendT(tile)
!
!-----------------------------------------------------------------------
!  East-West boundary conditions: Closed (free-slip/no-slip) or
!  gradient.
!-----------------------------------------------------------------------
!
      IF (Iend.eq.Lm(ng)) THEN
        DO j=JstrV,Jend
          A(Iend+1,j)=A(Iend,j)
        END DO
      END IF
      IF (Istr.eq.1) THEN
        DO j=Jstr,JendR
          A(Istr-1,j)=gamma2(ng)*A(Istr,j)
          A(Istr-1,j)=A(Istr-1,j)*GRID(ng)%vmask(Istr-1,j)
        END DO
      END IF
!
!-----------------------------------------------------------------------
!  North-South boundary conditions: Closed or Gradient.
!-----------------------------------------------------------------------
!
      IF (Jend.eq.Mm(ng)) THEN
        DO i=Istr,Iend
          A(i,Jend+1)=0.0_r8
        END DO
      END IF
      IF (Jstr.eq.1) THEN
        DO i=Istr,Iend
          A(i,Jstr)=0.0_r8
        END DO
      END IF
!
!-----------------------------------------------------------------------
!  Boundary corners.
!-----------------------------------------------------------------------
!
      IF ((Jstr.eq.1).and.(Istr.eq.1)) THEN
        A(Istr-1,Jstr  )=0.5_r8*(A(Istr  ,Jstr  )+                      &
     &                           A(Istr-1,Jstr+1))
      END IF
      IF ((Jstr.eq.1).and.(Iend.eq.Lm(ng))) THEN
        A(Iend+1,Jstr  )=0.5_r8*(A(Iend  ,Jstr  )+                      &
     &                           A(Iend+1,Jstr+1))
      END IF
      IF ((Jend.eq.Mm(ng)).and.(Istr.eq.1)) THEN
        A(Istr-1,Jend+1)=0.5_r8*(A(Istr-1,Jend  )+                      &
     &                           A(Istr  ,Jend+1))
      END IF
      IF ((Jend.eq.Mm(ng)).and.(Iend.eq.Lm(ng))) THEN
        A(Iend+1,Jend+1)=0.5_r8*(A(Iend+1,Jend  )+                      &
     &                           A(Iend  ,Jend+1))
      END IF
      RETURN
      END SUBROUTINE bc_v2d_tile
      END MODULE bc_2d_mod
