copyright (C) 2001  MSC-RPN COMM  %%%MC2%%%
***s/r traject -- Compute TRAJECTORIES
*
#if defined (NEC)
#define UPWND3 v_upwnd3
#endif

      subroutine traject ( xyzd, t1, dtm, dtp ) 1,8
      implicit none
*
      real t1(*)
      real*8 xyzd(*), dtm, dtp
*
*AUTHORs    M. Desgagne & C. Girard
*
*OBJECT
*
*    *******************************************************************
*    *                                                                 *
*    *               ANDRE ROBERT  SEMI-LAGRANGIAN SCHEME              *
*    *                                                                 *
*    *                            CALCULATES                           *
*    *                                                                 *
*    *                       TRAJECTORIES: x , y , z                   *
*    *                                      d   d   d                  *
*    *                                                                 *
*    *    1. MID-POINT trajectories                                    *
*    *                                                                 *
*    *               ___________________________________               *
*    *              |                                   |              *
*    *              |                                   |              *
*    *              | dr/2  =   [ x (r), y (r), z (r) ] |              *
*    *              |              d      d      d      |              *
*    *              |___________________________________|              *
*    *                                                                 *
*    *                                                                 *
*    *             FUNCTIONS OF UPSTREAM WIND ux , vy , wz             *
*    *                                          d    d    d            *
*    *                                                                 *
*    *        ux (r)  = u0 (r-dr/2)                                    *
*    *          d         d                     _____x                 *
*    *                                             _y                  *
*    *                       where     u0  =  [ u0*s  ] * dt/dx        *
*    *                                   d                             *
*    *                                                                 *
*    *                                                                 *
*    *        vy (r)  = v0 (r-dr/2)                                    *
*    *          d         d                     _____y                 *
*    *                                             _x                  *
*    *                       where     v0  =  [ v0*s  ] * dt/dy        *
*    *                                   d                             *
*    *                                                                 *
*    *                                                                 *
*    *        wz (r)  = w0 (r-dr/2)                                    *
*    *          d         d                                            *
*    *                                           __z                   *
*    *                       where     w0  =  [  w0   ] * dt/dz        *
*    *                                   d                             *
*    *                                                                 *
*    *      FOR STRAIGTH TRAJECTORIES: x  = ux , y  = vy , z  = wz     *
*    *                                  d     d   d     d   d     d    *
*    *                                                                 *
*    *      FOR GREAT CIRCLE TRAJECTORIES    cf    gc_itraj            *
*    *                                                                 *
*    *                                                                 *
*    *    2. DOUBLING the DISPLACEMENTS                                * 
*    *                                                                 * 
*    *               ___________________________________               *
*    *              |                                   |              *
*    *              |                                   |              *
*    *              |  [ x (r), y (r), z (r) ]  =  dr   |              *
*    *              |     d      d      d               |              *
*    *              |___________________________________|              *
*    *   
*    *                                                                 * 
*    *      FOR GREAT CIRCLE TRAJECTORIES    cf    gc_ddisp            * 
*    *                                                                 * 
*    ******************************************************************* 
* 
*ARGUMENTS 
*     _________________________________________________________________ 
*    |         |                                                 |     |
*    |  NAME   | DESCRIPTION                                     | I/O |
*    |---------|-------------------------------------------------|-----|
*    |         |                                                 |     |
*    |    xd   | lagrangian displacement along X                 |  o  |
*    |    yd   | lagrangian displacement along  Y                |  o  |
*    |    zd   | lagrangian displacement along   Z               |  o  |
*    |         |                                                 |     |
*    |    w0   | vertical motion in Z-coord at time t    (work)  |     |
*    |    wm   | vertical motion in Z-coord at time t-dt (work)  |     |
*    |         |                                                 |     |
*    |   u0d   | velocity at departure point along X     (work)  |     |
*    |   v0d   | velocity at departure point along  Y    (work)  |     |
*    |   w0d   | velocity at departure point along   Z   (work)  |     |
*    |         |                                                 |     |
*    |   uxd   | upstream velocity along X               (work)  |     |
*    |   vyd   | upstream velocity along  Y              (work)  |     |
*    |   wzd   | upstream velocity along   Z             (work)  |     |
*    |         |                                                 |     |
*    |   dtm   | timestep lenght (-)                             |  i  |
*    |   dtp   | timestep lenght (+)                             |  i  |
*    |         |                                                 |     |
*    |_________|_________________________________________________|_____|
*
#include "levels.cdk"
#include "dynmem.cdk"
#include "yomdyn.cdk"
#include "yomdyn1.cdk"
#include "topo.cdk"
#include "semilag.cdk"
#include "nbcpu.cdk"
#include "partopo.cdk"
#include "grd.cdk"
*
      real u0d,v0d,w0d,w0,wm,uxd,vyd,wzd,h2d
      pointer (pau0d, u0d(minx:maxx,miny:maxy,*)),
     $        (pav0d, v0d(minx:maxx,miny:maxy,*)),
     $        (paw0d, w0d(minx:maxx,miny:maxy,*)),
     $        (paw0,   w0(minx:maxx,miny:maxy,*)),
     $        (pawm,   wm(minx:maxx,miny:maxy,*)),
     $        (pauxd, uxd(minx:maxx,miny:maxy,*)),
     $        (pavyd, vyd(minx:maxx,miny:maxy,*)),
     $        (pawzd, wzd(minx:maxx,miny:maxy,*)),
     $        (pah2d, h2d(minx:maxx,miny:maxy,*))
      real*8 xd,yd,zd,xd2,yd2,fxx,fyy,fzz
      pointer (paxd,   xd(minx:maxx,miny:maxy,*)),
     $        (payd,   yd(minx:maxx,miny:maxy,*)),
     $        (pazd,   zd(minx:maxx,miny:maxy,*)),
     $        (paxd2, xd2(minx:maxx,miny:maxy,*)),
     $        (payd2, yd2(minx:maxx,miny:maxy,*)),
     $        (pafxx, fxx(minx:maxx,miny:maxy,*)),
     $        (pafyy, fyy(minx:maxx,miny:maxy,*)),
     $        (pafzz, fzz(minx:maxx,miny:maxy,*))
      integer   i, j, k, id, jd, iff, jf, iter
      real*8  zero, pt5, one, two, epsilon, pt5dt, double, c1,
     $        ebound, wbound, sbound, nbound, tbound, bbound
      character*3 lag_intp ! main choices: 'cub', 'qua', 'lin'
      real*8  lat0      ! to come from dynmem
      logical gc_traj   ! to come from yomdyn?
      logical lin_advec ! to come from semilag?
      real hor_wind     ! to come from?
      parameter (zero = 0.0d0, pt5 = 0.5d0, one = 1.0d0,
     $           two = 2.0d0, epsilon = 1.d-8)
*
*--------------------------------------------------------------------
      paxd  = loc(xyzd(        1))
      payd  = loc(xyzd(  dim3d+1))
      pazd  = loc(xyzd(2*dim3d+1))
      paxd2 = loc(xyzd(3*dim3d+1))
      payd2 = loc(xyzd(4*dim3d+1))
      pafxx = loc(xyzd(5*dim3d+1))
      pafyy = loc(xyzd(6*dim3d+1))
      pafzz = loc(xyzd(7*dim3d+1))
      pau0d = loc(t1  (        1))
      pav0d = loc(t1  (  dim3d+1))
      paw0d = loc(t1  (2*dim3d+1))
      paw0  = loc(t1  (3*dim3d+1))
      pawm  = loc(t1  (4*dim3d+1))
      pauxd = loc(t1  (5*dim3d+1))
      pavyd = loc(t1  (6*dim3d+1))
      pawzd = loc(t1  (7*dim3d+1))
      pah2d = loc(t1  (8*dim3d+1))
*
      lag_intp = "cub"
*
      gc_traj=.false.
      gc_traj=gc_traj.and.(Grd_proj_S.eq.'L'.or.Grd_proj_S.eq.'M')
*
*     Free-slip solid wall on top and bottom boundaries
*
      bbound = one          + epsilon
      tbound = dble(gnk-1)  - epsilon
*
*     Free-slip solid wall on processor horizontal boundaries
*     if courant number exceeds what is allowed by hx and hy
*
      wbound = dble(1            - hx + 1) + epsilon
      ebound = dble(ldni - east  + hx - 1) - epsilon
      sbound = dble(1            - hy + 1) + epsilon
      nbound = dble(ldnj - north + hy - 1) - epsilon
*
      pt5dt = pt5 * dble(grdt)
*
*    1A) Compute vertical motion in coordinate space
*
      call sw2w3(w0,uu0,vv0,ww0,sbxy,gg1,gg2,g0wr,dhdt,
     $                        minx,maxx,miny,maxy,gnk)
      call sw2w3(wm,uum,vvm,wwm,sbxy,gg1,gg2,g0wr,dhdt,
     $                        minx,maxx,miny,maxy,gnk)
*
*    1B) Compute u0d, v0d, w0d
*        and first guesses for xd,  yd,  zd
*        based on extrapolated winds: 2*u0-um,2*v0-vm,2*w0-wm
*
*  upwind-point range
*
      id =1-hx*west
      jd =1-hy*south
      iff=ldni+(hx-1)*east
      jf =ldnj+(hy-1)*north
*
!$omp do
      do k=1,gnk-1
      do j=jd,jf
      do i=id,iff
         xd(i,j,k) = min(dble(i)-wbound,max(dble(i)-ebound,dble(pt5dt
     $        * ((two*uu0(i  ,j,k)-uum(i  ,j,k))*sby(i  ,j)*odxu(1) +
     $           (two*uu0(i+1,j,k)-uum(i+1,j,k))*sby(i+1,j)*odxu(1) ))))
         u0d(i,j,k)= pt5dt * ( uu0(i  ,j,k) *sby(i  ,j)*odxu(1)
     $                       + uu0(i+1,j,k) *sby(i+1,j)*odxu(1) )
         yd(i,j,k) = min(dble(j)-sbound,max(dble(j)-nbound,dble(pt5dt
     $        * ((two*vv0(i,j  ,k)-vvm(i,j  ,k))*sbx(i,j  )*odyv(j  ) +
     $           (two*vv0(i,j+1,k)-vvm(i,j+1,k))*sbx(i,j+1)*odyv(j+1) ))))
         v0d(i,j,k)= pt5dt * ( vv0(i,j  ,k) *sbx(i,j  )*odyv(j  )
     $                       + vv0(i,j+1,k) *sbx(i,j+1)*odyv(j+1) )
         zd(i,j,k) = min(dble(k)-bbound,max(dble(k)-tbound,dble(pt5dt
     $        * ((two*w0(i,j,k  )-wm(i,j,k  )) +
     $           (two*w0(i,j,k+1)-wm(i,j,k+1)) ))))
         w0d(i,j,k)= pt5dt * ( ww0(i,j,k  ) - dhdt(i,j,k  )
     $                       + ww0(i,j,k+1) - dhdt(i,j,k+1) )
      end do
      end do
      end do
!$omp enddo
*
      lin_advec=.false.
      if (lin_advec) then
         hor_wind=10.  ! obviously a case dependent value !
!$omp do
         do k=1,gnk-1
         do j=jd,jf
         do i=id,iff
            xd (i,j,k) = min(dble(i)-wbound,max(dble(i)-ebound,
     $                   dble(grdt)*dble(hor_wind)*odxu(1)))
            u0d(i,j,k) = dble(grdt)*dble(hor_wind)*odxu(1)
            zd (i,j,k) = 0.0
            w0d(i,j,k) = 0.0
         end do
         end do
         end do
!$omp enddo
      endif
*
!$omp single
      call rpn_comm_xch_halo (u0d,minx,maxx,miny,maxy,ldni,ldnj,
     $                        4*gnk,hx,hy,period_x,period_y,ldni,0)
!$omp end single
*
*    1C) Compute iteratively u0 (r-dr),v0 (r-dr),w0 (r-dr)
*                              d         d         d
      do 100 iter = 1, Tsl_iter
*
      call UPWND3 ( uxd, u0d, xd, yd, zd, fxx, fyy, fzz,
     $              minx,maxx,miny,maxy,gnk-1,0,0,lag_intp)
*
      if (.not.gc_traj) then
!$omp do
         do k=1,gnk-1
         do j=1,ldnj-north
         do i=1,ldni-east
            xd(i,j,k) = min(dble(i)-wbound,
     $                  max(dble(i)-ebound,dble(uxd(i,j,k))))
         end do
         end do
         end do
!$omp enddo
      endif
*
      call UPWND3 ( vyd, v0d, xd, yd, zd, fxx, fyy, fzz,
     $              minx,maxx,miny,maxy,gnk-1,0,0,lag_intp)
*
      if (.not.gc_traj) then
!$omp do
         do k=1,gnk-1
         do j=1,ldnj-north
         do i=1,ldni-east
            yd(i,j,k) = min(dble(j)-sbound,
     $                  max(dble(j)-nbound,dble(vyd(i,j,k))))
         end do
         end do
         end do
!$omp enddo
*
      else
!$omp single
         call gc_itraj ( xd, yd, uxd, vyd, lat0, minx,maxx,miny,maxy )
!$omp end single
      endif
*
*     semi-lagrangian calculation of W
*
!$omp do
      do k=1,gnk-1
         do j=1,ldnj-north
         do i=1,ldni-east
            xd2(i,j,k) = min(dble(i)-wbound,
     $                   max(dble(i)-ebound,two*xd(i,j,k)))
            yd2(i,j,k) = min(dble(j)-sbound,
     $                   max(dble(j)-nbound,two*yd(i,j,k)))
         end do
         end do
      end do
!$omp enddo
*
      call UPWND3 ( wzd, w0d, xd, yd, zd, fxx, fyy, fzz,
     $              minx,maxx,miny,maxy,gnk-1,0,0,lag_intp)
*
      call UPWND3 ( h2d, hm(minx,miny,1), xd2, yd2, zd, fxx, fyy, fzz,
     $              minx,maxx,miny,maxy,gnk-1,0,0,'bcu')
*
!$omp do
      do k=1,gnk-1
      do j=1,ldnj-north
      do i=1,ldni-east
         c1 = (wzd(i,j,k)-pt5*(hm(i,j,k)-h2d(i,j,k)))*gg0r(i,j,k)
         zd(i,j,k) = min(dble(k)-bbound,max(dble(k)-tbound,c1))
      end do
      end do
      end do
!$omp enddo
*
 100  continue
*
      double = ( dtm + dtp ) / dble(grdt)
*
*--------------------------------------------------------------------
*
*    2) Doubling the displacements
*
      double = ( dtm + dtp ) / dble(grdt)
*
      if (gc_traj.and.double.gt.1.01d0) then
*
!$omp do
         do j=1,ldnj-north
         do i=1,ldni-east
            xd(i,j,gnk) = double *xd(i,j,gnk-1)
            yd(i,j,gnk) = double *yd(i,j,gnk-1)
            zd(i,j,gnk) = 0.0d0
         end do
         end do
!$omp enddo
*
!$omp single
         call gc_ddisp ( xd, yd, lat0, minx, maxx, miny, maxy )
!$omp end single
*
!$omp do
         do k=1,gnk
            do j=1,ldnj-north
            do i=1,ldni-east
               zd(i,j,k) = double * zd(i,j,k)
            end do
            end do
         end do
!$omp enddo
*
      else
*
!$omp do
         do k=1,gnk-1
         do j=1,ldnj-north
         do i=1,ldni-east
            xd(i,j,k) = double * xd(i,j,k)
            yd(i,j,k) = double * yd(i,j,k)
            zd(i,j,k) = double * zd(i,j,k)
         end do
         end do
         end do
!$omp enddo
*
!$omp do
         do j=1,ldnj-north
         do i=1,ldni-east
            xd(i,j,gnk) = xd(i,j,gnk-1)
            yd(i,j,gnk) = yd(i,j,gnk-1)
            zd(i,j,gnk) = 0.d0
         end do
         end do
!$omp enddo
*
      endif
*
*----------------------------------------------------------------------
      return
      end