!-------------------------------------- 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/p adw_trilin_turbo - Optimized tri-linear interpolation
*                         with SETINT inside 
*
#include "model_macros_f.h"
*

      subroutine adw_trilin_turbo ( F_out, F_in, F_dt,  13
     %                              F_x, F_y, F_z, F_capz,
     %                              Fn_I, F_num, i0, in, j0, jn, kn)
*
      implicit none
*
      integer F_num, Fn_I(F_num), i0, in, j0, jn, kn
*
      real F_dt, F_in(*)
*
      real F_out(F_num), F_x(F_num), F_y(F_num), F_z(F_num)
      real F_capz(F_num)
*
*authors
*     Valin & Tanguay  
*
*     (Based on adw_trilin v_3.1.1)
*
*revision
* v3_20 -Valin & Tanguay -  initial version 
* v3_21 -Tanguay M.      -  evaluate min-max vertical CFL as function of k 
*
*object
*     see id section
*
*     NOTE: capx,capy are recalculated but capz is stored in F_capz
*
*arguments
*______________________________________________________________________
*              |                                                 |     |
* NAME         | DESCRIPTION                                     | I/O |
*--------------|-------------------------------------------------|-----|
* F_out        | F_dt * result of interpolation                  |  o  |
* F_in         | field to interpolate                            |  i  |
*              |                                                 |     |
* F_dt         | multiplicative constant (1.0 or timestep lenght)|  i  |
*              |                                                 |     |
* F_x          | \                                               |  i  |
* F_y          |   x,y,z positions                               |  i  |
* F_z          | /                                               |  i  |
*              |                                                 |     |
* F_capz       | precomputed displacements along the z-direction |  io |
*              |                                                 |     |
* Fn_I         | localisation indices                            |  i  |
*              |                                                 |     |
* F_num        | number of points to interpolate                 |  i  |
*______________|_________________________________________________|_____|
*
*implicits
#include "glb_ld.cdk"
#include "adw.cdk"
#include "v4dcfl.cdk"
************************************************************************
*
      integer n, n0, nijag, nij, o1, o2, i, j, k, iimax, jjmax, kkmax,
     %        ii,jj,kk
*
      real capx, capy, capz
*
      real*8 rri, rrj, rrk, prf1, prf2, prf3, prf4
*
      integer cfl,err
      logical done_L
      data done_L /.false./
      save done_L
*
*     ----------------------------------------------------------------
*
*     Initialize min-max vertical CFL as function of k
*     ------------------------------------------------
      if(.not.done_L) then
         call hpalloc(V4dcfl_p_   ,l_nk, err,1)
         call hpalloc(V4dcfl_n_   ,l_nk, err,1)
         do k = 1,l_nk
            V4dcfl_p(k) = 0
            V4dcfl_n(k) = 0
         enddo
         done_L = .true.
      endif
*
      nijag = Adw_nit * Adw_njt
      nij = l_ni*l_nj
*
      iimax = G_ni+2*Adw_halox-1
      jjmax = G_nj+Adw_haloy
      kkmax = l_nk-1
*
!$omp parallel do private(n,n0,ii,jj,kk,rri,rrj,rrk,
!$omp&              capx,capy,capz,o1,o2,prf1,prf2,prf3,prf4,cfl)
      do 100 k=1,kn
      do  90 j=j0,jn
      n0 = (k-1)*nij + ((j-1)*l_ni)
      if ( Adw_hor_L ) then
        do  i=i0,in
          n = n0 + i
*
          rri= F_x(n)
          ii = ( rri - Adw_x00_8 ) * Adw_ovdx_8
          ii = Adw_lcx( ii+1 ) + 1
          if ( rri .lt. Adw_bsx_8(ii) ) ii = ii - 1
          ii = max(1,min(ii,iimax))
*
          rrj= F_y(n)
          jj = ( rrj - Adw_y00_8 ) * Adw_ovdy_8
          jj = Adw_lcy( jj+1 ) + 1
          if ( rrj .lt. Adw_bsy_8(jj) ) jj = jj - 1
          jj = max(Adw_haloy,min(jj,jjmax))
*
          kk = ishft(Fn_I(n) , -24)
          Fn_I(n) = ior( ior(ishft(jj,12) , ii) , ishft( kk , 24) )
*
        enddo
      endif
      if ( Adw_ver_L ) then
        do  i=i0,in
          n = n0 + i
*
          rrk= F_z(n)
          kk = ( rrk - Adw_z00_8 ) * Adw_ovdz_8
          kk = Adw_lcz( kk+1 )
          rrk = rrk - Adw_bsz_8(kk)
          if ( rrk .lt. 0.0 ) kk = kk - 1
*
          capz = rrk * Adw_diz_8(kk)
          if ( rrk .lt. 0.0 ) capz = 1.0 + capz
*
*         We keep F_capz, otherwise we would need rrk  
*         -------------------------------------------
          F_capz(n) = capz
*
          ii = and( Fn_I(n) , 4095 )
          jj = and( ishft( Fn_I(n) , -12 ) , 4095 )
          Fn_I(n) = ior( ior(ishft(jj,12) , ii) , ishft( kk , 24) )
*
*         Evaluate min-max vertical CFL as function of k 
*         ----------------------------------------------
          cfl = (kk+1) - k
          if (cfl.gt.V4dcfl_p(k) ) V4dcfl_p(k) = cfl
          if (cfl.lt.V4dcfl_n(k) ) V4dcfl_n(k) = cfl
*
        enddo
      endif
      do  80 i=i0,in
        n = n0 + i
*
        ii = and( Fn_I(n) , 4095 )
        jj = and( ishft( Fn_I(n) , -12 ) , 4095 )
        kk = ishft(Fn_I(n) , -24)
*
        rri= F_x(n)
        rrj= F_y(n)
*
        o1 = (kk)*nijag + (jj-Adw_int_j_off-1)*Adw_nit + (ii-Adw_int_i_off)
        o2 = o1 + Adw_nit
*
************************************************************************
*     x interpolation
************************************************************************
        capx = (rri-Adw_bsx_8(ii)) *Adw_xbc_8(ii)
*
        prf1 = (1.0 - capx) * F_in(o1) + capx * F_in(o1+1)
        prf2 = (1.0 - capx) * F_in(o2) + capx * F_in(o2+1)
*
        o1 = o1 + nijag
        o2 = o2 + nijag
*
        prf3 = (1.0 - capx) * F_in(o1) + capx * F_in(o1+1)
        prf4 = (1.0 - capx) * F_in(o2) + capx * F_in(o2+1)
*
************************************************************************
*     y interpolation
************************************************************************
        capy = (rrj-Adw_bsy_8(jj)) *Adw_ybc_8(jj)  
*
        prf1 = (1.0 - capy) * prf1 + capy  * prf2
        prf2 = (1.0 - capy) * prf3 + capy  * prf4
************************************************************************
*     z interpolation
************************************************************************
        capz = F_capz(n)
*
        F_out(n) = ( (1.0 - capz) * prf1 + capz  * prf2 ) * F_dt
*
   80 continue
   90 continue
  100 continue
!$omp end parallel do
*
      Adw_hor_L = .false.
      Adw_ver_L = .false.
*
      return
      end