!-------------------------------------- LICENCE BEGIN ------------------------------------
!Environment Canada - Atmospheric Science and Technology License/Disclaimer, 
!                     version 3; Last Modified: May 7, 2008.
!This is free but copyrighted software; you can use/redistribute/modify it under the terms 
!of the Environment Canada - Atmospheric Science and Technology License/Disclaimer 
!version 3 or (at your option) any later version that should be found at: 
!http://collaboration.cmc.ec.gc.ca/science/rpn.comm/license.html 
!
!This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
!without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
!See the above mentioned License/Disclaimer for more details.
!You should have received a copy of the License/Disclaimer along with this software; 
!if not, you can write to: EC-RPN COMM Group, 2121 TransCanada, suite 500, Dorval (Quebec), 
!CANADA, H9P 1J3; or send e-mail to service.rpn@ec.gc.ca
!-------------------------------------- LICENCE END --------------------------------------
***s/r vte_intvertx  cubic vertical interpolation from eta/sigma to hybrid
*

      subroutine vte_intvertx (F_dch,F_sch,F_srclev,F_dstlev,n,nks,nkd,F_var) 1
#include "impnone.cdk"
*
       integer n, nkd, nks
       real F_dch(n,nkd), F_sch(n,nks), F_srclev(n,nks),F_dstlev(n,nks)
       character*2 F_var
*
*author - Methot/Laroche - April 97 - v1_01
*
*revision
* v2_10 - L. Corbeil          - rewrited for optimization, 
* v2_10                         removed e_vcubique
* v2_30 - L. Corbeil          - renamed vte_ (no more called in gemntr)
* v2_31 - Lee V.              - F_srclev,F_dstlev is calculated outside
*
*object
*       see above id
*
*arguments
*  Name        I/O                 Description
*----------------------------------------------------------------
* F_dch                   Interpolated field           
* F_sch                   source       field           
* F_srclev                source levels
* F_dstlev                destination levels
* F_var                   name of the variable                 
*                                                           
*----------------------------------------------------------------------
*
*implicites
#include "model_macros_f.h"
#include "dcst.cdk"
*
**
*
      integer i,k,iter,niter,lev,lev_lin
      integer top(n),bot(n),topcub(n),botcub(n),ref(n)
      real*8 deltalev,prxd,prda,prdb,prsaf,prsbf,prsad,prsbd
*
*     ---------------------------------------------------------------
*
****  General case, we'll care about VT later
*
*     First, we find the level we are by squeezing the destination 
*     between increasing bot() and decreasing top(). We need log_2_(nks)
*     iteration to squeeze it completely (each integer between 1 and 
*     nks can be expressed as a sum of power of 2 such as sum c_i 2^i 
*     where c_i = 0 or 1 and i lower or equal than log_2_(nks)
*
*     WARNING
*  niter calculation is ok for nks.lt. 2097152: should be ok for now...
*  (Maybe the grid will be that precise in 2010!) (I don't even bother
*  to add an if statement, for performance purpose...)
*
      if (real(int(log(real(nks))/log(2.0))).eq.
     $     log(real(nks))/log(2.0)) then
         niter=int(log(real(nks))/log(2.0))
      else
         niter=int(log(real(nks))/log(2.0))+1
      endif
*
*     squeeze...
*
      do k=1,nkd
         do i=1,n
            top(i)=nks
            bot(i)=1
         enddo
         do iter=1,niter
            do i=1,n
*     divide by two (the old fashioned way...)
               ref(i)=ishft(top(i)+bot(i),-1)
*     adjust top or bot
               if(F_dstlev(i,k).lt.F_srclev(i,ref(i))) then
                  top(i)=ref(i)
               else
                  bot(i)=ref(i)
               endif
            enddo
         enddo
*     adjusting top and bot to ensure we can perform cubic interpolation
         do i=1,n
            botcub(i)=max(2,bot(i))
            topcub(i)=min(nks-1,top(i))
         enddo
*     cubic or linear interpolation
         do i=1,n
            lev=botcub(i)
            lev_lin=bot(i)
            deltalev=(F_srclev(i,lev_lin+1)-F_srclev(i,lev_lin))
*     
*     Interpolation: if not enough points to perform cubic interpolation
*                    we use linear interpolation or persistency
*
            if((lev.ne.lev_lin).or.(topcub(i).ne.top(i))) then
*
*     persistancy of this interval
*
               if(F_dstlev(i,k).le.F_srclev(i,1)) then
                  F_dch(i,k) = F_sch(i,1)
               else if(F_dstlev(i,k).ge.F_srclev(i,nks)) then
                  F_dch(i,k) = F_sch(i,nks)
               else
*     linear interpolation
                  prxd=(F_dstlev(i,k)-F_srclev(i,lev_lin))/deltalev
                  F_dch(i,k) = (1.0-prxd)*F_sch(i,lev_lin)
     $                        +prxd*F_sch(i,lev_lin+1)
               endif
            else
*     cubic interpolation
               prxd = (F_dstlev(i,k)-F_srclev(i,lev_lin))/
     $                 deltalev
               prda = ((F_sch(i,lev_lin+1)-F_sch(i,lev_lin-1))/
     $                (F_srclev(i,lev_lin+1)-F_srclev(i,lev_lin-1))*
     $                 deltalev)
               prdb = ((F_sch(i,lev_lin+2)-F_sch(i,lev_lin))/
     $                (F_srclev(i,lev_lin+2)-F_srclev(i,lev_lin))*
     $                 deltalev)
               prsaf= (1.0+2.0*prxd)*(1.0-prxd)*(1.0-prxd)
               prsbf= (3.0-2.0*prxd)*prxd*prxd
               prsad= prxd*(1.0-prxd)*(1.0-prxd)
               prsbd= (1.0-prxd)*prxd*prxd
               F_dch(i,k) = F_sch(i,lev_lin  )*prsaf
     $                     +F_sch(i,lev_lin+1)*prsbf+prda*prsad
     $                     -prdb*prsbd
            endif
         enddo
      enddo
*
*    special  case for VT
*
      if(F_var.eq.'VT') then
         do k=1,nkd
         do i=1,n
            if(F_srclev(i,nks).lt.F_dstlev(i,k)) then
                F_dch(i,k) = F_sch(i,nks) * exp ( 
     $           Dcst_rgasd_8*Dcst_stlo_8*(F_dstlev(i,k)-F_srclev(i,nks)) )
            endif
         enddo
         enddo
*
      endif
*
*     ---------------------------------------------------------------
*       
      return
      end