Subversion Repositories tropofold.echam

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

      real function int2d(ar,n1,n2,rid,rjd)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 2d-array to an arbitrary
c        location within the grid.
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2)
c        n1,n2     int   input   dimensions of ar
c        ri,rj     real  input   grid location to be interpolated to
c     History:
c-----------------------------------------------------------------------

c     argument declarations
      integer   n1,n2
      real      ar(n1,n2), rid,rjd

c     local declarations
      integer   i,j,ip1,jp1,ih,jh
      real      frac0i,frac0j,frac1i,frac1j,ri,rj

c     do linear interpolation
      ri=amax1(1.,amin1(float(n1),rid))
      rj=amax1(1.,amin1(float(n2),rjd))
      ih=nint(ri)
      jh=nint(rj)

c     Check for interpolation in i
*     if (abs(float(ih)-ri).lt.1.e-3) then
*       i  =ih
*       ip1=ih
*     else
        i =min0(int(ri),n1-1)
        ip1=i+1
*     endif

c     Check for interpolation in j
*     if (abs(float(jh)-rj).lt.1.e-3) then
*       j  =jh
*       jp1=jh
*     else
        j =min0(int(rj),n2-1)
        jp1=j+1
*     endif

      if ((i.eq.ip1).and.(j.eq.jp1)) then
c        no interpolation at all
         int2d=ar(i,j)
      else
         frac0i=ri-float(i)
         frac0j=rj-float(j)
         frac1i=1.-frac0i
         frac1j=1.-frac0j
         int2d = ar(i  ,j  ) * frac1i * frac1j
     &         + ar(i  ,jp1) * frac1i * frac0j
     &         + ar(ip1,j  ) * frac0i * frac1j
     &         + ar(ip1,jp1) * frac0i * frac0j
      endif
      end
      real function int2dm(ar,n1,n2,rid,rjd,misdat)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 2d-array to an arbitrary
c        location within the grid. The interpolation includes the
c        testing of the missing data flag 'misdat'.
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2)
c        n1,n2     int   input   dimensions of ar
c        ri,rj     real  input   grid location to be interpolated to
c        misdat    real  input   missing data flag (on if misdat<>0)
c     Warning:
c        This routine has not yet been seriously tested
c     History:
c-----------------------------------------------------------------------
 
c     argument declarations
      integer   n1,n2
      real      ar(n1,n2), rid,rjd, misdat
 
c     local declarations
      integer   i,j,ip1,jp1,ih,jh
      real      frac0i,frac0j,frac1i,frac1j,ri,rj,int2d
 
c     check if routine without missing data checking can be called instead
      if (misdat.eq.0.) then
        int2dm=int2d(ar,n1,n2,rid,rjd)
        return
      endif
 
c     do linear interpolation
      ri=amax1(1.,amin1(float(n1),rid))
      rj=amax1(1.,amin1(float(n2),rjd))
      ih=nint(ri)
      jh=nint(rj)
 
c     Check for interpolation in i
*     if (abs(float(ih)-ri).lt.1.e-3) then
*       i  =ih
*       ip1=ih
*     else
        i =min0(int(ri),n1-1)
        ip1=i+1
*     endif
 
c     Check for interpolation in j
*     if (abs(float(jh)-rj).lt.1.e-3) then
*       j  =jh
*       jp1=jh
*     else
        j =min0(int(rj),n2-1)
        jp1=j+1
*     endif
 
      if ((i.eq.ip1).and.(j.eq.jp1)) then
c        no interpolation at all
         int2dm=ar(i,j)
      else
         if ((misdat.eq.ar(i  ,j  )).or.
     &       (misdat.eq.ar(i  ,jp1)).or.
     &       (misdat.eq.ar(ip1,j  )).or.
     &       (misdat.eq.ar(ip1,jp1))) then
           int2dm=misdat
         else
           frac0i=ri-float(i)
           frac0j=rj-float(j)
           frac1i=1.-frac0i
           frac1j=1.-frac0j
           int2dm = ar(i  ,j  ) * frac1i * frac1j
     &            + ar(i  ,jp1) * frac1i * frac0j
     &            + ar(ip1,j  ) * frac0i * frac1j
     &            + ar(ip1,jp1) * frac0i * frac0j
         endif
      endif
      end
      real function int2dp(ar,n1,n2,rid,rjd)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 2d-array to an arbitrary
c        location within the grid. The 2d-array is periodic in the
c        i-direction: ar(0,.)=ar(n1,.) and ar(1,.)=ar(n1+1,.).
c        Therefore rid can take values in the range 0,...,n1+1
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2)
c        n1,n2     int   input   dimensions of ar
c        ri,rj     real  input   grid location to be interpolated to
c     History:
c-----------------------------------------------------------------------
 
c     argument declarations
      integer   n1,n2
      real      ar(0:n1+1,n2), rid,rjd
 
c     local declarations
      integer   i,j,ip1,jp1,ih,jh
      real      frac0i,frac0j,frac1i,frac1j,ri,rj
 
c     do linear interpolation
      ri=amax1(0.,amin1(float(n1+1),rid))
      rj=amax1(1.,amin1(float(n2),rjd))
      ih=nint(ri)
      jh=nint(rj)
 
c     Check for interpolation in i
*     if (abs(float(ih)-ri).lt.1.e-5) then
*       i  =ih
*       ip1=ih
*     else
        i =min0(int(ri),n1-1)
        ip1=i+1
*     endif
 
c     Check for interpolation in j
*     if (abs(float(jh)-rj).lt.1.e-5) then
*       j  =jh
*       jp1=jh
*     else
        j =min0(int(rj),n2-1)
        jp1=j+1
*     endif
 
      if ((i.eq.ip1).and.(j.eq.jp1)) then
c        no interpolation at all
         int2dp=ar(i,j)
      else
         frac0i=ri-float(i)
         frac0j=rj-float(j)
         frac1i=1.-frac0i
         frac1j=1.-frac0j
         int2dp = ar(i  ,j  ) * frac1i * frac1j
     &         + ar(i  ,jp1) * frac1i * frac0j
     &         + ar(ip1,j  ) * frac0i * frac1j
     &         + ar(ip1,jp1) * frac0i * frac0j
      endif
      end
      real function cint2d(ar,n1,n2,n3,rid,rjd,ikd)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 3d-array to an arbitrary
c        location in the horizontal. ikd specifies the level (must
c        be an integer). A bicubic method is applied (following
c        the Numerical Recipes).
c     Arguments:
c        ar           real  input   field, define as ar(n1,n2,n3)
c        n1,n2        int   input   dimensions of ar
c        rid,rjd      real  input   grid location to be interpolated to
c        ikd          int   input   level for interpolation
c     History:
c-----------------------------------------------------------------------

c     argument declarations
      integer   n1,n2,n3,ikd
      real      ar(n1,n2,n3), rid,rjd

c     local declarations
      integer   i,j,k
      real      y(4),y1(4),y2(4),y12(4)

c     indices of lower left corner of interpolation grid

      i=int(rid)
      j=int(rjd)
      k=ikd

c     do not interpolate if i or j are at the boundaries

      if ((i.eq.1).or.(j.eq.1).or.(i.eq.n1).or.(j.eq.n2)) then
        cint2d=ar(i,j,k)
        return
      endif

c     define the arrays y,y1,y2,y12 necessary for the bicubic
c     interpolation (following the Numerical Recipes).

      y(1)=ar(i,j,k)
      y(2)=ar(i+1,j,k)
      y(3)=ar(i+1,j+1,k)
      y(4)=ar(i,j+1,k)

      y1(1)=-(ar(i-1,j,k)-ar(i+1,j,k))/2.
      y1(2)=-(ar(i,j,k)-ar(i+2,j,k))/2.
      y1(3)=-(ar(i,j+1,k)-ar(i+2,j+1,k))/2.
      y1(4)=-(ar(i-1,j+1,k)-ar(i+1,j+1,k))/2.

      y2(1)=-(ar(i,j-1,k)-ar(i,j+1,k))/2.
      y2(2)=-(ar(i+1,j-1,k)-ar(i+1,j+1,k))/2.
      y2(3)=-(ar(i+1,j,k)-ar(i+1,j+2,k))/2.
      y2(4)=-(ar(i,j,k)-ar(i,j+2,k))/2.

      y12(1)=(ar(i+1,j+1,k)-ar(i+1,j-1,k)-ar(i-1,j+1,k)+ar(i-1,j-1,k))/4.
      y12(2)=(ar(i+2,j+1,k)-ar(i+2,j-1,k)-ar(i,j+1,k)+ar(i,j-1,k))/4.
      y12(3)=(ar(i+2,j+2,k)-ar(i+2,j,k)-ar(i,j+2,k)+ar(i,j,k))/4.
      y12(4)=(ar(i+1,j+2,k)-ar(i+1,j,k)-ar(i-1,j+2,k)+ar(i-1,j,k))/4.

      call bcuint(y,y1,y2,y12,i,j,rid,rjd,cint2d)
      return
      end
      real function int3d(ar,n1,n2,n3,rid,rjd,rkd)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 3d-array to an arbitrary
c        location within the grid.
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2,n3)
c        n1,n2,n3  int   input   dimensions of ar
c        ri,rj,rk  real  input   grid location to be interpolated to
c     History:
c-----------------------------------------------------------------------

c     argument declarations
      integer   n1,n2,n3
      real      ar(n1,n2,n3), rid,rjd,rkd

c     local declarations
      integer   i,j,k,ip1,jp1,kp1,ih,jh,kh
      real      frac0i,frac0j,frac0k,frac1i,frac1j,frac1k,ri,rj,rk

c     do linear interpolation
      ri=amax1(1.,amin1(float(n1),rid))
      rj=amax1(1.,amin1(float(n2),rjd))
      rk=amax1(1.,amin1(float(n3),rkd))
      ih=nint(ri)
      jh=nint(rj)
      kh=nint(rk)

c     Check for interpolation in i
*     if (abs(float(ih)-ri).lt.1.e-3) then
*       i  =ih
*       ip1=ih
*     else
        i =min0(int(ri),n1-1)
        ip1=i+1
*     endif

c     Check for interpolation in j
      if (abs(float(jh)-rj).lt.1.e-3) then
        j  =jh
        jp1=jh
      else
        j =min0(int(rj),n2-1)
        jp1=j+1
      endif

c     Check for interpolation in k
*     if (abs(float(kh)-rk).lt.1.e-3) then
*       k  =kh
*       kp1=kh
*     else
        k =min0(int(rk),n3-1)
        kp1=k+1
*     endif

      if (k.eq.kp1) then
c       no interpolation in k
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          no interpolation at all
           int3d=ar(i,j,k)
c          print *,'int3d 00: ',rid,rjd,rkd,int3d
        else
c          horizontal interpolation only
           frac0i=ri-float(i)
           frac0j=rj-float(j)
           frac1i=1.-frac0i
           frac1j=1.-frac0j
           int3d = ar(i  ,j  ,k  ) * frac1i * frac1j
     &           + ar(i  ,jp1,k  ) * frac1i * frac0j
     &           + ar(ip1,j  ,k  ) * frac0i * frac1j
     &           + ar(ip1,jp1,k  ) * frac0i * frac0j
c          print *,'int3d 10: ',rid,rjd,rkd,int3d
        endif
      else 
        frac0k=rk-float(k)
        frac1k=1.-frac0k
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          vertical interpolation only
           int3d = ar(i  ,j  ,k  ) * frac1k
     &           + ar(i  ,j  ,kp1) * frac0k
c          print *,'int3d 01: ',rid,rjd,rkd,int3d
        else
c          full 3d interpolation
           frac0i=ri-float(i)
           frac0j=rj-float(j)
           frac1i=1.-frac0i
           frac1j=1.-frac0j
           int3d = ar(i  ,j  ,k  ) * frac1i * frac1j * frac1k
     &           + ar(i  ,jp1,k  ) * frac1i * frac0j * frac1k 
     &           + ar(ip1,j  ,k  ) * frac0i * frac1j * frac1k
     &           + ar(ip1,jp1,k  ) * frac0i * frac0j * frac1k
     &           + ar(i  ,j  ,kp1) * frac1i * frac1j * frac0k
     &           + ar(i  ,jp1,kp1) * frac1i * frac0j * frac0k 
     &           + ar(ip1,j  ,kp1) * frac0i * frac1j * frac0k
     &           + ar(ip1,jp1,kp1) * frac0i * frac0j * frac0k
c          print *,'int3d 11: ',rid,rjd,rkd,int3d
        endif
      endif
      end
      real function int3dm(ar,n1,n2,n3,rid,rjd,rkd,misdat)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 3d-array to an arbitrary
c        location within the grid. The interpolation includes the 
c        testing of the missing data flag 'misdat'. 
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2,n3)
c        n1,n2,n3  int   input   dimensions of ar
c        ri,rj,rk  real  input   grid location to be interpolated to
c        misdat    real  input   missing data flag (on if misdat<>0)
c     Warning:
c        This routine has not yet been seriously tested
c     History:
c-----------------------------------------------------------------------

c     argument declarations
      integer   n1,n2,n3
      real      ar(n1,n2,n3), rid,rjd,rkd, misdat

c     local declarations
      integer   i,j,k,ip1,jp1,kp1,ih,jh,kh
      real      frac0i,frac0j,frac0k,frac1i,frac1j,frac1k,ri,rj,rk,int3d

c     check if routine without missing data checking can be called instead
      if (misdat.eq.0.) then
        int3dm=int3d(ar,n1,n2,n3,rid,rjd,rkd)
        return
      endif

c     do linear interpolation
      ri=amax1(1.,amin1(float(n1),rid))
      rj=amax1(1.,amin1(float(n2),rjd))
      rk=amax1(1.,amin1(float(n3),rkd))
      ih=nint(ri)
      jh=nint(rj)
      kh=nint(rk)

c     Check for interpolation in i
*     if (abs(float(ih)-ri).lt.1.e-3) then
*       i  =ih
*       ip1=ih
*     else
        i =min0(int(ri),n1-1)
        ip1=i+1
*     endif

c     Check for interpolation in j
*     if (abs(float(jh)-rj).lt.1.e-3) then
*       j  =jh
*       jp1=jh
*     else
        j =min0(int(rj),n2-1)
        jp1=j+1
*     endif

c     Check for interpolation in k
*     if (abs(float(kh)-rk).lt.1.e-3) then
*       k  =kh
*       kp1=kh
*     else
        k =min0(int(rk),n3-1)
        kp1=k+1
*     endif

      if (k.eq.kp1) then
c       no interpolation in k
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          no interpolation at all
           if (misdat.eq.ar(i,j,k)) then
             int3dm=misdat
           else
             int3dm=ar(i,j,k)
           endif
c          print *,'int3dm 00: ',rid,rjd,rkd,int3dm
        else
c          horizontal interpolation only
           if ((misdat.eq.ar(i  ,j  ,k  )).or.
     &         (misdat.eq.ar(i  ,jp1,k  )).or.
     &         (misdat.eq.ar(ip1,j  ,k  )).or.
     &         (misdat.eq.ar(ip1,jp1,k  ))) then
             int3dm=misdat
           else
             frac0i=ri-float(i)
             frac0j=rj-float(j)
             frac1i=1.-frac0i
             frac1j=1.-frac0j
             int3dm = ar(i  ,j  ,k  ) * frac1i * frac1j
     &              + ar(i  ,jp1,k  ) * frac1i * frac0j
     &              + ar(ip1,j  ,k  ) * frac0i * frac1j
     &              + ar(ip1,jp1,k  ) * frac0i * frac0j
c            print *,'int3dm 10: ',rid,rjd,rkd,int3dm
           endif
        endif
      else 
        frac0k=rk-float(k)
        frac1k=1.-frac0k
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          vertical interpolation only
           if ((misdat.eq.ar(i  ,j  ,k  )).or.
     &         (misdat.eq.ar(i  ,j  ,kp1))) then
             int3dm=misdat
           else
             int3dm = ar(i  ,j  ,k  ) * frac1k
     &              + ar(i  ,j  ,kp1) * frac0k
c            print *,'int3dm 01: ',rid,rjd,rkd,int3dm
           endif
        else
c          full 3d interpolation
           if ((misdat.eq.ar(i  ,j  ,k  )).or.
     &         (misdat.eq.ar(i  ,jp1,k  )).or.
     &         (misdat.eq.ar(ip1,j  ,k  )).or.
     &         (misdat.eq.ar(ip1,jp1,k  )).or.
     &         (misdat.eq.ar(i  ,j  ,kp1)).or.
     &         (misdat.eq.ar(i  ,jp1,kp1)).or.
     &         (misdat.eq.ar(ip1,j  ,kp1)).or.
     &         (misdat.eq.ar(ip1,jp1,kp1))) then
             int3dm=misdat
           else
             frac0i=ri-float(i)
             frac0j=rj-float(j)
             frac1i=1.-frac0i
             frac1j=1.-frac0j
             int3dm = ar(i  ,j  ,k  ) * frac1i * frac1j * frac1k
     &              + ar(i  ,jp1,k  ) * frac1i * frac0j * frac1k
     &              + ar(ip1,j  ,k  ) * frac0i * frac1j * frac1k
     &              + ar(ip1,jp1,k  ) * frac0i * frac0j * frac1k
     &              + ar(i  ,j  ,kp1) * frac1i * frac1j * frac0k
     &              + ar(i  ,jp1,kp1) * frac1i * frac0j * frac0k
     &              + ar(ip1,j  ,kp1) * frac0i * frac1j * frac0k
     &              + ar(ip1,jp1,kp1) * frac0i * frac0j * frac0k
c            print *,'int3dm 11: ',rid,rjd,rkd,int3dm
           endif
        endif
      endif
      end
      real function int3dmlog(ar,n1,n2,n3,rid,rjd,rkd,misdat)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 3d-array to an arbitrary
c        location within the grid. The interpolation includes the
c        testing of the missing data flag 'misdat'.
c        Prior to vertical interpolations the log is taken from the array.
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2,n3)
c        n1,n2,n3  int   input   dimensions of ar
c        ri,rj,rk  real  input   grid location to be interpolated to
c        misdat    real  input   missing data flag (on if misdat<>0)
c     Warning:
c        This routine has not yet been seriously tested
c     History:
c-----------------------------------------------------------------------

c     argument declarations
      integer   n1,n2,n3
      real      ar(n1,n2,n3), rid,rjd,rkd, misdat

c     local declarations
      integer   i,j,k,ip1,jp1,kp1,ih,jh,kh
      real      frac0i,frac0j,frac0k,frac1i,frac1j,frac1k,ri,rj,rk,int3d

c     print*,'hallo in SR int3dmlog'
c     check if routine without missing data checking can be called instead
      if (misdat.eq.0.) then
        int3dmlog=int3d(ar,n1,n2,n3,rid,rjd,rkd)
        return
      endif

c     do linear interpolation
      ri=amax1(1.,amin1(float(n1),rid))
      rj=amax1(1.,amin1(float(n2),rjd))
      rk=amax1(1.,amin1(float(n3),rkd))
      ih=nint(ri)
      jh=nint(rj)
      kh=nint(rk)

c     Check for interpolation in i
*     if (abs(float(ih)-ri).lt.1.e-3) then
*       i  =ih
*       ip1=ih
*     else
        i =min0(int(ri),n1-1)
        ip1=i+1
*     endif

c     Check for interpolation in j
*     if (abs(float(jh)-rj).lt.1.e-3) then
*       j  =jh
*       jp1=jh
*     else
        j =min0(int(rj),n2-1)
        jp1=j+1
*     endif

c     Check for interpolation in k
*     if (abs(float(kh)-rk).lt.1.e-3) then
*       k  =kh
*       kp1=kh
*     else
        k =min0(int(rk),n3-1)
        kp1=k+1
*     endif

      if (k.eq.kp1) then
c       no interpolation in k
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          no interpolation at all
           if (misdat.eq.ar(i,j,k)) then
             int3dmlog=misdat
           else
             int3dmlog=ar(i,j,k)
           endif
c          print *,'int3dmlog 00: ',rid,rjd,rkd,int3dmlog
        else
c          horizontal interpolation only
           if ((misdat.eq.ar(i  ,j  ,k  )).or.
     &         (misdat.eq.ar(i  ,jp1,k  )).or.
     &         (misdat.eq.ar(ip1,j  ,k  )).or.
     &         (misdat.eq.ar(ip1,jp1,k  ))) then
             int3dmlog=misdat
           else
             frac0i=ri-float(i)
             frac0j=rj-float(j)
             frac1i=1.-frac0i
             frac1j=1.-frac0j
             int3dmlog = ar(i  ,j  ,k  ) * frac1i * frac1j
     &              + ar(i  ,jp1,k  ) * frac1i * frac0j
     &              + ar(ip1,j  ,k  ) * frac0i * frac1j
     &              + ar(ip1,jp1,k  ) * frac0i * frac0j
c            print *,'int3dmlog 10: ',rid,rjd,rkd,int3dmlog
           endif
        endif
      else
        frac0k=rk-float(k)
        frac1k=1.-frac0k
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          vertical interpolation only
           if ((misdat.eq.ar(i  ,j  ,k  )).or.
     &         (misdat.eq.ar(i  ,j  ,kp1))) then
             int3dmlog=misdat
           else
             int3dmlog = log(ar(i  ,j  ,k  )) * frac1k
     &                 + log(ar(i  ,j  ,kp1)) * frac0k
             int3dmlog = exp(int3dmlog)
c            print *,'int3dmlog 01: ',rid,rjd,rkd,int3dmlog
           endif
        else
c          full 3d interpolation
           if ((misdat.eq.ar(i  ,j  ,k  )).or.
     &         (misdat.eq.ar(i  ,jp1,k  )).or.
     &         (misdat.eq.ar(ip1,j  ,k  )).or.
     &         (misdat.eq.ar(ip1,jp1,k  )).or.
     &         (misdat.eq.ar(i  ,j  ,kp1)).or.
     &         (misdat.eq.ar(i  ,jp1,kp1)).or.
     &         (misdat.eq.ar(ip1,j  ,kp1)).or.
     &         (misdat.eq.ar(ip1,jp1,kp1))) then
             int3dmlog=misdat
           else
             frac0i=ri-float(i)
             frac0j=rj-float(j)
             frac1i=1.-frac0i
             frac1j=1.-frac0j
             int3dmlog = log(ar(i  ,j  ,k  )) * frac1i * frac1j * frac1k
     &                 + log(ar(i  ,jp1,k  )) * frac1i * frac0j * frac1k
     &                 + log(ar(ip1,j  ,k  )) * frac0i * frac1j * frac1k
     &                 + log(ar(ip1,jp1,k  )) * frac0i * frac0j * frac1k
     &                 + log(ar(i  ,j  ,kp1)) * frac1i * frac1j * frac0k
     &                 + log(ar(i  ,jp1,kp1)) * frac1i * frac0j * frac0k
     &                 + log(ar(ip1,j  ,kp1)) * frac0i * frac1j * frac0k
     &                 + log(ar(ip1,jp1,kp1)) * frac0i * frac0j * frac0k
             int3dmlog = exp(int3dmlog)
c            print *,'int3dmlog 11: ',rid,rjd,rkd,int3dmlog
           endif
        endif
      endif
      end

      real function int3dmvc(ar,n1,n2,n3,rid,rjd,rkd,misdat)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 3d-array to an arbitrary
c        location within the grid. The interpolation includes the
c        testing of the missing data flag 'misdat'.
c        In the vertical a Lagrangian cubic interpolation is
c        performed.
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2,n3)
c        n1,n2,n3  int   input   dimensions of ar
c        ri,rj,rk  real  input   grid location to be interpolated to
c        misdat    real  input   missing data flag (on if misdat<>0)
c     Warning:
c        This routine has not yet been seriously tested
c     History:
c-----------------------------------------------------------------------

c     argument declarations
      integer   n1,n2,n3
      real      ar(n1,n2,n3), rid,rjd,rkd, misdat
 
c     local declarations
      integer   i,j,k,ip1,jp1,kp1,ih,jh,kh,klow,n
      real      frac0i,frac0j,frac1i,frac1j,ri,rj,rk
      real      int2d(4)

      real      int3dm

c     if n3 < 4 then do call linear interpolation in the vertical
      if (n3.lt.4) then
        int3dmvc=int3dm(ar,n1,n2,n3,rid,rjd,rkd,misdat)
        return
      endif
 
c     do linear interpolation in the horizontal
      ri=amax1(1.,amin1(float(n1),rid))
      rj=amax1(1.,amin1(float(n2),rjd))
      rk=amax1(1.,amin1(float(n3),rkd))
      ih=nint(ri)
      jh=nint(rj)
      kh=nint(rk)
 
c     Check for interpolation in i
*     if (abs(float(ih)-ri).lt.1.e-3) then
*       i  =ih
*       ip1=ih
*     else
        i =min0(int(ri),n1-1)
        ip1=i+1
*     endif
 
c     Check for interpolation in j
*     if (abs(float(jh)-rj).lt.1.e-3) then
*       j  =jh
*       jp1=jh
*     else
        j =min0(int(rj),n2-1)
        jp1=j+1
*     endif
 
c     Check for interpolation in k
*     if (abs(float(kh)-rk).lt.1.e-3) then
*       k  =kh
*       kp1=kh
*     else
        k =min0(int(rk),n3-1)
        kp1=k+1
*     endif
 
      if (k.eq.kp1) then
c       no interpolation in k
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          no interpolation at all
           int3dmvc=ar(i,j,k)
c          print *,'int3dmvc 00: ',rid,rjd,rkd,int3dmvc
        else
c          horizontal interpolation only
           if ((misdat.eq.ar(i  ,j  ,k  )).or.
     &         (misdat.eq.ar(i  ,jp1,k  )).or.
     &         (misdat.eq.ar(ip1,j  ,k  )).or.
     &         (misdat.eq.ar(ip1,jp1,k  ))) then
             int3dmvc=misdat
           else
             frac0i=ri-float(i)
             frac0j=rj-float(j)
             frac1i=1.-frac0i
             frac1j=1.-frac0j
             int3dmvc = ar(i  ,j  ,k  ) * frac1i * frac1j
     &              + ar(i  ,jp1,k  ) * frac1i * frac0j
     &              + ar(ip1,j  ,k  ) * frac0i * frac1j
     &              + ar(ip1,jp1,k  ) * frac0i * frac0j
c            print *,'int3dmvc 10: ',rid,rjd,rkd,int3dmvc
           endif
        endif
      else
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          vertical interpolation only
           if ((misdat.eq.ar(i  ,j  ,k  )).or.
     &         (misdat.eq.ar(i  ,j  ,kp1))) then
             int3dmvc=misdat
           else
             if (k-1.lt.1) then
               klow=1
             else if (k+2.gt.n3) then
               klow=n3-3
             else
               klow=k-1
             endif
             call cubint(ar(i,j,klow),ar(i,j,klow+1),ar(i,j,klow+2),
     &                   ar(i,j,klow+3),klow,rk,int3dmvc)
           endif
        else
c          full 3d interpolation
           if ((misdat.eq.ar(i  ,j  ,k  )).or.
     &         (misdat.eq.ar(i  ,jp1,k  )).or.
     &         (misdat.eq.ar(ip1,j  ,k  )).or.
     &         (misdat.eq.ar(ip1,jp1,k  )).or.
     &         (misdat.eq.ar(i  ,j  ,kp1)).or.
     &         (misdat.eq.ar(i  ,jp1,kp1)).or.
     &         (misdat.eq.ar(ip1,j  ,kp1)).or.
     &         (misdat.eq.ar(ip1,jp1,kp1))) then
             int3dmvc=misdat
           else
             frac0i=ri-float(i)
             frac0j=rj-float(j)
             frac1i=1.-frac0i
             frac1j=1.-frac0j
             if (k-1.lt.1) then
               klow=1
             else if (k+2.gt.n3) then
               klow=n3-3
             else
               klow=k-1
             endif
             do n=1,4
               int2d(n) = ar(i  ,j  ,klow-1+n  ) * frac1i * frac1j
     &                  + ar(i  ,jp1,klow-1+n  ) * frac1i * frac0j
     &                  + ar(ip1,j  ,klow-1+n  ) * frac0i * frac1j
     &                  + ar(ip1,jp1,klow-1+n  ) * frac0i * frac0j
             enddo
             call cubint(int2d(1),int2d(2),int2d(3),int2d(4),
     &                   klow,rk,int3dmvc)
           endif
        endif
      endif
      end
      real function int4d(ar,n1,n2,n3,n4,rid,rjd,rkd,rld)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 4d-array to an arbitrary
c        location within the grid.
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2,n3)
c        n1,..,n4  int   input   dimensions of ar
c        ri,..,rl  real  input   grid location to be interpolated to
c     History:
c-----------------------------------------------------------------------

c     argument declarations
      integer   n1,n2,n3,n4
      real      ar(n1,n2,n3,n4), rid,rjd,rkd,rld

c     local declarations
      integer   l,lp1,lh
      real      frac0l,frac1l,rl,int3d

c     do linear interpolation in l-direction
      rl=amax1(1.,amin1(float(n4),rld))
      lh=nint(rl)

c     Check for interpolation in l
*     if (abs(float(lh)-rl).lt.1.e-3) then
*       l  =lh
*       lp1=lh
*     else
        l =min0(int(rl),n4-1)
        lp1=l+1
*     endif

      if (l.eq.lp1) then
c       no interpolation in l
        int4d=int3d(ar(1,1,1,l),n1,n2,n3,rid,rjd,rkd)
      else
c       interpolation in l
        frac0l=rl-float(l)
        frac1l=1.-frac0l
        int4d = int3d(ar(1,1,1,l  ),n1,n2,n3,rid,rjd,rkd) * frac1l
     &        + int3d(ar(1,1,1,lp1),n1,n2,n3,rid,rjd,rkd) * frac0l
      endif
      end
      real function int4dm(ar,n1,n2,n3,n4,rid,rjd,rkd,rld,misdat)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 4d-array to an arbitrary
c        location within the grid. The interpolation includes the 
c        testing of the missing data flag 'misdat'. 
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2,n3)
c        n1,..,n4  int   input   dimensions of ar
c        ri,..,rl  real  input   grid location to be interpolated to
c        misdat    real  input   missing data flag (on if misdat<>0)
c     Warning:
c        This routine has not yet been seriously tested.
c     History:
c-----------------------------------------------------------------------

c     argument declarations
      integer   n1,n2,n3,n4
      real      ar(n1,n2,n3,n4), rid,rjd,rkd,rld, misdat

c     local declarations
      integer   l,lp1,lh
      real      frac0l,frac1l,rl,rint0,rint1,int4d,int3dm

c     check whether missing data checking is required
      if (misdat.eq.0.) then
        int4dm=int4d(ar,n1,n2,n3,n4,rid,rjd,rkd,rld)
        return
      endif

c     do linear interpolation in l-direction
      rl=amax1(1.,amin1(float(n4),rld))
      lh=nint(rl)

c     Check for interpolation in l
*     if (abs(float(lh)-rl).lt.1.e-3) then
*       l  =lh
*       lp1=lh
*     else
        l =min0(int(rl),n4-1)
        lp1=l+1
*     endif

      if (l.eq.lp1) then
c       no interpolation in l
        int4dm = int3dm(ar(1,1,1,l),n1,n2,n3,rid,rjd,rkd,misdat)
      else
c       interpolation in l
        frac0l=rl-float(l)
        frac1l=1.-frac0l
        rint0 = int3dm(ar(1,1,1,l  ),n1,n2,n3,rid,rjd,rkd,misdat)
        rint1 = int3dm(ar(1,1,1,lp1),n1,n2,n3,rid,rjd,rkd,misdat)
        if ((rint0.eq.misdat).or.(rint1.eq.misdat)) then
          int4dm = misdat
        else
          int4dm = rint0*frac1l + rint1*frac0l
        endif
      endif
      end
      real function int3dl(ar,n1,n2,n3,levels,rid,rjd,rkd)
c-----------------------------------------------------------------------
c     Purpose:
c        This subroutine interpolates a 3d-array to an arbitrary
c        location within the grid. The vertical interpolation is linear
c        in log(pressure).
c     Arguments:
c        ar        real  input   surface pressure, define as ar(n1,n2,n3)
c        n1,n2,n3  int   input   dimensions of ar
c        levels    real  input   array contains pressure levels for ar
c        ri,rj,rk  real  input   grid location to be interpolated to
c     History:
c        Based on int3d                 July 93
c-----------------------------------------------------------------------

c     argument declarations
      integer   n1,n2,n3
      real      ar(n1,n2,n3), rid,rjd,rkd
      real      levels(n3)

c     local declarations
      real      pval
      integer   i,j,k,ip1,jp1,kp1,ih,jh,kh
      real      frac0i,frac0j,frac0k,frac1i,frac1j,frac1k,ri,rj,rk

c     do linear interpolation
      ri=amax1(1.,amin1(float(n1),rid))
      rj=amax1(1.,amin1(float(n2),rjd))
      rk=amax1(1.,amin1(float(n3),rkd))
      ih=nint(ri)
      jh=nint(rj)
      kh=nint(rk)

c     Check for interpolation in i
*     if (abs(float(ih)-ri).lt.1.e-3) then
*       i  =ih
*       ip1=ih
*     else
        i =min0(int(ri),n1-1)
        ip1=i+1
*     endif

c     Check for interpolation in j
*     if (abs(float(jh)-rj).lt.1.e-3) then
*       j  =jh
*       jp1=jh
*     else
        j =min0(int(rj),n2-1)
        jp1=j+1
*     endif

c     Check for interpolation in k
*     if (abs(float(kh)-rk).lt.1.e-3) then
*       k  =kh
*       kp1=kh
*     else
        k =min0(int(rk),n3-1)
        kp1=k+1
*     endif

      if (k.eq.kp1) then
c       no interpolation in k
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          no interpolation at all
           int3dl=ar(i,j,k)
c          print *,'int3dl 00: ',rid,rjd,rkd,int3dl
        else
c          horizontal interpolation only
           frac0i=ri-float(i)
           frac0j=rj-float(j)
           frac1i=1.-frac0i
           frac1j=1.-frac0j
           int3dl = ar(i  ,j  ,k  ) * frac1i * frac1j
     &            + ar(i  ,jp1,k  ) * frac1i * frac0j
     &            + ar(ip1,j  ,k  ) * frac0i * frac1j
     &            + ar(ip1,jp1,k  ) * frac0i * frac0j
c          print *,'int3dl 10: ',rid,rjd,rkd,int3dl
        endif
      else
*       frac0k=rk-float(k)
c       calculate the pressure value to be interpolated to
        pval=levels(int(rk))
     >            -(rk-aint(rk))*(levels(int(rk))-levels(int(rk)+1))
        frac0k=log(levels(int(rk))/pval)
     &        /log(levels(int(rk))/levels(int(rk)+1))
        frac1k=1.-frac0k
        if ((i.eq.ip1).and.(j.eq.jp1)) then
c          vertical interpolation only
           int3dl = ar(i  ,j  ,k  ) * frac1k
     &            + ar(i  ,j  ,kp1) * frac0k
c          print *,'int3dl 01: ',rid,rjd,rkd,int3dl
        else
c          full 3d interpolation
           frac0i=ri-float(i)
           frac0j=rj-float(j)
           frac1i=1.-frac0i
           frac1j=1.-frac0j
           int3dl = ar(i  ,j  ,k  ) * frac1i * frac1j * frac1k
     &            + ar(i  ,jp1,k  ) * frac1i * frac0j * frac1k
     &            + ar(ip1,j  ,k  ) * frac0i * frac1j * frac1k
     &            + ar(ip1,jp1,k  ) * frac0i * frac0j * frac1k
     &            + ar(i  ,j  ,kp1) * frac1i * frac1j * frac0k
     &            + ar(i  ,jp1,kp1) * frac1i * frac0j * frac0k
     &            + ar(ip1,j  ,kp1) * frac0i * frac1j * frac0k
     &            + ar(ip1,jp1,kp1) * frac0i * frac0j * frac0k
c          print *,'int3dl 11: ',rid,rjd,rkd,int3dl
        endif
      endif
      end
      subroutine bcucof(y,y1,y2,y12,c)
c-----------------------------------------------------------------------
c       Given arrays y,y1,y2 and y12, each of length 4, containing the
c       function, gradients, and cross derivative at the four grid points
c       of a rectangular grid cell (numbered counterclockwise from the 
c       lower left), and given d1 and d2, the length of the grid cell in
c       the 1- and 2-directions, this routine returns the table c that is
c       used by routine bcuint for biqubic interpolation.
c     Source: Numerical Recipes, Fortran Version, p.99
c-----------------------------------------------------------------------
      real      c(4,4),y(4),y1(4),y2(4),y12(4),cl(16),x(16)
      integer   wt(16,16)

      data      wt/1,0,-3,2,4*0,-3,0,9,-6,2,0,-6,4,
     >          8*0,3,0,-9,6,-2,0,6,-4,
     >          10*0,9,-6,2*0,-6,4,2*0,3,-2,6*0,-9,6,2*0,6,-4,
     >          4*0,1,0,-3,2,-2,0,6,-4,1,0,-3,2,8*0,-1,0,3,-2,1,0,-3,2,
     >          10*0,-3,2,2*0,3,-2,6*0,3,-2,2*0,-6,4,2*0,3,-2,
     >          0,1,-2,1,5*0,-3,6,-3,0,2,-4,2,9*0,3,-6,3,0,-2,4,-2,
     >          10*0,-3,3,2*0,2,-2,2*0,-1,1,6*0,3,-3,2*0,-2,2,
     >          5*0,1,-2,1,0,-2,4,-2,0,1,-2,1,9*0,-1,2,-1,0,1,-2,1,
     >          10*0,1,-1,2*0,-1,1,6*0,-1,1,2*0,2,-2,2*0,-1,1/

      real      xx
      integer   i,j,k,l

      do i=1,4                  ! pack a temporary vector x
        x(i)=y(i)
        x(i+4)=y1(i)
        x(i+8)=y2(i)
        x(i+12)=y12(i)
      enddo     

      do i=1,16                 ! matrix multiply by the stored table
        xx=0.
        do k=1,16
          xx=xx+wt(i,k)*x(k)
        enddo
        cl(i)=xx
      enddo

      l=0
      do i=1,4                  ! unpack the result into the output table
      do j=1,4
        l=l+1
        c(i,j)=cl(l)
      enddo
      enddo

      return
      end
      subroutine bcuint(y,y1,y2,y12,x1l,x2l,x1,x2,ansy)
c-----------------------------------------------------------------------
c       Bicubic interpolation within a grid square. Input quantities are
c       y,y1,y2,y12 (as described in bcucof); x1l and x1u, the lower and
c       upper coordinates of the grid square in the 1-direction; x2l and
c       x2u likewise for the 2-direction; and x1,x2, the coordinates of
c       the desired point for the interpolation. The interplated function
c       value is returned as ansy. This routine calls bcucof.
c     Source: Numerical Recipes, Fortran Version, p.99/100
c     !!! changed the proposed code !!!
c-----------------------------------------------------------------------

      real      y(4),y1(4),y2(4),y12(4),c(4,4)
      real      ansy,x1,x2,t,u
      integer   i,x1l,x2l

      call bcucof(y,y1,y2,y12,c)

      t=x1-real(x1l)
      u=x2-real(x2l)

      ansy=0.

      do i=4,1,-1
        ansy=t*ansy+((c(i,4)*u+c(i,3))*u+c(i,2))*u+c(i,1)
      enddo

      return
      end
      subroutine cubint(ya1,ya2,ya3,ya4,k,x,y)
c-----------------------------------------------------------------------
c       Interface routine for SR polint for special case of cubic
c       interpolation in index space, with xa=k,k+1,k+2,k+3
c-----------------------------------------------------------------------
 
      integer   k
      real      ya1,ya2,ya3,ya4,x,y

      integer   n
      real      xa(4),ya(4),dy

      do n=1,4
        xa(1)=real(k)
        xa(2)=real(k+1)
        xa(3)=real(k+2)
        xa(4)=real(k+3)
  
        ya(1)=ya1
        ya(2)=ya2
        ya(3)=ya3
        ya(4)=ya4
      enddo

      call polint(xa,ya,4,x,y,dy)

      return
      end
      subroutine polint(xa,ya,n,x,y,dy)
c-----------------------------------------------------------------------
c       Given arrays xa and ya, each of length n, and given a value x, this
c       routine returns a value y, and an error estimate dy. If P(x) is the
c       polynomial of degree n-1 such that p(xa(i))=ya(i),i=1,...,n, then
c       the returned value y=p(x)
c     Source: Numerical Recipes, Fortran Version, p.82
c-----------------------------------------------------------------------

      integer   nmax,n
      parameter(nmax=10)
      real      xa(n),ya(n),x,y,dy
      integer   i,m,ns
      real      c(nmax),d(nmax),den,dif,dift,ho,hp,w

      ns=1
      dif=abs(x-xa(1))

      do i=1,n
        dift=abs(x-xa(i))
        if (dift.lt.dif) then
          ns=i
          dif=dift
        endif
        c(i)=ya(i)
        d(i)=ya(i)
      enddo

      y=ya(ns)
      ns=ns-1
      do m=1,n-1
        do i=1,n-m
          ho=xa(i)-x
          hp=xa(i+m)-x
          w=c(i+1)-d(i)
          den=ho-hp
          den=w/den
          d(i)=hp*den
          c(i)=ho*den
        enddo
        if (2*ns.lt.n-m) then
          dy=c(ns+1)
        else
          dy=d(ns)
          ns=ns-1
        endif
        y=y+dy
      enddo

      return
      end
      subroutine filt2d (a,af,f1,f2,nx,ny,fil,misdat,
     &                                     iperx,ipery,ispol,inpol)
c     =============================================================
c     Apply a conservative diffusion operator onto the 2d field a,
c     with full missing data checking.
c
c     a     real   inp  array to be filtered, dimensioned (nx,ny)
c     af    real   out  filtered array, dimensioned (nx,ny), can be
c                       equivalenced with array a in the calling routine
c     f1    real        workarray, dimensioned (nx+1,ny)
c     f2    real        workarray, dimensioned (nx,ny+1)
c     fil   real   inp  filter-coeff., 0<afil<=1. Maximum filtering with afil=1
c                       corresponds to one application of the linear filter.
c     misdat real  inp  missing-data value, a(i,j)=misdat indicates that
c                       the corresponding value is not available. The
c                       misdat-checking can be switched off with with misdat=0.
c     iperx int    inp  periodic boundaries in the x-direction (1=yes,0=no)
c     ipery int    inp  periodic boundaries in the y-direction (1=yes,0=no)
c     inpol int    inp  northpole at j=ny  (1=yes,0=no)
c     ispol int    inp  southpole at j=1   (1=yes,0=no)
c
c     Christoph Schaer, 1993
 
c     argument declaration
      integer     nx,ny
      real        a(nx,ny),af(nx,ny),f1(nx+1,ny),f2(nx,ny+1),fil,misdat
      integer     iperx,ipery,inpol,ispol
 
c     local variable declaration
      integer     i,j,is
      real        fh
 
c     compute constant fh
      fh=0.125*fil
 
c     compute fluxes in x-direction
      if (misdat.eq.0.) then
        do j=1,ny
        do i=2,nx
          f1(i,j)=a(i-1,j)-a(i,j)
        enddo
        enddo
      else
        do j=1,ny
        do i=2,nx
          if ((a(i,j).eq.misdat).or.(a(i-1,j).eq.misdat)) then
            f1(i,j)=0.
          else
            f1(i,j)=a(i-1,j)-a(i,j)
          endif
        enddo
        enddo
      endif
      if (iperx.eq.1) then
c       do periodic boundaries in the x-direction
        do j=1,ny
          f1(1,j)=f1(nx,j)
          f1(nx+1,j)=f1(2,j)
        enddo
      else
c       set boundary-fluxes to zero
        do j=1,ny
          f1(1,j)=0.
          f1(nx+1,j)=0.
        enddo
      endif
 
c     compute fluxes in y-direction
      if (misdat.eq.0.) then
        do j=2,ny
        do i=1,nx
          f2(i,j)=a(i,j-1)-a(i,j)
        enddo
        enddo
      else
        do j=2,ny
        do i=1,nx
          if ((a(i,j).eq.misdat).or.(a(i,j-1).eq.misdat)) then
            f2(i,j)=0.
          else
            f2(i,j)=a(i,j-1)-a(i,j)
          endif
        enddo
        enddo
      endif
c     set boundary-fluxes to zero
      do i=1,nx
        f2(i,1)=0.
        f2(i,ny+1)=0.
      enddo
      if (ipery.eq.1) then
c       do periodic boundaries in the x-direction
        do i=1,nx
          f2(i,1)=f2(i,ny)
          f2(i,ny+1)=f2(i,2)
        enddo
      endif
      if (iperx.eq.1) then
        if (ispol.eq.1) then
c         do south-pole
          is=(nx-1)/2
          do i=1,nx
            f2(i,1)=-f2(mod(i-1+is,nx)+1,2)
          enddo
        endif
        if (inpol.eq.1) then
c         do north-pole
          is=(nx-1)/2
          do i=1,nx
            f2(i,ny+1)=-f2(mod(i-1+is,nx)+1,ny)
          enddo
        endif
      endif
 
c     compute flux-convergence -> filter
      if (misdat.eq.0.) then
        do j=1,ny
        do i=1,nx
            af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
        enddo
        enddo
      else
        do j=1,ny
        do i=1,nx
          if (a(i,j).eq.misdat) then
            af(i,j)=misdat
          else
            af(i,j)=a(i,j)+fh*(f1(i,j)-f1(i+1,j)+f2(i,j)-f2(i,j+1))
          endif
        enddo
        enddo
      endif
      end

      subroutine pipo(var3d,p3d,lev,var,nx,ny,nz,mdv,mode)
C     ====================================================

C     Interpolates the 3d variable var3d on the pressure surface
C     defined by lev. The interpolated field is returned as var.
C     p3d denotes the 3d pressure array.
C     mode determines the way of vertical interpolation:
C       mode=0 is for linear interpolation
C       mode=1 is for logarithmic interpolation

      integer   nx,ny,nz,mode
      real      lev,mdv
      real      var3d(nx,ny,nz),p3d(nx,ny,nz),var(nx,ny)

      integer   i,j,k
      real      kind
      real      int3dm

      do i=1,nx
      do j=1,ny

        kind=0.
        do k=1,nz-1
          if ((p3d(i,j,k).ge.lev).and.(p3d(i,j,k+1).le.lev)) then
            kind=float(k)+(p3d(i,j,k)-lev)/
     >                   (p3d(i,j,k)-p3d(i,j,k+1))
            goto 100
          endif
        enddo
 100    continue

        if (kind.eq.0.) then
          var(i,j)=mdv
        else
          var(i,j)=int3dm(var3d,nx,ny,nz,float(i),float(j),kind,mdv)
        endif

      enddo
      enddo

      return
      end

      subroutine thipo(var3d,th3d,lev,var,nx,ny,nz,mdv,mode)
C     ======================================================

C     Interpolates the 3d variable var3d on the isentropic surface
C     defined by lev. The interpolated field is returned as var.
C     th3d denotes the 3d theta array.
C     mode determines the way of vertical interpolation:
C       mode=0 is for linear interpolation
C       mode=1 is for logarithmic interpolation

      integer   nx,ny,nz,mode
      real      lev,mdv
      real      var3d(nx,ny,nz),th3d(nx,ny,nz),var(nx,ny)

      integer   i,j,k
      real      kind
      real      int3dm

      do i=1,nx
      do j=1,ny

        kind=0
        do k=1,nz-1
          if ((th3d(i,j,k).le.lev).and.(th3d(i,j,k+1).ge.lev)) then
            kind=float(k)+(th3d(i,j,k)-lev)/
     >                   (th3d(i,j,k)-th3d(i,j,k+1))
            goto 100
          endif
        enddo
 100    continue

        if (kind.eq.0) then
          var(i,j)=mdv
        else
          var(i,j)=int3dm(var3d,nx,ny,nz,float(i),float(j),kind,mdv)
        endif

      enddo
      enddo

      return
      end