module init_grib2

 contains

 subroutine grib2_init(gfld)

!-----------------------------------------------------------
! initialize data structure required for grib 2 library
! with default values.
!-----------------------------------------------------------
 
 use grib_mod

 use program_setup, only   : imdl, jmdl, &
                             domain_type, dx_mdl,      &
                             dy_mdl,      &
                             centlat_parent_mdl, &
                             centlon_parent_mdl

 use calc_latlons, only    : lat_first_hpnt_unrot_mdl, &
                             lon_first_hpnt_unrot_mdl, &
                             lat_first_mdl, lon_first_mdl, &
                             lat_last_mdl, lon_last_mdl

 implicit none

 include 'mpif.h'

 integer          :: iret

 real             :: lat_last_hpnt_unrot_mdl
 real             :: lon_last_hpnt_unrot_mdl
 real             :: scale

 type(gribfield)  :: gfld

 nullify(gfld%idsect)
 nullify(gfld%local)
 nullify(gfld%list_opt)
 nullify(gfld%igdtmpl)
 nullify(gfld%ipdtmpl)
 nullify(gfld%coord_list)
 nullify(gfld%idrtmpl)
 nullify(gfld%bmap)
 nullify(gfld%fld)

! *** Section 0 ***

 gfld%version = 2
 gfld%discipline = 2

! *** Section 1 ***

 gfld%idsectlen=13
 allocate(gfld%idsect(gfld%idsectlen))
 gfld%idsect(1) = 7 ! octs 6-7; center (ncep)
 gfld%idsect(2) = 4 ! octs 8-9; subcenter (emc)
 gfld%idsect(3) = 8 ! oct 10;   grib master table version number
! note!! to use a parmeter number >= 192 you must set the local table to '1'
 gfld%idsect(4) = 1 ! oct 11;   local table
 gfld%idsect(5) = 0 ! oct 12;   significance of reference time (analysis time)
 gfld%idsect(6) = 1900 ! octs 13-14;  year
 gfld%idsect(7) = 1    ! oct 15; month
 gfld%idsect(8) = 1    ! oct 16; day
 gfld%idsect(9) = 0    ! oct 17; hour
 gfld%idsect(10) = 0   ! oct 18; minute
 gfld%idsect(11) = 0   ! oct 19; seconds
 gfld%idsect(12) = 0   ! oct 20; production status (operational product)
 gfld%idsect(13) = 0   ! oct 21; type of data (analysis products)

! *** Section 2 ***

 gfld%locallen=0

! *** Section 3 ***

 if (trim(domain_type) == 'bgrid') then
   gfld%igdtlen=22
   allocate(gfld%igdtmpl(gfld%igdtlen))
   gfld%griddef = 0         ! oct 6;  source of grid definition, specified in table 3.1
   gfld%ngrdpts = imdl*jmdl ! octs 7-10; number of grid points
   gfld%numoct_opt = 0      ! oct 11; number of octs for optional list of numbers defining # of grid points
                            ! oct 12; list of #s defining # of points
   gfld%igdtnum=1           ! octs 13-14; grid definition template number, template 3.1 - rotated lat/lon
   gfld%igdtmpl(1)=6         ! oct 15; shape of the earth, spherical with radius 6371229 meters.
   gfld%igdtmpl(2)=255       ! oct 16; scale factor of radius of spherical earth, not used.
   gfld%igdtmpl(3)=-1        ! octs 17-20; scale value of radius of spherical earth, not used.
   gfld%igdtmpl(4)=255       ! oct 21; scale factor of major axis of elliptical earth, not used.
   gfld%igdtmpl(5)=-1        ! octs 22-25; scaled value of major axis of elliptical earth, not used.
   gfld%igdtmpl(6)=255       ! oct 26; scale factor of minor axis of elliptical earth, not used.
   gfld%igdtmpl(7)=-1        ! octs 27-30; scaled value of minor axis of elliptical earth, not used.
   gfld%igdtmpl(8)=imdl       ! octs 31-34; # "i" points
   gfld%igdtmpl(9)=jmdl       ! octs 35-38; # "j" points
   gfld%igdtmpl(10)=1         ! octs 39-42; basic angle
   gfld%igdtmpl(11)=10**6     ! octs 43-46; subdivisions of basic angle
   scale=float(gfld%igdtmpl(10)*gfld%igdtmpl(11))

!  Note: for rotated lat/lon grids, the lat/lon of the corner points is the unrotated value.
!  The ecmwf and german wx service do it this way.  And wgrib2 assumes this as well (when
!  doing the -ijlat option). The grib 2 manual is unclear.

   gfld%igdtmpl(12)=nint(lat_first_hpnt_unrot_mdl*scale)  ! octs 47-50; lat of first grid point
   if (lon_first_hpnt_unrot_mdl < 0.0) then
     gfld%igdtmpl(13)=nint((lon_first_hpnt_unrot_mdl+360.0)*scale)  ! octs 51-54; lon of first grid point
   else
     gfld%igdtmpl(13)=nint(lon_first_hpnt_unrot_mdl*scale)
   endif
   gfld%igdtmpl(14)=48        ! oct 55;  resolution and component flags
   lat_last_hpnt_unrot_mdl=lat_first_hpnt_unrot_mdl + (jmdl-1)*dy_mdl
   lon_last_hpnt_unrot_mdl=lon_first_hpnt_unrot_mdl + (imdl-1)*dx_mdl
   gfld%igdtmpl(15)=nint(lat_last_hpnt_unrot_mdl*scale) ! octs 56-59; lat of last grid point
   if (lon_last_hpnt_unrot_mdl < 0.0) then
     gfld%igdtmpl(16)=nint((lon_last_hpnt_unrot_mdl+360.0)*scale) ! octs 60-63; lon of last grid point
   else
     gfld%igdtmpl(16)=nint(lon_last_hpnt_unrot_mdl*scale) ! octs 60-63; lon of last grid point
   endif
   gfld%igdtmpl(17)=nint(dx_mdl*scale)   ! oct 64-67; i direction increment
   gfld%igdtmpl(18)=nint(dy_mdl*scale)   ! oct 68-71; j direction increment
   gfld%igdtmpl(19)=64  ! oct 72; scanning mode flag
   gfld%igdtmpl(20)=nint((centlat_parent_mdl(1)-90.)*scale)  ! octs 73-76; lat of south pole of projection
   if (centlon_parent_mdl(1) < 0.) then
     gfld%igdtmpl(21)=nint((centlon_parent_mdl(1)+360.0)*scale) ! octs 77-80; long of southern pole of projection.
   else
     gfld%igdtmpl(21)=nint(centlon_parent_mdl(1)*scale) ! octs 77-80; long of southern pole of projection.
   endif
   gfld%igdtmpl(22)=nint(0.0)  ! octs 81-84; angle of rotation of projection
   gfld%num_opt = 0           ! octs 85-??; number of optional grid points.
 elseif (trim(domain_type) == 'gaussian') then
   gfld%igdtlen=19
   allocate(gfld%igdtmpl(gfld%igdtlen))
   gfld%griddef = 0         ! oct 6;  source of grid definition, specified in table 3.1
   gfld%ngrdpts = imdl*jmdl ! octs 7-10; number of grid points
   gfld%numoct_opt = 0      ! oct 11; number of octs for optional list of numbers defining # of grid points
                            ! oct 12; list of #s defining # of points
   gfld%igdtnum=40          ! octs 13-14; grid definition template number, template 3.40 - gaussain
   gfld%igdtmpl(1)=5          ! oct 15; shape of the earth, wgs84
   gfld%igdtmpl(2)=255        ! oct 16; scale factor of radius of spherical earth, not used.
   gfld%igdtmpl(3)=-1         ! octs 17-20; scale value of radius of spherical earth, not used.
   gfld%igdtmpl(4)=255        ! oct 21; scale factor of major axis of elliptical earth, not used.
   gfld%igdtmpl(5)=-1         ! octs 22-25; scaled value of major axis of elliptical earth, not used.
   gfld%igdtmpl(6)=255        ! oct 26; scale factor of minor axis of elliptical earth, not used.
   gfld%igdtmpl(7)=-1         ! octs 27-30; scaled value of minor axis of elliptical earth, not used.
   gfld%igdtmpl(8)=imdl       ! octs 31-34; # "i" points
   gfld%igdtmpl(9)=jmdl       ! octs 35-38; # "j" points
   gfld%igdtmpl(10)=1         ! octs 39-42; basic angle
   gfld%igdtmpl(11)=10**6     ! octs 43-46; subdivisions of basic angle
   scale=float(gfld%igdtmpl(10)*gfld%igdtmpl(11))
   gfld%igdtmpl(12)=nint(lat_first_mdl*scale)  ! octs 47-50; lat of first grid point
   if (lon_first_mdl < 0.0) then
     gfld%igdtmpl(13)=nint((lon_first_mdl+360.0)*scale)  ! octs 51-54; lon of first grid point
   else
     gfld%igdtmpl(13)=nint(lon_first_mdl*scale)
   endif
   gfld%igdtmpl(14)=48        ! oct 55;  resolution and component flags
   gfld%igdtmpl(15)=nint(lat_last_mdl*scale) ! octs 56-59; lat of last grid point
   if (lon_last_mdl < 0.0) then
     gfld%igdtmpl(16)=nint((lon_last_mdl+360.0)*scale) ! octs 60-63; lon of last grid point
   else
     gfld%igdtmpl(16)=nint(lon_last_mdl*scale) ! octs 60-63; lon of last grid point
   endif
   gfld%igdtmpl(17)=nint(dx_mdl*scale) ! octs 64-67; di of grid
   gfld%igdtmpl(18)= jmdl/2 ! octs 68-71; # grid pts between pole and equator
   gfld%igdtmpl(19)=0   ! oct 72; scanning mode flag
 else
   print*,'- GRIB2 OPTION DOES NOT SUPPORT THIS MAP PROJECTION ',trim(domain_type)
   call mpi_abort(mpi_comm_world, 1, iret)
 end if

! *** Section 4 ***

 gfld%num_coord=0           ! octs 6-7; number of coordinate values after template.
 gfld%ipdtnum=0             ! octs 8-9; product definition template number - table 4.0
 gfld%ipdtlen=15
 allocate(gfld%ipdtmpl(gfld%ipdtlen))
 gfld%ipdtmpl(1)= 0         ! oct 10; parameter category
! note!! to use a parmeter number >= 192 you must set the local table to '1'
 gfld%ipdtmpl(2)= 0         ! oct 11; parameter
 gfld%ipdtmpl(3)= 0         ! oct 12; type of generating process
 gfld%ipdtmpl(4)= 255       ! oct 13; background generating process identifier
 gfld%ipdtmpl(5)= 84        ! oct 14; analysis generating process identifier
 gfld%ipdtmpl(6)= 0         ! octs 15-16; hours after ob cutoff
 gfld%ipdtmpl(7)= 0         ! oct 17; minutes after ob cutoff
 gfld%ipdtmpl(8)= 1         ! oct 18; unit of time range
 gfld%ipdtmpl(9)= 0         ! octs 19-22; forecast time in units defined by oct 18
 gfld%ipdtmpl(10)=1         ! oct 23; type of first fixed surface
 gfld%ipdtmpl(11)=0         ! oct 24; scale factor of first fixed surface
 gfld%ipdtmpl(12)=0         ! octs 25-28; scale value of first fixed surface
 gfld%ipdtmpl(13)=255       ! oct 29; type of second fixed surface
 gfld%ipdtmpl(14)=255       ! oct 30; scale factor of second fixed surface
 gfld%ipdtmpl(15)=-2147483647 ! octs 31-34; scaled value of second fixed surface
                              ! note! for these particular octets, using -1 as
                              ! missing does not work because -1 may be an actual
                              ! scaled value.  after looking thru the g2 library
                              ! and some trial and error, i determined that missing
                              ! is minus 2**31-1.

! *** Section 5 ***

 gfld%idrtnum=0    ! data representation template number - table 5.0 simple packing
 gfld%idrtlen=5
 allocate(gfld%idrtmpl(gfld%idrtlen))
 gfld%idrtmpl=0
 gfld%idrtmpl(3)=2  ! decimal scaling factor

 gfld%ibmap=255   ! bitmap does not apply
 allocate(gfld%bmap(gfld%ngrdpts))
 gfld%bmap=.false.

 allocate(gfld%fld(gfld%ngrdpts)) ! will hold data values

 end subroutine grib2_init

 subroutine grib2_free(gfld)

! A modified copy of nco routine gf_free, which has serious
! logic problems.

 use grib_mod

 implicit none

 type(gribfield)  :: gfld

 deallocate(gfld%idsect)
 deallocate(gfld%igdtmpl)
 deallocate(gfld%ipdtmpl)
 deallocate(gfld%idrtmpl)
 deallocate(gfld%bmap)
 deallocate(gfld%fld)

 return

 end subroutine grib2_free

 end module init_grib2