      module gridtemplates
!$$$  SUBPROGRAM DOCUMENTATION BLOCK
!                .      .    .                                       .
! MODULE:    gridtemplates 
!   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-09
!
! ABSTRACT: This Fortran Module contains info on all the available 
!   GRIB2 Grid Definition Templates used in Section 3 (GDS).
!   Each Template has three parts: The number of entries in the template
!   (mapgridlen);  A map of the template (mapgrid), which contains the
!   number of octets in which to pack each of the template values; and
!   a logical value (needext) that indicates whether the Template needs 
!   to be extended.  In some cases the number of entries in a template 
!   can vary depending upon values specified in the "static" part of 
!   the template.  ( See Template 3.120 as an example )
!
!   This module also contains two subroutines.  Subroutine getgridtemplate
!   returns the octet map for a specified Template number, and
!   subroutine extgridtemplate will calculate the extended octet map
!   of an appropriate template given values for the "static" part of the 
!   template.  See docblocks below for the arguments and usage of these 
!   routines.
!
!   NOTE:  Array mapgrid contains the number of octets in which the 
!   corresponding template values will be stored.  A negative value in
!   mapgrid is used to indicate that the corresponding template entry can
!   contain negative values.  This information is used later when packing
!   (or unpacking) the template data values.  Negative data values in GRIB
!   are stored with the left most bit set to one, and a negative number
!   of octets value in mapgrid() indicates that this possibility should
!   be considered.  The number of octets used to store the data value
!   in this case would be the absolute value of the negative value in 
!   mapgrid().
!  
!
! PROGRAM HISTORY LOG:
! 2000-05-09  Gilbert
! 2003-09-02  Gilbert   -  Added GDT 3.31 - Albers Equal Area
! 2007-04-24  Vuong     -  Added GDT 3.204  Curilinear Orthogonal Grids
! 2008-05-29  Vuong     -  Added GDT 3.32768 Rotate Lat/Lon E-grid
! 2010-05-10  Vuong     -  Added GDT 3.32769 Rotate Lat/Lon Non E-Stagger grid
! 2013-08-06  Vuong     -  Added GDT 3.4,3.5,3.12,3.101,3.140
!
! USAGE:    use gridtemplates
!
! ATTRIBUTES:
!   LANGUAGE: Fortran 90
!   MACHINE:  IBM SP
!
!$$$

      integer,parameter :: MAXLEN=200,MAXTEMP=31

      type gridtemplate
          integer :: template_num
          integer :: mapgridlen
          integer,dimension(MAXLEN) :: mapgrid
          logical :: needext
      end type gridtemplate

      type(gridtemplate),dimension(MAXTEMP) :: templates

      data templates(1)%template_num /0/     !  Lat/Lon 
      data templates(1)%mapgridlen /19/
      data templates(1)%needext /.false./
      data (templates(1)%mapgrid(j),j=1,19) 
     &              /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1/

      data templates(2)%template_num /1/     !  Rotated Lat/Lon 
      data templates(2)%mapgridlen /22/
      data templates(2)%needext /.false./
      data (templates(2)%mapgrid(j),j=1,22) 
     &              /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1,-4,4,4/

      data templates(3)%template_num /2/     !  Stretched Lat/Lon 
      data templates(3)%mapgridlen /22/
      data templates(3)%needext /.false./
      data (templates(3)%mapgrid(j),j=1,22) 
     &              /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1,-4,4,-4/

      data templates(4)%template_num /3/     !  Stretched & Rotated Lat/Lon 
      data templates(4)%mapgridlen /25/
      data templates(4)%needext /.false./
      data (templates(4)%mapgrid(j),j=1,25) 
     &       /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1,-4,4,4,-4,4,-4/

      data templates(5)%template_num /10/     !  Mercator
      data templates(5)%mapgridlen /19/
      data templates(5)%needext /.false./
      data (templates(5)%mapgrid(j),j=1,19)
     &              /1,1,4,1,4,1,4,4,4,-4,4,1,-4,-4,4,1,4,4,4/

      data templates(6)%template_num /20/     !  Polar Stereographic
      data templates(6)%mapgridlen /18/
      data templates(6)%needext /.false./
      data (templates(6)%mapgrid(j),j=1,18) 
     &              /1,1,4,1,4,1,4,4,4,-4,4,1,-4,4,4,4,1,1/

      data templates(7)%template_num /30/     !  Lambert Conformal
      data templates(7)%mapgridlen /22/
      data templates(7)%needext /.false./
      data (templates(7)%mapgrid(j),j=1,22) 
     &              /1,1,4,1,4,1,4,4,4,-4,4,1,-4,4,4,4,1,1,-4,-4,-4,4/

      data templates(8)%template_num /40/     !  Gaussian Lat/Lon
      data templates(8)%mapgridlen /19/
      data templates(8)%needext /.false./
      data (templates(8)%mapgrid(j),j=1,19) 
     &              /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1/

      data templates(9)%template_num /41/     !  Rotated Gaussian Lat/Lon
      data templates(9)%mapgridlen /22/
      data templates(9)%needext /.false./
      data (templates(9)%mapgrid(j),j=1,22) 
     &              /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1,-4,4,4/

      data templates(10)%template_num /42/     !  Stretched Gaussian Lat/Lon
      data templates(10)%mapgridlen /22/
      data templates(10)%needext /.false./
      data (templates(10)%mapgrid(j),j=1,22) 
     &              /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1,-4,4,-4/

      data templates(11)%template_num /43/     !  Strtchd and Rot'd Gaus Lat/Lon
      data templates(11)%mapgridlen /25/
      data templates(11)%needext /.false./
      data (templates(11)%mapgrid(j),j=1,25) 
     &          /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1,-4,4,4,-4,4,-4/

      data templates(12)%template_num /50/    !  Spherical Harmonic Coefficients
      data templates(12)%mapgridlen /5/
      data templates(12)%needext /.false./
      data (templates(12)%mapgrid(j),j=1,5) /4,4,4,1,1/

      data templates(13)%template_num /51/   !  Rotated Spherical Harmonic Coeff
      data templates(13)%mapgridlen /8/
      data templates(13)%needext /.false./
      data (templates(13)%mapgrid(j),j=1,8) /4,4,4,1,1,-4,4,4/

      data templates(14)%template_num /52/   !  Stretch Spherical Harmonic Coeff
      data templates(14)%mapgridlen /8/
      data templates(14)%needext /.false./
      data (templates(14)%mapgrid(j),j=1,8) /4,4,4,1,1,-4,4,-4/

      data templates(15)%template_num /53/   !  Strch and Rot Spher Harm Coeffs
      data templates(15)%mapgridlen /11/
      data templates(15)%needext /.false./
      data (templates(15)%mapgrid(j),j=1,11) /4,4,4,1,1,-4,4,4,-4,4,-4/

      data templates(16)%template_num /90/     !  Space view Perspective
      data templates(16)%mapgridlen /21/
      data templates(16)%needext /.false./
      data (templates(16)%mapgrid(j),j=1,21) 
     &              /1,1,4,1,4,1,4,4,4,-4,4,1,4,4,4,4,1,4,4,4,4/

      data templates(17)%template_num /100/    !  Triangular grid (icosahedron)
      data templates(17)%mapgridlen /11/
      data templates(17)%needext /.false./
      data (templates(17)%mapgrid(j),j=1,11) /1,1,2,1,-4,4,4,1,1,1,4/

      data templates(18)%template_num /110/ !  Equatorial Azimuthal equidistant
      data templates(18)%mapgridlen /16/
      data templates(18)%needext /.false./
      data (templates(18)%mapgrid(j),j=1,16) 
     &              /1,1,4,1,4,1,4,4,4,-4,4,1,4,4,1,1/

       data templates(19)%template_num /120/     !  Azimuth-range 
       data templates(19)%mapgridlen /7/
       data templates(19)%needext /.true./
       data (templates(19)%mapgrid(j),j=1,7) /4,4,-4,4,4,4,1/

       data templates(20)%template_num /1000/     !  Cross Section Grid 
       data templates(20)%mapgridlen /20/
       data templates(20)%needext /.true./
       data (templates(20)%mapgrid(j),j=1,20) 
     &              /1,1,4,1,4,1,4,4,4,4,-4,4,1,4,4,1,2,1,1,2/

       data templates(21)%template_num /1100/     !  Hovmoller Diagram Grid 
       data templates(21)%mapgridlen /28/
       data templates(21)%needext /.false./
       data (templates(21)%mapgrid(j),j=1,28) 
     &    /1,1,4,1,4,1,4,4,4,4,-4,4,1,-4,4,1,4,1,-4,1,1,-4,2,1,1,1,1,1/

       data templates(22)%template_num /1200/     !  Time Section Grid 
       data templates(22)%mapgridlen /16/
       data templates(22)%needext /.true./
       data (templates(22)%mapgrid(j),j=1,16) 
     &              /4,1,-4,1,1,-4,2,1,1,1,1,1,2,1,1,2/

      data templates(23)%template_num /31/     !  Albers Equal Area
      data templates(23)%mapgridlen /22/
      data templates(23)%needext /.false./
      data (templates(23)%mapgrid(j),j=1,22) 
     &              /1,1,4,1,4,1,4,4,4,-4,4,1,-4,4,4,4,1,1,-4,-4,-4,4/

      data templates(24)%template_num /204/     !  Curilinear Orthogonal Grids
      data templates(24)%mapgridlen /19/
      data templates(24)%needext /.false./
      data (templates(24)%mapgrid(j),j=1,19)
     &              /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1/

      data templates(25)%template_num /32768/   ! Rotate Lat/Lon E-grid
      data templates(25)%mapgridlen /19/
      data templates(25)%needext /.false./
      data (templates(25)%mapgrid(j),j=1,19)
     &              /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1/

      data templates(26)%template_num /32769/   ! Rotate Lat/Lon Non-E Stagger grid
      data templates(26)%mapgridlen /21/
      data templates(26)%needext /.false./
      data (templates(26)%mapgrid(j),j=1,21)
     &              /1,1,4,1,4,1,4,4,4,4,4,-4,4,1,-4,4,4,4,1,4,4/
!
!     GDT 3.4 Added (08/05/2013)
!
      data templates(27)%template_num /4/     !  Variable resolution Latitude/Longitude
      data templates(27)%mapgridlen /13/
      data templates(27)%needext /.true./
      data (templates(27)%mapgrid(j),j=1,13)
     &              /1,1,4,1,4,1,4,4,4,4,4,1,1/
!
!     GDT 3.5 Added (08/05/2013)
!
      data templates(28)%template_num /5/     !  Variable resolution rotate Latitude/Longitude
      data templates(28)%mapgridlen /16/
      data templates(28)%needext /.true./
      data (templates(28)%mapgrid(j),j=1,16)
     &              /1,1,4,1,4,1,4,4,4,4,4,1,1,-4,4,4/
!
!     GDT 3.12 Added (08/05/2013)
!
      data templates(29)%template_num /12/     !  Transverse Mercator
      data templates(29)%mapgridlen /22/
      data templates(29)%needext /.false./
      data (templates(29)%mapgrid(j),j=1,22)
     &              /1,1,4,1,4,1,4,4,4,-4,4,1,-4,4,4,1,4,4,-4,-4,-4,-4/
!
!     GDT 3.101 Added (08/05/2013)
!
      data templates(30)%template_num /101/     !  General unstructured grid
      data templates(30)%mapgridlen /4/
      data templates(30)%needext /.false./
      data (templates(30)%mapgrid(j),j=1,4)
     &              /1,4,1,-4/
!
!     GDT 3.140 Added (08/05/2013)
!
      data templates(31)%template_num /140/     !  Lambert Azimuthal Equal Area Projection
      data templates(31)%mapgridlen /17/
      data templates(31)%needext /.false./
      data (templates(31)%mapgrid(j),j=1,17)
     &              /1,1,4,1,4,1,4,4,4,-4,4,4,4,1,4,4,1/

      contains


         integer function getgridindex(number)
!$$$  SUBPROGRAM DOCUMENTATION BLOCK
!                .      .    .                                       .
! SUBPROGRAM:    getgridindex
!   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2001-06-28
!
! ABSTRACT: This function returns the index of specified Grid
!   Definition Template 3.NN (NN=number) in array templates.
!
! PROGRAM HISTORY LOG:
! 2001-06-28  Gilbert
!
! USAGE:    index=getgridindex(number)
!   INPUT ARGUMENT LIST:
!     number   - NN, indicating the number of the Grid Definition
!                Template 3.NN that is being requested.
!
! RETURNS:  Index of GDT 3.NN in array templates, if template exists.
!           = -1, otherwise.
!
! REMARKS: None
!
! ATTRIBUTES:
!   LANGUAGE: Fortran 90
!   MACHINE:  IBM SP
!
!$$$
           integer,intent(in) :: number

           getgridindex=-1

           do j=1,MAXTEMP
              if (number.eq.templates(j)%template_num) then
                 getgridindex=j
                 return
              endif
           enddo

         end function


         subroutine getgridtemplate(number,nummap,map,needext,iret)
!$$$  SUBPROGRAM DOCUMENTATION BLOCK
!                .      .    .                                       .
! SUBPROGRAM:    getgridtemplate 
!   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-09
!
! ABSTRACT: This subroutine returns grid template information for a 
!   specified Grid Definition Template 3.NN.
!   The number of entries in the template is returned along with a map
!   of the number of octets occupied by each entry.  Also, a flag is
!   returned to indicate whether the template would need to be extended.
!
! PROGRAM HISTORY LOG:
! 2000-05-09  Gilbert
!
! USAGE:    CALL getgridtemplate(number,nummap,map,needext,iret)
!   INPUT ARGUMENT LIST:
!     number   - NN, indicating the number of the Grid Definition 
!                Template 3.NN that is being requested.
!
!   OUTPUT ARGUMENT LIST:      
!     nummap   - Number of entries in the Template
!     map()    - An array containing the number of octets that each 
!                template entry occupies when packed up into the GDS.
!     needext  - Logical variable indicating whether the Grid Defintion
!                Template has to be extended.  
!     ierr     - Error return code.
!                0 = no error
!                1 = Undefine Grid Template number.
!
! REMARKS: None
!
! ATTRIBUTES:
!   LANGUAGE: Fortran 90
!   MACHINE:  IBM SP
!
!$$$
           integer,intent(in) :: number
           integer,intent(out) :: nummap,map(*),iret
           logical,intent(out) :: needext

           iret=0

           index=getgridindex(number)

           if (index.ne.-1) then
              nummap=templates(index)%mapgridlen
              needext=templates(index)%needext
              map(1:nummap)=templates(index)%mapgrid(1:nummap)
           else
             nummap=0
             needext=.false.
             print *,'getgridtemplate: Grid Template ',number,
     &               ' not defined.'
             iret=1
           endif

         end subroutine


         subroutine extgridtemplate(number,list,nummap,map)
!$$$  SUBPROGRAM DOCUMENTATION BLOCK
!                .      .    .                                       .
! SUBPROGRAM:    extgridtemplate 
!   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-09
!
! ABSTRACT: This subroutine generates the remaining octet map for a 
!   given Grid Definition Template, if required.  Some Templates can 
!   vary depending on data values given in an earlier part of the 
!   Template, and it is necessary to know some of the earlier entry
!   values to generate the full octet map of the Template.
!
! PROGRAM HISTORY LOG:
! 2000-05-09  Gilbert
! 2013-07-30  Vuong     -  Added GDT 3.4,3.5,3.12,3.101,3.140
!
! USAGE:    CALL extgridtemplate(number,list,nummap,map)
!   INPUT ARGUMENT LIST:
!     number   - NN, indicating the number of the Grid Definition 
!                Template 3.NN that is being requested.
!     list()   - The list of values for each entry in 
!                the Grid Definition Template.
!
!   OUTPUT ARGUMENT LIST:      
!     nummap   - Number of entries in the Template
!     map()    - An array containing the number of octets that each 
!                template entry occupies when packed up into the GDS.
!
! ATTRIBUTES:
!   LANGUAGE: Fortran 90
!   MACHINE:  IBM SP
!
!$$$
           integer,intent(in) :: number,list(*)
           integer,intent(out) :: nummap,map(*)

           index=getgridindex(number)
           if (index.eq.-1) return

           if ( .not. templates(index)%needext ) return
           nummap=templates(index)%mapgridlen
           map(1:nummap)=templates(index)%mapgrid(1:nummap)

           if ( number.eq.120 ) then
              N=list(2)
              do i=1,N
                map(nummap+1)=2
                map(nummap+2)=-2
                nummap=nummap+2
              enddo
           elseif ( number.eq.4 ) then
              NI=list(8)
              do i=1,NI
                map(nummap+1)=4
                nummap=nummap+1
              enddo
              NJ=list(9)
              do i=1,NJ
                map(nummap+1)=-4
                nummap=nummap+1
              enddo
           elseif ( number.eq.5 ) then
              NI=list(8)
              do i=1,NI
                map(nummap+1)=4
                nummap=nummap+1
              enddo
              NJ=list(9)
              do i=1,NJ
                map(nummap+1)=-4
                nummap=nummap+1
              enddo
           elseif ( number.eq.1000 ) then
              N=list(20)
              do i=1,N
                map(nummap+1)=4
                nummap=nummap+1
              enddo
           elseif ( number.eq.1200 ) then
              N=list(16)
              do i=1,N
                map(nummap+1)=4
                nummap=nummap+1
              enddo
           endif

         end subroutine

         integer function getgdtlen(number)
!$$$  SUBPROGRAM DOCUMENTATION BLOCK
!                .      .    .                                       .
! SUBPROGRAM:    getgdtlen
!   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2004-05-11
!
! ABSTRACT: This function returns the initial length (number of entries) in
!   the "static" part of specified Grid Definition Template 3.number.
!
! PROGRAM HISTORY LOG:
! 2004-05-11  Gilbert
!
! USAGE:    CALL getgdtlen(number)
!   INPUT ARGUMENT LIST:
!     number   - NN, indicating the number of the Grid Definition
!                Template 3.NN that is being requested.
!
! RETURNS:     Number of entries in the "static" part of GDT 3.number
!              OR returns 0, if requested template is not found.
!
! REMARKS: If user needs the full length of a specific template that
!    contains additional entries based on values set in the "static" part
!    of the GDT, subroutine extgridtemplate can be used.
!
! ATTRIBUTES:
!   LANGUAGE: Fortran 90
!   MACHINE:  IBM SP
!
!$$$
           integer,intent(in) :: number

           getgdtlen=0

           index=getgridindex(number)

           if (index.ne.-1) then
              getgdtlen=templates(index)%mapgridlen
           endif

         end function


      end

