!-------------------------------------- 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 adw_set - sets different advection parameters
*
#include "model_macros_f.h"
*

      subroutine adw_set 1,3
      implicit none
*
*author
*     alain patoine
*
*revision
* v3_20 - Gravel & Valin & Tanguay - Lagrange 3D and optimized SETINT/TRILIN
* v3_31 - Bilodeau & Lee - Correction for offline mode
* v3_31 - Desgagne M.    - Remove validation of halo sizes
*
*language
*     fortran 77
*
*object
*     see id section
*
*arguments
*     none
*
*implicits
#include "glb_ld.cdk"
#include "dcst.cdk"
#include "geomg.cdk"
#include "adw.cdk"
#include "schm.cdk"
************************************************************************
      integer i, j, k, ij, pnerr, trj_i_off, nij, n
      integer i0, j0, k0, pnx, pny, pnz, ii1, ii2
*
      real*8 ZERO, HALF, ONE, TWO
      parameter( ZERO  = 0.0 )
      parameter( HALF  = 0.5 )
      parameter( ONE   = 1.0 )
      parameter( TWO   = 2.0 )
*
      real*8  prhxmn, prhymn, prhzmn, large, dummy, pdfi, pdov6
      real*8 whx(G_ni+2*Adw_halox),why(G_nj+2*Adw_haloy),
     $       whz(0:G_nk+1),w2(G_nk,6)
*
      real *8 triprd,za,zb,zc,zd,ra,rb,rc,rd
      triprd(za,zb,zc,zd)=(za-zb)*(za-zc)*(za-zd)
*
      large = 1.0e20
      pdov6 = 1.0d0/6.0d0
************************************************************************
* In the general situation where only the tiles adjacent to the poles  *
* would have an advection source grid periodic in x, we would have the *
* following decision tree:                                             *
************************************************************************
*     if ( l_south .or. l_north ) then                                 *
*        Adw_nic       = G_ni                                          *
*        Adw_int_i_off = 0          <--- offset global-advection grids *
*            trj_i_off = l_i0 - 1   <--- offset advection-local  grids *
*     else                                                             *
*        Adw_nic       = l_ni                                          *
*        Adw_int_i_off = l_i0 - 1   <--- offset global-advection grids *
*            trj_i_off = 0          <--- offset advection-local  grids *
*     endif                                                            *
************************************************************************
* However, in the present situation where all the tiles have an        *
* advection source grid periodic in x, we have this:                   *
************************************************************************
      if (G_lam) then
      Adw_nic       = l_ni
      Adw_int_i_off = l_i0 - 1
          trj_i_off = 0
      else
      Adw_nic       = G_ni
      Adw_int_i_off = 0
          trj_i_off = l_i0 - 1
      endif
*
      Adw_njc       = l_nj
      Adw_int_j_off = l_j0 - 1
*
      Adw_nit       = Adw_nic + 2 * Adw_halox
      Adw_njt       = Adw_njc + 2 * Adw_haloy
************************************************************************
      call hpalloc ( Adw_xg_8_,   G_ni+2*Adw_halox, pnerr, 8 )
      call hpalloc ( Adw_yg_8_,   G_nj+2*Adw_haloy, pnerr, 8 )
      call hpalloc ( Adw_xx_8_,   Adw_nit,          pnerr, 8 )
      call hpalloc ( Adw_cx_8_,   Adw_nic,          pnerr, 8 )
      call hpalloc ( Adw_sx_8_,   Adw_nic,          pnerr, 8 )
      call hpalloc ( Adw_wx_8_,   Adw_nic,          pnerr, 8 )
      call hpalloc ( Adw_yy_8_,   Adw_njt,          pnerr, 8 )
      call hpalloc ( Adw_cy_8_,   Adw_njc,          pnerr, 8 )
      call hpalloc ( Adw_sy_8_,   Adw_njc,          pnerr, 8 )
      call hpalloc ( Adw_cx2d_8_, l_ni*l_nj,        pnerr, 8 )
      call hpalloc ( Adw_sx2d_8_, l_ni*l_nj,        pnerr, 8 )
      call hpalloc ( Adw_cy2d_8_, l_ni*l_nj,        pnerr, 8 )
      call hpalloc ( Adw_sy2d_8_, l_ni*l_nj,        pnerr, 8 )
************************************************************************
* set global grid                                                      *
************************************************************************
      do i=1,G_ni
      Adw_xg_8(Adw_halox+i)      = G_xg_8(i)
      enddo
*
      if (.not.G_lam) then
      do i=1,Adw_halox
      Adw_xg_8(i)                = Adw_xg_8(G_ni+i)
     %                           - TWO*Dcst_pi_8
      Adw_xg_8(Adw_halox+G_ni+i) = Adw_xg_8(Adw_halox+i)
     %                           + TWO*Dcst_pi_8
      enddo
      else
      prhxmn =  G_xg_8(2)-G_xg_8(1)
      do i=Adw_halox,1,-1
      Adw_xg_8(i)                = Adw_xg_8(i+1)-prhxmn
      enddo
      do i=1,Adw_halox
      Adw_xg_8(Adw_halox+G_ni+i) = Adw_xg_8(Adw_halox+G_ni+i-1)+prhxmn
      enddo
      endif
*
*     Allocation and Initialization for linear interpolation and Lagrange 3D in x  
*     ---------------------------------------------------------------------------
      call hpalloc( Adw_xbc_8_,   G_ni+2*Adw_halox , pnerr, 8 ) ! (xc-xb)     along x
*
      call hpalloc( Adw_xabcd_8_, G_ni+2*Adw_halox , pnerr, 8 ) ! triproducts along x
      call hpalloc( Adw_xbacd_8_, G_ni+2*Adw_halox , pnerr, 8 )
      call hpalloc( Adw_xcabd_8_, G_ni+2*Adw_halox , pnerr, 8 )
      call hpalloc( Adw_xdabc_8_, G_ni+2*Adw_halox , pnerr, 8 )
*
c      Adw_xabcd_8(1:G_ni+2*Adw_halox) = transfer(-1,1.0)
c      Adw_xbacd_8(1:G_ni+2*Adw_halox) = transfer(-1,1.0)
c      Adw_xcabd_8(1:G_ni+2*Adw_halox) = transfer(-1,1.0)
c      Adw_xdabc_8(1:G_ni+2*Adw_halox) = transfer(-1,1.0)
      do i=2,G_ni+2*Adw_halox-2
        ra=Adw_xg_8(i-1)
        rb=Adw_xg_8(i)
        rc=Adw_xg_8(i+1)
        rd=Adw_xg_8(i+2)
*
        Adw_xabcd_8(i) = 1.0/triprd(ra,rb,rc,rd)
        Adw_xbacd_8(i) = 1.0/triprd(rb,ra,rc,rd)
        Adw_xcabd_8(i) = 1.0/triprd(rc,ra,rb,rd)
        Adw_xdabc_8(i) = 1.0/triprd(rd,ra,rb,rc)
      enddo
*
c      Adw_xbc_8(1:G_ni+2*Adw_halox) = transfer(-1,1.0)
      do i=1,G_ni+2*Adw_halox-1
        rb=Adw_xg_8(i)
        rc=Adw_xg_8(i+1)
        Adw_xbc_8  (i) = 1.0/(rc-rb)
      enddo
***
      do j=1,G_nj
      Adw_yg_8 (Adw_haloy+j)     = G_yg_8(j)
      enddo
*
      if (.not.G_lam) then
      Adw_yg_8(Adw_haloy-1)      = -(Dcst_pi_8+Adw_yg_8(Adw_haloy+1) )
      Adw_yg_8(Adw_haloy)        = - Dcst_pi_8*HALF
      Adw_yg_8(Adw_haloy+G_nj+1) =   Dcst_pi_8*HALF
      Adw_yg_8(Adw_haloy+G_nj+2) =  (Dcst_pi_8-Adw_yg_8(Adw_haloy+G_nj))
*
      do j=3,Adw_haloy
      Adw_yg_8(Adw_haloy+1-j)    = TWO*Adw_yg_8(Adw_haloy+1   -j+1)
     %                           -     Adw_yg_8(Adw_haloy+1   -j+2)
      Adw_yg_8(Adw_haloy+G_nj+j) = TWO*Adw_yg_8(Adw_haloy+G_nj+j-1)
     %                           -     Adw_yg_8(Adw_haloy+G_nj+j-2)
      enddo
      else
      prhymn =  G_yg_8(2)-G_yg_8(1)
      do j=Adw_haloy,1,-1
      Adw_yg_8(j)                = Adw_yg_8(j+1)-prhymn
      enddo
      do j=1,Adw_haloy
      Adw_yg_8(Adw_haloy+G_nj+j) = Adw_yg_8(Adw_haloy+G_nj+j-1)+prhymn
      enddo
      endif
*
*     Allocation and Initialization for linear interpolation and Lagrange 3D in y  
*     ---------------------------------------------------------------------------
      call hpalloc( Adw_ybc_8_,   G_nj+2*Adw_haloy , pnerr, 8 ) ! (yc-yb)     along y 
*
      call hpalloc( Adw_yabcd_8_, G_nj+2*Adw_haloy , pnerr, 8 ) ! triproducts along y
      call hpalloc( Adw_ybacd_8_, G_nj+2*Adw_haloy , pnerr, 8 )
      call hpalloc( Adw_ycabd_8_, G_nj+2*Adw_haloy , pnerr, 8 )
      call hpalloc( Adw_ydabc_8_, G_nj+2*Adw_haloy , pnerr, 8 )
*
c      Adw_yabcd_8(1:G_nj+2*Adw_haloy) = transfer(-1,1.0)
c      Adw_ybacd_8(1:G_nj+2*Adw_haloy) = transfer(-1,1.0)
c      Adw_ycabd_8(1:G_nj+2*Adw_haloy) = transfer(-1,1.0)
c      Adw_ydabc_8(1:G_nj+2*Adw_haloy) = transfer(-1,1.0)
      do j=2,G_nj+2*Adw_haloy-2
        ra=Adw_yg_8(j-1)
        rb=Adw_yg_8(j)
        rc=Adw_yg_8(j+1)
        rd=Adw_yg_8(j+2)
*
        Adw_yabcd_8(j) = 1.0/triprd(ra,rb,rc,rd)
        Adw_ybacd_8(j) = 1.0/triprd(rb,ra,rc,rd)
        Adw_ycabd_8(j) = 1.0/triprd(rc,ra,rb,rd)
        Adw_ydabc_8(j) = 1.0/triprd(rd,ra,rb,rc)
      enddo
*
c      Adw_ybc_8(1:G_nj+2*Adw_haloy) = transfer(-1,1.0)
      do j=1,G_nj+2*Adw_haloy-1
        rb=Adw_yg_8(j)
        rc=Adw_yg_8(j+1)
        Adw_ybc_8  (j) = 1.0/(rc-rb)
      enddo
*
************************************************************************
* set advection grid                                                   *
************************************************************************
      do i=1,Adw_nit
         Adw_xx_8 (i) = Adw_xg_8(Adw_int_i_off+i)
      enddo
*
      if (.not.G_lam) then
      do i=1,Adw_nic
         Adw_wx_8(i) =( Adw_xx_8(Adw_halox+i+1)
     %                 -Adw_xx_8(Adw_halox+i-1))*HALF/(TWO*Dcst_pi_8)
      enddo
      endif
      do i=1,Adw_nic
         Adw_cx_8(i) = cos ( Adw_xx_8(Adw_halox+i) )
         Adw_sx_8(i) = sin ( Adw_xx_8(Adw_halox+i) )
      enddo
*
      do j=1,Adw_njt
         Adw_yy_8 (j) = Adw_yg_8(Adw_int_j_off+j)
      enddo
*
      do j=1,Adw_njc
         Adw_cy_8(j) = cos ( Adw_yy_8(Adw_haloy+j) )
         Adw_sy_8(j) = sin ( Adw_yy_8(Adw_haloy+j) )
      enddo
************************************************************************
* fill 2D fields for use in adw_trajsp and adw_trajex                  *
************************************************************************
      do j= 1, l_nj 
      do i= 1, l_ni 
         ij = i + ( j-1 ) * l_ni
         Adw_cy2d_8(ij) = Adw_cy_8 ( j )
         Adw_sy2d_8(ij) = Adw_sy_8 ( j )
         Adw_cx2d_8(ij) = Adw_cx_8 ( trj_i_off + i )
         Adw_sx2d_8(ij) = Adw_sx_8 ( trj_i_off + i )
      enddo
      enddo
************************************************************************
* precompute localisation and interpolation parameters                 *
************************************************************************
*
      Adw_x00_8 = Adw_xg_8(1)
      Adw_y00_8 = Adw_yg_8(1)
      Adw_z00_8 = Geomg_z_8(1)
*
      prhxmn = large
      prhymn = large
      prhzmn = large
*
      do i=1,G_ni+2*Adw_halox-1
      whx(i) = Adw_xg_8(i+1) - Adw_xg_8(i)
      prhxmn = min( whx(i), prhxmn )
      enddo
*
      do j=1,G_nj+2*Adw_haloy-1
      why(j) = Adw_yg_8(j+1) - Adw_yg_8(j)
      prhymn = min( why(j), prhymn )
      enddo
*
      whz(0     ) = 1.0
      whz(G_nk  ) = 1.0
      whz(G_nk+1) = 1.0
      do k=1,G_nk-1
      whz(k) = Geomg_z_8(k+1) - Geomg_z_8(k)
      prhzmn = min( whz(k), prhzmn )
      enddo
*
      Adw_ovdx_8 = 1.0d0/prhxmn
      Adw_ovdy_8 = 1.0d0/prhymn
      Adw_ovdz_8 = 1.0d0/prhzmn
*
      pnx = int(1.0+(Adw_xg_8(G_ni+2*Adw_halox)-Adw_x00_8 )*Adw_ovdx_8)
      pny = int(1.0+(Adw_yg_8(G_nj+2*Adw_haloy)-Adw_y00_8 )*Adw_ovdy_8)
      pnz = int(1.0+(Geomg_z_8(G_nk)           -Adw_z00_8 )*Adw_ovdz_8)
*
      call hpalloc( Adw_lcx_, pnx, pnerr, 0 )
      call hpalloc( Adw_lcy_, pny, pnerr, 0 )
      call hpalloc( Adw_lcz_, pnz, pnerr, 0 )
*
      call hpalloc( Adw_bsx_8_, G_ni+2*Adw_halox , pnerr, 8 )
      call hpalloc( Adw_dlx_8_, G_ni+2*Adw_halox , pnerr, 8 )
      call hpalloc( Adw_dix_8_, G_ni+2*Adw_halox , pnerr, 8 )
*
      call hpalloc( Adw_bsy_8_, G_nj+2*Adw_haloy , pnerr, 8 )
      call hpalloc( Adw_dly_8_, G_nj+2*Adw_haloy , pnerr, 8 )
      call hpalloc( Adw_diy_8_, G_nj+2*Adw_haloy , pnerr, 8 )
*
      call hpalloc( Adw_bsz_8_, G_nk             , pnerr, 8 )
      call hpalloc( Adw_dlz_8_, G_nk+2           , pnerr, 8 )
      call hpalloc( Adw_diz_8_, G_nk+2           , pnerr, 8 )
      call hpalloc( Adw_dbz_8_, G_nk             , pnerr, 8 )
*
      call hpalloc( Adw_iln_  , G_ni                 , pnerr, 0 )
      call hpalloc( Adw_lnr_8_, 2*(G_ni+2*Adw_halox) , pnerr, 8 )
*
      call hpalloc( Adw_qzz_8_, 3 * G_nk , pnerr, 8 )
      call hpalloc( Adw_qzi_8_, 4 * G_nk , pnerr, 8 )
*
      i0 = 1
      do i=1,pnx
      pdfi = Adw_xg_8(1) + (i-1) * prhxmn
      if ( pdfi .gt. Adw_xg_8(i0+1) ) i0 = min(G_ni+2*Adw_halox-1,i0+1)
      Adw_lcx(i) = i0
      enddo
      do i=1,G_ni+2*Adw_halox-1
      Adw_dlx_8(i) =       whx(i)
      Adw_dix_8(i) = 1.0d0/whx(i)
      enddo
      do i=1,G_ni+2*Adw_halox
      Adw_bsx_8(i) = Adw_xg_8(i)
      enddo
*
      j0 = 1
      do j=1,pny
      pdfi = Adw_yg_8(1) + (j-1) * prhymn
      if ( pdfi .gt. Adw_yg_8(j0+1) ) j0 = min(G_nj+2*Adw_haloy-1,j0+1)
      Adw_lcy(j) = j0
      enddo
      do j=1,G_nj+2*Adw_haloy-1
      Adw_dly_8(j) =       why(j)
      Adw_diy_8(j) = 1.0d0/why(j)
      enddo
      do j=1,G_nj+2*Adw_haloy
      Adw_bsy_8(j) = Adw_yg_8(j)
      enddo
*
      k0 = 1
      do k=1,pnz
      pdfi = Geomg_z_8(1) + (k-1) * prhzmn
      if ( pdfi .gt. Geomg_z_8(k0+1) ) k0 = min( G_nk-2, k0+1)
      Adw_lcz(k) = k0
      enddo
      do k=0,G_nk+1                    !! warning note the shift in k !!
      Adw_dlz_8(k-1) =       whz(k)
      Adw_diz_8(k-1) = 1.0d0/whz(k)
      enddo
      do k=1,G_nk
      Adw_bsz_8(k-1) = Geomg_z_8(k)
      Adw_dbz_8(k-1) = ( whz(k) * whz(k) ) * pdov6
      enddo
*
*     Allocation and Initialization for linear interpolation and Lagrange 3D in z  
*     ---------------------------------------------------------------------------
      call hpalloc( Adw_zbc_8_,   G_nk             , pnerr, 8 ) ! (zc-zb)     along z 
*
      call hpalloc( Adw_zabcd_8_, G_nk             , pnerr, 8 ) ! triproducts along z
      call hpalloc( Adw_zbacd_8_, G_nk             , pnerr, 8 )
      call hpalloc( Adw_zcabd_8_, G_nk             , pnerr, 8 )
      call hpalloc( Adw_zdabc_8_, G_nk             , pnerr, 8 )
*
c      Adw_zabcd_8(1:G_nk) = transfer(-1,1.0)
c      Adw_zbacd_8(1:G_nk) = transfer(-1,1.0)
c      Adw_zcabd_8(1:G_nk) = transfer(-1,1.0)
c      Adw_zdabc_8(1:G_nk) = transfer(-1,1.0)
      do k=2,G_nk-2
        ra=Geomg_z_8(k-1)
        rb=Geomg_z_8(k)
        rc=Geomg_z_8(k+1)
        rd=Geomg_z_8(k+2)
*
        Adw_zabcd_8(k) = 1.0/triprd(ra,rb,rc,rd)
        Adw_zbacd_8(k) = 1.0/triprd(rb,ra,rc,rd)
        Adw_zcabd_8(k) = 1.0/triprd(rc,ra,rb,rd)
        Adw_zdabc_8(k) = 1.0/triprd(rd,ra,rb,rc)
      enddo
*
c      Adw_zbc_8(1:G_nk) = transfer(-1,1.0)
      do k=1,G_nk-1
        rb=Geomg_z_8(k)
        rc=Geomg_z_8(k+1)
        Adw_zbc_8(k) = 1.0/(rc-rb)
      enddo
*
      call set_ops8 ( Adw_qzz_8, whz(1), two, .false., G_nk, G_nk, 1 )
      call set_ops8 ( w2       , whz(1), two, .false., G_nk, G_nk, 2 )
*
      w2(1,2) = 1.0
      w2(1,3) = 0.0
      if ( Adw_nkbz_L ) then
         k = G_nk - 1
         w2(2,1) = 0.0
         if ( G_nk. gt. 3 ) then
            w2(2,2) = (whz(1)+whz(2  ))*(1.0+whz(1)/(2.0*whz(2  )))/3.0
            w2(2,3) = (whz(1)+whz(2  ))*(1.0-whz(1)/     whz(2  )) /6.0
            w2(k,1) = (whz(k)+whz(k-1))*(1.0-whz(k)/     whz(k-1)) /6.0
            w2(k,2) = (whz(k)+whz(k-1))*(1.0+whz(k)/(2.0*whz(k-1)))/3.0
         else
            w2(2,2) = ( whz(1)+whz(2) )/2.0
         endif
         w2(k,3) = 0.0
      endif
      w2(G_nk,1) = 0.0
      w2(G_nk,2) = 1.0
*
      call set_trig21 (Adw_qzi_8,Adw_qzi_8(G_nk+1),Adw_qzi_8(2*G_nk+1), 
     %                 dummy,w2(1,1),w2(1,2),w2(1,3),
     %                 1, 1, G_nk, 1, .false.)
*
*     Initialization for localisation indices (used in optimized SETINT/TRILIN) 
*     ------------------------------------------------------------------------- 
      call hpalloc( Adw_Fn_I_   , l_ni*l_nj*l_nk   , pnerr, 0 )
*
      Adw_hor_L = .true.
      Adw_ver_L = .true.
*
c      nij = l_ni*l_nj
c      if (.not.Schm_offline_L) then
c      do k=1,l_nk
c      do j=1,l_nj
c      do i=1,l_ni
c         n = (k-1)*nij + ((j-1)*l_ni) + i
c         Adw_Fn_I (n) = transfer(-1,1.0) 
c      enddo
c      enddo
c      enddo
c      endif
*
************************************************************************
* set 1-D interpolation of grid reflexion across the pole
************************************************************************
      do 10 i=1,G_ni
         ii1 = i+Adw_halox
         if ( Adw_xg_8(ii1) .lt. Adw_xg_8(Adw_halox+1) + Dcst_pi_8 ) then
            Adw_lnr_8(i) = Adw_xg_8(ii1) + Dcst_pi_8
         else
            Adw_lnr_8(i) = Adw_xg_8(ii1) - Dcst_pi_8
         endif
         do j=1,G_ni     
            ii2 = j+Adw_halox
            Adw_iln(i) = j
            if ( Adw_lnr_8(i).ge.Adw_xg_8(ii2) .and. 
     %           Adw_lnr_8(i).lt.Adw_xg_8(ii2+1) ) go to 10
         enddo
 10   continue
*
      return
      end