program adjustps    
!
!ifort -I${NEMSIO_INC} adjustps.f90 ${NEMSIO_LIB} ${W3NCO_LIB4} ${BACIO_LIB4}
!
!$$$  main program documentation block
!
! program:  adjustps
!
! prgmmr: whitaker         org: esrl/psd               date: 2017-11-02
!
! abstract:  change orography in file 1 to match file 2, adjust ps
!            to new orography, interpolate 3d fields to new pressures, 
!            write out updated file.
!
! program history log:
!   2017-11-02  Initial version.
!
! usage: adjustps.x <file_1> <file_2> <fileout> <nlevt>
! nlevt is optional - sets level index for Benjamin and Miller temperature
! that is used in pressure adjustment.
!
! attributes:
!   language: f95
!
!$$$

  use nemsio_module, only:  nemsio_init,nemsio_open,nemsio_close,nemsio_charkind
  use nemsio_module, only:  nemsio_gfile,nemsio_getfilehead,nemsio_readrec,&
       nemsio_writerec,nemsio_readrecv,nemsio_writerecv,nemsio_getrechead

  implicit none

  real,parameter:: zero=0.0_4, one=1.0_4

  character*500 filename_1,filename_2,filename_o
  character*3 charnlev
  integer iret,latb,lonb,nlevs,npts,k,n,nlevt,idsl
  integer nrec,nrec2,latb2,lonb2,nlevs2,npts2
  integer krecdp,ndpres,krect,krecq,krecu,krecv,ntrac,kq,kt,krecoz,kreccwmr,krecicmr
  real,allocatable,dimension(:,:,:) :: vcoord
  real,allocatable,dimension(:,:) ::&
  rwork_1,rwork_2,pressi,pressl,pressi_new,pressl_new
  real,allocatable,dimension(:) :: delz,delps,ak,bk,t0
  character(len=nemsio_charkind),allocatable,dimension(:) :: recnam
  character(len=nemsio_charkind) field
  real tpress,tv,kap1,kapr,rd,cp,grav,rlapse,alpha,ps,preduced,zob,zmodel,rv,fv
  type(nemsio_gfile) :: gfile_1,gfile_2,gfile_o
  logical ldpres 

! constants.
  grav = 9.8066
  rlapse = 0.0065
  rd = 287.05
  rv = 461.5
  fv = rv/(rd-one)
  cp = 1004.
  kap1 = (rd/cp)+1.0
  kapr = (cp/rd)
  alpha = rd*rlapse/grav

  call w3tagb('ADJUSTPS',2011,0319,0055,'NP25')

! read data from this file
  call getarg(1,filename_1)

! subtract this mean
  call getarg(2,filename_2)

! then add to this mean
  call getarg(3,filename_o)

! model level to use for Benjamin and Miller pressure adjustment
  if (iargc() > 3) then
    call getarg(4,charnlev)
    read(charnlev,'(i3)') nlevt
  else
    nlevt = 1 ! default value
  endif

  write(6,*)'ADJUSTPS:'
  write(6,*)'filename_1=',trim(filename_1)
  write(6,*)'filename_2=',trim(filename_2)
  write(6,*)'filename_o=',trim(filename_o)
  write(6,*)'nlevt=',nlevt

  call nemsio_open(gfile_1,trim(filename_1),'READ',iret=iret)
  if (iret == 0 ) then
      write(6,*)'Read nemsio ',trim(filename_1),' iret=',iret
      call nemsio_getfilehead(gfile_1, nrec=nrec, dimx=lonb, dimy=latb, dimz=nlevs, idsl=idsl,iret=iret)
      write(6,*)' lonb=',lonb,' latb=',latb,' levs=',nlevs,' nrec=',nrec
  else
      write(6,*)'***ERROR*** ',trim(filename_1),' contains unrecognized format.  ABORT'
  endif
  ! is dpres in the file?
  allocate(recnam(nrec))
  call nemsio_getfilehead(gfile_1,recname=recnam,iret=iret)
  ldpres = .false.
  ndpres = 0
  field = 'dpres'
  do n=1,nrec
     !print *,n,trim(field),' ',trim(recnam(n))
     if (trim(field) == trim(recnam(n))) then
        ldpres = .true.
        ndpres = 1
        exit
     endif
  enddo
  print *,'ldpres = ',ldpres

  call nemsio_open(gfile_2,trim(filename_2),'READ',iret=iret)
  if (iret /= 0) then
     print *,'Error opening ',trim(filename_2)
     stop
  endif
  call nemsio_getfilehead(gfile_2, nrec=nrec2, dimx=lonb2, dimy=latb2, dimz=nlevs2, iret=iret)

  npts=lonb*latb
  npts2=lonb2*latb2
  ! assumes ps,zs are first two records, then u,v,t,optionally dpres,q,oz,cwmr and optionally icmr
  if (nrec > 2 + (7+ndpres)*nlevs) then
     print *,'cannot handle nrec > ',2 + 7*nlevs
     stop
  endif
  ! q, oz, then microphys tracers are last (after u,v,T,dpres)
  krecq    = 2 + (3+ndpres)*nlevs + 1
  ntrac = (nrec-(krecq-1))/nlevs
  print *,'ntrac,nrec,idsl',ntrac,nrec,idsl
  if (npts .ne. npts2 .or. nlevs .ne. nlevs2) then
     print *,'grid size in file not what is expected, aborting..'
     stop
  endif
  allocate(rwork_1(npts,nrec))
  allocate(rwork_2(npts,nrec))
  allocate(delz(npts))
  allocate(delps(npts))
  allocate(t0(npts))
  allocate(pressi(npts,nlevs+1))
  allocate(pressi_new(npts,nlevs+1))
  allocate(pressl(npts,nlevs))
  allocate(pressl_new(npts,nlevs))
  allocate(ak(nlevs+1))
  allocate(bk(nlevs+1))
  rwork_1 = zero; rwork_2 = zero
  allocate(vcoord(nlevs+1,3,2))
  call nemsio_getfilehead(gfile_1,vcoord=vcoord,iret=iret)
  if (iret /= 0) then
     print *,'Error reading vcoord from ',trim(filename_1)
     stop
  endif
  ak = vcoord(:,1,1); bk = vcoord(:,2,1)
  deallocate(vcoord)

  ! read ps,zs from filename_2
  call nemsio_readrecv(gfile_2,'pres','sfc',1,rwork_2(:,1),iret=iret)
  if (iret /= 0) then
     print *,'Error reading ps from ',trim(filename_2)
     stop
  endif
  call nemsio_readrecv(gfile_2,'hgt','sfc',1,rwork_2(:,2),iret=iret)
  if (iret /= 0) then
     print *,'Error reading zs from ',trim(filename_1)
     stop
  endif
  ! read all fields from filename_1
  call nemsio_readrecv(gfile_1,'pres','sfc',1,rwork_1(:,1),iret=iret)
  if (iret /= 0) then
     print *,'Error reading ps from ',trim(filename_1)
     stop
  endif
  call nemsio_readrecv(gfile_1,'hgt','sfc',1,rwork_1(:,2),iret=iret)
  if (iret /= 0) then
     print *,'Error reading zs from ',trim(filename_1)
     stop
  endif
  print *,minval(rwork_1(:,1)),maxval(rwork_1(:,1))
  print *,minval(rwork_2(:,1)),maxval(rwork_2(:,1))
  print *,minval(rwork_1(:,2)),maxval(rwork_1(:,2))
  print *,minval(rwork_2(:,2)),maxval(rwork_2(:,2))
  do k = 1,nlevs
      krecu    = 2 + 0*nlevs + k
      krecv    = 2 + 1*nlevs + k
      krect    = 2 + 2*nlevs + k
      krecdp   = 2 + 3*nlevs + k
      krecq    = 2 + (3+ndpres)*nlevs + k
      krecoz   = 2 + (4+ndpres)*nlevs + k
      kreccwmr = 2 + (5+ndpres)*nlevs + k
      if (nrec > 2 + (6+ndpres)*nlevs) then
         krecicmr = 2 + (6+ndpres)*nlevs + k
      endif
      call nemsio_readrecv(gfile_1,'ugrd', 'mid layer',k,rwork_1(:,krecu),   iret=iret)
      if (iret /= 0) then
         print *,'Error reading u from ',trim(filename_1),k
         stop
      endif
      call nemsio_readrecv(gfile_1,'vgrd', 'mid layer',k,rwork_1(:,krecv),   iret=iret)
      if (iret /= 0) then
         print *,'Error reading v from ',trim(filename_1),k
         stop
      endif
      call nemsio_readrecv(gfile_1,'tmp',  'mid layer',k,rwork_1(:,krect),   iret=iret)
      if (iret /= 0) then
         print *,'Error reading t from ',trim(filename_1),k
         stop
      endif
      if (ldpres) then
         call nemsio_readrecv(gfile_1,'dpres',  'mid layer',k,rwork_1(:,krecdp),   iret=iret)
         if (iret /= 0) then
            print *,'Error reading dpres from ',trim(filename_1),k
            stop
         endif
         !print *,k,minval(rwork_1(:,krecdp)),maxval(rwork_1(:,krecdp))
      endif
      call nemsio_readrecv(gfile_1,'spfh', 'mid layer',k,rwork_1(:,krecq),   iret=iret)
      if (iret /= 0) then
         print *,'Error reading q from ',trim(filename_1),k
         stop
      endif
      call nemsio_readrecv(gfile_1,'o3mr', 'mid layer',k,rwork_1(:,krecoz),  iret=iret)
      if (iret /= 0) then
         print *,'Error reading o3 from ',trim(filename_1),k
         stop
      endif
      call nemsio_readrecv(gfile_1,'clwmr','mid layer',k,rwork_1(:,kreccwmr),iret=iret)
      if (iret /= 0) then
         print *,'Error reading cwmr from ',trim(filename_1),k
         stop
      endif
      if (nrec > 2 + 6*nlevs) then
      call nemsio_readrecv(gfile_1,'icmr','mid layer',k,rwork_1(:,krecicmr),iret=iret)
      if (iret /= 0) then
         print *,'Error reading icmr from ',trim(filename_1),k
         stop
      endif
      endif
  enddo

  delz = rwork_1(:,2) - rwork_2(:,2)
  delps = rwork_1(:,1) - rwork_2(:,1)
  print *,'min/max delz = ',minval(delz),maxval(delz)
  print *,'min/max delps = ',minval(delps),maxval(delps)
  if (iret /= 0) then
     print *,'Error closing ',trim(filename_1)
     stop
  endif

  !==> pressure at layers and interfaces.
  do k=1,nlevs+1
     pressi(:,k)=ak(k)+bk(k)*rwork_1(:,1) 
  enddo
  if (idsl == 2) then
! IDSL: TYPE OF SIGMA STRUCTURE (1 FOR PHILLIPS OR 2 FOR MEAN)
     do k=1,nlevs
        pressl(:,k)=0.5*(pressi(:,k)+pressi(:,k+1))
     end do
  else
     do k=1,nlevs
        ! "phillips" vertical interpolation
        pressl(:,k)=((pressi(:,k)**kap1-pressi(:,k+1)**kap1)/&
                     (kap1*(pressi(:,k)-pressi(:,k+1))))**kapr
     end do
  endif

  ! adjust surface pressure.
  ! update first two fields in output (rwork_2)
  do n=1,npts
! compute MAPS pressure reduction from model to station elevation
! See Benjamin and Miller (1990, MWR, p. 2100)
! uses 'effective' surface temperature extrapolated
! from virtual temp (tv) at pressure tpress
! using standard atmosphere lapse rate.
! ps - surface pressure to reduce.
! t - virtual temp. at pressure tpress.
! zmodel - model orographic height.
! zob - station height
     kt    = 2 + 2*nlevs + nlevt
     kq    = 2 + (3+ndpres)*nlevs + nlevt
     tv = (1.+fv*rwork_1(n,kq))*rwork_1(n,kt)
     tpress = pressl(n,nlevt); ps = rwork_1(n,1)
     zmodel = rwork_2(n,2); zob = rwork_1(n,2)
     t0(n) = tv*(ps/tpress)**alpha ! eqn 4 from B&M
     preduced = ps*((t0(n) + rlapse*(zob-zmodel))/t0(n))**(1./alpha) ! eqn 1 from B&M
     delps(n) = ps-preduced 
     rwork_1(n,1) = rwork_2(n,1) ! save old ps 
     rwork_2(n,1) = preduced     ! new surface pressure adjusted to new orography
  enddo
  print *,'min/max effective surface t',minval(t0),maxval(t0)
  print *,'min/max ps adjustment',minval(delps),maxval(delps)
  delps = rwork_1(:,1) - rwork_2(:,1)
  print *,'min/max delps after adjustment = ',minval(delps),maxval(delps)
  !==> new pressure at layers and interfaces.
  do k=1,nlevs+1
     pressi_new(:,k)=ak(k)+bk(k)*rwork_2(:,1)  ! updated ps
  enddo
  if (idsl == 2) then
     do k=1,nlevs
        pressl_new(:,k)=0.5*(pressi_new(:,k)+pressi_new(:,k+1))
     end do
  else
     do k=1,nlevs
        pressl_new(:,k)=((pressi_new(:,k)**kap1-pressi_new(:,k+1)**kap1)/&
                        (kap1*(pressi_new(:,k)-pressi_new(:,k+1))))**kapr
     end do
  endif
  gfile_o=gfile_1
  call nemsio_open(gfile_o,trim(filename_o),'WRITE',iret=iret)
  if (iret /= 0) then
     print *,'Error opening ',trim(filename_o)
     stop
  endif
! interpolate fields to new pressures (update rest of rwork_2).
  krecu    = 2 + 0*nlevs + 1
  krecv    = 2 + 1*nlevs + 1
  krect    = 2 + 2*nlevs + 1
  krecq    = 2 + (3+ndpres)*nlevs + 1
  print *,'min/max pressi diff',minval(pressi-pressi_new),maxval(pressi-pressi_new)
  print *,'min/max pressl diff',minval(pressl-pressl_new),maxval(pressl-pressl_new)
  call vintg(npts,npts,nlevs,nlevs,ntrac,pressl,&
             rwork_1(:,krecu:krecu+nlevs-1),rwork_1(:,krecv:krecv+nlevs-1),&
             rwork_1(:,krect:krect+nlevs-1),rwork_1(:,krecq:nrec),&
             pressl_new,&
             rwork_2(:,krecu:krecu+nlevs-1),rwork_2(:,krecv:krecv+nlevs-1),&
             rwork_2(:,krect:krect+nlevs-1),rwork_2(:,krecq:nrec))
  print *,'min/max u diff',minval(rwork_1(:,krecu:krecu+nlevs-1)-rwork_2(:,krecu:krecu+nlevs-1)),&
                           maxval(rwork_1(:,krecu:krecu+nlevs-1)-rwork_2(:,krecu:krecu+nlevs-1))
  print *,'min/max v diff',minval(rwork_1(:,krecv:krecv+nlevs-1)-rwork_2(:,krecv:krecv+nlevs-1)),&
                           maxval(rwork_1(:,krecv:krecv+nlevs-1)-rwork_2(:,krecv:krecv+nlevs-1))
  print *,'min/max t diff',minval(rwork_1(:,krect:krect+nlevs-1)-rwork_2(:,krect:krect+nlevs-1)),&
                           maxval(rwork_1(:,krect:krect+nlevs-1)-rwork_2(:,krect:krect+nlevs-1))
  print *,'min/max q diff',minval(rwork_1(:,krecq:krecq+nlevs-1)-rwork_2(:,krecq:krecq+nlevs-1)),&
                           maxval(rwork_1(:,krecq:krecq+nlevs-1)-rwork_2(:,krecq:krecq+nlevs-1))
  print *,'min/max tracer diff',minval(rwork_1(:,krecq+nlevs:nrec)-rwork_2(:,krecq+nlevs:nrec)),&
                           maxval(rwork_1(:,krecq+nlevs:nrec)-rwork_2(:,krecq+nlevs:nlevs))
  ! write out all fields to filename_o
  call nemsio_writerecv(gfile_o,'pres','sfc',1,rwork_2(:,1),iret=iret)
  if (iret /= 0) then
     print *,'Error writing ps to ',trim(filename_o)
     stop
  else
     print *,'wrote ps ',k,minval(rwork_2(:,1)),maxval(rwork_2(:,1))
  endif
  call nemsio_writerecv(gfile_o,'hgt','sfc',1,rwork_2(:,2),iret=iret)
  if (iret /= 0) then
     print *,'Error writing zs to ',trim(filename_o)
     stop
  else
     print *,'wrote zs ',k,minval(rwork_2(:,2)),maxval(rwork_2(:,2))
  endif
  do k = 1,nlevs
      krecu    = 2 + 0*nlevs + k
      krecv    = 2 + 1*nlevs + k
      krect    = 2 + 2*nlevs + k
      if (ldpres) then
         ndpres = 1
         krecdp = 2 + 3*nlevs + k
      else
         ndpres = 0
      endif
      krecq    = 2 + (3+ndpres)*nlevs + k
      krecoz   = 2 + (4+ndpres)*nlevs + k
      kreccwmr = 2 + (5+ndpres)*nlevs + k
      if (nrec > 2 + (6+ndpres)*nlevs) then
         krecicmr = 2 + (6+ndpres)*nlevs + k
      endif
      call nemsio_writerecv(gfile_o,'ugrd', 'mid layer',k,rwork_2(:,krecu),   iret=iret)
      if (iret /= 0) then
         print *,'Error writing u to ',trim(filename_o),k
         stop
      else
         print *,'wrote u level ',k,minval(rwork_2(:,krecu)),maxval(rwork_2(:,krecu))
      endif
      call nemsio_writerecv(gfile_o,'vgrd', 'mid layer',k,rwork_2(:,krecv),   iret=iret)
      if (iret /= 0) then
         print *,'Error writing v to ',trim(filename_o),k
         stop
      else
         print *,'wrote v level ',k,minval(rwork_2(:,krecv)),maxval(rwork_2(:,krecv))
      endif
      call nemsio_writerecv(gfile_o,'tmp',  'mid layer',k,rwork_2(:,krect),   iret=iret)
      if (iret /= 0) then
         print *,'Error writing t to ',trim(filename_o),k
         stop
      else
         print *,'wrote t level ',k,minval(rwork_2(:,krect)),maxval(rwork_2(:,krect))
      endif
      if (ldpres) then
         rwork_2(:,krecdp) = pressi_new(:,k)-pressi_new(:,k+1)
         call nemsio_writerecv(gfile_o,'dpres',  'mid layer',k,rwork_2(:,krecdp),   iret=iret)
         if (iret /= 0) then
            print *,'Error writing dpres to ',trim(filename_o),k
            stop
         else
            print *,'wrote dpres level ',k,minval(rwork_2(:,krecdp)),maxval(rwork_2(:,krecdp))
         endif
      endif
      call nemsio_writerecv(gfile_o,'spfh', 'mid layer',k,rwork_2(:,krecq),   iret=iret)
      if (iret /= 0) then
         print *,'Error writing q to ',trim(filename_o),k
         stop
      else
         print *,'wrote q level ',k,minval(rwork_2(:,krecq)),maxval(rwork_2(:,krecq))
      endif
      call nemsio_writerecv(gfile_o,'o3mr', 'mid layer',k,rwork_2(:,krecoz),  iret=iret)
      if (iret /= 0) then
         print *,'Error writing o3 to ',trim(filename_o),k
         stop
      else
         print *,'wrote o3 level ',k,minval(rwork_2(:,krecoz)),maxval(rwork_2(:,krecoz))
      endif
      call nemsio_writerecv(gfile_o,'clwmr','mid layer',k,rwork_2(:,kreccwmr),iret=iret)
      if (iret /= 0) then
         print *,'Error writing cwmr to ',trim(filename_o),k
         stop
      else
         print *,'wrote cwmr level ',k,minval(rwork_2(:,kreccwmr)),maxval(rwork_2(:,kreccwmr))
      endif
      if (nrec > 2 + 6*nlevs) then
      call nemsio_writerecv(gfile_o,'icmr','mid layer',k,rwork_2(:,krecicmr),iret=iret)
      if (iret /= 0) then
         print *,'Error writing icmr to ',trim(filename_o),k
         stop
      else
         print *,'wrote icmr level ',k,minval(rwork_2(:,krecicmr)),maxval(rwork_2(:,krecicmr))
      endif
      endif
  enddo
  deallocate(delps,delz,t0)
  deallocate(rwork_1,rwork_2)
  deallocate(ak,bk,pressi,pressl,pressi_new,pressl_new)
  call nemsio_close(gfile_o,iret=iret)
  if (iret /= 0) then
     print *,'Error closing ',trim(filename_o)
     stop
  endif
  call nemsio_close(gfile_1,iret=iret)
  if (iret /= 0) then
     print *,'Error closing ',trim(filename_1)
     stop
  endif
  call nemsio_close(gfile_2,iret=iret)
  if (iret /= 0) then
     print *,'Error closing ',trim(filename_2)
     stop
  endif

  call w3tage('ADJUSTPS')

END program adjustps

! these routines copied from global_chgres with minor mods to VINTG

      SUBROUTINE VINTG(IM,IX,KM1,KM2,NT,P1,U1,V1,T1,Q1,P2, &
                       U2,V2,T2,Q2)
!$$$  SUBPROGRAM DOCUMENTATION BLOCK
!
! SUBPROGRAM:    VINTG       VERTICALLY INTERPOLATE UPPER-AIR FIELDS
!   PRGMMR: IREDELL          ORG: W/NMC23     DATE: 92-10-31
!
! ABSTRACT: VERTICALLY INTERPOLATE UPPER-AIR FIELDS.
!   WIND, TEMPERATURE, HUMIDITY AND OTHER TRACERS ARE INTERPOLATED.
!   THE INTERPOLATION IS CUBIC LAGRANGIAN IN LOG PRESSURE
!   WITH A MONOTONIC CONSTRAINT IN THE CENTER OF THE DOMAIN.
!   IN THE OUTER INTERVALS IT IS LINEAR IN LOG PRESSURE.
!   OUTSIDE THE DOMAIN, FIELDS ARE GENERALLY HELD CONSTANT,
!   EXCEPT FOR TEMPERATURE AND HUMIDITY BELOW THE INPUT DOMAIN,
!   WHERE THE TEMPERATURE LAPSE RATE IS HELD FIXED AT -6.5 K/KM AND
!   THE RELATIVE HUMIDITY IS HELD CONSTANT.
!
! PROGRAM HISTORY LOG:
!   91-10-31  MARK IREDELL
!
! USAGE:    CALL VINTG(IM,IX,KM1,KM2,NT,P1,U1,V1,T1,Q1,P2,
!    &                 U2,V2,T2,Q2)
!   INPUT ARGUMENT LIST:
!     IM           INTEGER NUMBER OF POINTS TO COMPUTE
!     IX           INTEGER FIRST DIMENSION
!     KM1          INTEGER NUMBER OF INPUT LEVELS
!     KM2          INTEGER NUMBER OF OUTPUT LEVELS
!     NT           INTEGER NUMBER OF TRACERS
!     P1           REAL (IX,KM1) INPUT PRESSURES
!                  ORDERED FROM BOTTOM TO TOP OF ATMOSPHERE
!     U1           REAL (IX,KM1) INPUT ZONAL WIND
!     V1           REAL (IX,KM1) INPUT MERIDIONAL WIND
!     T1           REAL (IX,KM1) INPUT TEMPERATURE (K)
!     Q1           REAL (IX,KM1,NT) INPUT TRACERS (HUMIDITY FIRST)
!     P2           REAL (IX,KM2) OUTPUT PRESSURES
!   OUTPUT ARGUMENT LIST:
!     U2           REAL (IX,KM2) OUTPUT ZONAL WIND
!     V2           REAL (IX,KM2) OUTPUT MERIDIONAL WIND
!     T2           REAL (IX,KM2) OUTPUT TEMPERATURE (K)
!     Q2           REAL (IX,KM2,NT) OUTPUT TRACERS (HUMIDITY FIRST)
!
! SUBPROGRAMS CALLED:
!   TERP3        CUBICALLY INTERPOLATE IN ONE DIMENSION
!
! ATTRIBUTES:
!   LANGUAGE: FORTRAN
!
!C$$$
      INTEGER, INTENT(IN) :: IX,KM1,KM2,NT
      REAL, INTENT(IN) :: P1(IX,KM1),U1(IX,KM1),V1(IX,KM1),T1(IX,KM1),Q1(IX,NT*KM1)
!    &     ,W1(IX,KM1)
      REAL, INTENT(IN) :: P2(IX,KM2)
      REAL, INTENT(OUT) :: U2(IX,KM2),V2(IX,KM2),T2(IX,KM2),Q2(IX,NT*KM2)
!    &     ,W2(IX,KM2)
      REAL,  PARAMETER :: DLTDZ=-6.5E-3*287.05/9.80665
      REAL,  PARAMETER :: DLPVDRT=-2.5E6/461.50

      REAL,allocatable :: Z1(:,:),Z2(:,:)
      REAL,allocatable :: C1(:,:,:),C2(:,:,:),J2(:,:,:)
      real dz
      integer             :: im,k,i,n
!
      allocate (Z1(IM+1,KM1),Z2(IM+1,KM2))
      allocate (C1(IM+1,KM1,4+NT),C2(IM+1,KM2,4+NT),J2(IM+1,KM2,4+NT))
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  COMPUTE LOG PRESSURE INTERPOLATING COORDINATE
!  AND COPY INPUT WIND, TEMPERATURE, HUMIDITY AND OTHER TRACERS
!!$OMP PARALLEL DO DEFAULT(SHARED)
!!$OMP+ PRIVATE(K,I)
      !print *,minval(u1),maxval(u1)
      !print *,minval(t1),maxval(t1)
      DO K=1,KM1
        DO I=1,IM
          Z1(I,K)   = -LOG(P1(I,K))
          C1(I,K,1) =  U1(I,K)
          C1(I,K,2) =  V1(I,K)
!         C1(I,K,3) =  W1(I,K)
          C1(I,K,4) =  T1(I,K)
          C1(I,K,5) =  Q1(I,K)
        ENDDO
      ENDDO
!!$OMP END PARALLEL DO
      DO N=2,NT
        DO K=1,KM1
          DO I=1,IM
            C1(I,K,4+N) = Q1(I,(N-1)*KM1+K)
          ENDDO
        ENDDO
      ENDDO
!      print *,' p2=',p2(1,:)
!      print *,' im=',im,' km2=',km2,' ix=',ix,'nt=',nt
!!$OMP PARALLEL DO DEFAULT(SHARED)
!!$OMP+ PRIVATE(K,I)
      DO K=1,KM2
        DO I=1,IM
          Z2(I,K) = -LOG(P2(I,K))
        ENDDO
      ENDDO
!!$OMP END PARALLEL DO
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  PERFORM LAGRANGIAN ONE-DIMENSIONAL INTERPOLATION
!  THAT IS 4TH-ORDER IN INTERIOR, 2ND-ORDER IN OUTSIDE INTERVALS
!  AND 1ST-ORDER FOR EXTRAPOLATION.
      CALL TERP3(IM,1,1,1,1,4+NT,(IM+1)*KM1,(IM+1)*KM2,&
                 KM1,IM+1,IM+1,Z1,C1,KM2,IM+1,IM+1,Z2,C2,J2)
!      print *,' c2=',maxval(c2(1,:,:)),minval(c2(1,:,:))
!     print *,' j2:=',j2(1,1,:)
!     print *,' j2:=',j2(im,km2,:)
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  COPY OUTPUT WIND, TEMPERATURE, HUMIDITY AND OTHER TRACERS
!  EXCEPT BELOW THE INPUT DOMAIN, LET TEMPERATURE INCREASE WITH A FIXED
!  LAPSE RATE AND LET THE RELATIVE HUMIDITY REMAIN CONSTANT.
      DO K=1,KM2
        DO I=1,IM
          U2(I,K)=C2(I,K,1)
          V2(I,K)=C2(I,K,2)
!         W2(I,K)=C2(I,K,3)
          DZ=Z2(I,K)-Z1(I,1)
          IF(DZ.GE.0) THEN
            T2(I,K)=C2(I,K,4)
            Q2(I,K)=C2(I,K,5)
          ELSE
            T2(I,K)=T1(I,1)*EXP(DLTDZ*DZ)
            Q2(I,K)=Q1(I,1)*EXP(DLPVDRT*(1/T2(I,K)-1/T1(I,1))-DZ)
          ENDIF
        ENDDO
      ENDDO
      DO N=2,NT
        DO K=1,KM2
          DO I=1,IM
            Q2(I,(N-1)*KM2+K)=C2(I,K,4+N)
          ENDDO
        ENDDO
      ENDDO
      !print *,minval(u2),maxval(u2)
      !print *,minval(t2),maxval(t2)
      deallocate (Z1,Z2,C1,C2,J2)
      END

      SUBROUTINE TERP3(IM,IXZ1,IXQ1,IXZ2,IXQ2,NM,NXQ1,NXQ2, &
                       KM1,KXZ1,KXQ1,Z1,Q1,KM2,KXZ2,KXQ2,Z2,Q2,J2)
!$$$  SUBPROGRAM DOCUMENTATION BLOCK
!
! SUBPROGRAM:    TERP3       CUBICALLY INTERPOLATE IN ONE DIMENSION
!   PRGMMR: IREDELL          ORG: W/NMC23     DATE: 98-05-01
!
! ABSTRACT: INTERPOLATE FIELD(S) IN ONE DIMENSION ALONG THE COLUMN(S).
!   THE INTERPOLATION IS CUBIC LAGRANGIAN WITH A MONOTONIC CONSTRAINT
!   IN THE CENTER OF THE DOMAIN.  IN THE OUTER INTERVALS IT IS LINEAR.
!   OUTSIDE THE DOMAIN, FIELDS ARE HELD CONSTANT.
!
! PROGRAM HISTORY LOG:
!   98-05-01  MARK IREDELL
! 1999-01-04  IREDELL  USE ESSL SEARCH
!
! USAGE:    CALL TERP3(IM,IXZ1,IXQ1,IXZ2,IXQ2,NM,NXQ1,NXQ2,
!    &                 KM1,KXZ1,KXQ1,Z1,Q1,KM2,KXZ2,KXQ2,Z2,Q2,J2)
!   INPUT ARGUMENT LIST:
!     IM           INTEGER NUMBER OF COLUMNS
!     IXZ1         INTEGER COLUMN SKIP NUMBER FOR Z1
!     IXQ1         INTEGER COLUMN SKIP NUMBER FOR Q1
!     IXZ2         INTEGER COLUMN SKIP NUMBER FOR Z2
!     IXQ2         INTEGER COLUMN SKIP NUMBER FOR Q2
!     NM           INTEGER NUMBER OF FIELDS PER COLUMN
!     NXQ1         INTEGER FIELD SKIP NUMBER FOR Q1
!     NXQ2         INTEGER FIELD SKIP NUMBER FOR Q2
!     KM1          INTEGER NUMBER OF INPUT POINTS
!     KXZ1         INTEGER POINT SKIP NUMBER FOR Z1
!     KXQ1         INTEGER POINT SKIP NUMBER FOR Q1
!     Z1           REAL (1+(IM-1)*IXZ1+(KM1-1)*KXZ1)
!                  INPUT COORDINATE VALUES IN WHICH TO INTERPOLATE
!                  (Z1 MUST BE STRICTLY MONOTONIC IN EITHER DIRECTION)
!     Q1           REAL (1+(IM-1)*IXQ1+(KM1-1)*KXQ1+(NM-1)*NXQ1)
!                  INPUT FIELDS TO INTERPOLATE
!     KM2          INTEGER NUMBER OF OUTPUT POINTS
!     KXZ2         INTEGER POINT SKIP NUMBER FOR Z2
!     KXQ2         INTEGER POINT SKIP NUMBER FOR Q2
!     Z2           REAL (1+(IM-1)*IXZ2+(KM2-1)*KXZ2)
!                  OUTPUT COORDINATE VALUES TO WHICH TO INTERPOLATE
!                  (Z2 NEED NOT BE MONOTONIC)
!     
!   OUTPUT ARGUMENT LIST:
!     Q2           REAL (1+(IM-1)*IXQ2+(KM2-1)*KXQ2+(NM-1)*NXQ2)
!                  OUTPUT INTERPOLATED FIELDS
!     J2           REAL (1+(IM-1)*IXQ2+(KM2-1)*KXQ2+(NM-1)*NXQ2)
!                  OUTPUT INTERPOLATED FIELDS CHANGE WRT Z2
!
! SUBPROGRAMS CALLED:
!   RSEARCH      SEARCH FOR A SURROUNDING REAL INTERVAL
!
! ATTRIBUTES:
!   LANGUAGE: FORTRAN
!
!C$$$
      IMPLICIT NONE
      INTEGER IM,IXZ1,IXQ1,IXZ2,IXQ2,NM,NXQ1,NXQ2
      INTEGER KM1,KXZ1,KXQ1,KM2,KXZ2,KXQ2
      INTEGER I,K1,K2,N
      REAL Z1(1+(IM-1)*IXZ1+(KM1-1)*KXZ1)
      REAL Q1(1+(IM-1)*IXQ1+(KM1-1)*KXQ1+(NM-1)*NXQ1)
      REAL Z2(1+(IM-1)*IXZ2+(KM2-1)*KXZ2)
      REAL Q2(1+(IM-1)*IXQ2+(KM2-1)*KXQ2+(NM-1)*NXQ2)
      REAL J2(1+(IM-1)*IXQ2+(KM2-1)*KXQ2+(NM-1)*NXQ2)
      REAL FFA(IM),FFB(IM),FFC(IM),FFD(IM)
      REAL GGA(IM),GGB(IM),GGC(IM),GGD(IM)
      INTEGER K1S(IM,KM2)
      REAL Z1A,Z1B,Z1C,Z1D,Q1A,Q1B,Q1C,Q1D,Z2S,Q2S,J2S
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  FIND THE SURROUNDING INPUT INTERVAL FOR EACH OUTPUT POINT.
      CALL RSEARCH(IM,KM1,IXZ1,KXZ1,Z1,KM2,IXZ2,KXZ2,Z2,1,IM,K1S)
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  GENERALLY INTERPOLATE CUBICALLY WITH MONOTONIC CONSTRAINT
!  FROM TWO NEAREST INPUT POINTS ON EITHER SIDE OF THE OUTPUT POINT,
!  BUT WITHIN THE TWO EDGE INTERVALS INTERPOLATE LINEARLY.
!  KEEP THE OUTPUT FIELDS CONSTANT OUTSIDE THE INPUT DOMAIN.

!!$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(IM,IXZ1,IXQ1,IXZ2)
!!$OMP+ SHARED(IXQ2,NM,NXQ1,NXQ2,KM1,KXZ1,KXQ1,Z1,Q1,KM2,KXZ2)
!!$OMP+ SHARED(KXQ2,Z2,Q2,J2,K1S)

      DO K2=1,KM2
        DO I=1,IM
          K1=K1S(I,K2)
          IF(K1.EQ.1.OR.K1.EQ.KM1-1) THEN
            Z2S=Z2(1+(I-1)*IXZ2+(K2-1)*KXZ2)
            Z1A=Z1(1+(I-1)*IXZ1+(K1-1)*KXZ1)
            Z1B=Z1(1+(I-1)*IXZ1+(K1+0)*KXZ1)
            FFA(I)=(Z2S-Z1B)/(Z1A-Z1B)
            FFB(I)=(Z2S-Z1A)/(Z1B-Z1A)
            GGA(I)=1/(Z1A-Z1B)
            GGB(I)=1/(Z1B-Z1A)
          ELSEIF(K1.GT.1.AND.K1.LT.KM1-1) THEN
            Z2S=Z2(1+(I-1)*IXZ2+(K2-1)*KXZ2)
            Z1A=Z1(1+(I-1)*IXZ1+(K1-2)*KXZ1)
            Z1B=Z1(1+(I-1)*IXZ1+(K1-1)*KXZ1)
            Z1C=Z1(1+(I-1)*IXZ1+(K1+0)*KXZ1)
            Z1D=Z1(1+(I-1)*IXZ1+(K1+1)*KXZ1)
            FFA(I)=(Z2S-Z1B)/(Z1A-Z1B)* &
                   (Z2S-Z1C)/(Z1A-Z1C)* &
                   (Z2S-Z1D)/(Z1A-Z1D)
            FFB(I)=(Z2S-Z1A)/(Z1B-Z1A)* &
                   (Z2S-Z1C)/(Z1B-Z1C)* &
                   (Z2S-Z1D)/(Z1B-Z1D)
            FFC(I)=(Z2S-Z1A)/(Z1C-Z1A)* &
                   (Z2S-Z1B)/(Z1C-Z1B)* &
                   (Z2S-Z1D)/(Z1C-Z1D)
            FFD(I)=(Z2S-Z1A)/(Z1D-Z1A)* &
                   (Z2S-Z1B)/(Z1D-Z1B)* &
                   (Z2S-Z1C)/(Z1D-Z1C)
            GGA(I)=        1/(Z1A-Z1B)* &
                   (Z2S-Z1C)/(Z1A-Z1C)* &
                   (Z2S-Z1D)/(Z1A-Z1D)+ &
                   (Z2S-Z1B)/(Z1A-Z1B)* &
                           1/(Z1A-Z1C)* &
                   (Z2S-Z1D)/(Z1A-Z1D)+ &
                   (Z2S-Z1B)/(Z1A-Z1B)* &
                   (Z2S-Z1C)/(Z1A-Z1C)* &
                           1/(Z1A-Z1D)   
            GGB(I)=        1/(Z1B-Z1A)* &
                   (Z2S-Z1C)/(Z1B-Z1C)* &
                   (Z2S-Z1D)/(Z1B-Z1D)+ &
                   (Z2S-Z1A)/(Z1B-Z1A)* &
                           1/(Z1B-Z1C)* &
                   (Z2S-Z1D)/(Z1B-Z1D)+ &
                   (Z2S-Z1A)/(Z1B-Z1A)* &
                   (Z2S-Z1C)/(Z1B-Z1C)* &
                           1/(Z1B-Z1D)  
            GGC(I)=        1/(Z1C-Z1A)* &
                   (Z2S-Z1B)/(Z1C-Z1B)* &
                   (Z2S-Z1D)/(Z1C-Z1D)+ &
                   (Z2S-Z1A)/(Z1C-Z1A)* &
                           1/(Z1C-Z1B)* &
                   (Z2S-Z1D)/(Z1C-Z1D)+ &
                   (Z2S-Z1A)/(Z1C-Z1A)* &
                   (Z2S-Z1B)/(Z1C-Z1B)* &
                           1/(Z1C-Z1D)
            GGD(I)=        1/(Z1D-Z1A)* &    
                   (Z2S-Z1B)/(Z1D-Z1B)* &
                   (Z2S-Z1C)/(Z1D-Z1C)+ &
                   (Z2S-Z1A)/(Z1D-Z1A)* &
                           1/(Z1D-Z1B)* &
                   (Z2S-Z1C)/(Z1D-Z1C)+ &
                   (Z2S-Z1A)/(Z1D-Z1A)* &
                   (Z2S-Z1B)/(Z1D-Z1B)* &
                           1/(Z1D-Z1C)
          ENDIF
        ENDDO
!  INTERPOLATE.
        DO N=1,NM
          DO I=1,IM
            K1=K1S(I,K2)
            IF(K1.EQ.0) THEN
              Q2S=Q1(1+(I-1)*IXQ1+(N-1)*NXQ1)
              J2S=0
            ELSEIF(K1.EQ.KM1) THEN
              Q2S=Q1(1+(I-1)*IXQ1+(KM1-1)*KXQ1+(N-1)*NXQ1)
              J2S=0
            ELSEIF(K1.EQ.1.OR.K1.EQ.KM1-1) THEN
              Q1A=Q1(1+(I-1)*IXQ1+(K1-1)*KXQ1+(N-1)*NXQ1)
              Q1B=Q1(1+(I-1)*IXQ1+(K1+0)*KXQ1+(N-1)*NXQ1)
              Q2S=FFA(I)*Q1A+FFB(I)*Q1B
              J2S=GGA(I)*Q1A+GGB(I)*Q1B
            ELSE
              Q1A=Q1(1+(I-1)*IXQ1+(K1-2)*KXQ1+(N-1)*NXQ1)
              Q1B=Q1(1+(I-1)*IXQ1+(K1-1)*KXQ1+(N-1)*NXQ1)
              Q1C=Q1(1+(I-1)*IXQ1+(K1+0)*KXQ1+(N-1)*NXQ1)
              Q1D=Q1(1+(I-1)*IXQ1+(K1+1)*KXQ1+(N-1)*NXQ1)
              Q2S=FFA(I)*Q1A+FFB(I)*Q1B+FFC(I)*Q1C+FFD(I)*Q1D
              J2S=GGA(I)*Q1A+GGB(I)*Q1B+GGC(I)*Q1C+GGD(I)*Q1D
              IF(Q2S.LT.MIN(Q1B,Q1C)) THEN
                Q2S=MIN(Q1B,Q1C)
                J2S=0
              ELSEIF(Q2S.GT.MAX(Q1B,Q1C)) THEN
                Q2S=MAX(Q1B,Q1C)
                J2S=0
              ENDIF
            ENDIF
            Q2(1+(I-1)*IXQ2+(K2-1)*KXQ2+(N-1)*NXQ2)=Q2S
            J2(1+(I-1)*IXQ2+(K2-1)*KXQ2+(N-1)*NXQ2)=J2S
          ENDDO
        ENDDO
      ENDDO
!!$OMP END PARALLEL DO
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      END
!-----------------------------------------------------------------------
      SUBROUTINE RSEARCH(IM,KM1,IXZ1,KXZ1,Z1,KM2,IXZ2,KXZ2,Z2,IXL2,KXL2,&
                         L2)
!$$$  SUBPROGRAM DOCUMENTATION BLOCK
!
! SUBPROGRAM:    RSEARCH     SEARCH FOR A SURROUNDING REAL INTERVAL
!   PRGMMR: IREDELL          ORG: W/NMC23     DATE: 98-05-01
!
! ABSTRACT: THIS SUBPROGRAM SEARCHES MONOTONIC SEQUENCES OF REAL NUMBERS
!   FOR INTERVALS THAT SURROUND A GIVEN SEARCH SET OF REAL NUMBERS.
!   THE SEQUENCES MAY BE MONOTONIC IN EITHER DIRECTION; THE REAL NUMBERS
!   MAY BE SINGLE OR DOUBLE PRECISION; THE INPUT SEQUENCES AND SETS
!   AND THE OUTPUT LOCATIONS MAY BE ARBITRARILY DIMENSIONED.
!
! PROGRAM HISTORY LOG:
! 1999-01-05  MARK IREDELL
!
! USAGE:    CALL RSEARCH(IM,KM1,IXZ1,KXZ1,Z1,KM2,IXZ2,KXZ2,Z2,IXL2,KXL2,
!    &                   L2)
!   INPUT ARGUMENT LIST:
!     IM           INTEGER NUMBER OF SEQUENCES TO SEARCH
!     KM1          INTEGER NUMBER OF POINTS IN EACH SEQUENCE
!     IXZ1         INTEGER SEQUENCE SKIP NUMBER FOR Z1
!     KXZ1         INTEGER POINT SKIP NUMBER FOR Z1
!     Z1           REAL (1+(IM-1)*IXZ1+(KM1-1)*KXZ1)
!                  SEQUENCE VALUES TO SEARCH
!                  (Z1 MUST BE MONOTONIC IN EITHER DIRECTION)
!     KM2          INTEGER NUMBER OF POINTS TO SEARCH FOR
!                  IN EACH RESPECTIVE SEQUENCE
!     IXZ2         INTEGER SEQUENCE SKIP NUMBER FOR Z2
!     KXZ2         INTEGER POINT SKIP NUMBER FOR Z2
!     Z2           REAL (1+(IM-1)*IXZ2+(KM2-1)*KXZ2)
!                  SET OF VALUES TO SEARCH FOR
!                  (Z2 NEED NOT BE MONOTONIC)
!     IXL2         INTEGER SEQUENCE SKIP NUMBER FOR L2
!     KXL2         INTEGER POINT SKIP NUMBER FOR L2
!     
!   OUTPUT ARGUMENT LIST:
!     L2           INTEGER (1+(IM-1)*IXL2+(KM2-1)*KXL2)
!                  INTERVAL LOCATIONS HAVING VALUES FROM 0 TO KM1
!                  (Z2 WILL BE BETWEEN Z1(L2) AND Z1(L2+1))
!
! SUBPROGRAMS CALLED:
!   SBSRCH       ESSL BINARY SEARCH
!   DBSRCH       ESSL BINARY SEARCH
!
! REMARKS:
!   IF THE ARRAY Z1 IS DIMENSIONED (IM,KM1), THEN THE SKIP NUMBERS ARE
!   IXZ1=1 AND KXZ1=IM; IF IT IS DIMENSIONED (KM1,IM), THEN THE SKIP
!   NUMBERS ARE IXZ1=KM1 AND KXZ1=1; IF IT IS DIMENSIONED (IM,JM,KM1),
!   THEN THE SKIP NUMBERS ARE IXZ1=1 AND KXZ1=IM*JM; ETCETERA.
!   SIMILAR EXAMPLES APPLY TO THE SKIP NUMBERS FOR Z2 AND L2.
!
!   RETURNED VALUES OF 0 OR KM1 INDICATE THAT THE GIVEN SEARCH VALUE
!   IS OUTSIDE THE RANGE OF THE SEQUENCE.
!
!   IF A SEARCH VALUE IS IDENTICAL TO ONE OF THE SEQUENCE VALUES
!   THEN THE LOCATION RETURNED POINTS TO THE IDENTICAL VALUE.
!   IF THE SEQUENCE IS NOT STRICTLY MONOTONIC AND A SEARCH VALUE IS
!   IDENTICAL TO MORE THAN ONE OF THE SEQUENCE VALUES, THEN THE
!   LOCATION RETURNED MAY POINT TO ANY OF THE IDENTICAL VALUES.
!
!   TO BE EXACT, FOR EACH I FROM 1 TO IM AND FOR EACH K FROM 1 TO KM2,
!   Z=Z2(1+(I-1)*IXZ2+(K-1)*KXZ2) IS THE SEARCH VALUE AND
!   L=L2(1+(I-1)*IXL2+(K-1)*KXL2) IS THE LOCATION RETURNED.
!   IF L=0, THEN Z IS LESS THAN THE START POINT Z1(1+(I-1)*IXZ1)
!   FOR ASCENDING SEQUENCES (OR GREATER THAN FOR DESCENDING SEQUENCES).
!   IF L=KM1, THEN Z IS GREATER THAN OR EQUAL TO THE END POINT
!   Z1(1+(I-1)*IXZ1+(KM1-1)*KXZ1) FOR ASCENDING SEQUENCES
!   (OR LESS THAN OR EQUAL TO FOR DESCENDING SEQUENCES).
!   OTHERWISE Z IS BETWEEN THE VALUES Z1(1+(I-1)*IXZ1+(L-1)*KXZ1) AND
!   Z1(1+(I-1)*IXZ1+(L-0)*KXZ1) AND MAY EQUAL THE FORMER.
!
! ATTRIBUTES:
!   LANGUAGE: FORTRAN
!
!C$$$
!     IMPLICIT NONE
!     INTEGER,INTENT(IN):: IM,KM1,IXZ1,KXZ1,KM2,IXZ2,KXZ2,IXL2,KXL2
!     REAL,INTENT(IN):: Z1(1+(IM-1)*IXZ1+(KM1-1)*KXZ1)
!     REAL,INTENT(IN):: Z2(1+(IM-1)*IXZ2+(KM2-1)*KXZ2)
!     INTEGER,INTENT(OUT):: L2(1+(IM-1)*IXL2+(KM2-1)*KXL2)
!     INTEGER(4) INCX,N,INCY,M,INDX(KM2),RC(KM2),IOPT
!     INTEGER I,K2
! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!  FIND THE SURROUNDING INPUT INTERVAL FOR EACH OUTPUT POINT.
!     DO I=1,IM
!       IF(Z1(1+(I-1)*IXZ1).LE.Z1(1+(I-1)*IXZ1+(KM1-1)*KXZ1)) THEN
!  INPUT COORDINATE IS MONOTONICALLY ASCENDING.
!         INCX=KXZ2
!         N=KM2
!         INCY=KXZ1
!         M=KM1
!         IOPT=1
!         IF(DIGITS(1.).LT.DIGITS(1._8)) THEN
!           CALL SBSRCH(Z2(1+(I-1)*IXZ2),INCX,N,
!    &                  Z1(1+(I-1)*IXZ1),INCY,M,INDX,RC,IOPT)
!         ELSE
!           CALL DBSRCH(Z2(1+(I-1)*IXZ2),INCX,N,
!    &                  Z1(1+(I-1)*IXZ1),INCY,M,INDX,RC,IOPT)
!         ENDIF
!         DO K2=1,KM2
!           L2(1+(I-1)*IXL2+(K2-1)*KXL2)=INDX(K2)-RC(K2)
!         ENDDO
!       ELSE
!  INPUT COORDINATE IS MONOTONICALLY DESCENDING.
!         INCX=KXZ2
!         N=KM2
!         INCY=-KXZ1
!         M=KM1
!         IOPT=0
!         IF(DIGITS(1.).LT.DIGITS(1._8)) THEN
!           CALL SBSRCH(Z2(1+(I-1)*IXZ2),INCX,N,
!    &                  Z1(1+(I-1)*IXZ1),INCY,M,INDX,RC,IOPT)
!         ELSE
!           CALL DBSRCH(Z2(1+(I-1)*IXZ2),INCX,N,
!    &                  Z1(1+(I-1)*IXZ1),INCY,M,INDX,RC,IOPT)
!         ENDIF
!         DO K2=1,KM2
!           L2(1+(I-1)*IXL2+(K2-1)*KXL2)=KM1+1-INDX(K2)
!         ENDDO
!       ENDIF
!     ENDDO
!
      IMPLICIT NONE
      INTEGER,INTENT(IN):: IM,KM1,IXZ1,KXZ1,KM2,IXZ2,KXZ2,IXL2,KXL2
      REAL,INTENT(IN):: Z1(1+(IM-1)*IXZ1+(KM1-1)*KXZ1)
      REAL,INTENT(IN):: Z2(1+(IM-1)*IXZ2+(KM2-1)*KXZ2)
      INTEGER,INTENT(OUT):: L2(1+(IM-1)*IXL2+(KM2-1)*KXL2)
      INTEGER I,K2,L
      REAL Z
!C - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
!C  FIND THE SURROUNDING INPUT INTERVAL FOR EACH OUTPUT POINT.
      DO I=1,IM
        IF(Z1(1+(I-1)*IXZ1).LE.Z1(1+(I-1)*IXZ1+(KM1-1)*KXZ1)) THEN
!C  INPUT COORDINATE IS MONOTONICALLY ASCENDING.
          DO K2=1,KM2
            Z=Z2(1+(I-1)*IXZ2+(K2-1)*KXZ2)
            L=0
            DO
              IF(Z.LT.Z1(1+(I-1)*IXZ1+L*KXZ1)) EXIT
              L=L+1
              IF(L.EQ.KM1) EXIT
            ENDDO
            L2(1+(I-1)*IXL2+(K2-1)*KXL2)=L
          ENDDO
        ELSE
!C  INPUT COORDINATE IS MONOTONICALLY DESCENDING.
          DO K2=1,KM2
            Z=Z2(1+(I-1)*IXZ2+(K2-1)*KXZ2)
            L=0
            DO
              IF(Z.GT.Z1(1+(I-1)*IXZ1+L*KXZ1)) EXIT
              L=L+1
              IF(L.EQ.KM1) EXIT
            ENDDO
            L2(1+(I-1)*IXL2+(K2-1)*KXL2)=L
          ENDDO
        ENDIF
      ENDDO

      END SUBROUTINE