!-------------------------------------- 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 zongini - initialization of the zonal diagnostics package
*
#include "model_macros_f.h"
*

      subroutine zongini 1,4
      implicit none
*
*author andre methot - cmc - aug 1994 - v0_14
*
*revision
* v2_31 - Methot A. and Dugas B.
* v2_31 -               - generalized weight and bin calculation
* v2_31 -                 for rotated or variable grids
* v2_31 - Dugas B.      - account for MPI geometry
* v3_00 - Desgagne & Lee    - Lam configuration
* v3_30 - Desgagne M.   - new physics interface
* v3_30 - Winger K.     - call inzono3 instead of inzono2
*                         with variable names as 
*                         characters instead of r4a
*                       - initialize theta and poid
*                       - allow LAM grids, therefore
*                         - make fielda allocatable
*                         - change G_ni,G_nj to PG_ni,PG_nj
*                         - pass nbin to inzono3
*
*object
*               This routine initializes the variables used by
*      the zonal diagnostic package: number of timesteps between
*      saves (P_zong_znli), the mode (P_zong_znmod), the lenght of
*      the time steps, the list of nomvar names to extract,
*      informations about the grid,...etc...etc.
*	
*arguments
*	none
*
*notes
*       the code takes into account all grid rotations.
*  Each grid point is placed in the appropriate latitude
*  band according to its real geographical latitude.
*
*  Within each latitude band, grid points are weighted
*  according to their actual horizontal area coverage
*  on the sphere.
*
*implicits
#include "glb_ld.cdk"
#include "glb_pil.cdk"
#include "dcst.cdk"
#include "cstv.cdk"
#include "p_zong.cdk"
*
#include "grd.cdk"
#include "geomg.cdk"
#include "geomn.cdk"
*
#include "lun.cdk"
#include "out3.cdk"
#include "rstr.cdk"
*
#include "itf_phy_config.cdk"
*
#include "ptopo.cdk"
*
**
*     INZONO3 arguments pour which will be calculated here
*
      integer,  dimension (:,:), allocatable :: rang
      real,     dimension (:,:), allocatable :: poid, theta
      integer   ndelt,nlatmn
      character noutzon_S*256
*
*     Work space for coordinate calculations
*
      integer,  dimension (:), allocatable :: boxlat
      real*8,   dimension (:), allocatable :: hxu, hyv
      real,     dimension (:), allocatable :: lon, lat
      real*8,   dimension (:), allocatable :: lonr, latr
      real*8,   dimension (:), allocatable :: cosy, siny, cosx, sinx
      real*8,   dimension (:), allocatable :: cart, carot
      integer   irot
      real*8    ri_8(3,3)
      real      polon,polat,rot
*
      logical debug_L
      character*6 dummy_S,mype_S
      integer i,j,k,l, ij,jj, ni,nj, nbin, nvar,cnt
      integer PG_ni,PG_nj, PG_ni0,PG_nj0
      real*8  mp(3,2),mt(2,3), sinteta,costeta, thetaz
      real*8  dlat,latmn, norm, pis2, rmp
*
      integer fnom,ierr
      external fnom
*
*     ---------------------------------------------------------------
*
*     Allocate variables
*
      if (G_lam) then
        PG_ni0 = Glb_pil_w - 3
        PG_nj0 = Glb_pil_s - 3
        PG_ni  = G_ni  - Glb_pil_e - Glb_pil_w + 6
        PG_nj  = G_nj  - Glb_pil_n - Glb_pil_s + 6
      else
        PG_ni0 = 0
        PG_nj0 = 0
        PG_ni  = G_ni
        PG_nj  = G_nj
      endif
*
      allocate (rang(PG_ni,PG_nj))
      allocate (poid(PG_ni,PG_nj), theta(PG_ni,PG_nj))
*
      allocate (boxlat(PG_nj))
      allocate (hxu(0:PG_ni+1), hyv(0:PG_nj+1))
      allocate (lon((PG_ni+1)*PG_nj), lat((PG_ni+1)*PG_nj))
      allocate (lonr((PG_ni+1)*PG_nj),latr((PG_ni+1)*PG_nj))
      allocate (cosy(PG_nj),siny(PG_nj),cosx(PG_ni+1),sinx(PG_ni+1))
      allocate (cart(3*(PG_ni+1)*PG_nj),carot(3*(PG_ni+1)*PG_nj))
*
*     ---------------------------------------------------------------
*
      debug_L = .false. 
**
      irot = 999
      pis2 = Dcst_pi_8/2.0
*
*     Build the name of the zonal diagnostic output file
*
      write (dummy_S,'(i2.2,"_",i2.2)') Ptopo_mycol,Ptopo_myrow
      cnt=0
      mype_S=""
      do i=1,6
         if (dummy_S(i:i).ne." ") then
            cnt=cnt+1
            mype_S(cnt:cnt) = dummy_S(i:i)
         endif
      end do
*
      noutzon_S =  'zonaux_' // mype_S
*
      if ( P_zong_znli  .le. 0 .or.
     &   ( P_zong_znprf .le. 0 .and.
     &     P_zong_znsrf .le. 0 )) then
*
*        Nothing to do
*
         if (Lun_out.gt.0) write(Lun_out,1100)
         goto 700
*
      else if ( Rstri_rstn_L ) then
*
*        Initializing Lun_zonl for MZONOPR
*
         Lun_zonl = 0
         ierr = fnom( Lun_zonl, noutzon_S, 'STD+RND',0 )
*
         if (ierr.ne.0) then
*
*           Cannot open noutzon_S, disabling zonal diagnostics
*
            Lun_zonl    = -1
            P_zong_znli =  0
*
            if (Lun_out.gt.0) write(Lun_out,1300) trim( noutzon_S )
*
            goto 700
*
         endif
*
         call fclos( Lun_zonl )
*
         if (Lun_out.gt.0) write(Lun_out,1001)
         goto 600
*
      endif
*
      if (Lun_out.gt.0) write(Lun_out,1000)
      if (Lun_out.gt.0) write(Lun_out,1001)
*
*
*C     1. Calculates weights, row indicies, and angles
*         --------------------------------------------
*
 100  continue
*
      ni    = PG_ni+1
      if (G_lam)
     &ni    = PG_ni
      nj    = PG_nj
*
      nbin  = P_zong_nbin
      dlat  = 180./nbin           
      latmn = -90.0
*
      if ( .not. Grd_roule ) then
*
         if (.not. G_lam) nbin = min( nbin, PG_nj )
         dlat = 180./nbin
         irot = 0
*
         ij = 0
         do j=1,nj
         do i=1,ni
            ij = ij+1
            lat(ij) = Geomn_latgs(j+PG_nj0)
            lon(ij) = Geomn_longs(i+PG_ni0)
         end do
         end do
*     
      else
*
*        Calcul des latitudes et longitudes de la
*        grille tournee dans le cadre non-tourne
*
         call llacar( cart, Geomn_longs(PG_ni0+1:PG_ni0+ni),
     +                      Geomn_latgs(PG_nj0+1:PG_nj0+nj), ni,nj )
*
         do i=1,3
         do j=1,3
            ri_8(i,j) = Grd_rot_8(j,i)
         end do
         end do
*
         call mxma8( ri_8,1,3,cart,1,3,carot,1,3, 3,3, ni*nj )
         call cartall( lon, lat, carot, ni*nj)
*
*        Calcul de l'angle entre les poles des deux grilles
*
         call llacar( cart, 90.,90., 1,1 )
         call mxma8 (ri_8,1,3,cart,1,3,carot,1,3, 3,3,1)
         call cartall( polon, polat, carot, 1 )
*
         rot  = 90. - polat
         irot = nint( rot )
*
         do i=1,ni*nj
            lon(i)  = mod(lon(i) + 360.0,360.0)
            lonr(i) = lon(i)*Dcst_pi_8/180.
            latr(i) = lat(i)*Dcst_pi_8/180.
         end do
*
      endif
*
*     Pre-calcul de certains autres facteurs trigonometriques globaux
*
      hyv(0) = (G_yg_8(2+PG_nj0)- G_yg_8(PG_nj0)) * 0.5
      hxu(0) = (G_xg_8(2+PG_ni0)- G_xg_8(PG_ni0)) * 0.5
*
      do j=1,nj
         cosy(j) = cos( G_yg_8(j+PG_nj0) )
         siny(j) = sin( G_yg_8(j+PG_nj0) )
         hyv(j)  = (G_yg_8(j+2+PG_nj0)- G_yg_8(j+PG_nj0)) * 0.5
      end do

      do i=1,ni
         cosx(i) = cos( G_xg_8(i+PG_ni0) )
         sinx(i) = sin( G_xg_8(i+PG_ni0) )
         hxu(i)  = (G_xg_8(i+2+PG_ni0)- G_xg_8(i+PG_ni0)) * 0.5
      end do
*
      if ( irot.ne.0 .and. Lun_out.gt.0) write(Lun_out,1200)
*
*     Boucle sur les nbin bandes de latitudes geographiques
*
      theta = 0.
      poid  = 0.
      do 105 jj=1,nbin
*
         boxlat(jj) = 0
         thetaz     = latmn + (jj-1)*dlat
         norm       = 0.
*
         if ( irot .eq. 0 )
     &      theta(jj,1) = thetaz
*
*         Boucle sur le domaine complet pour l'identification
*         de tous les points pour UNE BANDE jj DONNEE 

         do 102 j=1,PG_nj 
         do 102 i=1,PG_ni
*
            ij = (j-1)*ni+i
*
            if (  ( lat(ij) .ge. thetaz ) .and.
     &            ( lat(ij) .lt. thetaz+dlat ) ) then
*
               poid(i,j) = hxu(i-1)*hyv(j-1)*cosy(j)
*                          delta X  delta Y  map scale
*
               norm       = norm + poid(i,j)
               boxlat(jj) = boxlat(jj)+1
               rang(i,j)  = jj
*
*C             2. Calcul de la matrice de rotation des vents
*                 ------------------------------------------
*
               if ( irot.ne.0 ) then
*
*                 Definir les composantes requises de M' 
*                 [ ou M':(u,v)geo --> (dx/dt,dy/dt,dz/dt)geo ]
                  mp(1,1) = -sin( lonr(ij) )
                  mp(2,1) =  cos( lonr(ij) )
                  mp(3,1) =  0.0
CCC               mp(1,2) = -sin( latr(ij) )*cos( lonr(ij) )
CCC               mp(2,2) = -sin( latr(ij) )*sin( lonr(ij) )
CCC               mp(3,2) =  cos( latr(ij) )
*
*                 Definir les composantes de MT, la transposee de M
*                 [ ou M:(u,v)mod --> (dx/dt,dy/dt,dz/dt)mod ]
                  mt(1,1) = -sinx(i)
                  mt(1,2) =  cosx(i)
                  mt(1,3) =  0.0
                  mt(2,1) = -siny(j)*cosx(i)
                  mt(2,2) = -siny(j)*sinx(i)
                  mt(2,3) =  cosy(j)
*
*                 Calculer la premiere colonne du produit MT RT M' = TT
*                 [ ou R:(repere modele) --> (repere geographique) ] 
                  sinteta = 0.0
                  costeta = 0.0
*
*                 On ne calcule donc que -TT(1,1) (= sin(theta)) et
*                 TT(2,1) (= cos(theta) dans la routine mvznxst)
*
                  do k=1,3
                     rmp       = 0.0
                     do l=1,3
                        rmp    = rmp+Grd_rot_8(k,l)*mp(l,1)
                     enddo
                     sinteta   = sinteta - mt(1,k)*rmp
                     costeta   = costeta + mt(2,k)*rmp
                  enddo
*
*                 Trouver theta a partir de sin(theta) et cos(theta)
                  if ( costeta .ne. 0.0 ) then
                     theta(i,j) = atan( sinteta/costeta )
                  else if ( sinteta .gt. 0.0 ) then
                     theta(i,j) = pis2
                  else if ( sinteta .lt. 0.0 ) then
                     theta(i,j) = -pis2
                  endif
*
*                 theta est defini dans l'interval [ -pi , +pi ]
                  if ( costeta .lt. 0.0 ) then
                     if ( sinteta .ge. 0.0 ) then
                        theta(i,j) = theta(i,j) + Dcst_pi_8
                     else
                        theta(i,j) = theta(i,j) - Dcst_pi_8
                     endif
                  endif
*
               endif
*
            endif
 102     continue
*
*         Deuxieme boucle sur le domaine complet pour la normalisation
         do 104 j=1,PG_nj
         do 104 i=1,PG_ni
            if (  rang(i,j) .eq. jj ) then
               poid(i,j)=poid(i,j) / norm
            endif
 104     continue 
*
 105  continue
*
*C     3. Variable types conversion for compatibility with package
*         --------------------------------------------------------
*
*     The zonal diagnostic package should be revised ( inzono )
*     such that those conversions become un-necessary.
*
      ndelt  = nint( Cstv_dt_8 )
      nlatmn = nint( latmn )
*
*
*     Print debug-mode information (1)
*
      if (  debug_L .and. Lun_out.gt.0 ) then
         write(Lun_out,*) 'znprf: ', (P_zong_znprf_s(nvar),
     +                         nvar=1,P_zong_znprf)
         write(Lun_out,*) 'znsrf: ', (P_zong_znsrf_s(nvar),
     +                         nvar=1,P_zong_znsrf)
         write(Lun_out,*) 'rot:   ', irot
         write(Lun_out,*) 'Poids: ', poid
         write(Lun_out,*) 'Rangs: ', rang
         write(Lun_out,*) 'Theta: ', theta
         write(Lun_out,*) 'P_zong_znli' , P_zong_znli
      endif
*
*C     4. writes information records on zonal standard file
*         -------------------------------------------------
*
      call inzono3(poid, rang, theta, P_zong_znli, ndelt,
     %       P_zong_znmod, P_zong_znsrf, P_zong_znsrf_s, P_zong_znprf,
     %       P_zong_znprf_s, nlatmn, irot, Lun_zonl, Geomg_hyb, Out3_etik_s,
     %       Out3_date, PG_ni, PG_nj, G_nk, nbin, Lun_out,
     %       trim( noutzon_S ))
*
*
 600  continue
*
*     Print debug-mode information (2)
*
      if (  debug_L .and. Lun_out.gt.0 ) then
         write(Lun_out,*) 'noutzon_S ', trim( noutzon_S )
         write(Lun_out,*) 'Lun_zonl ', Lun_zonl
      endif
*
      call mzonfil( noutzon_S )
*
 700  continue
*
 1000 format(/,'INIT OF ZONAL DIAGNOSTICS PACKAGE (S/R ZONGINI)',
     +       /,'===============================================')
 1001 format(/,'INIT OF EXTRACTORS FOR ZONAL DIAGNOSTICS (S/R ZONGINI)',
     +       /,'======================================================')
 1100 format(/,'NO ZONAL DIAGNOSTICS REQUESTED (S/R ZONGINI)',
     +       /,'============================================')
 1200 format(' Note that the local rotation angles will',
     +       ' be passed on to INZONO3')
 1300 format(/,'UNABLE TO OPEN ZONAL DIAGNOSTICS FILE ',A,
     +       /,'DISABLING FURTHER PROCESSING BY PACKAGE ')
*
*     ---------------------------------------------------------------
*
      return
      end