!
!--------------------------------------------------------------------------
!


SUBROUTINE updgrd(mptr) 1,8
!
! To update a coarse grid by interpolating from finer grid(s).
!
  INCLUDE 'nodal.inc'
  INCLUDE 'agrigrid.inc'
  INCLUDE 'agrialloc.inc'
  INCLUDE 'grddsc.inc'
  INCLUDE 'agricst.inc'
  DIMENSION msrcs(30),iupvar(nxy2d+nxyz3d),iupsta(nxy2d+nxyz3d)
  LOGICAL :: smstg2

  IF( intrpodr == 2 ) THEN
    nwhts=9
  ELSE
    nwhts=4
  END IF

  level = node(4,mptr)
  IF(level >= lfine) RETURN
!
! Get all the possible source grids on the next level for mptr.
!
  numscs=0
  mgrid=lstart(level+1)
  15    IF(mgrid == 0) GO TO 20
  numscs=numscs+1
  msrcs(numscs)=mgrid
  mgrid=node(10,mgrid)
  GO TO 15
  20    CONTINUE

  nx=node(5,mptr)
  ny=node(6,mptr)
!
! --------------------------------------------------------------------
! update 2-d scalars
! --------------------------------------------------------------------
!
  IF (verbose6) WRITE(6,'(''  UPDATING 2-D SCALAR(S):''//)')
  ndim=2
!
! initialize the updating status flag with value 1
!
  DO i=1,nxy2d
    iupsta(i)=1
  END DO

  100   CONTINUE
!
! search for unupdated 2-d scalars and group them according to staggering
!
  nupvar=0
  DO iup=1,nxy2d
!
! look for 1st 2-d scalar that needs updating
!
    IF(iupxy(1,iup) == 1.AND.iupsta(iup) == 1.AND. iupxy(2,iup) == 0)THEN
      nupvar=nupvar+1
      iupvar(nupvar)=iup
      iupsta(iup)=0
      DO ivar=iup+1,nxy2d
!
! list additonal scalars with matching staggering to that of iup.
!
        IF(iupxy(1,ivar) == 1.AND.iupsta(ivar) == 1.AND.                &
              iupxy(2,ivar) == 0.AND. smstg2(ivar,iup,2)) THEN
          nupvar=nupvar+1
          iupvar(nupvar)=ivar
          iupsta(ivar)=0
        END IF
      END DO
    END IF
  END DO
!
! if no 2-d scalar needs updating goto next step
!
  IF(nupvar == 0)GO TO 200
!
! perform interpolations for 3-d scalars listed in iupvar(nupvar).
!
  IF( verbose6) THEN
    WRITE(6,'(/''  UPDATING '',I3,''  2-D SCALAR(S)''/)')nupvar
    WRITE(6,9992) (iupvar(ii),ii=1,nupvar)
9992 FORMAT(1X, 10I5)
  END IF
!
  mxpts=nx*ny
  iptr1=igetsp(2*mxpts)
  iptr2=igetsp(2*mxpts)
  iptr3=igetsp(2*mxpts)
  iptr4=igetsp(  mxpts)
  iptr5=igetsp(nwhts*mxpts)
  iptr6=igetsp(2*mxpts)
  iptr7=igetsp(2*mxpts)
!
  CALL itpscl(mptr,msrcs,numscs,a(iptr1),a(iptr2),a(iptr3),             &
              a(iptr4),a(iptr5),a(iptr6),a(iptr7),                      &
              mxpts,nwhts,iupvar,nupvar,ndim)
!
!  restore tem space
!
  CALL resett
!
! go back to check if any more var's need updating
!
  GO TO 100
  200   CONTINUE
!
! --------------------------------------------------------------------
! update 3-d scalars
! --------------------------------------------------------------------
!
  IF(verbose6) WRITE(6,'(''  UPDATING 3-D SCALAR(S):''//)')
  ndim=3
!
! initialize the updating status flag with value 1
!
  DO i=1,nxyz3d
    iupsta(i)=1
  END DO
!
! search for unupdated 3-d scalars and group them according to staggering
!
  300   CONTINUE
  nupvar=0
  DO iup=1,nxyz3d
!
! look for 1st 3-d scalar that needs updating
!
    IF(iupxyz(1,iup) == 1.AND.iupsta(iup) == 1.AND. iupxyz(2,iup) == 0)THEN
      nupvar=nupvar+1
      iupvar(nupvar)=iup
      iupsta(iup)=0
      DO ivar=iup+1,nxyz3d
!
! list additonal 3-d scalars with matching staggering to that of iup.
!
        IF(iupxyz(1,ivar) == 1.AND.iupsta(ivar) == 1.AND.               &
              iupxyz(2,ivar) == 0.AND. smstg2(ivar,iup,3))THEN
          nupvar=nupvar+1
          iupvar(nupvar)=ivar
          iupsta(ivar)=0
        END IF
      END DO
    END IF
  END DO
!
! if no more 3-d scalar needs updating goto next step
!
  IF(nupvar == 0) GO TO 400
!
! perform interpolations for 3-d scalars listed in iupvar(nupvar).
!
  IF(verbose6) THEN
    WRITE(6,'(/''  UPDATING '',I3,''  3-D SCALAR(S)''/)')nupvar
    WRITE(6,9992) (iupvar(ii),ii=1,nupvar)
  END IF
!
  mxpts=nx*ny
  iptr1=igetsp(2*mxpts)
  iptr2=igetsp(2*mxpts)
  iptr3=igetsp(2*mxpts)
  iptr4=igetsp(  mxpts)
  iptr5=igetsp(nwhts*mxpts)
  iptr6=igetsp(2*mxpts)
  iptr7=igetsp(2*mxpts)
!
  CALL itpscl(mptr,msrcs,numscs,a(iptr1),a(iptr2),a(iptr3),             &
              a(iptr4),a(iptr5),a(iptr6),a(iptr7),                      &
              mxpts,nwhts,iupvar,nupvar,ndim)
!
!  restore tem space
!
  CALL resett
!
! go back to check if any more var's need updating
!
  GO TO 300
  400   CONTINUE
!
!-------------------------------------------------------------------
! update 2-d vectors
! --------------------------------------------------------------------
!
!  write(6,'(''  updating 2-d vector(s):''//)')
  ndim=2
!
! initialize the updating status flag with value 1
!
  DO i=1,nxy2d
    iupsta(i)=1
  END DO

  500   CONTINUE
!
! search for a vector that needs updating and store the compnt No. in
! array iupvar.
!
  nupvar=0
  DO iup=1,nxy2d
!
! look for 1st 2-d vector that needs updating
!
    IF(iupxy(1,iup) == 1.AND.iupxy(2,iup) > 0.AND. iupsta(iup) == 1) THEN
      iup2=iupxy(2,iup)
      iupvar(nupvar+1)=iup
      iupvar(nupvar+2)=iup2
      nupvar=nupvar+2
      iupsta(iup )=0
      iupsta(iup2)=0
      EXIT
    END IF
  END DO
  67    CONTINUE
!
! if no more 2-d vector needs updating goto next step
!
  IF(nupvar == 0)GO TO 600
!
! perform interpolations for 2-d vectors listed in iupvar(nupvar).
!
  IF(verbose6) THEN
    WRITE(6,'(//''  UPDATING 2-D VECTOR '',I5,I5//)')                   &
         iupvar(1),iupvar(2)
  END IF
!
  mxpts=nx*ny
  iptr1=igetsp(4*mxpts)
  iptr2=igetsp(4*mxpts)
  iptr3=igetsp(4*mxpts)
  iptr4=igetsp(2*mxpts)
  iptr5=igetsp(2*nwhts*mxpts)
  iptr6=igetsp(4*mxpts)
  iptr7=igetsp(4*mxpts)
!
  CALL itpvtr(mptr,msrcs,numscs,a(iptr1),a(iptr2),a(iptr3),             &
              a(iptr4),a(iptr5),a(iptr6),a(iptr7),                      &
              mxpts,nwhts,iupvar,nupvar,ndim)
!
!  restore tem space
!
  CALL resett
!
! go back to check if any more var's need updating
!
  GO TO 500
  600   CONTINUE
!
!------------------------------------------------------------------
! update 3-d vectors
!------------------------------------------------------------------
!
  IF(verbose6) WRITE(6,'(''  UPDATING 3-D VECTOR(S):''//)')
  ndim=3
!
! initialize the updating status flag with value 1
!
  DO i=1,nxyz3d
    iupsta(i)=1
  END DO
!
  700   CONTINUE
!
! search for a vector that needs updating and store the compnt No. in
! array iupvar.
!
  nupvar=0
  DO iup=1,nxyz3d
!
! pick out the 1st 3-d vector that needs updating
!
    IF(iupxyz(1,iup) == 1.AND.iupxyz(2,iup) > 0.AND. iupsta(iup) == 1) THEN
      iup2=iupxyz(2,iup)
      iupvar(nupvar+1)=iup
      iupvar(nupvar+2)=iup2
      nupvar=nupvar+2
      iupsta(iup )=0
      iupsta(iup2)=0
      EXIT
    END IF
  END DO
  92    CONTINUE
!
! if no more 3-d vector needs updating goto next step
!
  IF(nupvar == 0)GO TO 800
!
! perform interpolations for 3-d vectors listed in iupvar(nupvar).
!
  IF(verbose6) THEN
    WRITE(6,'(//''  UPDATING 3-D VECTOR '',I5,I5//)')                   &
          iupvar(1),iupvar(2)
  END IF
!
  mxpts=nx*ny
  iptr1=igetsp(4*mxpts)
  iptr2=igetsp(4*mxpts)
  iptr3=igetsp(4*mxpts)
  iptr4=igetsp(2*mxpts)
  iptr5=igetsp(2*nwhts*mxpts)
  iptr6=igetsp(4*mxpts)
  iptr7=igetsp(4*mxpts)
!
  CALL itpvtr(mptr,msrcs,numscs,a(iptr1),a(iptr2),a(iptr3),             &
              a(iptr4),a(iptr5),a(iptr6),a(iptr7),                      &
              mxpts,nwhts,iupvar,nupvar,ndim)
!
!  restore tem space
!
  CALL resett
!
! go back to check if any more var's need updating
!
  GO TO 700
  800   CONTINUE
  RETURN
END SUBROUTINE updgrd
!
!--------------------------------------------------------------------------
!


SUBROUTINE itpscl(mrec,msrcs,numscs,ptsrec,                             & 2,9
           irec,isrc,igsrc,whts,pts,irecp,mxpts,nwhts,                  &
           iupvar,nupvar,ndim)
!
  DIMENSION msrcs(numscs),ptsrec(2,mxpts),irec(2,mxpts),                &
            isrc(2,mxpts),igsrc(mxpts),whts(nwhts,mxpts),               &
            pts(2,mxpts),irecp(2,mxpts),                                &
            iupvar(nupvar)

  INCLUDE 'nodal.inc'
  INCLUDE 'agrigrid.inc'
  INCLUDE 'agrialloc.inc'
  INCLUDE 'grddsc.inc'
  nw1=nint( SQRT(FLOAT(nwhts)) )
  nw2=nw1
!
! Calculate and store the coor's of p-points of the receive
! grid in array ptsrec with their indecies stored in irec.
!
  IF(nupvar == 0) RETURN

  nx=node(5,mrec)
  ny=node(6,mrec)
  cosr=rnode(21,mrec)
  sinr=rnode(22,mrec)
  dxr=rnode(9 ,mrec)
  dyr=rnode(10,mrec)
  xor=rnode(1,mrec)
  yor=rnode(2,mrec)

  ivar=iupvar(1)
  IF(ndim == 2) THEN
    xshift=stgxy(1,ivar)
    yshift=stgxy(2,ivar)
    nx1=nx-idmxy(1,ivar)
    ny1=ny-idmxy(2,ivar)
  ELSE IF(ndim == 3)THEN
    xshift=stgxyz(1,ivar)
    yshift=stgxyz(2,ivar)
    nx1=nx-idmxyz(1,ivar)
    ny1=ny-idmxyz(2,ivar)
  ELSE
    PRINT*,'Error in ITPSCL: Variable dimension ndim set wrong!'
    PRINT*,'ndim should be 2 or 3, input was',ndim
  END IF

  xc=xshift*dxr*cosr
  ys=yshift*dyr*sinr
  xs=xshift*dxr*sinr
  yc=yshift*dyr*cosr

  xorp=xor+xc-ys
  yorp=yor+xs+yc
!
! To calculate the absolute coordinates of the model interior
! points that may need updating.
!
! Attention:
!
! here we assume that in x direction the interior points start
! at i=2 and finish at i=nx1-1. The boundaries are at i=1 and nx1.
! Similarly in y direction, the boundaries are at j=1 and ny1.
! If in a particular solver (model), the boundaries for certain
! variables are defined at points other the above, the use needs to
! change the following loop accordingly (i.e. change ist, jst, iend
! and jend). As a result, the part in routine ITPBSL that calculates
! the points for boundary value interpolations also need change.
!
  ist=2
  jst=2
  iend=nx1-1
  jend=ny1-1
  DO j=jst,jend
    jj=(j-jst)*(iend-ist+1)
    DO i=ist,iend
      ii           = jj+i-ist+1
      x            = (i-1)*dxr
      y            = (j-1)*dyr
      ptsrec(1,ii) = xorp+x*cosr-y*sinr
      ptsrec(2,ii) = yorp+x*sinr+y*cosr
      irec  (1,ii) = i
      irec  (2,ii) = j
    END DO
  END DO
  numpts=(iend-ist+1)*(jend-jst+1)
!
! Find the source points for receive grid points ptsrec
!
  ierfl=0
  iptcmp=1
  CALL getsrc(mrec,msrcs,numscs,xshift,yshift,ptsrec,numpts,            &
       irec,igsrc,ierfl,iptcmp)
!
! if no point can be updated from listed source grids, skip through
! this loop
!
  IF(numpts == 0) THEN
    WRITE(6,'(''NO SRC. POINT FOUND FOR'',I2,''-d variable(s)'')')ndim
    WRITE(6,'(20i4)') iupvar
    RETURN
  END IF
!
! Loop through all source grids
!
  DO ks=1,numscs

    msrc=msrcs(ks)
!
! sort rec. grid points according to their source grid
!
    npts=0
    DO np=1,numpts
      IF(igsrc(np) == msrc) THEN
        npts=npts+1
        pts(1,npts)=ptsrec(1,np)
        pts(2,npts)=ptsrec(2,np)
        irecp(1,npts)=irec(1,np)
        irecp(2,npts)=irec(2,np)
      END IF
    END DO
    IF(npts == 0) CYCLE

    nxr=node(5,mrec)
    nyr=node(6,mrec)
    nzr=node(14,mrec)

    nxs=node(5,msrc)
    nys=node(6,msrc)
    nzs=node(14,msrc)

!
! Calculate weights of interpolation for points pts.
!
    CALL calwht(mrec,msrc,pts,isrc,whts,npts,nwhts,ivar,ndim)
!  print*,'after calling calwht'
!    do 1111 ii=1,npts
!     write(6,'(5i5,10f10.5)') ii,irecp(1,ii),irecp(2,ii),
!    : isrc(1,ii),isrc(2,ii),(whts(jj,ii),jj=1,nw1*nw2)
!1111   continue
!
! update variables in list iupvar
!
    DO i=1,nupvar
      ivar=iupvar(i)
      IF(ndim == 2) THEN
        n3rd=1
        irptr=igtnxy(mrec,ivar,1)
        isptr=igtnxy(msrc,ivar,1)
      ELSE
        n3rd=nzs
        irptr=igtxyz(mrec,ivar,1)
        isptr=igtxyz(msrc,ivar,1)
      END IF
      needsp =nxs*nys*n3rd
      iavrg=igetsp(needsp)

      CALL hrzavg(
      CALL intrps(          irecp,isrc,whts,npts,nw1,nw2)

      IF(ndim == 2) THEN
        CALL retnxy(mrec,ivar,1,irptr,.true.)
        CALL retnxy(msrc,ivar,1,isptr,.false.)
      ELSE
        CALL retxyz(mrec,ivar,1,irptr,.true.)
        CALL retxyz(msrc,ivar,1,isptr,.false.)
      END IF
      CALL reclam(iavrg,nxs*nys*n3rd)
    END DO
!
  END DO
  500   CONTINUE
  RETURN
END SUBROUTINE itpscl
!
!--------------------------------------------------------------------------
!


SUBROUTINE intrps(varrec,varsrc,nxr,nyr,nxs,nys,nz,                     & 5
           irec,isrc,whts,numpts,nw1,nw2)
  DIMENSION varrec(nxr,nyr,nz),varsrc(nxs,nys,nz),                      &
            irec(2,numpts),isrc(2,numpts),whts(nw1,nw2,numpts)
!
  itest = 0
  IF(itest == 1) THEN
    WRITE(6,'(''  DATA DUMP IN INTRPS '',8I6)')                         &
        nxr,nyr,nxs,nys,nz,numpts,nw1,nw2
    DO ip=1,20
      WRITE(7,1114) irec(1,ip),irec(2,ip),isrc(1,ip),isrc(2,ip),        &
            whts(1,1,ip),whts(2,1,ip),whts(1,2,ip),whts(2,2,ip)
    END DO
1114 FORMAT(1X,4I7,4E10.3)
  END IF
  IF(nw1 == 2.AND.nw2 == 2) THEN
!
! The interpolation calculations are all independent of each other,
! they can be vecotrized in inner loop and parellelized in outer loop.
!
    nzswap=2
!
! if nz if small, swap the loop order
!
    IF(nz <= nzswap)THEN
!fpp$ nodepchk
      DO ks=1,nz
!DIR$ IVDEP
        DO np=1,numpts
          ir = irec(1,np)
          jr = irec(2,np)
          is = isrc(1,np)
          js = isrc(2,np)
          varrec(ir,jr,ks)=varsrc(is,js,ks)*whts(1,1,np)                &
              +varsrc(is+1,js,ks)*whts(2,1,np)                          &
              +varsrc(is,js+1,ks)*whts(1,2,np)                          &
              +varsrc(is+1,js+1,ks)*whts(2,2,np)
        END DO
      END DO
    ELSE
!fpp$ nodepchk
      DO np=1,numpts
        ir = irec(1,np)
        jr = irec(2,np)
        is = isrc(1,np)
        js = isrc(2,np)
!DIR$ IVDEP
        DO ks=1,nz
          varrec(ir,jr,ks)=varsrc(is,js,ks)*whts(1,1,np)                &
              +varsrc(is+1,js,ks)*whts(2,1,np)                          &
              +varsrc(is,js+1,ks)*whts(1,2,np)                          &
              +varsrc(is+1,js+1,ks)*whts(2,2,np)
        END DO
      END DO
    END IF

  ELSE

    IF(nz <= nzswap)THEN
!fpp$ nodepchk
      DO ks=1,nz
!DIR$ IVDEP
        DO np=1,numpts
          ir = irec(1,np)
          jr = irec(2,np)
          is = isrc(1,np)
          js = isrc(2,np)
          varrec(ir,jr,ks)=                                             &
              varsrc(is-1,js-1,ks)*whts(1,1,np)                         &
              +varsrc(is  ,js-1,ks)*whts(2,1,np)                        &
              +varsrc(is+1,js-1,ks)*whts(3,1,np)                        &
              +varsrc(is-1,js  ,ks)*whts(1,2,np)                        &
              +varsrc(is  ,js  ,ks)*whts(2,2,np)                        &
              +varsrc(is+1,js  ,ks)*whts(3,2,np)                        &
              +varsrc(is-1,js+1,ks)*whts(1,3,np)                        &
              +varsrc(is  ,js+1,ks)*whts(2,3,np)                        &
              +varsrc(is+1,js+1,ks)*whts(3,3,np)
        END DO
      END DO
    ELSE
!fpp$ nodepchk
      DO np=1,numpts
        ir = irec(1,np)
        jr = irec(2,np)
        is = isrc(1,np)
        js = isrc(2,np)
!DIR$ IVDEP
        DO ks=1,nz
          varrec(ir,jr,ks)=                                             &
              varsrc(is-1,js-1,ks)*whts(1,1,np)                         &
              +varsrc(is  ,js-1,ks)*whts(2,1,np)                        &
              +varsrc(is+1,js-1,ks)*whts(3,1,np)                        &
              +varsrc(is-1,js  ,ks)*whts(1,2,np)                        &
              +varsrc(is  ,js  ,ks)*whts(2,2,np)                        &
              +varsrc(is+1,js  ,ks)*whts(3,2,np)                        &
              +varsrc(is-1,js+1,ks)*whts(1,3,np)                        &
              +varsrc(is  ,js+1,ks)*whts(2,3,np)                        &
              +varsrc(is+1,js+1,ks)*whts(3,3,np)
        END DO
      END DO
    END IF

  END IF

  RETURN
END SUBROUTINE intrps
!
!--------------------------------------------------------------------------
!


SUBROUTINE itpvtr(mrec,msrcs,numscs,ptsrec,                             & 2,13
           irec,isrc,igsrc,whts,pts,irecp,mxpts,nwhts,                  &
           iupvar,nupvar,ndim)
!
  DIMENSION msrcs(numscs),ptsrec(2,mxpts,2),irec(2,mxpts,2),            &
            isrc(2,mxpts,2),igsrc(mxpts,2),whts(nwhts,mxpts,2),         &
            pts(2,mxpts,2),irecp(2,mxpts,2),iupvar(nupvar),             &
            numpts(2),npts(2)

  INCLUDE 'nodal.inc'
  INCLUDE 'agrigrid.inc'
  INCLUDE 'agrialloc.inc'
  INCLUDE 'grddsc.inc'
  LOGICAL :: samstg,smstg2

  nw1=nint( SQRT(FLOAT(nwhts)) )
  nw2=nw1
!
  IF(nupvar == 0) RETURN
  nxr=node(5,mrec)
  nyr=node(6,mrec)
  nzr=node(14,mrec)
  cosr=rnode(21,mrec)
  sinr=rnode(22,mrec)
  dxr=rnode(9 ,mrec)
  dyr=rnode(10,mrec)
  xor=rnode(1,mrec)
  yor=rnode(2,mrec)
!
  CALL chkdim(ndim,'ITPVTR')
!
! To loop through all vectors, which has two components stored consecutively
! in nupvar. The 1st compt. has to be the one in x direction.
!
  DO ivtr=1,nupvar,2

    ivar1=iupvar(ivtr)
    ivar2=iupvar(ivtr+1)

    samstg=smstg2(ivar1,ivar2,ndim)
    IF(ndim == 2) THEN
      xshft = MAX( stgxy(1,ivar1),stgxy(1,ivar2) )
      yshft = MAX( stgxy(2,ivar1),stgxy(2,ivar2) )
    ELSE IF(ndim == 3)THEN
      xshft = MAX( stgxyz(1,ivar1),stgxyz(1,ivar2) )
      yshft = MAX( stgxyz(2,ivar1),stgxyz(2,ivar2) )
    END IF
!
! Find the points on rec. grid for both compnts. and the source grid for
! them.If the two compnts have the samew staggering, they have the
! same coordinate points and the source grid, therefore those for the
! 2nd compnt. do not need to be recalculated.
!
    DO icmpr=1,2
!
! icmpr=1 for the 1st component of vectors
!   =2 for the 2nd component of vectors
!
      IF(icmpr == 2.AND.samstg)THEN
        numpts(2)=numpts(1)
        DO ip=1,numpts(2)
          ptsrec(1,ip,2)=ptsrec(1,ip,1)
          ptsrec(2,ip,2)=ptsrec(2,ip,1)
          irec(1,ip,2)=irec(1,ip,1)
          irec(2,ip,2)=irec(2,ip,1)
          igsrc(ip,2)=igsrc(ip,1)
        END DO
        CYCLE
      END IF

      ivar=iupvar(ivtr+icmpr-1)

      IF(ndim == 2) THEN
        xshift=stgxy(1,ivar)
        yshift=stgxy(2,ivar)
        nx1=nxr-idmxy(1,ivar)
        ny1=nyr-idmxy(2,ivar)
      ELSE IF(ndim == 3)THEN
        xshift=stgxyz(1,ivar)
        yshift=stgxyz(2,ivar)
        nx1=nxr-idmxyz(1,ivar)
        ny1=nyr-idmxyz(2,ivar)
      END IF

      xc=xshift*dxr*cosr
      ys=yshift*dyr*sinr
      xs=xshift*dxr*sinr
      yc=yshift*dyr*cosr

      xorp=xor+xc-ys
      yorp=yor+xs+yc
!
! The following loop calculates the absolute coordinates of the model
! interior points that may need updating.
!
! Attention:
!
! here we assume that in x direction the interior points start
! at i=2 and finish at i=nx1-1. The boundaries are at i=1 and nx1.
! Similarly in y direction, the boundaries are at j=1 and ny1.
! If in a particular solver (model), the boundaries for certain
! variables are defined at points other the above, the use needs to
! change the following loop accordingly (i.e. change ist, jst, iend
! and jend). As a result, the part in routine ITPBVT that calculates
! the points for boundary value interpolations also need change.
!
      ist=2
      jst=2
      iend=nx1-1
      jend=ny1-1
      DO j=jst,jend
        jj=(j-jst)*(iend-ist+1)
        DO i=ist,iend
          ii=jj+i-ist+1
          x=(i-1)*dxr
          y=(j-1)*dyr
          ptsrec(1,ii,icmpr) = xorp+x*cosr-y*sinr
          ptsrec(2,ii,icmpr) = yorp+x*sinr+y*cosr
          irec  (1,ii,icmpr) = i
          irec  (2,ii,icmpr) = j
        END DO
      END DO
      numpts(icmpr)=(iend-ist+1)*(jend-jst+1)
      16    CONTINUE
!
! Find the source grid for receive grid points ptsrec
!
      ierfl=0
      iptcmp=1
      CALL getsrc(mrec,msrcs,numscs,xshft,yshft,ptsrec(1,1,icmpr),      &
          numpts(icmpr),irec(1,1,icmpr),igsrc(1,icmpr),ierfl,iptcmp)

    END DO
!
! if no point can be updated from listed source grids, skip through
! this loop
!
    IF(numpts(1) == 0.AND.numpts(2) == 0) THEN
      WRITE(6,'(''NO SRC. POINT FOUND FOR'',I2,                         &
      &   ''-d vector no. '', 2I6)')ndim,iupvar(ivtr),iupvar(ivtr+1)
      CYCLE
    END IF
!
! find storage pointers for the receive grid variables (2 compnts of vector).
! uppack them if neccesary.
!
    IF(ndim == 2) THEN
      irptr1=igtnxy(mrec,ivar1,1)
      irptr2=igtnxy(mrec,ivar2,1)
    ELSE
      irptr1=igtxyz(mrec,ivar1,1)
      irptr2=igtxyz(mrec,ivar2,1)
    END IF
!
! Loop through all source grids
!
    DO ks=1,numscs

      msrc=msrcs(ks)
      nxs=node(5,msrc)
      nys=node(6,msrc)
      nzs=node(14,msrc)
      coss=rnode(21,msrc)
      sins=rnode(22,msrc)

      cossr= coss*cosr+sins*sinr
      sinsr= coss*sinr-sins*cosr

      DO icmps=1,2

        DO  icmpr=1,2

          IF(icmpr == 2.AND.samstg)THEN
            npts(2)=npts(1)
            DO ip=1,npts(2)
              pts  (1,ip,2)=pts  (1,ip,1)
              pts  (2,ip,2)=pts  (2,ip,1)
              isrc (1,ip,2)=isrc (1,ip,1)
              isrc (2,ip,2)=isrc (2,ip,1)
              irecp(1,ip,2)=irecp(1,ip,1)
              irecp(2,ip,2)=irecp(2,ip,1)
            END DO
            DO iw=1,nwhts
              DO ip=1,npts(2)
                whts(iw,ip,2)=whts(iw,ip,1)
              END DO
            END DO
            PRINT*,'irecp, isrc, whts with icmps=:',icmps
            CYCLE
          END IF
!
! sort rec. grid points according to their source grid
!
          npt=0
          DO np=1,numpts(icmpr)
            IF(igsrc(np,icmpr) == msrc) THEN
              npt=npt+1
              pts(1,npt,icmpr)=ptsrec(1,np,icmpr)
              pts(2,npt,icmpr)=ptsrec(2,np,icmpr)
              irecp(1,npt,icmpr)=irec(1,np,icmpr)
              irecp(2,npt,icmpr)=irec(2,np,icmpr)
            END IF
          END DO
          npts(icmpr)=npt
          IF(npts(icmpr) == 0) CYCLE
!
! Calculate weights of interpolation for points pts.
!
          ivsrc=iupvar(ivtr+icmps-1)
          CALL calwht(mrec,msrc,pts(1,1,icmpr),isrc(1,1,icmpr),         &
                      whts(1,1,icmpr),npts(icmpr),nwhts,ivsrc,ndim)
        END DO
        IF(npts(1) == 0.AND.npts(2) == 0) CYCLE
!
! find pointer for one of the components (icmps) of the source grid
! vector. If it is packed, do uppacking for this variable.
!
        ivsrc=iupvar(ivtr+icmps-1)
        IF(ndim == 2) THEN
          n3rd=1
          isptr=igtnxy(msrc,ivsrc,1)
        ELSE
          n3rd=nzs
          isptr=igtxyz(msrc,ivsrc,1)
        END IF
        needsp = nxs*nys*n3rd
        iavrg=igetsp(needsp)
        CALL hrzavg(
        IF(icmps == 1)THEN
          proj1=cossr
          proj2=-sinsr
        ELSE
          proj1=sinsr
          proj2=cossr
        END IF

        icmpr=1
        IF(npts(icmpr) /= 0) THEN
          CALL intrpv(              irecp(1,1,icmpr),isrc(1,1,icmpr),whts(1,1,icmpr),         &
              npts(icmpr),nw1,nw2,icmps,proj1)
        END IF

        icmpr=2
        IF(npts(icmpr) /= 0) THEN
          CALL intrpv(              irecp(1,1,icmpr),isrc(1,1,icmpr),whts(1,1,icmpr),         &
              npts(icmpr),nw1,nw2,icmps,proj2)
        END IF

        CALL reclam(iavrg,nxs*nys*n3rd)
        IF(ndim == 2) THEN
          CALL retnxy(msrc,ivsrc,1,isptr,.false.)
        ELSE
          CALL retxyz(msrc,ivsrc,1,isptr,.false.)
        END IF
      END DO
!
    END DO
    IF(ndim == 2) THEN
      CALL retnxy(mrec,ivar1,1,irptr1,.true.)
      CALL retnxy(mrec,ivar2,1,irptr2,.true.)
    ELSE
      CALL retxyz(mrec,ivar1,1,irptr1,.true.)
      CALL retxyz(mrec,ivar2,1,irptr2,.true.)
    END IF
  END DO
  RETURN
END SUBROUTINE itpvtr
!
!--------------------------------------------------------------------------
!


SUBROUTINE intrpv(varrec,varsrc,nxr,nyr,nxs,nys,nz,                     & 6
           irec,isrc,whts,numpts,nw1,nw2,mode,proj)
  DIMENSION varrec(nxr,nyr,nz),varsrc(nxs,nys,nz),                      &
            irec(2,numpts),isrc(2,numpts),whts(nw1,nw2,numpts)
!
  itest = 0
  IF(itest == 1) THEN
    WRITE(6,'(''  DATA DUMP IN INTRPV '',8I6)')                         &
        nxr,nyr,nxs,nys,nz,numpts,nw1,nw2
    DO ip=1,20
      WRITE(7,1114) irec(1,ip),irec(2,ip),isrc(1,ip),isrc(2,ip),        &
            whts(1,1,ip),whts(2,1,ip),whts(1,2,ip),whts(2,2,ip)
    END DO
1114 FORMAT(1X,4I7,4E10.3)
  END IF

  iaccum=0
  IF(mode == 2) iaccum=1

  IF(nw1 == 2.AND.nw2 == 2) THEN
!
! The interpolation calculations are all independent of each other,
! they can be vecotrized in inner loop and parellelized in outer loop.
!
    nzswap=2
!
! if nz if small, swap the loop order
!
    IF(nz <= nzswap)THEN
!fpp$ nodepchk
      DO ks=1,nz
!DIR$ IVDEP
        DO np=1,numpts
          ir = irec(1,np)
          jr = irec(2,np)
          is = isrc(1,np)
          js = isrc(2,np)
          varrec(ir,jr,ks)=varrec(ir,jr,ks)*iaccum                      &
              +(varsrc(is,js,ks)*whts(1,1,np)                           &
              +varsrc(is+1,js,ks)*whts(2,1,np)                          &
              +varsrc(is,js+1,ks)*whts(1,2,np)                          &
              +varsrc(is+1,js+1,ks)*whts(2,2,np))*proj
        END DO
      END DO
    ELSE
!fpp$ nodepchk
      DO np=1,numpts
        ir = irec(1,np)
        jr = irec(2,np)
        is = isrc(1,np)
        js = isrc(2,np)
!DIR$ IVDEP
        DO ks=1,nz
          varrec(ir,jr,ks)=varrec(ir,jr,ks)*iaccum                      &
              +(varsrc(is,js,ks)*whts(1,1,np)                           &
              +varsrc(is+1,js,ks)*whts(2,1,np)                          &
              +varsrc(is,js+1,ks)*whts(1,2,np)                          &
              +varsrc(is+1,js+1,ks)*whts(2,2,np))*proj
        END DO
      END DO
    END IF

  ELSE

    IF(nz <= nzswap)THEN
!fpp$ nodepchk
      DO ks=1,nz
!DIR$ IVDEP
        DO np=1,numpts
          ir = irec(1,np)
          jr = irec(2,np)
          is = isrc(1,np)
          js = isrc(2,np)
          varrec(ir,jr,ks)=varrec(ir,jr,ks)*iaccum                      &
              +(varsrc(is-1,js-1,ks)*whts(1,1,np)                       &
              +varsrc(is  ,js-1,ks)*whts(2,1,np)                        &
              +varsrc(is+1,js-1,ks)*whts(3,1,np)                        &
              +varsrc(is-1,js  ,ks)*whts(1,2,np)                        &
              +varsrc(is  ,js  ,ks)*whts(2,2,np)                        &
              +varsrc(is+1,js  ,ks)*whts(3,2,np)                        &
              +varsrc(is-1,js+1,ks)*whts(1,3,np)                        &
              +varsrc(is  ,js+1,ks)*whts(2,3,np)                        &
              +varsrc(is+1,js+1,ks)*whts(3,3,np))*proj
        END DO
      END DO
    ELSE
!fpp$ nodepchk
      DO np=1,numpts
        ir = irec(1,np)
        jr = irec(2,np)
        is = isrc(1,np)
        js = isrc(2,np)
!DIR$ IVDEP
        DO ks=1,nz
          varrec(ir,jr,ks)=varrec(ir,jr,ks)*iaccum                      &
              +(varsrc(is-1,js-1,ks)*whts(1,1,np)                       &
              +varsrc(is  ,js-1,ks)*whts(2,1,np)                        &
              +varsrc(is+1,js-1,ks)*whts(3,1,np)                        &
              +varsrc(is-1,js  ,ks)*whts(1,2,np)                        &
              +varsrc(is  ,js  ,ks)*whts(2,2,np)                        &
              +varsrc(is+1,js  ,ks)*whts(3,2,np)                        &
              +varsrc(is-1,js+1,ks)*whts(1,3,np)                        &
              +varsrc(is  ,js+1,ks)*whts(2,3,np)                        &
              +varsrc(is+1,js+1,ks)*whts(3,3,np))*proj
        END DO
      END DO
    END IF

  END IF

  RETURN
END SUBROUTINE intrpv
!
!--------------------------------------------------------------------------
!


SUBROUTINE getsrc(mrec,msrcs,numscs,xshift,yshift,ptsrec,numpts,        & 9
           irec,igsrc,ierfl,iptcmp)
  DIMENSION msrcs(numscs),ptsrec(2,numpts),irec(2,numpts),              &
            igsrc(numpts)
!
  INCLUDE 'nodal.inc'
  INCLUDE 'agrigrid.inc'
  INCLUDE 'agrialloc.inc'
  INCLUDE 'grddsc.inc'
  levelr = node(4,mrec)
!
  DO i=1,numpts
    igsrc(i)=0
  END DO
!
  DO lvlchk=levelr-1,levelr+1
!
    IF(lvlchk == 0) CYCLE

    DO ig=1,numscs
      msrc=msrcs(ig)
      IF(node(4,msrc) /= lvlchk) CYCLE
!
! now find points with msrc as source
!
      dx = rnode(9,msrc)
      dy = rnode(10,msrc)
      hx=2*hxposs(lvlchk)+xshift*dx
      hy=2*hyposs(lvlchk)+yshift*dy
      t1=rnode(16,msrc)-hx
      t2=rnode(17,msrc)+hx
      t3=rnode(18,msrc)-hy
      t4=rnode(19,msrc)+hy

      DO i=1,numpts
        ex1=ptsrec(1,i)*rnode(12,msrc)+ptsrec(2,i)*rnode(13,msrc)
        ex2=ptsrec(1,i)*rnode(14,msrc)+ptsrec(2,i)*rnode(15,msrc)
        IF((t1-ex1 >= 0).AND.(ex1-t2 >= 0).AND.                         &
            (t3-ex2 >= 0).AND.(ex2-t4 >= 0)) igsrc(i)=msrc
      END DO
    END DO

  END DO
!
! next check if source has been found for all points
!
  ierfl0=ierfl
  IF(ierfl == 1) THEN
    ierfl=0
    DO i=1,numpts
      IF(igsrc(i) == 0) ierfl=ierfl+1
    END DO

    IF(ierfl > 0) THEN
!
!   some points do not have a source, problems here
!
      WRITE(6,'(''  IN SOURCE, POINTS LACKING SOURCE, GRID '',i4)') mrec
      WRITE(6,'(''  POSSIBLE SOURCE GRIDS '',10I4)')(msrcs(i),i=1,numscs)
      DO i=1,numpts
        IF(igsrc(i) == 0) WRITE(6,240) ptsrec(1,i),ptsrec(2,i)
      END DO
240   FORMAT('  point  ',2(1X,e12.5))
      ierfl=1
    END IF

  END IF
!
!  finally, return only those points that have source
!
  IF(ierfl0 == 1.AND.ierfl == 0) RETURN
  IF(iptcmp == 1) THEN

    ist=0
    DO i=1,numpts
      IF(igsrc(i) /= 0)THEN
        ist=ist+1
        igsrc(ist)=igsrc(i)
        ptsrec(1,ist)=ptsrec(1,i)
        ptsrec(2,ist)=ptsrec(2,i)
        irec(1,ist)=irec(1,i)
        irec(2,ist)=irec(2,i)
      END IF
    END DO
    numpts=ist

    310   CONTINUE
  END IF

  RETURN
END SUBROUTINE getsrc

!
!--------------------------------------------------------------------------
!


SUBROUTINE calwht(mrec,msrc,points,isrc,whts,numpts,nwhts,              & 8
           ivar,ndim)
  DIMENSION points(2,numpts),whts(nwhts,numpts),isrc(2,numpts)
!
!  this routine calculates the weights for the interpolation
!  of mass points or vertical velocity (stuff that doesn't need
!  any rotation from grid msrc to grid mrec
!
!  if nw = 4 bilinear interp., = 9 bi-quadratic
!
  INCLUDE 'nodal.inc'
  INCLUDE 'agrigrid.inc'
  INCLUDE 'agrialloc.inc'
  INCLUDE 'grddsc.inc'

  fq(xp,x1,x2,x3,x4)=(xp-x2)*(xp-x3)/                                   &
                    ((x1-x2)*(x1-x3))+x4
  fl(xp,x1,x2)=(xp-x2)/(x1-x2)
!
  cosc = rnode( 21,msrc)
  sinc = rnode( 22,msrc)
  dxc  = rnode(9,msrc)
  dyc  = rnode(10,msrc)
  odxc = 1./dxc
  odyc = 1./dyc
  xor  = rnode(1,msrc)
  yor  = rnode(2,msrc)
!
  IF(ndim == 2) THEN
    xshift=stgxy(1,ivar)
    yshift=stgxy(2,ivar)
  ELSE
    xshift=stgxyz(1,ivar)
    yshift=stgxyz(2,ivar)
  END IF

  xc=xshift*dxc*cosc
  ys=yshift*dyc*sinc
  xs=xshift*dxc*sinc
  yc=yshift*dyc*cosc

  xorp=xor+xc-ys
  yorp=yor+xs+yc

  DO i=1,numpts
    x=points(1,i)
    y=points(2,i)
    points(1,i)=1+( cosc*(x-xorp)+sinc*(y-yorp))*odxc
    points(2,i)=1+(-sinc*(x-xorp)+cosc*(y-yorp))*odyc
  END DO
!
!   next, calculate weights for the interpolation
!
  IF(nwhts == 9) THEN
    alpha=0.
    alpha2=0.
    DO i=1,numpts
      xp=points(1,i)-FLOAT( nint(points(1,i)) )
      yp=points(2,i)-FLOAT( nint(points(2,i)) )
      tempy1=fq(yp,-1.,0.,1.,alpha)
      tempy2=fq(yp,0.,-1.,1.,alpha2)
      tempy3=fq(yp,1.,-1.,0.,alpha)
      tempx1=fq(xp,-1.,0.,1.,alpha)
      tempx2=fq(xp,0.,-1.,1.,alpha2)
      tempx3=fq(xp,1.,-1.,0.,alpha)
      whts(1,i)=tempy1*tempx1
      whts(2,i)=tempy1*tempx2
      whts(3,i)=tempy1*tempx3
      whts(4,i)=tempy2*tempx1
      whts(5,i)=tempy2*tempx2
      whts(6,i)=tempy2*tempx3
      whts(7,i)=tempy3*tempx1
      whts(8,i)=tempy3*tempx2
      whts(9,i)=tempy3*tempx3
      isrc(1,i)=nint(points(1,i))
      isrc(2,i)=nint(points(2,i))
    END DO
  ELSE
    DO i=1,numpts
      xp=points(1,i)-FLOAT( INT(points(1,i)) )
      yp=points(2,i)-FLOAT( INT(points(2,i)) )
      tempy1=fl(yp,0.,1.)
      tempy2=fl(yp,1.,0.)
      tempx1=fl(xp,0.,1.)
      tempx2=fl(xp,1.,0.)
      whts(1,i)=tempy1*tempx1
      whts(2,i)=tempy1*tempx2
      whts(3,i)=tempy2*tempx1
      whts(4,i)=tempy2*tempx2
      isrc(1,i)=INT(points(1,i))
      isrc(2,i)=INT(points(2,i))
    END DO
  END IF
  RETURN
END SUBROUTINE calwht
!
!--------------------------------------------------------------------------
!


SUBROUTINE hrzavg(vout,vin,nx,ny,nz) 2
!
! Perform horizontal plane average over nine points.
!
  DIMENSION vout(nx,ny,nz),vin(nx,ny,nz)

  a19 = 1.0/9.0
  DO k=1,nz
    DO j=2,ny-1
      DO i=2,nx-1
        vout(i,j,k)=(vin(i,j,k)+vin(i-1,j,k)+vin(i+1,j,k)               &
             +vin(i,j-1,k)+vin(i,j+1,k)+vin(i+1,j+1,k)                  &
             +vin(i+1,j-1,k)+vin(i-1,j+1,k)+vin(i-1,j-1,k))*a19
      END DO
    END DO
  END DO
  DO k=1,nz
    DO j=1,ny
      vout(1 ,j,k)=vin(1, j,k)
      vout(nx,j,k)=vin(nx,j,k)
    END DO
    DO i=1,nx
      vout(i,1 ,k)=vin(i,1 ,k)
      vout(i,ny,k)=vin(i,ny,k)
    END DO
  END DO
  RETURN
END SUBROUTINE hrzavg


  FUNCTION smstg2(ivar1,ivar2, ndim),1
  INCLUDE 'agrigrid.inc'
  INCLUDE 'grddsc.inc'

  LOGICAL :: smstg2
  smstg2=.false.
  eps=1.0E-6
  CALL chkdim(ndim,'SMSTG2')
  IF(ndim == 2) THEN
    IF(ABS(stgxy (1,ivar1)-stgxy (1,ivar2 )) < eps .AND.                &
        ABS(stgxy (2,ivar1)-stgxy (2,ivar2)) < eps) smstg2=.true.
  ELSE
    IF(ABS(stgxyz(1,ivar1)-stgxyz(1,ivar2 )) < eps .AND.                &
        ABS(stgxyz(2,ivar1)-stgxyz(2,ivar2)) < eps) smstg2=.true.
  END IF
  RETURN
  END FUNCTION smstg2


  FUNCTION smstg3(ivar1,ivar2, ndim),1
  INCLUDE 'agrigrid.inc'
  INCLUDE 'grddsc.inc'
  LOGICAL :: smstg3
  smstg3=.false.
  eps=1.0E-6
  CALL chkdim(ndim,'SMSTG3')
  IF(ndim == 2) THEN
    IF(ABS(stgxy (1,ivar1)-stgxy (1,ivar2)) < eps.AND.                  &
        ABS(stgxy (2,ivar1)-stgxy (2,ivar2)) < eps) smstg3=.true.
  ELSE
    IF(ABS(stgxyz(1,ivar1)-stgxyz(1,ivar2)) < eps.AND.                  &
        ABS(stgxyz(2,ivar1)-stgxyz(2,ivar2)) < eps.AND.                 &
        ABS(stgxyz(3,ivar1)-stgxyz(3,ivar2)) < eps) smstg3=.true.
  END IF
  RETURN
  END FUNCTION smstg3
!


SUBROUTINE addcst(mptr,ndim,ivar,cst),3
!
! to add a constant CST to ndim-D variable IVAR for grid MPTR.
!
  INCLUDE 'nodal.inc'
  INCLUDE 'agrigrid.inc'
  INCLUDE 'grddsc.inc'
  INCLUDE 'agrialloc.inc'

  nx=node(5,mptr)
  ny=node(6,mptr)

  CALL chkdim(ndim,'GTRCRD')
  IF(ndim == 2) THEN
    nz=1
    iptr=igtnxy(mptr,ivar,1)
  ELSE
    nz=node(14,mptr)
    iptr=igtxyz(mptr,ivar,1)
  END IF

  DO ijk=1,nx*ny*nz
    a(ijk-1+iptr)=a(ijk-1+iptr)+cst
  END DO
  IF(ndim == 2) THEN
    CALL retnxy(mptr,ivar,1,iptr,.true.)
  ELSE
    CALL retxyz(mptr,ivar,1,iptr,.true.)
  END IF
  RETURN
END SUBROUTINE addcst