#include "CPP_EEOPTIONS.h"

CBOP
C     !ROUTINE: EXCH2_GET_UV_BOUNDS

C     !INTERFACE:
      SUBROUTINE EXCH2_GET_UV_BOUNDS(
     I                 fCode, eWdth, updateCorners,
     I                 tgTile, tgNb,
     O                 tIlo1, tIhi1, tJlo1, tJhi1,
     O                 tIlo2, tIhi2, tJlo2, tJhi2,
     O                 tiStride, tjStride,
     O                 e2_oi1, e2_oj1, e2_oi2, e2_oj2,
     I                 myThid )

C     !DESCRIPTION:
C     Return the index range & step of the part of the array (overlap-region)
C     which is going to be updated by the exchange with 1 neighbour.
C     2 components vector field (UV) version.


C     !USES:
      IMPLICIT NONE
C     == Global data ==
#include "SIZE.h"
#include "W2_EXCH2_SIZE.h"
#include "W2_EXCH2_TOPOLOGY.h"

C     !INPUT/OUTPUT PARAMETERS:
C     fCode         :: field code (position on staggered grid)
C     eWdth         :: width of data region to exchange
C     updateCorners :: flag, do update corner halo region if true
C     tgTile        :: target tile
C     tgNb          :: target Neighbour entry
C     tIlo1, tIhi1  :: index range in I that will be filled in 1rst comp. array
C     tJlo1, tJhi1  :: index range in J that will be filled in 1rst comp. array
C     tIlo2, tIhi2  :: index range in I that will be filled in 2nd  comp. array
C     tJlo2, tJhi2  :: index range in J that will be filled in 2nd  comp. array
C     tiStride      :: index step  in I that will be filled in target arrays
C     tjStride      :: index step  in J that will be filled in target arrays
C     e2_oi1        :: index offset in target to source-1 index relation
C     e2_oj1        :: index offset in target to source-1 index relation
C     e2_oi2        :: index offset in target to source-2 index relation
C     e2_oj2        :: index offset in target to source-2 index relation
C     myThid        :: my Thread Id. number

      CHARACTER*2 fCode
      INTEGER     eWdth
      LOGICAL     updateCorners
      INTEGER     tgTile, tgNb
      INTEGER     tIlo1, tIhi1, tJlo1, tJhi1
      INTEGER     tIlo2, tIhi2, tJlo2, tJhi2
      INTEGER     tiStride, tjStride
      INTEGER     e2_oi1, e2_oj1
      INTEGER     e2_oi2, e2_oj2
      INTEGER     myThid
C
C     !LOCAL VARIABLES:
C     soTile        :: source tile
C     soNb          :: source Neighbour entry
      INTEGER  soTile
      INTEGER  soNb
      INTEGER  tIlo,  tIhi,  tJlo,  tJhi
      INTEGER  i, e2_pij(4)

C---  exch2 target to source index relation:
C     is = pij(1)*it + pij(2)*jt + oi
C     js = pij(3)*it + pij(4)*jt + oj

C---  Initialise index range from Topology values:
      tIlo = exch2_iLo(tgNb,tgTile)
      tIhi = exch2_iHi(tgNb,tgTile)
      tJlo = exch2_jLo(tgNb,tgTile)
      tJhi = exch2_jHi(tgNb,tgTile)
      soNb = exch2_opposingSend(tgNb,tgTile)
      soTile = exch2_neighbourId(tgNb,tgTile)
      e2_oi1 = exch2_oi(soNb,soTile)
      e2_oj1 = exch2_oj(soNb,soTile)
      DO i=1,4
        e2_pij(i) = exch2_pij(i,soNb,soTile)
      ENDDO

C---  Expand index range according to exchange-Width "eWdth"
      IF ( tIlo.EQ.tIhi .AND. tIlo.EQ.0 ) THEN
C      Filling a west edge overlap
       tIlo1 = 1-eWdth
       tIhi1 = 0
       tiStride = 1
       IF ( tJlo.LE.tJhi ) THEN
        tjStride=1
       ELSE
        tjStride=-1
       ENDIF
       IF ( updateCorners ) THEN
        tJlo1 = tJlo-tjStride*(eWdth-1)
        tJhi1 = tJhi+tjStride*(eWdth-1)
       ELSE
        tJlo1 = tJlo+tjStride
        tJhi1 = tJhi-tjStride
       ENDIF
      ENDIF
      IF ( tIlo.EQ.tIhi .AND. tIlo.GT.1 ) THEN
C      Filling an east edge overlap
       tIlo1 = tIlo
       tIhi1 = tIhi+eWdth-1
       tiStride = 1
       IF ( tJlo.LE.tJhi ) THEN
        tjStride = 1
       ELSE
        tjStride =-1
       ENDIF
       IF ( updateCorners ) THEN
        tJlo1 = tJlo-tjStride*(eWdth-1)
        tJhi1 = tJhi+tjStride*(eWdth-1)
       ELSE
        tJlo1 = tJlo+tjStride
        tJhi1 = tJhi-tjStride
       ENDIF
      ENDIF
      IF ( tJlo.EQ.tJhi .AND. tJlo.EQ.0 ) THEN
C      Filling a south edge overlap
       tJlo1 = 1-eWdth
       tJhi1 = 0
       tjStride = 1
       IF ( tIlo .LE. tIhi ) THEN
        tiStride = 1
       ELSE
        tiStride =-1
       ENDIF
       IF ( updateCorners ) THEN
        tIlo1 = tIlo-tiStride*(eWdth-1)
        tIhi1 = tIhi+tiStride*(eWdth-1)
       ELSE
        tIlo1 = tIlo+tiStride
        tIhi1 = tIhi-tiStride
       ENDIF
      ENDIF
      IF ( tJlo.EQ.tJhi .AND. tJlo.GT.1 ) THEN
C      Filling a north edge overlap
       tJlo1 = tJlo
       tJhi1 = tJhi+eWdth-1
       tjStride = 1
       IF ( tIlo.LE.tIhi ) THEN
        tiStride = 1
       ELSE
        tiStride =-1
       ENDIF
       IF ( updateCorners ) THEN
        tIlo1 = tIlo-tiStride*(eWdth-1)
        tIhi1 = tIhi+tiStride*(eWdth-1)
       ELSE
        tIlo1 = tIlo+tiStride
        tIhi1 = tIhi-tiStride
       ENDIF
      ENDIF

C---  copy to 2nd set of indices
      tIlo2 = tIlo1
      tIhi2 = tIhi1
      tJlo2 = tJlo1
      tJhi2 = tJhi1
      e2_oi2 = e2_oi1
      e2_oj2 = e2_oj1

      IF ( fCode.EQ.'Cg' ) THEN
C---  UV C-Grid specific code: start here

C---  half grid-cell location with inverse index relation
C     => increase the offset by 1 (relative to tracer cell-centered offset)
C     if pij(1) is -1 then +i in source aligns with -i in target
C     if pij(3) is -1 then +j in source aligns with -i in target
        IF ( e2_pij(1) .EQ. -1 ) THEN
         e2_oi1 = e2_oi1 + 1
        ENDIF
        IF ( e2_pij(3) .EQ. -1 ) THEN
         e2_oj1 = e2_oj1 + 1
        ENDIF
C     if pij(2) is -1 then +i in source aligns with -j in target
C     if pij(4) is -1 then +j in source aligns with -j in target
        IF ( e2_pij(2) .EQ. -1 ) THEN
         e2_oi2 = e2_oi2 + 1
        ENDIF
        IF ( e2_pij(4) .EQ. -1 ) THEN
         e2_oj2 = e2_oj2 + 1
        ENDIF

C---  adjust index lower and upper bounds (fct of updateCorners):
       IF ( updateCorners ) THEN

C--   as a consequence, need also to increase the index lower bound
C     (avoid "out-of bounds" problems ; formerly itlreduce,jtlreduce)
        IF ( e2_pij(1).EQ.-1 .OR. e2_pij(3).EQ.-1 ) tIlo1 = tIlo1+1
        IF ( e2_pij(2).EQ.-1 .OR. e2_pij(4).EQ.-1 ) tJlo2 = tJlo2+1

C---  Avoid updating (some) tile-corner halo region if across faces
c       IF ( tIlo.EQ.tIhi .AND. tIlo.EQ.0 ) THEN
c         IF ( exch2_isSedge(tgTile).EQ.1 ) THEN
C-      West edge is touching the face S edge
c           tJlo1 = tJlo+1
c           tJlo2 = tJlo+1
c         ENDIF
c         IF ( exch2_isNedge(tgTile).EQ.1 ) THEN
C-      West edge is touching the face N edge
c           tJhi1 = tJhi-1
c           tJhi2 = tJhi
c         ENDIF
c       ENDIF
        IF ( tIlo.EQ.tIhi .AND. tIlo.GT.1 ) THEN
          IF ( exch2_isSedge(tgTile).EQ.1 ) THEN
C-      East edge is touching the face S edge
            tJlo1 = tJlo+1
            tJlo2 = tJlo+1
          ENDIF
          IF ( exch2_isNedge(tgTile).EQ.1 ) THEN
C-      East edge is touching the face N edge
            tJhi1 = tJhi-1
            tJhi2 = tJhi
          ENDIF
        ENDIF
c       IF ( tJlo.EQ.tJhi .AND. tJlo.EQ.0 ) THEN
c         IF ( exch2_isWedge(tgTile).EQ.1 ) THEN
C-      South edge is touching the face W edge
c           tIlo1 = tIlo+1
c           tIlo2 = tIlo+1
c         ENDIF
c         IF ( exch2_isEedge(tgTile).EQ.1 ) THEN
C-      South Edge is touching the face E edge
c           tIhi1 = tIhi
c           tIhi2 = tIhi-1
c         ENDIF
c       ENDIF
        IF ( tJlo.EQ.tJhi .AND. tJlo.GT.1 ) THEN
          IF ( exch2_isWedge(tgTile).EQ.1 ) THEN
C-      North edge is touching the face W edge
            tIlo1 = tIlo+1
            tIlo2 = tIlo+1
          ENDIF
          IF ( exch2_isEedge(tgTile).EQ.1 ) THEN
C-      North Edge is touching the face E edge
            tIhi1 = tIhi
            tIhi2 = tIhi-1
          ENDIF
        ENDIF

       ELSE
C---  adjust index lower and upper bounds (updateCorners = F case):
        IF ( e2_pij(1).EQ.-1 .OR. e2_pij(3).EQ.-1 ) THEN
          tIlo1 = tIlo1+1
          tIhi1 = tIhi1+1
        ENDIF
        IF ( e2_pij(2).EQ.-1 .OR. e2_pij(4).EQ.-1 ) THEN
          tJlo2 = tJlo2+1
          tJhi2 = tJhi2+1
        ENDIF
       ENDIF

C---  UV C-Grid specific code: end

      ELSEIF ( fCode.NE.'Ag' ) THEN
        STOP 'ABNORMAL END: S/R EXCH2_GET_UV_BOUNDS (wrong fCode)'
      ENDIF

      RETURN
      END
