!-------------------------------------- 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 v4d_zonewnd_ad - ADJ of v4d_zonewnd 
*
#include "model_macros_f.h"
*

      subroutine v4d_zonewnd_ad (px,py,npts,fldu,fldv,wx_8,cox_8,six_8,siy_8,i1,i2,j1,j2, 2,3
     %                           nk,jmin,jmax,ni,nimax,gni,grtypi,degree,var,
     %                           l_north,l_south,kind)
*
      use v4dzone
*
      implicit none
*
      integer npts,i1,i2,j1,j2,nk,jmin,jmax,ni,nimax,gni,degree,kind
*
      real,   pointer, dimension(:)   :: px,py
*
      real fldu(i1:i2,j1:j2,nk),fldv(i1:i2,j1:j2,nk)
*
      character*2 var
*
      character*1 grtypi
*
      real*8 wx_8(*),cox_8(*),six_8(*),siy_8(*)
*
      logical l_north,l_south
*
*author Tanguay M.
*
*revision
* v3_00 - Tanguay M.        - initial MPI version
* v3_11 - Tanguay M.        - select processors at north or south 
*
*object
*     see id section
*
*ADJOINT of
*arguments
* Name         I/O        Description
*----------------------------------------------------------------
* px            I         Position x in INPUT grid
* py            I         Position y in INPUT grid
* npts          I         Number of positions
* fldu-v        I         Wind fields on INPUT grid
* wx            I         Weights on INPUT grid x axe
* cox,six,siy   I         Cosinus or Sinus of INPUT grid axes
* i1-i2         I         Dimension x in INPUT grid
* j1-j2         I         Dimension y in INPUT grid
* nk            I         Dimension z in INPUT grid
* jmin          I         Lower  limit j
* jmax          I         Higher limit j
* ni            I         Period if grid='G', Heart if grid = 'Z'
* nimax         I         ni maximal over all processors
* gni           I         Global dimension of a latitude circle
* grtypi        I         Type of INPUT grid
* degree        I         Degree of interpolation
* var           I         Name of fldsc
* l_north       I         TRUE if processor near north pole
* l_south       I         TRUE if processor near south pole
* kind          I         kind=1=Preparation, kind=2=Closing
*----------------------------------------------------------------
*
*implicits
#include "ptopo.cdk"
*
      integer i,j,k,ier,ig,status
*
      real reverse(2,nk,gni),revsum(2,nk,gni),lineg(2,gni,nk)
*
      real*8 vx_8,vy_8,coef1_8,coef2_8
      real*8, parameter :: ZERO_8 = 0.0
*
*     Zero adjoint variables
*     ----------------------
      do i=1,gni
      do k=1,nk
         reverse(1,k,i) = ZERO_8
         reverse(2,k,i) = ZERO_8
         revsum (1,k,i) = ZERO_8
         revsum (2,k,i) = ZERO_8
      enddo
      enddo
*
      do k=1,nk
      do i=1,gni
         lineg(1,i,k) = ZERO_8
         lineg(2,i,k) = ZERO_8
      enddo
      enddo
*
      vx_8 = 0.0
      vy_8 = 0.0
*
*     Adjoint of
*     --------------------------------
*     Preparation for polar correction
*     --------------------------------
      if(kind.eq.1) then
*
*        Adjoint of
*        Calculations in zone near south pole
*        ------------------------------------
*
*           Adjoint of
*           Estimate value and fill latitude circle at south pole
*           based on ADV_POLW
*           -----------------------------------------------------
            if(V4dz_nzon(2).ne.0) then
*
               j       = jmin 
               coef1_8 = -1.0
               coef2_8 =  1.0
*
               do k=nk,1,-1
*
                  do i=i2,i1,-1
                     ig = i+Ptopo_gindx(1,Ptopo_myproc+1)-1
                     if(ig.ge.1.and.ig.le.gni) then
                        lineg       (2,ig,k) = V4dz_linepolvs(i,k) + lineg(2,ig,k)
                        V4dz_linepolvs( i,k) = ZERO_8
                        lineg       (1,ig,k) = V4dz_linepolus(i,k) + lineg(1,ig,k)
                        V4dz_linepolus( i,k) = ZERO_8
                     elseif(ig.lt.  1) then
                        lineg   (2,ig+gni,k) = V4dz_linepolvs(i,k) + lineg(2,ig+gni,k)
                        V4dz_linepolvs( i,k) = ZERO_8
                        lineg   (1,ig+gni,k) = V4dz_linepolus(i,k) + lineg(1,ig+gni,k)
                        V4dz_linepolus( i,k) = ZERO_8
                     elseif(ig.gt.gni) then
                        lineg   (2,ig-gni,k) = V4dz_linepolvs(i,k) + lineg(2,ig-gni,k)
                        V4dz_linepolvs( i,k) = ZERO_8
                        lineg   (1,ig-gni,k) = V4dz_linepolus(i,k) + lineg(1,ig-gni,k)
                        V4dz_linepolus( i,k) = ZERO_8
                     endif
                  enddo
*
                  do i=gni,1,-1
                     vx_8         = coef1_8 * lineg(2,i,k) * cox_8(i) + vx_8 
                     vy_8         = coef2_8 * lineg(2,i,k) * six_8(i) + vy_8
                     lineg(2,i,k) = ZERO_8
                     vx_8         = lineg(1,i,k) * six_8(i) + vx_8 
                     vy_8         = lineg(1,i,k) * cox_8(i) + vy_8
                     lineg(1,i,k) = ZERO_8
                  enddo
*
                  do i=gni,1,-1
                      lineg(1,i,k) = sngl(wx_8(i) * ( cox_8(i)             * vy_8 )) 
     %              + lineg(1,i,k)
                      lineg(2,i,k) = sngl(wx_8(i) * (-six_8(i) *  siy_8(j) * vy_8 )) 
     %              + lineg(2,i,k)
                      lineg(1,i,k) = sngl(wx_8(i) * ( six_8(i)             * vx_8 )) 
     %              + lineg(1,i,k)
                      lineg(2,i,k) = sngl(wx_8(i) * ( cox_8(i) *  siy_8(j) * vx_8 ))
     %              + lineg(2,i,k)
                  enddo
*
                  vx_8 = 0.0
                  vy_8 = 0.0
*
               enddo
*
            endif
*
*           Adjoint of
*           Gather global first latitude if GRTYPI='Z'
*           -----------------------------------------
            if(l_south.and.grtypi.eq.'Z') then
*
               do k=nk,1,-1
               do i=gni,1,-1
                  reverse(2,k,i) = lineg(2,i,k) + reverse(2,k,i) 
                  lineg  (2,i,k) = ZERO_8
                  reverse(1,k,i) = lineg(1,i,k) + reverse(1,k,i)
                  lineg  (1,i,k) = ZERO_8
               enddo
               enddo
*
               call rpn_comm_Allreduce(reverse,revsum,2*gni*nk,"MPI_REAL",
     $                                 "MPI_SUM","EW",ier)
*
               do i=1,gni
               do k=1,nk
                  reverse(1,k,i) = ZERO_8
                  reverse(2,k,i) = ZERO_8
               enddo
               enddo
*
               do k=nk,1,-1
               do i=ni,1,-1
                  fldv(i,jmin,k) = revsum(2,k,i+Ptopo_gindx(1,Ptopo_myproc+1)-1) 
     %          + fldv(i,jmin,k)
                  fldu(i,jmin,k) = revsum(1,k,i+Ptopo_gindx(1,Ptopo_myproc+1)-1) 
     %          + fldu(i,jmin,k)
               enddo
               enddo
*
               do i=1,gni
               do k=1,nk
                  revsum(1,k,i) = ZERO_8
                  revsum(2,k,i) = ZERO_8
               enddo
               enddo
*
*           Adjoint of
*           Store global first latitude if GRTYPI='G'
*           -----------------------------------------
            elseif(grtypi.eq.'G') then
*
               do k = nk,1,-1
               do i = gni,1,-1
                  fldu (i,jmin,k) = lineg(1,i,k) + fldu(i,jmin,k)
                  lineg(1,   i,k) = ZERO_8
                  fldv (i,jmin,k) = lineg(2,i,k) + fldv(i,jmin,k)
                  lineg(2,   i,k) = ZERO_8
               enddo
               enddo
*
            endif
*
*        Adjoint of
*        Calculations in zone near north pole
*        ------------------------------------
*
*           Adjoint of
*           Estimate value and fill latitude circle at north pole
*           based on ADV_POLW
*           -----------------------------------------------------
            if(V4dz_nzon(1).ne.0) then
*
               j       = jmax 
               coef1_8 =  1.0
               coef2_8 = -1.0
*
               do k= nk,1,-1
*
                  do i=i2,i1,-1
                     ig = i+Ptopo_gindx(1,Ptopo_myproc+1)-1
                     if(ig.ge.1.and.ig.le.gni) then
                        lineg       (2,ig,k) = V4dz_linepolvn(i,k) + lineg(2,ig,k)
                        V4dz_linepolvn( i,k) = ZERO_8
                        lineg       (1,ig,k) = V4dz_linepolun(i,k) + lineg(1,ig,k)
                        V4dz_linepolun( i,k) = ZERO_8
                     elseif(ig.lt.  1) then
                        lineg   (2,ig+gni,k) = V4dz_linepolvn(i,k) + lineg(2,ig+gni,k)
                        V4dz_linepolvn( i,k) = ZERO_8
                        lineg   (1,ig+gni,k) = V4dz_linepolun(i,k) + lineg(1,ig+gni,k)
                        V4dz_linepolun( i,k) = ZERO_8
                     elseif(ig.gt.gni) then
                        lineg   (2,ig-gni,k) = V4dz_linepolvn(i,k) + lineg(2,ig-gni,k)
                        V4dz_linepolvn( i,k) = ZERO_8
                        lineg   (1,ig-gni,k) = V4dz_linepolun(i,k) + lineg(1,ig-gni,k)
                        V4dz_linepolun( i,k) = ZERO_8
                     endif
                  enddo
*
                  do i=gni,1,-1
                     vx_8         = coef1_8 * lineg(2,i,k) * cox_8(i) + vx_8
                     vy_8         = coef2_8 * lineg(2,i,k) * six_8(i) + vy_8
                     lineg(2,i,k) = ZERO_8
                     vx_8         = lineg(1,i,k) * six_8(i) + vx_8
                     vy_8         = lineg(1,i,k) * cox_8(i) + vy_8
                     lineg(1,i,k) = ZERO_8
                  enddo
*
                  do i=gni,1,-1
                     lineg(1,i,k) = sngl(wx_8(i) * ( cox_8(i)             * vy_8 ))
     %             + lineg(1,i,k)
                     lineg(2,i,k) = sngl(wx_8(i) * (-six_8(i) *  siy_8(j) * vy_8 ))
     %             + lineg(2,i,k)
                     lineg(1,i,k) = sngl(wx_8(i) * ( six_8(i)             * vx_8 ))
     %             + lineg(1,i,k)
                     lineg(2,i,k) = sngl(wx_8(i) * ( cox_8(i) *  siy_8(j) * vx_8 ))
     %             + lineg(2,i,k)
*
                  enddo
*
                  vx_8 = 0.0
                  vy_8 = 0.0
*
               enddo
*
            endif
*
*           Adjoint of
*           Gather global last latitude if GRTYPI='Z'
*           -----------------------------------------
            if(l_north.and.grtypi.eq.'Z') then
*
               do k=nk,1,-1
               do i=gni,1,-1
                  reverse(2,k,i) = lineg(2,i,k) + reverse(2,k,i)
                  lineg  (2,i,k) = ZERO_8
                  reverse(1,k,i) = lineg(1,i,k) + reverse(1,k,i)
                  lineg  (1,i,k) = ZERO_8
               enddo
               enddo
*
               call rpn_comm_Allreduce(reverse,revsum,2*gni*nk,"MPI_REAL",
     $                                 "MPI_SUM","EW",ier)
*
               do i=1,gni
               do k=1,nk
                  reverse(1,k,i) = ZERO_8
                  reverse(2,k,i) = ZERO_8
               enddo
               enddo
*
               do k=nk,1,-1
               do i=ni,1,-1
                  fldv(i,jmax,k) = revsum(2,k,i+Ptopo_gindx(1,Ptopo_myproc+1)-1) 
     %          + fldv(i,jmax,k)
                  fldu(i,jmax,k) = revsum(1,k,i+Ptopo_gindx(1,Ptopo_myproc+1)-1) 
     %          + fldu(i,jmax,k)
               enddo
               enddo
*
               do i=1,gni
               do k=1,nk
                  revsum(1,k,i) = ZERO_8
                  revsum(2,k,i) = ZERO_8
               enddo
               enddo
*
*           Store global last latitude if GRTYPI='G'
*           ----------------------------------------
            elseif(grtypi.eq.'G') then
*
               do k=nk,1,-1
               do i=gni,1,-1
                  fldu (i,jmax,k) = lineg(1,i,k) + fldu(i,jmax,k)
                  lineg(1,   i,k) = ZERO_8
                  fldv (i,jmax,k) = lineg(2,i,k) + fldv(i,jmax,k)
                  lineg(2,   i,k) = ZERO_8
               enddo
               enddo
*
            endif

         if(V4dz_nzon(1).gt.0) then
            deallocate( V4dz_linepolun, STAT=status )
            deallocate( V4dz_linepolvn, STAT=status )
         endif
         if(V4dz_nzon(2).gt.0) then
            deallocate( V4dz_linepolus, STAT=status )
            deallocate( V4dz_linepolvs, STAT=status )
         endif
*
*        Additional deallocations
*        ------------------------
         if(npts.gt.0) call v4d_pxpypole (px,py,npts,i1,i2,nk,jmin,jmax,degree,l_north,l_south,2)
*
*     Adjoint of
*     --------------------------------------
*     Deallocations of ZONES internal arrays
*     --------------------------------------
      elseif(kind.eq.2) then
*
*        Accumulate px,py positions in zones near north and south poles
*        --------------------------------------------------------------
         if(npts.gt.0) then
            call v4d_pxpypole (px,py,npts,i1,i2,nk,jmin,jmax,degree,l_north,l_south,1)
         else
            V4dz_nzon(1) = 0
            V4dz_nzon(2) = 0
         endif
*
         if(V4dz_nzon(2).ne.0) then
            allocate ( V4dz_linepolus(i1:i2,nk), STAT=status )
            allocate ( V4dz_linepolvs(i1:i2,nk), STAT=status )
*
*           Zero adjoint variables
*           ----------------------
            do k=1,nk
            do i=i1,i2
               V4dz_linepolus(i,k) = ZERO_8
               V4dz_linepolvs(i,k) = ZERO_8
            enddo
            enddo
         endif
*
         if(V4dz_nzon(1).ne.0) then
            allocate ( V4dz_linepolun(i1:i2,nk), STAT=status )
            allocate ( V4dz_linepolvn(i1:i2,nk), STAT=status )
*
*           Zero adjoint variables
*           ----------------------
            do k=1,nk
            do i=i1,i2
               V4dz_linepolun(i,k) = ZERO_8
               V4dz_linepolvn(i,k) = ZERO_8
            enddo
            enddo
         endif
*
      endif
*
      return
      end