      subroutine bssl_interp(fld_in,undef,gxout,gyout,
     $     nii,nji,nio,njo,fld_out,iunit_diag,
     $     cyclicxi,spole_point,npole_point,bessel,istat)

      dimension fld_in(nii,nji),fld_out(nio,njo),
     $     gxout(nio+1),gyout(njo+1)

      dimension fr(4)

      logical cyclicxi,diag_out,bessel,spole_point,npole_point
      
      diag_out=.false.
ccc      diag_out=.true.
      jchk=2
      istat=1
C         
C         convert the box boundaries to grid point center
C         
      do i=1,nio
C         
C         check for crossing the boundaries 
C         the only way for this to occur is if the field is 
C         cyclically continuous in x
C

        if(gxout(i+1).lt.gxout(i)) then
          gxout(i)=((gxout(i)-float(nii))+gxout(i+1))*0.5+0.5
          if(gxout(i).lt.1.0) gxout(i)=float(nii)+gxout(i)
        else
          gxout(i)=(gxout(i)+gxout(i+1))*0.5+0.5
          if(gxout(i).lt.1.0) gxout(i)=float(nii)+gxout(i)
        endif
      end do

      do j=1,njo
        gyout(j)=(gyout(j)+gyout(j+1))*0.5+0.5
C         
C         check if a pole points on the input grid
C         
        if(spole_point.and.gyout(j).lt.1.0) gyout(j)=1.0
        if(npole_point.and.gyout(j).gt.nji+0.5) gyout(j)=nji

      end do

      ibb=1
      iee=nio
      jbb=1
      jee=njo

      niim1=nii-1
      njim1=nji-1
      
      do j=jbb,jee
        do i=ibb,iee
          
          ic=ifix(gxout(i))
          jc=ifix(gyout(j))
          icp1=ic+1
          if(cyclicxi.and.icp1.gt.nii) icp1=icp1-nii 
          jcp1=jc+1
          
          if(diag_out.and.j.eq.jchk) write(iunit_diag,*)
     $         'i,j,gxout,gyout,ic,jc',
     $         i,j,gxout(i),gyout(j),ic,jc
          
          if((jc.lt.1.or.jc.gt.nji).or.
     $         (.not.cyclicxi.and.(ic.lt.1.or.ic.gt.nii))) then
            fld_out(i,j)=undef
            if(diag_out.and.j.eq.jchk) 
     $           write(iunit_diag,*) 'out of bounds ' 
            go to 100
          end if
C         
C------------------------------------------------
C         
C         bilinear/bessel interpolation based on the FNOC routine
C         bssl5 by D. Hensen, FNOC
C         
C------------------------------------------------
C         
          r=gxout(i)-ic
          s=gyout(j)-jc
C         
C         interior check
C         
          if((jc.ge.2.and.jc.lt.njim1.and.cyclicxi).or.
     $         (ic.ge.2.and.jc.ge.2.and.
     $         ic.lt.niim1.and.jc.lt.njim1)) go to 10
C         
C         border zone check
C         
          if((jc.lt.nji.and.cyclicxi).or.
     $         (ic.lt.nii.and.jc.lt.nji)) go to 5 
C         
C------------------------------------------------
C         
C         top and right edge processing
C         
C------------------------------------------------
C         
          if(ic.eq.nii.and.jc.eq.nji) then
            
            fld_out(i,j)=fld_in(nii,nji)
            if(diag_out.and.j.eq.jchk) 
     $           write(iunit_diag,*) 'upper right hand corenr'
            
          else if(ic.eq.nii) then
            
            if(diag_out.and.j.eq.jchk) 
     $           write(iunit_diag,*) 'right edge'
            
            if(fld_in(ic,jc).ne.undef.and.
     $           fld_in(ic,jcp1).ne.undef) then
              fld_out(i,j)=(1.0-s)*fld_in(ic,jc)+
     $             s*fld_in(ic,jcp1)
            else
              fld_out(i,j)=undef
            endif
            
          else if(jc.eq.nji) then
            
            if(diag_out.and.j.eq.jchk) 
     $           write(iunit_diag,*) 'top edge'
            
            if(fld_in(ic,jc).ne.undef.and.
     $           fld_in(icp1,jc).ne.undef) then
              fld_out(i,j)=(1.0-r)*fld_in(ic,jc)+
     $             r*fld_in(icp1,jc)
            else
              fld_out(i,j)=undef
            endif
            
          endif
          
          go to 100
          
 5        continue
C         
C------------------------------------------------
C         
C         border zone; bilinear
C         
C------------------------------------------------
C         
          iok_bilinear=1
          if(fld_in(ic,jc).eq.undef.or.
     $         fld_in(icp1,jc).eq.undef.or.
     $         fld_in(ic,jcp1).eq.undef.or.
     $         fld_in(icp1,jcp1).eq.undef) iok_bilinear=0
          
          if(diag_out.and.j.eq.jchk) 
     $         write(iunit_diag,*) 
     $         'border zone, iok_bilinear= ',iok_bilinear
                    
          if(iok_bilinear.eq.0) then
            fld_out(i,j)=undef
          else
            fld_out(i,j)=(1.-s)*((1.-r)*fld_in(ic,jc)
     $           +r*fld_in(icp1,jc))
     $           +s*((1.-r)*fld_in(ic,jcp1)
     $           +r*fld_in(icp1,jcp1))
          endif

          go to 100
 
 10       continue
C         
C------------------------------------------------
C         
C         interior zone
C         
C------------------------------------------------
C         
C         first check if bilinear is OK
C         
          iok_bilinear=1
          if(fld_in(ic,jc).eq.undef.or.
     $         fld_in(icp1,jc).eq.undef.or.
     $         fld_in(ic,jcp1).eq.undef.or.
     $         fld_in(icp1,jcp1).eq.undef) iok_bilinear=0
          
          if(diag_out.and.j.eq.jchk) 
     $         write(iunit_diag,*) 
     $         'interior zone, iok_bilinear= ',iok_bilinear
          
          if(iok_bilinear.eq.0) then
            fld_out(i,j)=undef
            go to 100
          else 
C         
C         bilinear value is the first guess
C         
            fld_out(i,j)=(1.-s)*((1.-r)*fld_in(ic,jc)
     $           +r*fld_in(icp1,jc))
     $           +s*((1.-r)*fld_in(ic,jcp1)
     $           +r*fld_in(icp1,jcp1))
C         
C         exit if only doing bilinear
C         
            if(.not.bessel) go to 100
            
          endif
          
          
C         
C         interpolate 4 columns (i-1,i,i+1,i+2) to j+s and store in fr(1)
C         through fr(4)
C         
          r1=r-0.5
          r2=r*(r-1.)*0.5
          r3=r1*r2*0.3333333333334
          s1=s-0.5
          s2=s*(s-1.)*0.5
          s3=s1*s2*0.3333333333334
C         
          k=0
          im1=ic-1
          ip2=ic+2
          
          if(diag_out.and.j.eq.jck) write(iunit_diag,*) 'bessel interp'
          
C         
          do ii=im1,ip2
            
            k=k+1
            
            i1=ii
            
            if(cyclicxi.and.i1.lt.1) i1=nii-i1
            if(cyclicxi.and.i1.gt.nii) i1=i1-nii
            
            j1=jc
            
            j1p1=j1+1
            j1p2=j1+2
            j1m1=j1-1
            
            fij=fld_in(i1,j1)
            fijp1=fld_in(i1,j1p1)
            fijp2=fld_in(i1,j1p2)
            fijm1=fld_in(i1,j1m1)
            if(diag_out.and.j.eq.jchk) 
     $           write(iunit_diag,*) 'i1,j1 = ',i1,j1,
     $           fij,fijp1,fijp2,fijm1
C         
C         exit if any value undefined
C         
            if(fij.eq.undef.or.
     $           fijp1.eq.undef.or.
     $           fijp2.eq.undef.or.
     $           fijm1.eq.undef) go to 100 
            
            u=(fij+fijp1)*0.5
            del=fijp1-fij
            udel2=(fijp2-fijp1+fijm1-fij)*0.5
            del3=fijp2-fijp1-2.*del+fij-fijm1
            
            fr(k)=u+s1*del+s2*udel2+s3*del3
            
          end do
          
C         
C         interpolate the fr row to ii+r
C         
          u=(fr(2)+fr(3))*0.5
          del=fr(3)-fr(2)
          udel2=(fr(4)-fr(3)+fr(1)-fr(2))*0.5
          del3=fr(4)-fr(3)-2.*del+fr(2)-fr(1)
          
          fld_out(i,j)=u+r1*del+r2*udel2+r3*del3
          
          
 100      continue
          if(diag_out.and.j.eq.jchk) 
     $         write(iunit_diag,*) 'interp value = ',fld_out(i,j)
          
        end do
      end do
      
 999  continue
      
      return
      end
      
