c %Z% %M% %I% (IDS) %G%

       subroutine lobill(win_d, delx, dely,  wou_d, ii,
     &                      jj, lower, upper, ja, jb)


      include "slgcm.slgprm"
      include "slgcm.mp"

      implicit none

      integer nx, nx0, ny, ny0, nynth, nysth, nxest, nxwst
      common /commvars/ nx,nx0,ny,ny0, nynth, nysth, nxest, nxwst

      real      win_d(1:imp3,1:max_col_p3),
     &          delx(1:imp3,1:max_col_p3),
     &          dely(1:imp3,1:max_col_p3),
     &          wou_d(1:imp3,1:max_col_p3)

      integer  ii(1:imp3,1:max_col_p3), 
     &          jj(1:imp3,1:max_col_p3)
      integer  lower, 
     &          upper,
     &         ja, jb


C***    Timing Code 
      real*8   etime,
     &         btime,
     &         itime 
C***    Timing Code 

      real w1( imp3, max_col_p3)
      real w2( imp3, max_col_p3)
      real w3( imp3, max_col_p3)
      real w4( imp3, max_col_p3)
      real win_n( imp3, max_col_p3)
      real landing( imp3, max_col_p3)
      real nbuf( imp3, max_col_p3)
      real depart( imp3, max_col_p3)

      integer i, j, k, l, m
      integer max_iter(2)
      integer tmp, range, tupper, tlower
      integer lo, up
      integer st, fi, rem, lim
      
      integer mp_send_and_rcvint
      integer dk, dj

C***    Timing Code 
      integer mp_timer_clear
      integer mp_timer_start
      integer mp_timer_stop
      real*8 mp_elapsed_time
      real*8 mp_busy_time
      real*8 mp_idle_time
C***    Timing Code 

D      print *, "Starting"

       call mp_init()

      call mp_sync()

      range = upper - lower + 1

      lo = 1
      up = range
      if (ny0 .eq. 0) then
         lo = ja
      else if (ny0 .eq. ny - 1) then
         up = jb - lower + 1
      endif

      call get_lsd_bl_rng(max_col, lo, up, jj, max_iter,
     *                        ny, ny0, nysth)

C
C     Add a border at the northern boundary so that
C     an interpolation can be performed locally.
C
C***    Timing Code 
CT	tmp = mp_timer_clear(1)
CT        if (tmp .eq. -1) then
CT           print *, 'Failure in clearing timer'
CT           stop
CT        end if
C***    Timing Code 

CC        if (tmp .lt. NS_OVERLAP) then
        if (max_col .lt. NS_OVERLAP) then
           tmp = max_col
           rem = NS_OVERLAP
           st = 1
           fi = tmp
           goto 80
        else
              
           call circ_winbuf( nynth, 0, nbuf, 
     &                       imp3, max_col_p3, nysth, 0, 
     &                       win_d, imp3, max_col_p3)
           goto 85
        endif

 80     lim = nint(real(rem)/max_col)
CD        print *, "No. of steps to const. nbuf : ", lim

        do i = 1, imp3
           do j = 1, max_col_p3
              depart(i,j) = win_d(i,j)
           end do
        end do

        do k = 1, lim
CC           call circ_winbuf( nynth, 0, nbuf, 
CC     &                          imp3, max_col_p3, nysth, 0, 
CC     &                          win_d, imp3, max_col_p3)
           call circ_winbuf( nynth, 0, nbuf, 
     &                          imp3, max_col_p3, nysth, 0, 
     &                          depart, imp3, max_col_p3)
           do i = 1, imp3
CC              do j = st, fi
              do j = 1, tmp
CC                 win_n(i, range + j) = nbuf(i, j)
                 win_n(i, range +st+j -1) = nbuf(i, j)
              end do
           end do

           do i = 1, imp3
              do j = 1, max_col_p3
                 depart(i,j) = nbuf(i,j)
              end do
           end do

           rem = rem - tmp
           if (tmp .gt. rem) then
              tmp = rem
           endif
           st = fi + 1
           fi = fi + tmp
        end do

        do i = 1, imp3
           do j = 1, range
              win_n(i,j)  = win_d(i,j)
           end do
        end do
        goto 90

D      print *, ny0, " : Created a north buffer, range : ", range
 85   do i = 1, imp3
         do j = 1, range
            win_n(i,j)  = win_d(i,j)
         end do

         do j = 1, 3
            win_n(i, range + j) = nbuf(i, j)
         end do
         
      end do

C
C     Select the required grid points for an interpolation,
C     from local data
C
D         print *, ny0, " Part 1 iter : ",  max_iter(1)

 90   call sel_bill_elems(w1, w2, w3, w4, win_n, 
     *                     ii, jj, lower, upper, lo, up)

D      print *, ny0, " : First Selection"
      call mp_sync()

D         print *, ny0, " Part 2 iter : ", max_iter(1)

      call comm_south(win_n, w1, w2, w3, w4, 
     &                ii, jj, up, lo, upper, lower,
     &                max_iter)

      call comm_north(win_n, w1, w2, w3, w4, 
     &                ii, jj, up, lo, upper, lower,
     &                max_iter)

      


      lo = 1
      range = upper - lower + 1

      if (ny0 .eq. 0) then
         lo = ja
      else if (ny0 .eq. ny - 1) then
         range = jb - lower + 1
      endif
         

C1      do 116, j = 1, range
        do 116, j = lo, range
         do 115, i = 1, imp3
            wou_d(i,j) = (1.0 - delx(i,j)) * ((1.0 - dely(i,j)) 
     &                          * w1(i,j) + dely(i,j) * w2(i,j)) 
     &             + delx(i,j) * ((1.0 - dely(i,j)) * w3(i,j) 
     &                             + dely(i,j) * w4(i,j))

 115      continue
 116  continue

 101  format( 1X, '+', 4F16.8 //, '+' 3F16.8)

C1       print *, '+WOU'
C1       print 101, ((wou_d(dk, dj), dj = 1, max_col_p3), dk = 1, imp3)
C1       print *, '+WOU OVER'

C***    Timing Code 
CT        btime = mp_busy_time(1)
C2        etime = mp_elapsed_time(1)

C2       print 200, ">Node : ", ny0, " , Comm. Time:",
C2     &             etime
C1       print 200, ">Node : ", ny0, " , Comm. Time:",
C1     &             btime
 200   format (A, I4, A, E22.15.3)
C***    Timing Code 


      end
C
C     end of subroutine lobill
C

      subroutine sel_bill_elems(w1, w2, w3, w4, win_n, 
     *                          ii, jj, lower, upper, lo, up)

      include "slgcm.slgprm"
C1      include "slgcm.mpp"
      include "slgcm.mp"

      implicit none

      integer nx, nx0, ny, ny0, nynth, nysth, nxest, nxwst
      common /commvars/ nx,nx0,ny,ny0, nynth, nysth, nxest, nxwst

C
C     Parameters
C

      real w1( imp3, max_col_p3)
      real w2( imp3, max_col_p3)
      real w3( imp3, max_col_p3)
      real w4( imp3, max_col_p3)
      real win_n( imp3, max_col_p3)

C1      integer  ii(1:imp3,1:max_col_p3), 
C1     &          jj(1:imp3,1:max_col_p3)
      integer  ii(imp3,max_col_p3), 
     &         jj(imp3,max_col_p3)
      
      integer  lower, upper, lo, up
C
C     Local Variables
C      
      integer i, j
C1    , range

C1      range = upper - lower + 1
C1      do 106, j = 1, range
        do 106, j = lo, up
         do 105, i = 1, imp3

            if ((jj(i,j) .ge. lower) .and. (jj(i,j) .le. upper)) then
                  w1(i,j) = win_n(ii(i,j), jj(i,j) - lower + 3)
                  w2(i,j) = win_n(ii(i,j), jj(i,j) - lower + 4)
                  w3(i,j) = win_n(ii(i,j) + 1, jj(i,j) - lower + 3)
                  w4(i,j) = win_n(ii(i,j) + 1, jj(i,j) - lower + 4)
            end if
 105     continue
 106  continue

      end
C
C*     End of subroutine sel_bill_elems



      subroutine get_lsd_bl_rng(width, lo1, up1, jj, max_iter,
     *                            ny, ny0, nysth)

      include "slgcm.slgprm"
      include "slgcm.mp"

      integer lo1,
     &        up1,
     &        width,
     &        max_iter(2),
c
c    !!! Change Dimensions of jj to jj(imp3, max_col_p3)
c
C     &        jj(4,4),
     &         jj(imp3, max_col_p3),
     &        ny, ny0, nysth

        integer mp_timer_clear
        integer mp_timer_start
        integer mp_timer_stop
C        real*8 mp_elapsed_time
C        real*8   etime
CT
         real*8 gcbtime, lcbtime, cabtime
         common /ntime/ cabtime, gcbtime, lcbtime

         real*8 mp_busy_time
CT

      implicit none

        integer lmax_iter(2),
     &           dist,
     &           ownp0, ownp3, i, j, tmp
  
	lmax_iter(1) = 0
        lmax_iter(2) = 0
        dist      = 0
  
          do j = lo1, up1
           do i = 1, imp3
              ownp0 = int((jj(i,j)) / width)
CC              ownp0 = int((jj(i,j)+2) / width)
CC              ownp3 = int((jj(i,j)+3) / width)

              tmp = mod(jj(i,j), width)
              if (tmp .eq. 0) then
                 ownp0 = ownp0 -1
              else if (ownp0 .ge. ny) then
                 ownp0 = ny -1
              endif
                 
CC              if (mod(jj(i,j)+3, width) .eq. 0) then
CC                 ownp3 = ownp3 -1
CC              else if (ownp3 .ge. ny) then
CC                 ownp3 = ny -1
CC              endif

C
C	      Shift address of current node ny0 to 0.  
C             Thus ownp0, ownp3 will be shifted accordingly.
C             Then try to find the shortest path to the further
C             of the two in either the southerly or northerly 
C             direction.
C
CC		ownp3 = ownp3 - ny0
		ownp0 = ownp0 - ny0

CC		if (ownp3 .lt. 0) ownp3 = ny + ownp3
		if (ownp0 .lt. 0) ownp0 = ny + ownp0

                if (ownp0 .gt. ny / 2) then
    		  dist = ny - ownp0
		  if (lmax_iter(2) .lt. dist) lmax_iter(2) = dist  
                else 
		  dist = ownp0
		  if (lmax_iter(1) .lt. dist) lmax_iter(1) = dist
		endif

CC                if (ownp3 .gt. ny / 2) then
CC    		  dist = ny - ownp3
CC		  if (lmax_iter(2) .lt. dist) lmax_iter(2) = dist  
CC                else 
CC		  dist = ownp3
CC		  if (lmax_iter(1) .lt. dist) lmax_iter(1) = dist
CC		endif

CC                if (lmax_iter(1) .gt. 5 ) then
CC                   print *, ">Nor NY0 : ", ny0, " JJ ", jj(i,j), " J ",
CC     &                  j,  " width : ", width, " iter ", lmax_iter(1)
CC                end if
CC                if (lmax_iter(2) .gt. 5 ) then
CC                   print *, ">Sou NY0 : ", ny0, " JJ ", jj(i,j), " J ",
CC     &                  j,  " width : ", width, " iter ", lmax_iter(2)
CC                end if
           enddo
        enddo

C***    Timing Code 
	tmp = mp_timer_clear(0)
        if (tmp .eq. -1) then
           print *, 'Failure in clearing timer'
           stop
        end if

        tmp = mp_timer_start(0)
        if (tmp .eq. -1) then
           print *, 'Failure in starting timer'
           stop
        end if
C***    Timing Code 

        max_iter(1) = cmmd_reduce_int(lmax_iter(1), CMMD_combiner_max) 
        max_iter(2) = cmmd_reduce_int(lmax_iter(2), CMMD_combiner_max) 
C1        max_iter(1) = lmax_iter(1) ?
C1        max_iter(2) = lmax_iter(2) ?
C***    Timing Code 
        tmp = mp_timer_stop(0)
        if (tmp .eq. -1) then
           print *, 'Failure in stopping timer'
           stop
        end if
        gcbtime = gcbtime + mp_busy_time(0)
C
C         print 200, ">Node : ", ny0, " , Global Comm. Time: ",
C     &             etime
 200    format (A, I4, A, E22.15.3)

C***    Timing Code 
D        print *, "L Max Iter is : ", lmax_iter(1), " (N), ", 
D     &            lmax_iter(2), " (S)", " Node : ", ny0
 
         if (ny0 .eq. 0) then
            print *, "> North Iter", max_iter(1), "  South Iter", 
     &      max_iter(2)
         endif


      end

C** end of subroutine get_lsd_bl_rng


