Subversion Repositories lagranto.ecmwf

Rev

Blame | Last modification | View Log | Download | RSS feed

      subroutine copyar(array1,array2,nsize)
C     ======================================
C
C     Copy the array1 on array2.
C
C     array1    input   array to copy
C     array2    output  array to write
C     nsize     input   size of arrays

      integer   i,nsize
      real      array1(nsize),array2(nsize)

      do i=1,nsize
        array2(i)=array1(i)
      enddo

      return
      end
      subroutine clipreg2(plon,plat,varmin,varmax,nx,ny,ak,bk,nz,sp,
     >           prelevs,kcl0,kcl1,xcorner,ycorner,pmin,pmax,ind,
     >           nxy,single,onelev,ierr)
C     ==============================================================
C
C     Clip a region to calculate trajectories.
C
C     plon      input   longitude of computational pole
C     plat      input   latitude of computational pole
C     varmin    input   array with minimum phys. coord.  of data region
C     varmax    input   array with maximum phys. coord.  of data region
C     nx        input   number of data points along latitude
C     ny        input   number of data points along longitude
C     ak        input   array contains ak values to calculate data-levels
C     bk        input   array contains bk values to calculate data-levels
C     nz        input   number of levels
C     sp        input   array contains surface pressure
C     prelevs   input   logical var (=.true. if data is on pressure levels)
C     kcl0,1    output  lowest,highest index for level of clipped region
C     xcorner   output  x-coordinates of corners of clipped region
C     ycorner   output  y-coordinates of corners of clipped region
C     pmin      output  minimum pressure value of clipped region
C     pmax      output  maximum pressure value of clipped region
C     ind       output  array with index of grid points within clipped region
C     nxy       output  number of points within clipped region
C     single    output  logical flag for single trajectories
C     onelev    output  logical flag if clipmin(3)=clipmax(3)
C     ierr      output  error flag

      real      pmin,pmax,varmin(4),varmax(4)
      real      xcorner(4),ycorner(4),xmax,ymax,xmin,ymin,xx,yy
      real      ak(nz),bk(nz)
      real      sp(nx,ny)
      real      dx,dy
      real      plon,plat,xphys,yphys
      integer   kcl0,kcl1,i,j,k,l,nx,ny,nz,nxy,ierr
      integer   ind(400*100)
      logical   prelevs,onelev,single

      real      lmtolms,phtophs

C     Reset error flag

      ierr=0

C     Calculate grid increments

      dx=(varmax(1)-varmin(1))/(nx-1)
      dy=(varmax(2)-varmin(2))/(ny-1)

C     Read corners of region to clip from tape 9

      read(9,10)xcorner(1)
      read(9,10)ycorner(1)
      read(9,10)xcorner(2)
      read(9,10)ycorner(2)
      read(9,10)xcorner(3)
      read(9,10)ycorner(3)
      read(9,10)xcorner(4)
      read(9,10)ycorner(4)
      read(9,10)pmax
      read(9,10)pmin

   10 format(f7.3)

C     If necessary transform corners to the computational coordinates

      if ((plon.ne.0.).or.(plat.ne.90.)) then
        do i=1,4
          xphys=lmtolms(ycorner(i),xcorner(i),plat,plon)
          yphys=phtophs(ycorner(i),xcorner(i),plat,plon)
          xcorner(i)=xphys
          ycorner(i)=yphys
        enddo
      endif

C     Test if corners are within data domain

      do i=1,4
        if (xcorner(i).lt.varmin(1)) goto 980
        if (ycorner(i).lt.varmin(2)) goto 980
        if (xcorner(i).gt.varmax(1)) goto 980
        if (ycorner(i).gt.varmax(2)) goto 980
      enddo
      if (pmax.gt.varmin(3)) goto 980
      if (pmin.lt.varmax(3)) goto 980

C     Set onelev flag

      if (pmin.eq.pmax) then
        onelev=.true.
      else
        onelev=.false.
      endif

C     Check for single trajectory

      single=.false.
      if ((xcorner(1).eq.xcorner(2)).and.
     >    (xcorner(2).eq.xcorner(3)).and.
     >    (xcorner(3).eq.xcorner(4)).and.
     >    (ycorner(1).eq.ycorner(2)).and.
     >    (ycorner(2).eq.ycorner(3)).and.
     >    (ycorner(3).eq.ycorner(4))) then
        if (pmin.eq.pmax) then
          nxy=1
          single=.true.
          return
        else
          goto 980
        endif
      endif

C     Determine which grid points are within clipped region

      xmax=xcorner(1)
      xmin=xcorner(1)
      ymax=ycorner(1)
      ymin=ycorner(1)
      do i=2,4
        if (xcorner(i).lt.xmin) xmin=xcorner(i)
        if (xcorner(i).gt.xmax) xmax=xcorner(i)
        if (ycorner(i).lt.ymin) ymin=ycorner(i)
        if (ycorner(i).gt.ymax) ymax=ycorner(i)
      enddo

      nxy=0

      do i=1,nx
        xx=varmin(1)+(i-1)*dx
        do j=1,ny
          yy=varmin(2)+(j-1)*dy
          if (xx.lt.xmin) goto 970
          if (xx.gt.xmax) goto 970
          if (yy.lt.ymin) goto 970
          if (yy.gt.ymax) goto 970
          if ((xx-xcorner(1))*(ycorner(2)-ycorner(1))-
     >        (yy-ycorner(1))*(xcorner(2)-xcorner(1)).gt.0.) goto 970
          if ((xx-xcorner(2))*(ycorner(3)-ycorner(2))-
     >        (yy-ycorner(2))*(xcorner(3)-xcorner(2)).gt.0.) goto 970
          if ((xx-xcorner(3))*(ycorner(4)-ycorner(3))-
     >        (yy-ycorner(3))*(xcorner(4)-xcorner(3)).gt.0.) goto 970
          if ((xx-xcorner(4))*(ycorner(1)-ycorner(4))-
     >        (yy-ycorner(4))*(xcorner(1)-xcorner(4)).gt.0.) goto 970

          nxy=nxy+1
          ind(nxy)=i+(j-1)*nx
 970      continue
        enddo
      enddo
 
C     Calculate vertical indices for clipped region

      if (.not.onelev) then
        if (prelevs) then               ! data on pressure levels
          do k=1,nz-1
            if ((pmax.le.ak(k)).and.(pmax.ge.ak(k+1))) then
              if (ak(k)-pmax.gt.pmax-ak(k+1)) then
                kcl0=k+1
              else
                kcl0=k
              endif
            endif
            if ((pmin.le.ak(k)).and.(pmin.ge.ak(k+1))) then
              if (ak(k)-pmin.gt.pmin-ak(k+1)) then
                kcl1=k+1
              else
                kcl1=k
              endif
            endif
          enddo
        else                    ! data on model levels
          kcl0=1                        ! initialize kcl0 to lowest level
          kcl1=nz                       ! initialize kcl1 to highest level
          do k=nz-1,1,-1
          do l=1,nxy
            i=mod(mod(ind(l)-1,nx*ny),nx)+1
            j=int(mod(ind(l)-1,nx*ny)/nx)+1
            if ((pmax.le.ak(k)+bk(k)*sp(i,j)).and.
     >          (pmax.gt.ak(k+1)+bk(k+1)*sp(i,j))) kcl0=k+1
          enddo
          enddo
          do k=1,nz-1
          do l=1,nxy
            i=mod(mod(ind(l)-1,nx*ny),nx)+1
            j=int(mod(ind(l)-1,nx*ny)/nx)+1
            if ((pmin.lt.ak(k)+bk(k)*sp(i,j)).and.
     >          (pmin.ge.ak(k+1)+bk(k+1)*sp(i,j))) kcl1=k
          enddo
          enddo
        endif
      endif

C     Inform about eventually corrected boundary values

      if (.not.onelev) then
        if (prelevs) then
          write(*,*)pmin,' corrected to --> ',ak(kcl0)
          write(*,*)pmax,' corrected to --> ',ak(kcl1)
        else
          write(*,*)kcl0,' is level index for lower boundary'
          write(*,*)kcl1,' is level index for upper boundary'
        endif
      endif

C     Save eventually corrected boundary values

      if (prelevs.and.(.not.onelev)) then
        pmin=ak(kcl0)
        pmax=ak(kcl1)
      endif

      return

  980 ierr=1
      return
      end
      subroutine getnpoints(plon,plat,varmin,varmax,nx,ny,ak,bk,nz,sp,
     >           levtyp,grid,delh,delp,vcflag,xcorner,ycorner,
     >           pmin,pmax,nxy,nlev,ierr)
C     ================================================================
C
C     Determine approximate number of points within clipped region.
C
C     plon      input   longitude of computational pole
C     plat      input   latitude of computational pole
C     varmin    input   array with minimum phys. coord.  of data region
C     varmax    input   array with maximum phys. coord.  of data region
C     nx        input   number of data points along latitude
C     ny        input   number of data points along longitude
C     ak        input   array contains ak values to calculate data-levels
C     bk        input   array contains bk values to calculate data-levels
C     nz        input   number of levels
C     sp        input   array contains surface pressure
C     levtyp    input   int (=1 pressure =2 theta =3 model levels)
C     delh      input   desired horizontal resol of starting points (deg or km)
C     delp      input   desired vertical resol of starting points (hPa)
C     xcorner   output  corners of clipped region
C     pmin      output  minimum pressure value of clipped region
C     pmax      output  maximum pressure value of clipped region
C     nxy       output  number of points (horizontally) within clipped region
C     nv        output  number of vertical points within clipped region
C     ierr      output  error flag

      real      deltay,pi
      parameter (deltay=111.2)        ! distance in km between 2 lat circles
      parameter (pi=3.1415927)
 
      real      pmin,pmax,varmin(4),varmax(4),delx,dely,delh,delp
      real      xcorner(4),ycorner(4),xmax,ymax,xmin,ymin,x,y
      real      ak(nz),bk(nz)
      real      sp(nx,ny)
      real      dx,dy
      real      plon,plat,xphys,yphys
      integer   kcl0,kcl1,i,j,k,nx,ny,nz,nxy,nlev,vcflag,ierr
      integer   nnx,nny
      integer   levtyp
      logical   grid
 
      real      lmtolms,phtophs
 
C     Reset error flag
 
      ierr=0

C     Initialize nlev

      nlev=0
 
C     Calculate grid increments
 
      dx=(varmax(1)-varmin(1))/(nx-1)
      dy=(varmax(2)-varmin(2))/(ny-1)
 
C     Read vcflag (=1 if pmin/max denote pressure values;
C                  =2 if pmin/max denote layers)
      read(9,*)vcflag
 
C     Read corners of region to clip from tape 9
 
      read(9,10)xcorner(1)
      read(9,10)ycorner(1)
      read(9,10)xcorner(2)
      read(9,10)ycorner(2)
      read(9,10)xcorner(3)
      read(9,10)ycorner(3)
      read(9,10)xcorner(4)
      read(9,10)ycorner(4)
      read(9,10)pmax
      read(9,10)pmin
   10 format(f7.3)

      if ((plon.eq.0.).and.(plat.eq.90.)) then
        if (xcorner(1).eq.-999.) xcorner(1)=varmin(1)
        if (xcorner(2).eq.-999.) xcorner(2)=varmax(1)-dx
        if (xcorner(3).eq.-999.) xcorner(3)=varmax(1)-dx
        if (xcorner(4).eq.-999.) xcorner(4)=varmin(1)
        if (ycorner(1).eq.-999.) ycorner(1)=varmin(2)
        if (ycorner(2).eq.-999.) ycorner(2)=varmin(2)
        if (ycorner(3).eq.-999.) ycorner(3)=varmax(2)-dy
        if (ycorner(4).eq.-999.) ycorner(4)=varmax(2)-dy
      endif
 
C     Special treatment for rotated coordinate systems (transform corners to
C     rotated grid)
 
      if ((plon.ne.0.).or.(abs(plat-90.).gt.1.e-3)) then
        if (.not.grid) goto 975
        do i=1,4
          if ((xcorner(i).eq.-999.).and.(ycorner(i).eq.-999.)) then
            if (i.eq.1) then
              xcorner(i)=varmin(1)
              ycorner(i)=varmin(2)
            else if (i.eq.2) then
              xcorner(i)=varmax(1)-dx
              ycorner(i)=varmin(2)
            else if (i.eq.3) then
              xcorner(i)=varmax(1)-dx
              ycorner(i)=varmax(2)-dy
            else if (i.eq.4) then
              xcorner(i)=varmin(1)
              ycorner(i)=varmax(2)-dy
            endif
          else if ((xcorner(i).eq.-999.).or.(ycorner(i).eq.-999.)) then
            goto 985
          else
            xphys=lmtolms(ycorner(i),xcorner(i),plat,plon)
            yphys=phtophs(ycorner(i),xcorner(i),plat,plon)
            xcorner(i)=xphys
            ycorner(i)=yphys
          endif
        enddo
      endif
 
C     Test if corners are within data domain
 
      do i=1,4
*       if (xcorner(i).lt.varmin(1)) goto 980
*       if (ycorner(i).lt.varmin(2)) goto 980
*       if (xcorner(i).gt.varmax(1)) goto 980
*       if (ycorner(i).gt.varmax(2)) goto 980
        if (xcorner(i)+1.e-4.lt.varmin(1)) then
          print*,'1 ',xcorner(i),varmin(1)
          goto 980
        endif
        if (ycorner(i)+1.e-4.lt.varmin(2)) then
          print*,'2 ',xcorner(i),varmin(2)
          goto 980
        endif
        if (xcorner(i)-1.e-4.gt.varmax(1)) then
          print*,'3 ',xcorner(i),varmax(1)
          goto 980
        endif
        if (ycorner(i)-1.e-4.gt.varmax(2)) then
          print*,'4 ',xcorner(i),varmax(2)
          goto 980
        endif
      enddo

      if (vcflag.eq.1) then
        if (levtyp.eq.2) then
          if (pmax.lt.varmin(3)) goto 980
          if (pmin.gt.varmax(3)) goto 980
        else
          if (pmax.gt.varmin(3)) goto 980
          if (pmin.lt.varmax(3)) goto 980
        endif
      endif
 
C     Control output of clipped region
 
      write(*,*)'corners of the clipped region:'
      write(*,*)'        ',xcorner(1),ycorner(1)
      write(*,*)'        ',xcorner(2),ycorner(2)
      write(*,*)'        ',xcorner(3),ycorner(3)
      write(*,*)'        ',xcorner(4),ycorner(4)
 
C     Set nlev=1 if regions contains only one level
 
      if (pmin.eq.pmax) nlev=1
 
C     Check for single trajectory
 
      if ((xcorner(1).eq.xcorner(2)).and.
     >    (xcorner(2).eq.xcorner(3)).and.
     >    (xcorner(3).eq.xcorner(4)).and.
     >    (ycorner(1).eq.ycorner(2)).and.
     >    (ycorner(2).eq.ycorner(3)).and.
     >    (ycorner(3).eq.ycorner(4))) then
        if (nlev.eq.1) then
          nxy=1
          return
        else
          goto 980
        endif
      endif
 
C     Determine number of grid points within clipped region (horizontally)
 
      xmax=xcorner(1)
      xmin=xcorner(1)
      ymax=ycorner(1)
      ymin=ycorner(1)
      do i=2,4
        if (xcorner(i).lt.xmin) xmin=xcorner(i)
        if (xcorner(i).gt.xmax) xmax=xcorner(i)
        if (ycorner(i).lt.ymin) ymin=ycorner(i)
        if (ycorner(i).gt.ymax) ymax=ycorner(i)
      enddo
 
      nxy=0
 
      if (grid) then
        do i=1,nx
          x=varmin(1)+(i-1)*dx
          do j=1,ny
            y=varmin(2)+(j-1)*dy
            if (x.lt.xmin) goto 970
            if (x.gt.xmax) goto 970
            if (y.lt.ymin) goto 970
            if (y.gt.ymax) goto 970
            if ((x-xcorner(1))*(ycorner(2)-ycorner(1))-
     >          (y-ycorner(1))*(xcorner(2)-xcorner(1)).gt.0.) goto 970
            if ((x-xcorner(2))*(ycorner(3)-ycorner(2))-
     >          (y-ycorner(2))*(xcorner(3)-xcorner(2)).gt.0.) goto 970
            if ((x-xcorner(3))*(ycorner(4)-ycorner(3))-
     >          (y-ycorner(3))*(xcorner(4)-xcorner(3)).gt.0.) goto 970
            if ((x-xcorner(4))*(ycorner(1)-ycorner(4))-
     >          (y-ycorner(4))*(xcorner(1)-xcorner(4)).gt.0.) goto 970
   
            nxy=nxy+1
 970        continue
          enddo
        enddo
      else
        nny=nint((ymax-ymin)*deltay/delh)+1
        dely=(ymax-ymin)/real(nny-1)
        print*,ymax,ymin,delh,nny
        write(*,*)'value of dely set to ',dely,' (in deg)'
        do j=1,nny
          y=ymin+(j-1)*dely
          nnx=nint((xmax-xmin)*cos(y*pi/180.)*deltay/delh)
          if (nnx.gt.0) then
            delx=(xmax-xmin)/real(nnx)
          else
            delx=360.
            nnx=1
          endif
          write(*,*)'val of delx at lat ',y,' set to ',delx,' (in deg)'
          do i=1,nnx
            x=xmin+(i-1)*delx
            if ((x-xcorner(1))*(ycorner(2)-ycorner(1))-
     >          (y-ycorner(1))*(xcorner(2)-xcorner(1)).gt.0.01) goto 971
            if ((x-xcorner(2))*(ycorner(3)-ycorner(2))-
     >          (y-ycorner(2))*(xcorner(3)-xcorner(2)).gt.0.01) goto 971
            if ((x-xcorner(3))*(ycorner(4)-ycorner(3))-
     >          (y-ycorner(3))*(xcorner(4)-xcorner(3)).gt.0.01) goto 971
            if ((x-xcorner(4))*(ycorner(1)-ycorner(4))-
     >          (y-ycorner(4))*(xcorner(1)-xcorner(4)).gt.0.01) goto 971
  
            nxy=nxy+1
 971        continue
          enddo
        enddo
      endif

      write(*,*)'num of pts in the clipped region (horizontally): ',nxy
 
      if (.not.grid) then
        nlev=nint((pmax-pmin)/delp)+1
        write(*,*)'number of levels in the data domain: ',nlev
        return
      endif

C     Calculate vertical indices for whole data domain
 
      if (vcflag.eq.1) then
        if (nlev.ne.1) then
          if (levtyp.eq.1) then               ! data on pressure levels
            do k=1,nz-1
              if ((pmax.le.ak(k)).and.(pmax.ge.ak(k+1))) then
                if (ak(k)-pmax.gt.pmax-ak(k+1)) then
                  kcl0=k+1
                else
                  kcl0=k
                endif
              endif
              if ((pmin.le.ak(k)).and.(pmin.ge.ak(k+1))) then
                if (ak(k)-pmin.gt.pmin-ak(k+1)) then
                  kcl1=k+1
                else
                  kcl1=k
                endif
              endif
            enddo
          else if (levtyp.eq.2) then    ! data on theta levels
            do k=1,nz-1
              if ((pmax.ge.ak(k)).and.(pmax.le.ak(k+1))) then
                if (pmax-ak(k).gt.ak(k+1)-pmax) then
                  kcl0=k+1
                else
                  kcl0=k
                endif
              endif
              if ((pmin.ge.ak(k)).and.(pmin.le.ak(k+1))) then
                if (pmin-ak(k).gt.ak(k+1)-pmin) then
                  kcl1=k+1
                else
                  kcl1=k
                endif
              endif
            enddo
          else                    ! data on model levels
            kcl0=1                        ! initialize kcl0 to lowest level
            kcl1=nz                       ! initialize kcl1 to highest level
            do k=nz-1,1,-1
              do i=1,nx
              do j=1,ny
                if ((pmax.le.ak(k)+bk(k)*sp(i,j)).and.
     >              (pmax.gt.ak(k+1)+bk(k+1)*sp(i,j))) then
                  kcl0=k+1
                  goto 950
                endif
              enddo
              enddo
 950          continue
            enddo
            if (kcl0.eq.2) then
              do i=1,nx
              do j=1,ny
                if (pmax.ge.ak(1)+bk(1)*sp(i,j)) then
                  kcl0=1
                  goto 952
                endif
              enddo
              enddo
            endif
 952        continue
            do k=1,nz-1
              do i=1,nx
              do j=1,ny
                if ((pmin.lt.ak(k)+bk(k)*sp(i,j)).and.
     >              (pmin.ge.ak(k+1)+bk(k+1)*sp(i,j))) then
                  kcl1=k
                  goto 951
                endif
              enddo
              enddo
 951          continue
            enddo
          endif
          nlev=kcl1-kcl0+1
          write(*,*)'number of levels in the data domain: ',nlev
          write(*,*)'from indices',kcl0,' to ',kcl1
        endif
      else if (vcflag.eq.2) then
        kcl0=nint(pmin)
        kcl1=nint(pmax)
        nlev=kcl1-kcl0+1
        write(*,*)'number of levels in the data domain: ',nlev
        write(*,*)'from indices',kcl0,' to ',kcl1
      endif
 
      return
 
  975 ierr=3
      return
  980 ierr=1
      return
  985 ierr=2
      return
      end
      subroutine clipreg(plon,plat,varmin,varmax,nx,ny,ak,bk,nz,sp,
     >           levtyp,grid,delh,delp,vcflag,xcorner,ycorner,
     >           pmin,pmax,xx,yy,pp,ntra,ierr)
C     =============================================================
C
C     Clip a region to calculate trajectories.
C
C     plon      input   longitude of computational pole
C     plat      input   latitude of computational pole
C     varmin    input   array with minimum phys. coord.  of data region
C     varmax    input   array with maximum phys. coord.  of data region
C     nx        input   number of data points along latitude
C     ny        input   number of data points along longitude
C     ak        input   array contains ak values to calculate data-levels
C     bk        input   array contains bk values to calculate data-levels
C     nz        input   number of levels
C     sp        input   array contains surface pressure
C     levtyp    input   int (=1 pressure =2 theta =3 model levels)
C     delh      input   desired horizontal resol of starting points (km)
C     delp      input   desired vertical resol of starting points (hPa)
C     xx        output  starting coordinate of trajectories (longitude)
C     yy        output  starting coordinate of trajectories (latitude)
C     pp        output  starting coordinate of trajectories (pressure)
C     ntra      in/output number of grid points within clipped region
C     ierr      output  error flag
 
      real      deltay,pi
      parameter (deltay=111.2)        ! distance in km between 2 lat circles
      parameter (pi=3.1415927)

      real,allocatable, dimension (:) :: xval,yval,spval

      real      xx(*),yy(*),pp(*)
      real      pmin,pmax,pval,varmin(4),varmax(4),delh,delx,dely,delp
      real      xcorner(4),ycorner(4),xmax,ymax,xmin,ymin,x,y
      real      ak(nz),bk(nz)
      real      sp(nx,ny)
      real      dx,dy
      real      plon,plat,xphys,yphys
      integer   kcl0,kcl1,i,j,k,l,nx,ny,nz,nxy,nlev,ntra,vcflag,ierr
      integer   ii,jj
      integer   levtyp,stat
      logical   grid
 
      real      lmtolms,phtophs,int2d

C     Allocate memory for dynamical arrays

      allocate(xval(ntra),stat=stat)
      if (stat.ne.0) print*,'*** error allocating array xval ***'
      allocate(yval(ntra),stat=stat)
      if (stat.ne.0) print*,'*** error allocating array yval ***'
      allocate(spval(ntra),stat=stat)
      if (stat.ne.0) print*,'*** error allocating array spval ***'
 
C     Reset error flag
 
      ierr=0
 
C     Calculate grid increments
 
      dx=(varmax(1)-varmin(1))/(nx-1)
      dy=(varmax(2)-varmin(2))/(ny-1)

      write(*,*)'corners of the clipped region in SR clipreg:'
      write(*,*)'        ',xcorner(1),ycorner(1)
      write(*,*)'        ',xcorner(2),ycorner(2)
      write(*,*)'        ',xcorner(3),ycorner(3)
      write(*,*)'        ',xcorner(4),ycorner(4)
 
C     Set nlev=1 if regions contains only one level 
 
      if (pmin.eq.pmax) nlev=1
 
C     Check for single trajectory
 
      if ((xcorner(1).eq.xcorner(2)).and.
     >    (xcorner(2).eq.xcorner(3)).and.
     >    (xcorner(3).eq.xcorner(4)).and.
     >    (ycorner(1).eq.ycorner(2)).and.
     >    (ycorner(2).eq.ycorner(3)).and.
     >    (ycorner(3).eq.ycorner(4))) then
        if (nlev.eq.1) then
          ntra=1
          xx(1)=xcorner(1)
          yy(1)=ycorner(1)
          if (vcflag.eq.1) then
            pp(1)=pmin
          else if (vcflag.eq.2) then
            ii=nint((xx(1)-varmin(1))/dx)+1
            jj=nint((yy(1)-varmin(2))/dy)+1
            pp(1)=ak(nint(pmin))+bk(nint(pmin))*sp(ii,jj)
          endif
          return
        else
          goto 980
        endif
      endif
 
C     Determine which grid points are within clipped region (horizontally)
 
      xmax=xcorner(1)
      xmin=xcorner(1)
      ymax=ycorner(1)
      ymin=ycorner(1)
      do i=2,4
        if (xcorner(i).lt.xmin) xmin=xcorner(i)
        if (xcorner(i).gt.xmax) xmax=xcorner(i)
        if (ycorner(i).lt.ymin) ymin=ycorner(i)
        if (ycorner(i).gt.ymax) ymax=ycorner(i)
      enddo

C     Cut the last grid points of the data domain
C     (this prevents problems in subroutine trace: calls to getsdat)

*     if (xmax.gt.varmax(1)-dx) xmax=varmax(1)-dx
*     if (ymax.gt.varmax(2)-dy) ymax=varmax(2)-dy
 
      nxy=0
 
      if (grid) then
        do i=1,nx
          x=varmin(1)+(i-1)*dx
          do j=1,ny
            y=varmin(2)+(j-1)*dy
*           print*,x,y,xmin,xmax,ymin,ymax,
*    >             xcorner(1),ycorner(1),xcorner(2),ycorner(2),
*    >             xcorner(3),ycorner(3),xcorner(4),ycorner(4)
            if (x.lt.xmin) goto 970
            if (x.gt.xmax) goto 970
            if (y.lt.ymin) goto 970
            if (y.gt.ymax) goto 970
            if ((x-xcorner(1))*(ycorner(2)-ycorner(1))-
     >          (y-ycorner(1))*(xcorner(2)-xcorner(1)).gt.0.) goto 970
            if ((x-xcorner(2))*(ycorner(3)-ycorner(2))-
     >          (y-ycorner(2))*(xcorner(3)-xcorner(2)).gt.0.) goto 970
            if ((x-xcorner(3))*(ycorner(4)-ycorner(3))-
     >          (y-ycorner(3))*(xcorner(4)-xcorner(3)).gt.0.) goto 970
            if ((x-xcorner(4))*(ycorner(1)-ycorner(4))-
     >          (y-ycorner(4))*(xcorner(1)-xcorner(4)).gt.0.) goto 970
   
            nxy=nxy+1
*           print*,i,j,nxy
            xval(nxy)=x
            yval(nxy)=y
            spval(nxy)=sp(i,j)
 970        continue
          enddo
        enddo
      else
        nny=nint((ymax-ymin)*deltay/delh)+1
        dely=(ymax-ymin)/real(nny-1)
        print*,ymax,ymin,delh,nny
        write(*,*)'value of dely set to ',dely,' (in deg)'
        do j=1,nny
          y=ymin+(j-1)*dely
          nnx=nint((xmax-xmin)*cos(y*pi/180.)*deltay/delh)
          if (nnx.gt.0) then
            delx=(xmax-xmin)/real(nnx)
          else
            delx=360.
            nnx=1
          endif
          write(*,*)'val of delx at lat ',y,' set to ',delx,' (in deg)'
          do i=1,nnx
            x=xmin+(i-1)*delx
            if ((x-xcorner(1))*(ycorner(2)-ycorner(1))-
     >          (y-ycorner(1))*(xcorner(2)-xcorner(1)).gt.0.01) goto 971
            if ((x-xcorner(2))*(ycorner(3)-ycorner(2))-
     >          (y-ycorner(2))*(xcorner(3)-xcorner(2)).gt.0.01) goto 971
            if ((x-xcorner(3))*(ycorner(4)-ycorner(3))-
     >          (y-ycorner(3))*(xcorner(4)-xcorner(3)).gt.0.01) goto 971
            if ((x-xcorner(4))*(ycorner(1)-ycorner(4))-
     >          (y-ycorner(4))*(xcorner(1)-xcorner(4)).gt.0.01) goto 971
  
            nxy=nxy+1
*           print*,i,j,nxy
            xval(nxy)=x
            yval(nxy)=y
*           write(*,'(i8,2f9.2)')nxy,xval(nxy),yval(nxy)
            ri=(x-varmin(1))/dx+1.
            rj=(y-varmin(2))/dy+1.
            spval(nxy)=int2d(sp,nx,ny,ri,rj)
 971        continue
          enddo
        enddo
      endif
      write(*,*)'num of pts in the clipped region (horizontally): ',nxy

      if (.not.grid) then
        nlev=nint((pmax-pmin)/delp)+1
        delp=(pmax-pmin)/real(nlev-1)
        write(*,*)'number of levels in the data domain: ',nlev
        goto 960
      endif
 
C     Calculate vertical indices for clipped region
 
      if (vcflag.eq.1) then
        if (nlev.ne.1) then
          if (levtyp.eq.1) then               ! data on pressure levels
            do k=1,nz-1
              if ((pmax.le.ak(k)).and.(pmax.ge.ak(k+1))) then
                if (ak(k)-pmax.gt.pmax-ak(k+1)) then
                  kcl0=k+1
                else
                  kcl0=k
                endif
              endif
              if ((pmin.le.ak(k)).and.(pmin.ge.ak(k+1))) then
                if (ak(k)-pmin.gt.pmin-ak(k+1)) then
                  kcl1=k+1
                else
                  kcl1=k
                endif
              endif
            enddo
          else if (levtyp.eq.2) then    ! data on theta levels
            do k=1,nz-1
              if ((pmax.ge.ak(k)).and.(pmax.le.ak(k+1))) then
                if (pmax-ak(k).gt.ak(k+1)-pmax) then
                  kcl0=k+1
                else
                  kcl0=k
                endif
              endif
              if ((pmin.ge.ak(k)).and.(pmin.le.ak(k+1))) then
                if (pmin-ak(k).gt.ak(k+1)-pmin) then
                  kcl1=k+1
                else
                  kcl1=k
                endif
              endif
            enddo
          else                    ! data on model levels
            kcl0=1                        ! initialize kcl0 to lowest level
            kcl1=nz                       ! initialize kcl1 to highest level
            do k=nz-1,1,-1
              do l=1,nxy
                if ((pmax.le.ak(k)+bk(k)*spval(l)).and.
     >              (pmax.gt.ak(k+1)+bk(k+1)*spval(l))) then
                  kcl0=k+1
                  goto 950
                endif
              enddo
 950          continue
            enddo
            if (kcl0.eq.2) then
              do l=1,nxy
                if (pmax.ge.ak(1)+bk(1)*spval(l)) then
                  kcl0=1
                  goto 952
                endif
              enddo
            endif
 952        continue
            do k=1,nz-1
              do l=1,nxy
                if ((pmin.lt.ak(k)+bk(k)*spval(l)).and.
     >              (pmin.ge.ak(k+1)+bk(k+1)*spval(l))) then
                  kcl1=k
                  goto 951
                endif
              enddo
 951          continue
            enddo
          endif
          nlev=kcl1-kcl0+1
          write(*,*)'number of levels in the clipped region: ',nlev
          write(*,*)'from indices ',kcl0,' to ',kcl1
        endif
      else if (vcflag.eq.2) then
        kcl0=nint(pmin)
        kcl1=nint(pmax)
        nlev=kcl1-kcl0+1
        write(*,*)'number of levels in the clipped region: ',nlev
        write(*,*)'from indices ',kcl0,' to ',kcl1
      endif

 960  continue

C     Serach grid points within clipped region

      ntra=0

      do k=1,nlev
      do l=1,nxy
        if (nlev.eq.1) then
          pval=pmin
        else
          if (grid) then
            pval=ak(k+kcl0-1)+bk(k+kcl0-1)*spval(l)
          else
            pval=pmin+(k-1)*delp
          endif
        endif

        if (vcflag.eq.1) then
          if ((levtyp.eq.1).and.(pval.le.spval(l))) then
            ntra=ntra+1
            xx(ntra)=xval(l)
            yy(ntra)=yval(l)
            pp(ntra)=pval
          else if (levtyp.eq.2) then
            ntra=ntra+1
            xx(ntra)=xval(l)
            yy(ntra)=yval(l)
            pp(ntra)=pval
          else if (levtyp.eq.3) then
            if (grid) then
              if ((pval.ge.pmin).and.(pval.le.pmax)) then
                ntra=ntra+1
                xx(ntra)=xval(l)
                yy(ntra)=yval(l)
                pp(ntra)=pval
              endif
            else
              if (pval.le.spval(l)) then
                ntra=ntra+1
                xx(ntra)=xval(l)
                yy(ntra)=yval(l)
                pp(ntra)=pval
              endif
            endif
          endif
        else if (vcflag.eq.2) then
          if ((levtyp.eq.1).and.(pval.le.spval(l))) then
            ntra=ntra+1
            xx(ntra)=xval(l)
            yy(ntra)=yval(l)
            pp(ntra)=pval
          else
            ntra=ntra+1
            xx(ntra)=xval(l)
            yy(ntra)=yval(l)
            pp(ntra)=pval
          endif
        endif
      enddo
      enddo
          
      write(*,*)'number of grid points in clipped region: ',ntra
 
C     Inform about eventually corrected boundary values
 
      if ((levtyp.eq.1).and.(nlev.gt.1)) then
        write(*,*)pmin,' corrected from ',pmin,' to --> ',ak(kcl0)
        write(*,*)pmax,' corrected from ',pmax,' to --> ',ak(kcl1)
        pmin=ak(kcl0)
        pmax=ak(kcl1)
      endif
 
      return
 
  980 ierr=1
      return
      end
      subroutine timediff(date1,date2,diff)
C     =====================================
 
C     New version with hour and minutes! (for hour and step [in hours]
C     use the routine oldtimediff!)
C
C     Calculates the time difference in hours (and minutes) for the two
C     dates specified by the two arrays date1 and date2.
C     They are expected to contain the following date information:
C     year      month   day     hour    minute.
C
C     date1     array specifying the first date
C     date2     array specifying the second date
C     diff      time differenc between date1 and date2 in hours
C
 
      integer   date1(5),date2(5)
      integer   idays(12)       ! array containing the days of the monthes
      real      diff
      integer   ixday,imdiff,ihdiff,iddiff,j
      integer   yy,yy1,yy2
 
      idays(1)=31
      idays(2)=28
      idays(3)=31
      idays(4)=30
      idays(5)=31
      idays(6)=30
      idays(7)=31
      idays(8)=31
      idays(9)=30
      idays(10)=31
      idays(11)=30
      idays(12)=31
 
C     Check format of year (YYYY or YY - in case of YY assume 19YY)

      if (date1(1).lt.100) date1(1)=1900+date1(1)
      if (date2(1).lt.100) date2(1)=1900+date2(1)

C     Determine if the period between date1 and date2 contains a Feb.29
 
      ixday=0   ! extra day flag
 
      yy1=min(date1(1),date2(1))
      yy2=max(date1(1),date2(1))
      if (yy1.eq.yy2) then
        if (mod(yy1,4).eq.0) then
          idays(2)=29
        endif
      else
        if (mod(yy1,4).eq.0) then
          if (((yy1.eq.date1(1)).and.(date1(2).le.2)).or.
     >        ((yy1.eq.date2(1)).and.(date2(2).le.2))) then
            ixday=ixday+1
          endif
        endif
        if (mod(yy2,4).eq.0) then
          if (((yy2.eq.date1(1)).and.(date1(2).gt.2)).or.
     >        ((yy2.eq.date2(1)).and.(date2(2).gt.2))) then
            ixday=ixday+1
          endif
        endif
        if (yy2-yy1.gt.1) then
          do yy=yy1+1,yy2-1
            if (mod(yy,4).eq.0) then
              ixday=ixday+1
            endif
          enddo
        endif
      endif
 
      ihdiff=0  ! diff. in hours between date1/date2
      iddiff=0  ! diff. in days  between date1/date2
 
      if (date1(1).gt.date2(1)) then            ! compare years
        do j=date2(1),date1(1)-1
          iddiff=iddiff+365
        enddo
        iddiff=iddiff+ixday
      else if (date1(1).lt.date2(1)) then
        do j=date1(1),date2(1)-1
          iddiff=iddiff-365
        enddo
        iddiff=iddiff-ixday
      endif
 
      if (date1(2).gt.date2(2)) then            ! compare monthes
        do j=date2(2),date1(2)-1
          iddiff=iddiff+idays(j)
        enddo
      else if (date1(2).lt.date2(2)) then
        do j=date1(2),date2(2)-1
          iddiff=iddiff-idays(j)
        enddo
      endif
 
      iddiff=iddiff+date1(3)-date2(3)
      ihdiff=iddiff*24+date1(4)-date2(4)
      imdiff=ihdiff*60+date1(5)-date2(5)
 
      ihdiff=imdiff/60
      imdiff=mod(imdiff,60)
 
      diff=real(ihdiff)+real(imdiff)/60.
 
      return
      end
      subroutine oldtimediff(date1,date2,diff)
C     ========================================
 
C     Calculates the time difference in hours for the two dates specified
C     by the two arrays date1 and date2. They are expected to contain the
C     following date information:
C     year      month   day     time    step.
C
C     date1     array specifying the first date
C     date2     array specifying the second date
C     diff      time differenc between date1 and date2 in hours
C
C     Warning:  ihdiff is equal to 0 for date1/2 = 880203_12_00 and
C               880202_12_24 !!!
 
      integer   date1(5),date2(5)
      integer   idays(12)       ! array containing the days of the monthes
      real      diff
      integer   ixday,ihdiff,iddiff,j
 
      data idays/31,28,31,30,31,30,31,31,30,31,30,31/
 
C     Determine if the period between date1 and date2 contains a Feb.29
 
      ixday=0   ! extra day flag
 
      if (((mod(date1(1),4).eq.0).and.(date1(1).ne.0)).or.
     >    ((mod(date2(1),4).eq.0).and.(date2(1).ne.0))) then
        if (((date1(2).le.2).and.(date2(2).gt.2)).or.
     >      ((date1(2).gt.2).and.(date2(2).le.2))) then
          ixday=1       ! set extra day flag to 1
          idays(2)=29   ! february has 29 days
        endif
      endif
 
      ihdiff=0  ! diff. in hours between date1/date2
      iddiff=0  ! diff. in days  between date1/date2
 
      if (date1(1).gt.date2(1)) then            ! compare years
        do j=date2(1),date1(1)-1
          iddiff=iddiff+365+ixday
        enddo
      else if (date1(1).lt.date2(1)) then
        do j=date1(1),date2(1)-1
          iddiff=iddiff-365-ixday
        enddo
      endif
 
      if (date1(2).gt.date2(2)) then            ! compare monthes
        do j=date2(2),date1(2)-1
          iddiff=iddiff+idays(j)
        enddo
      else if (date1(2).lt.date2(2)) then
        do j=date1(2),date2(2)-1
          iddiff=iddiff-idays(j)
        enddo
      endif
 
      iddiff=iddiff+date1(3)-date2(3)
      ihdiff=iddiff*24+date1(4)-date2(4)+date1(5)-date2(5)
 
      diff=real(ihdiff)
 
      return
      end
      subroutine newdate(date1,diff,date2)
C     ====================================
C
C     Routine calculates the new date when diff (in hours) is added to
C     date1.
C     date1     int     input   array contains a date in the form
C                               year,month,day,hour,step
C     diff      real    input   timestep in hours to go from date1
C     date2     int     output  array contains new date in the same form

      integer   date1(5),date2(5)
      integer   idays(12)       ! array containing the days of the monthes
      real      diff
      logical   yearchange

      data idays/31,28,31,30,31,30,31,31,30,31,30,31/

      yearchange=.false.

      if ((mod(date1(1),4).eq.0).and.(date1(2).le.2)) idays(2)=29

      date2(1)=date1(1)
      date2(2)=date1(2)
      date2(3)=date1(3)
      date2(4)=date1(4)
      date2(5)=0
      date2(4)=date1(4)+int(diff)+date1(5)

      if (date2(4).ge.24) then
        date2(3)=date2(3)+int(date2(4)/24)
        date2(4)=date2(4)-int(date2(4)/24)*24
      endif
      if (date2(4).lt.0) then
        if (mod(date2(4),24).eq.0) then
          date2(3)=date2(3)-int(abs(date2(4))/24)
          date2(4)=date2(4)+int(abs(date2(4))/24)*24
        else
          date2(3)=date2(3)-(1+int(abs(date2(4))/24))
          date2(4)=date2(4)+(1+int(abs(date2(4))/24))*24
        endif
      endif

  100 if (date2(3).gt.idays(date2(2))) then
        if ((date2(2).eq.2).and.(mod(date2(1),4).eq.0)) idays(2)=29
        date2(3)=date2(3)-idays(date2(2))
        if (idays(2).eq.29) idays(2)=28
        date2(2)=date2(2)+1
        if (date2(2).gt.12) then
*         date2(1)=date2(1)+int(date2(2)/12)
*         date2(2)=date2(2)-int(date2(2)/12)*12
          date2(1)=date2(1)+1
          date2(2)=date2(2)-12
        endif
        if (date2(2).lt.1) then
          date2(1)=date2(1)-(1+int(abs(date2(2)/12)))
          date2(2)=date2(2)+(1+int(abs(date2(2)/12)))*12
        endif
        goto 100
      endif     
  200 if (date2(3).lt.1) then
        date2(2)=date2(2)-1
        if (date2(2).gt.12) then
          date2(1)=date2(1)+int(date2(2)/12)
          date2(2)=date2(2)-int(date2(2)/12)*12
        endif
        if (date2(2).lt.1) then
          date2(1)=date2(1)-(1+int(abs(date2(2)/12)))
          date2(2)=date2(2)+(1+int(abs(date2(2)/12)))*12
        endif
        if ((date2(2).eq.2).and.(mod(date2(1),4).eq.0)) idays(2)=29
        date2(3)=date2(3)+idays(date2(2))
        if (idays(2).eq.29) idays(2)=28
        goto 200
      endif

      if (date2(2).gt.12) then
        date2(1)=date2(1)+int(date2(2)/12)
        date2(2)=date2(2)-int(date2(2)/12)*12
      endif
      if (date2(2).lt.1) then
        date2(1)=date2(1)-(1+int(abs(date2(2)/12)))
        date2(2)=date2(2)+(1+int(abs(date2(2)/12)))*12
      endif

      if (date2(1).lt.1000) then
      if (date2(1).ge.100) date2(1)=date2(1)-100
      endif

      return
      end
      subroutine indipo(lonw,lone,lats,latn,dx,dy,nx,ny,nz,ak,bk,
     >           sp0,sp1,reltpos,levtyp,xpo,ypo,ppo,xind,yind,pind)
C     =============================================================
C
C     Calculates the position in the grid space from the physical
C     position.
C
      integer   nx,ny,nz,i
      real      dx,dy
      real      ak(nz),bk(nz)
      real      sp0(nx,ny),sp1(nx,ny),spval0,spval1,spval
      real      lonw,lone,lats,latn
      real      xpo,ypo,ppo,reltpos
      real      xind,yind,pind
      integer   levtyp
      real      int2d

C     levtyp=1 pressure levels
C     levtyp=2 theta levels
C     levtyp=3 model levels

C     Calculate the grid location to be interpolated to

      xind=(xpo-lonw)/dx+1.
      yind=(ypo-lats)/dy+1.

      if (nz.eq.1) then
        pind=1.
        return
      endif

      if (levtyp.eq.1) then
        do i=1,nz-1
          if ((ak(i).ge.ppo).and.(ak(i+1).le.ppo)) then
            pind=real(i)+(ak(i)-ppo)/(ak(i)-ak(i+1))
            return
          endif
        enddo
      else if (levtyp.eq.2) then
        do i=1,nz-1
          if ((ak(i).le.ppo).and.(ak(i+1).ge.ppo)) then
            pind=real(i)+(ak(i)-ppo)/(ak(i)-ak(i+1))
            return
          endif
        enddo
      else
        if (ppo.eq.1050.) then
          pind=1.
          return
        else
          if (reltpos.eq.0.) then
            spval=int2d(sp0,nx,ny,xind,yind)
          else if (reltpos.eq.1.) then
            spval=int2d(sp1,nx,ny,xind,yind)
          else
            spval0=int2d(sp0,nx,ny,xind,yind)
            spval1=int2d(sp1,nx,ny,xind,yind)
            spval=(1.-reltpos)*spval0+reltpos*spval1
          endif
          do i=1,nz-1
            if ((ak(i)+bk(i)*spval.ge.ppo).and.
     >          (ak(i+1)+bk(i+1)*spval.le.ppo)) then
              pind=real(i)+(ak(i)+bk(i)*spval-ppo)/
     >             (ak(i)+bk(i)*spval-ak(i+1)-bk(i+1)*spval)
              return
            endif
          enddo
        endif
      endif
      if (levtyp.lt.3) then
        write(*,*)'error in indipo: ppo ',ppo,' is outside the levels'
      else
        if (ppo.gt.(ak(1)+bk(1)*spval)) then
*         pind=1.
          pind=(spval-ppo)/(spval-(ak(1)+bk(1)*spval))
          return
        else
          write(*,*)'pos ',xpo,ypo,ppo,' sp ',ak(1)+bk(1)*spval
          write(*,*)'error in indipo: ppo is outside the levels'
        endif
      endif

      return
      end
      subroutine nindipo(lonw0,lats0,lonw1,lats1,dx,dy,nx0,ny0,
     >           nx1,ny1,nz,ak,bk,sp0,sp1,reltpos,prelevs,
     >           xpo,ypo,ppo,xind0,yind0,xind1,yind1,pind)
C     ==============================================================
C
C     Calculates the position in the grid space from the physical
C     position.
C
      integer   nx0,ny0,nx1,ny1,nz,i
      real      dx,dy
      real      ak(nz),bk(nz)
      real      sp0(nx0,ny0),sp1(nx1,ny1),spval0,spval1,spval
      real      lonw0,lats0,lonw1,lats1
      real      xpo,ypo,ppo,reltpos
      real      xind0,yind0,xind1,yind1,pind
      logical   prelevs
      real      int3d
 
C     Calculate the grid location to be interpolated to
 
      xind0=(xpo-lonw0)/dx+1.
      yind0=(ypo-lats0)/dy+1.
      xind1=(xpo-lonw1)/dx+1.
      yind1=(ypo-lats1)/dy+1.
 
      if (prelevs) then
        do i=1,nz-1
          if ((ak(i).ge.ppo).and.(ak(i+1).le.ppo)) then
            pind=real(i)+(ak(i)-ppo)/(ak(i)-ak(i+1))
            return
          endif
        enddo
      else
        if (ppo.eq.1050.) then
          pind=1.
          return
        else
          if (reltpos.eq.0.) then
            spval=int3d(sp0,nx0,ny0,nz,xind0,yind0,1.)
          else if (reltpos.eq.1.) then
            spval=int3d(sp1,nx1,ny1,nz,xind1,yind1,1.)
          else
            spval0=int3d(sp0,nx0,ny0,nz,xind0,yind0,1.)
            spval1=int3d(sp1,nx1,ny1,nz,xind1,yind1,1.)
            spval=(1.-reltpos)*spval0+reltpos*spval1
          endif
          do i=1,nz-1
            if ((ak(i)+bk(i)*spval.ge.ppo).and.
     >          (ak(i+1)+bk(i+1)*spval.le.ppo)) then
              pind=real(i)+(ak(i)+bk(i)*spval-ppo)/
     >             (ak(i)+bk(i)*spval-ak(i+1)-bk(i+1)*spval)
              return
            endif
          enddo
        endif
      endif
      if (prelevs) then
        write(*,*)'error in indipo: ppo is outside the levels'
      else
        if (ppo.gt.(ak(1)+bk(1)*spval)) then
          pind=1.
          return
        else
          write(*,*)'pos ',xpo,ypo,ppo,' sp ',ak(1)+bk(1)*spval
          write(*,*)'error in indipo: ppo is outside the levels'
        endif
      endif
 
      return
      end
      subroutine indipo_mc2(lonw,lone,lats,latn,dx,dy,nx,ny,nz,
     >           bklev,bklay,bkt,zb,
     >           xpo,ypo,ppo,xind,yind,pindlev,pindlay)
C     =========================================================
C
C     Calculates the position in the grid space from the physical
C     position.
C
      implicit none

      integer   nx,ny,nz,i
      real      dx,dy
      real      bklev(nz),bklay(nz),bkt
      real      zb(nx,ny),spval0,spval1,spval,zbval
      real      lonw,lone,lats,latn
      real      xpo,ypo,ppo
      real      xind,yind,pindlev,pindlay
      real      int3d

C     Calculate the grid location to be interpolated to

      xind=(xpo-lonw)/dx+1.
      yind=(ypo-lats)/dy+1.

      if (ppo.eq.0.) then
        pindlev=1.                  
        pindlay=1.
        return
      endif
      zbval=int3d(zb,nx,ny,nz,xind,yind,1.)
      do i=1,nz-1
        if ((bklev(i)+(1.-bklev(i)/bkt)*zbval.le.ppo).and.
     >       bklev(i+1)+(1.-bklev(i+1)/bkt)*zbval.gt.ppo) then
          pindlev=real(i)+(ppo-bklev(i)-(1.-bklev(i)/bkt)*zbval)/
     >       ((1.-zbval/bkt)*(bklev(i+1)-bklev(i)))
          goto 40
        endif
      enddo
      if (ppo.lt.zbval) then
        write(*,*)'error in indipo_mc2: ppo is below the ground'
        call exit(1)
      else if (ppo.lt.bklev(1)+(1.-bklev(1)/bkt)*zbval) then
        pindlev=(ppo-zbval)/(bklev(1)-bklev(1)/bkt*zbval)
        return
      else
        write(*,*)'pos ',xpo,ypo,ppo,bklev(1)+(1.-bklev(1)/bkt)*zbval
        write(*,*)'error in indipo_mc2: ppo is outside the levels'
        call exit(1)
      endif
   40 do i=1,nz-1
        if ((bklay(i)+(1.-bklay(i)/bkt)*zbval.le.ppo).and.
     >       bklay(i+1)+(1.-bklay(i+1)/bkt)*zbval.gt.ppo) then
          pindlay=real(i)+(ppo-bklay(i)-(1.-bklay(i)/bkt)*zbval)/
     >       ((1.-zbval/bkt)*(bklay(i+1)-bklay(i)))
          return
        endif
      enddo
      if (ppo.lt.zbval) then
        write(*,*)'error in indipo_mc2: ppo is below the ground'
        call exit(1)
      else if (ppo.lt.bklay(1)+(1.-bklay(1)/bkt)*zbval) then
        pindlay=(ppo-zbval)/(bklay(1)-bklay(1)/bkt*zbval)
        return
      else
        write(*,*)'pos ',xpo,ypo,ppo,bklay(1)+(1.-bklay(1)/bkt)*zbval
        write(*,*)'error in indipo_mc2: ppo is outside the layers'
        call exit(1)
      endif

      end
      subroutine ipo(nx,ny,nz,field0,field1,reltpos,
     >               xind,yind,pind,mdv,ipomode,value)
C     ================================================
C
C     Decides what kind of interpolation should be done.
C
      integer   nx,ny,nz
      real      field0(nx,ny,nz)
      real      field1(nx,ny,nz)
      real      reltpos
      real      xind,yind,pind
      real      value,mdv
      integer   ipomode

      if (ipomode.eq.1) then
        call linipo(nx,ny,nz,field0,field1,reltpos,
     >              xind,yind,pind,mdv,value)
      else if (ipomode.eq.2) then
        call bicipo(nx,ny,nz,field0,field1,reltpos,
     >              xind,yind,pind,value)
      else if (ipomode.eq.3) then
        call vcuipo(nx,ny,nz,field0,field1,reltpos,
     >              xind,yind,pind,mdv,value)
      else if (ipomode.eq.11) then
        call linipolog(nx,ny,nz,field0,field1,reltpos,
     >                 xind,yind,pind,mdv,value)
      else
        write(*,*)'*** error in SR ipo: unknown ipomode'
        stop
      endif

      return
      end
      subroutine nipo(nx0,ny0,nx1,ny1,nz,field0,field1,reltpos,
     >           xind0,yind0,xind1,yind1,pind,mdv,ipomode,value)
C     ==========================================================
C
C     Decides what kind of interpolation should be done.
C
      integer   nx0,ny0,nx1,ny1,nz
      real      field0(nx0,ny0,nz)
      real      field1(nx1,ny1,nz)
      real      reltpos
      real      xind0,yind0,xind1,yind1,pind
      real      value,mdv
      integer   ipomode
 
      if (ipomode.eq.1) then
        call nlinipo(nx0,ny0,nx1,ny1,nz,field0,field1,reltpos,
     >               xind0,yind0,xind1,yind1,pind,mdv,value)
      else
        write(*,*)'*** error in SR ipo: unknown ipomode'
        stop
      endif
 
      return
      end
      subroutine linipo(nx,ny,nz,field0,field1,reltpos,
     >                  xind,yind,pind,mdv,value)
C     =================================================
C
C     Does linear interpolation both in time and space.
C
      integer   nx,ny,nz
      real      field0(nx,ny,nz)
      real      field1(nx,ny,nz)
      real      reltpos
      real      xind,yind,pind
      real      value,val0,val1,mdv
      real      int3dm,int2dm

      if (reltpos.eq.0.) then
        if (nz.eq.1) then
          value=int2dm(field0,nx,ny,xind,yind,mdv)
        else
          value=int3dm(field0,nx,ny,nz,xind,yind,pind,mdv)
        endif
      else if (reltpos.eq.1.) then
        if (nz.eq.1) then
          value=int2dm(field1,nx,ny,xind,yind,mdv)
        else
          value=int3dm(field1,nx,ny,nz,xind,yind,pind,mdv)
        endif
      else
        if (nz.eq.1) then
          val0=int2dm(field0,nx,ny,xind,yind,mdv)
          val1=int2dm(field1,nx,ny,xind,yind,mdv)
        else
          val0=int3dm(field0,nx,ny,nz,xind,yind,pind,mdv)
          val1=int3dm(field1,nx,ny,nz,xind,yind,pind,mdv)
        endif
        if ((val0.eq.mdv).or.(val1.eq.mdv)) then
          value=mdv
        else
          value=(1.-reltpos)*val0+reltpos*val1
        endif
      endif
      
      return
      end
      subroutine linipolog(nx,ny,nz,field0,field1,reltpos,
     >                     xind,yind,pind,mdv,value)
C     ====================================================
C
C     Does linear interpolation both in time and space.
C
      integer   nx,ny,nz
      real      field0(nx,ny,nz)
      real      field1(nx,ny,nz)
      real      reltpos
      real      xind,yind,pind
      real      value,val0,val1,mdv
      real      int3dmlog

      if (reltpos.eq.0.) then
        value=int3dmlog(field0,nx,ny,nz,xind,yind,pind,mdv)
      else if (reltpos.eq.1.) then
        value=int3dmlog(field1,nx,ny,nz,xind,yind,pind,mdv)
      else
        val0=int3dmlog(field0,nx,ny,nz,xind,yind,pind,mdv)
        val1=int3dmlog(field1,nx,ny,nz,xind,yind,pind,mdv)
        if ((val0.eq.mdv).or.(val1.eq.mdv)) then
          value=mdv
        else
          value=(1.-reltpos)*val0+reltpos*val1
        endif
      endif

      return
      end
      subroutine nlinipo(nx0,ny0,nx1,ny1,nz,field0,field1,reltpos,
     >                  xind0,yind0,xind1,yind1,pind,mdv,value)
C     ============================================================
C
C     Does linear interpolation both in time and space.
C
      integer   nx0,ny0,nx1,ny1,nz
      real      field0(nx0,ny0,nz)
      real      field1(nx1,ny1,nz)
      real      reltpos
      real      xind0,yind0,xind1,yind1,pind
      real      value,val0,val1,mdv
      real      int3dm
 
      if (reltpos.eq.0.) then
        value=int3dm(field0,nx0,ny0,nz,xind0,yind0,pind,mdv)
      else if (reltpos.eq.1.) then
        value=int3dm(field1,nx1,ny1,nz,xind1,yind1,pind,mdv)
      else
        val0=int3dm(field0,nx0,ny0,nz,xind0,yind0,pind,mdv)
        val1=int3dm(field1,nx1,ny1,nz,xind1,yind1,pind,mdv)
        value=(1.-reltpos)*val0+reltpos*val1
      endif
 
      return
      end
      subroutine vcuipo(nx,ny,nz,field0,field1,reltpos,
     >                  xind,yind,pind,mdv,value)
C     =================================================
C
C     Does linear interpolation both in time and space, except for a cubic
C     interpolation in the vertical.
C
      integer   nx,ny,nz
      real      field0(nx,ny,nz)
      real      field1(nx,ny,nz)
      real      reltpos
      real      xind,yind,pind
      real      value,val0,val1,mdv
      real      int3dmvc
 
      if (reltpos.eq.0.) then
        value=int3dmvc(field0,nx,ny,nz,xind,yind,pind,mdv)
      else if (reltpos.eq.1.) then
        value=int3dmvc(field1,nx,ny,nz,xind,yind,pind,mdv)
      else
        val0=int3dmvc(field0,nx,ny,nz,xind,yind,pind,mdv)
        val1=int3dmvc(field1,nx,ny,nz,xind,yind,pind,mdv)
        value=(1.-reltpos)*val0+reltpos*val1
      endif
 
      return
      end
      subroutine linipom(nx,ny,nz,field0,field1,reltpos,
     >                  mdv,xind,yind,pind,value)
C     =================================================
C
C     Does linear interpolation both in time and space.
C
      integer   nx,ny,nz
      real      field0(nx,ny,nz)
      real      field1(nx,ny,nz)
      real      reltpos,mdv
      real      xind,yind,pind
      real      value,val0,val1
      real      int3dm

      if (reltpos.eq.0.) then
        value=int3dm(field0,nx,ny,nz,xind,yind,pind,mdv)
      else if (reltpos.eq.1.) then
        value=int3dm(field1,nx,ny,nz,xind,yind,pind,mdv)
      else
        val0=int3dm(field0,nx,ny,nz,xind,yind,pind,mdv)
        val1=int3dm(field1,nx,ny,nz,xind,yind,pind,mdv)
        value=(1.-reltpos)*val0+reltpos*val1
      endif

      return
      end
      subroutine bicipo(nx,ny,nz,fld0,fld1,reltpos,
     >                  xind,yind,pind,value)
C     ===================================================
C
C     Does linear interpolation in time and bicubic interpolation
C     in space (horizontally)
C
      integer   nx,ny,nz
      real      fld0(nx,ny,nz),fld1(nx,ny,nz)
      real      reltpos,value
      real      xind,yind,pind

C     Declarations of local variables

      integer   k1,k2
      real      frac1k,frac2k
      real      val0,val1,val10,val20,val11,val21
      real      cint2d

      k1=int(pind)
      k2=k1+1

      frac1k=pind-aint(pind)
      frac2k=1.-frac1k

C     Interpolate value on lower level for first time

      if ((reltpos.ne.1.).and.(frac2k.ne.0.)) then
        val10=cint2d(fld0,nx,ny,nz,xind,yind,k1)
      endif

C     Interpolate value on upper level for first time

      if ((reltpos.ne.1.).and.(frac1k.ne.0.)) then
        val20=cint2d(fld0,nx,ny,nz,xind,yind,k2)
      endif

C     Interpolate value on lower level for second time

      if ((reltpos.ne.0.).and.(frac2k.ne.0.)) then
        val11=cint2d(fld1,nx,ny,nz,xind,yind,k1)
      endif

C     Interpolate value on upper level for second time

      if ((reltpos.ne.0.).and.(frac1k.ne.0.)) then
        val21=cint2d(fld1,nx,ny,nz,xind,yind,k2)
      endif

C     Do vertical interpolation and interpolation in time

      if (reltpos.eq.0.) then
        value=frac2k*val10+frac1k*val20
      else if (reltpos.eq.1.) then
        value=frac2k*val11+frac1k*val21
      else
        val0=frac2k*val10+frac1k*val20
        val1=frac2k*val11+frac1k*val21
        value=(1.-reltpos)*val0+reltpos*val1
      endif

      return
      end