NCEPLIBS-g2  3.4.9
g2create.F90
Go to the documentation of this file.
1 
4 
53 subroutine gribcreate(cgrib, lcgrib, listsec0, listsec1, ierr)
54  implicit none
55 
56  character(len = 1), intent(inout) :: cgrib(lcgrib)
57  integer, intent(in) :: listsec0(*), listsec1(*)
58  integer, intent(in) :: lcgrib
59  integer, intent(out) :: ierr
60 
61  integer :: i, lensec1, nbits
62  character(len = 4), parameter :: grib = 'GRIB'
63  integer, parameter :: ZERO = 0, one = 1
64  integer, parameter :: mapsec1len = 13
65  integer, parameter :: mapsec1(mapsec1len) = (/ 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1 /)
66  integer lensec0, iofst, ibeg
67 
68  ierr = 0
69 
70 #ifdef LOGGING
71  print *, 'gribcreate lcgrib ', lcgrib
72 #endif
73 
74  ! Currently handles only GRIB Edition 2.
75  if (listsec0(2) .ne. 2) then
76  print *, 'gribcreate: can only code GRIB edition 2.'
77  ierr = 1
78  return
79  endif
80 
81  ! Pack Section 0 - Indicator Section (except for total length of
82  ! GRIB message).
83  cgrib(1) = grib(1:1) ! Beginning of GRIB message
84  cgrib(2) = grib(2:2)
85  cgrib(3) = grib(3:3)
86  cgrib(4) = grib(4:4)
87  call g2_sbytec(cgrib, zero, 32, 16) ! reserved for future use
88  call g2_sbytec(cgrib, listsec0(1), 48, 8) ! Discipline
89  call g2_sbytec(cgrib, listsec0(2), 56, 8) ! GRIB edition number
90  lensec0 = 16 ! bytes (octets)
91 
92  ! Pack Section 1 - Identification Section.
93  ibeg = lensec0 * 8 ! Calculate offset for beginning of section 1
94  iofst = ibeg + 32 ! leave space for length of section
95  call g2_sbytec(cgrib, one, iofst, 8) ! Store section number ( 1 )
96  iofst = iofst + 8
97 
98  ! Pack up each input value in array listsec1 into the the
99  ! appropriate number of octets, which are specified in corresponding
100  ! entries in array mapsec1.
101  do i = 1, mapsec1len
102  nbits = mapsec1(i) * 8
103  call g2_sbytec(cgrib, listsec1(i), iofst, nbits)
104  iofst = iofst + nbits
105  enddo
106 
107  ! Calculate length of section 1 and store it in octets 1-4 of
108  ! section 1.
109  lensec1 = (iofst - ibeg) / 8
110  call g2_sbytec(cgrib, lensec1, ibeg, 32)
111 
112  ! Put current byte total of message into Section 0.
113  call g2_sbytec(cgrib, zero, 64, 32)
114  call g2_sbytec(cgrib, lensec0 + lensec1, 96, 32)
115 end subroutine gribcreate
116 
183 subroutine addfield(cgrib,lcgrib,ipdsnum,ipdstmpl,ipdstmplen, &
184  coordlist,numcoord,idrsnum,idrstmpl, &
185  idrstmplen,fld,ngrdpts,ibmap,bmap,ierr)
186  use pdstemplates
187  use drstemplates
188  implicit none
189 
190  logical :: match
191  character(len=1),intent(inout) :: cgrib(lcgrib)
192  integer,intent(in) :: ipdsnum,ipdstmpl(*)
193  integer,intent(in) :: idrsnum,numcoord,ipdstmplen,idrstmplen
194  integer,intent(in) :: lcgrib,ngrdpts,ibmap
195  real,intent(in) :: coordlist(numcoord)
196  real(kind = 4) :: coordlist_4(numcoord)
197  real,target,intent(in) :: fld(ngrdpts)
198  integer,intent(out) :: ierr
199  integer,intent(inout) :: idrstmpl(*)
200  logical*1,intent(in) :: bmap(ngrdpts)
201 
202  character(len=4),parameter :: grib='GRIB',c7777='7777'
203  character(len=4):: ctemp
204  character(len=1),allocatable :: cpack(:)
205  real,pointer,dimension(:) :: pfld
206  real(4) :: coordieee(numcoord), re00, tmpre00(1)
207  integer(4) :: ire00,allones
208  integer :: mappds(ipdstmplen),intbmap(ngrdpts),mapdrs(idrstmplen)
209  integer,parameter :: zero=0,one=1,four=4,five=5,six=6,seven=7
210  integer,parameter :: minsize=50000
211  integer iofst,ibeg,lencurr,len,mappdslen,mapdrslen,lpos3
212  integer width,height,ndpts
213  integer lensec3,lensec4,lensec5,lensec6,lensec7
214  logical issec3,needext,isprevbmap
215  integer :: nbits, newlen, nsize, lcpack, left
216  integer :: ibmprev, ilen, ioctet, iscan, isecnum, itemp
217  integer :: i, jj, kk, mm
218  integer :: iret, istat
219  real (kind = 4) :: tmpfld(1)
220 
221  allones = int(z'FFFFFFFF')
222  ierr=0
223 
224  ! Check to see if beginning of GRIB message exists
225  match=.true.
226  do i=1,4
227  if(cgrib(i) /= grib(i:i)) then
228  match=.false.
229  endif
230  enddo
231  if (.not. match) then
232  print *,'addfield: GRIB not found in given message.'
233  print *,'addfield: Call to routine gribcreate required to initialize GRIB messge.'
234  ierr=1
235  return
236  endif
237 
238  ! Get current length of GRIB message
239  call g2_gbytec(cgrib,lencurr,96,32)
240 
241  ! Check to see if GRIB message is already complete
242  ctemp=cgrib(lencurr-3)//cgrib(lencurr-2)//cgrib(lencurr-1) //cgrib(lencurr)
243  if (ctemp.eq.c7777) then
244  print *,'addfield: GRIB message already complete. Cannot add new section.'
245  ierr=2
246  return
247  endif
248 
249  ! Loop through all current sections of the GRIB message to
250  ! find the last section number.
251  issec3=.false.
252  isprevbmap=.false.
253  len=16 ! length of Section 0
254  do
255  ! Get number and length of next section
256  iofst=len*8
257  call g2_gbytec(cgrib,ilen,iofst,32)
258  iofst=iofst+32
259  call g2_gbytec(cgrib,isecnum,iofst,8)
260  iofst=iofst+8
261  ! Check if previous Section 3 exists and save location of
262  ! the section 3 in case needed later.
263  if (isecnum.eq.3) then
264  issec3=.true.
265  lpos3=len+1
266  lensec3=ilen
267  endif
268  ! Check if a previous defined bitmap exists
269  if (isecnum.eq.6) then
270  call g2_gbytec(cgrib,ibmprev,iofst,8)
271  iofst=iofst+8
272  if ((ibmprev.ge.0).and.(ibmprev.le.253)) isprevbmap=.true.
273  endif
274  len=len+ilen
275  ! Exit loop if last section reached
276  if (len.eq.lencurr) exit
277  ! If byte count for each section does not match current
278  ! total length, then there is a problem.
279  if (len.gt.lencurr) then
280  print *,'addfield: Section byte counts don''t add to total.'
281  print *,'addfield: Sum of section byte counts = ',len
282  print *,'addfield: Total byte count in Section 0 = ',lencurr
283  ierr=3
284  return
285  endif
286  enddo
287 
288  ! Sections 4 through 7 can only be added after section 3 or 7.
289  if ((isecnum.ne.3) .and. (isecnum.ne.7)) then
290  print *,'addfield: Sections 4-7 can only be added after', &
291  ' Section 3 or 7.'
292  print *,'addfield: Section ',isecnum,' was the last found in', &
293  ' given GRIB message.'
294  ierr=4
295  return
296 
297  ! Sections 4 through 7 can only be added if section 3 was previously defined.
298  elseif (.not.issec3) then
299  print *,'addfield: Sections 4-7 can only be added if Section', &
300  ' 3 was previously included.'
301  print *,'addfield: Section 3 was not found in given GRIB message.'
302  print *,'addfield: Call to routine addgrid required', &
303  ' to specify Grid definition.'
304  ierr=6
305  return
306  endif
307 
308  ! Add Section 4 - Product Definition Section
309  ibeg=lencurr*8 ! Calculate offset for beginning of section 4
310  iofst=ibeg+32 ! leave space for length of section
311  call g2_sbytec(cgrib,four,iofst,8) ! Store section number (4)
312  iofst=iofst+8
313  call g2_sbytec(cgrib,numcoord,iofst,16) ! Store num of coordinate values
314  iofst=iofst+16
315  call g2_sbytec(cgrib,ipdsnum,iofst,16) ! Store Prod Def Template num.
316  iofst=iofst+16
317 
318  ! Get Product Definition Template
319  call getpdstemplate(ipdsnum,mappdslen,mappds,needext,iret)
320  if (iret.ne.0) then
321  ierr=5
322  return
323  endif
324 
325  ! Extend the Product Definition Template, if necessary.
326  ! The number of values in a specific template may vary
327  ! depending on data specified in the "static" part of the
328  ! template.
329  if (needext) then
330  call extpdstemplate(ipdsnum,ipdstmpl,mappdslen,mappds)
331  endif
332 
333  ! Pack up each input value in array ipdstmpl into the
334  ! the appropriate number of octets, which are specified in
335  ! corresponding entries in array mappds.
336  do i=1,mappdslen
337  nbits=iabs(mappds(i))*8
338  if ((mappds(i).ge.0).or.(ipdstmpl(i).ge.0)) then
339  call g2_sbytec(cgrib,ipdstmpl(i),iofst,nbits)
340  else
341  call g2_sbytec(cgrib,one,iofst,1)
342  call g2_sbytec(cgrib,iabs(ipdstmpl(i)),iofst+1,nbits-1)
343  endif
344  iofst=iofst+nbits
345  enddo
346 
347  ! Add Optional list of vertical coordinate values
348  ! after the Product Definition Template, if necessary.
349  if (numcoord .ne. 0) then
350  do i = 1, numcoord
351  coordlist_4(i) = real(coordlist(i), 4)
352  end do
353  call mkieee(coordlist_4, coordieee, numcoord)
354  call g2_sbytescr(cgrib, coordieee, iofst, 32, 0, numcoord)
355  iofst = iofst + (32 * numcoord)
356  endif
357 
358  ! Calculate length of section 4 and store it in octets
359  ! 1-4 of section 4.
360  lensec4=(iofst-ibeg)/8
361  call g2_sbytec(cgrib,lensec4,ibeg,32)
362 
363  ! Pack Data using appropriate algorithm
364 
365  ! Get Data Representation Template
366  call getdrstemplate(idrsnum,mapdrslen,mapdrs,needext,iret)
367  if (iret.ne.0) then
368  ierr=5
369  return
370  endif
371 
372  ! contract data field, removing data at invalid grid points,
373  ! if bit-map is provided with field.
374  if (ibmap.eq.0 .OR. ibmap.eq.254) then
375  allocate(pfld(max(2,ngrdpts)))
376  ndpts=0;
377  do jj=1,ngrdpts
378  intbmap(jj)=0
379  if (bmap(jj)) then
380  intbmap(jj)=1
381  ndpts=ndpts+1
382  pfld(ndpts)=fld(jj);
383  endif
384  enddo
385  if(ndpts==0 .and. ngrdpts>0) then
386  pfld(1)=0
387  endif
388  else
389  ndpts=ngrdpts;
390  pfld=>fld;
391  endif
392  lcpack=0
393  nsize=ndpts*4
394  if (nsize .lt. minsize) nsize=minsize
395  allocate(cpack(nsize),stat=istat)
396  if (idrsnum.eq.0) then ! Simple Packing
397  call simpack(pfld,ndpts,idrstmpl,cpack,lcpack)
398  elseif (idrsnum.eq.2.or.idrsnum.eq.3) then ! Complex Packing
399  call cmplxpack(pfld,ndpts,idrsnum,idrstmpl,cpack,lcpack)
400  elseif (idrsnum.eq.50) then ! Sperical Harmonic Simple Packing
401  call simpack(pfld(2),ndpts-1,idrstmpl,cpack,lcpack)
402  tmpfld(1) = real(pfld(1), 4)
403  call mkieee(tmpfld, tmpre00, 1) ! ensure RE(0,0) value is IEEE format
404  re00 = tmpre00(1)
405  ire00 = transfer(re00, ire00)
406  idrstmpl(5) = ire00
407  elseif (idrsnum.eq.51) then ! Sperical Harmonic Complex Packing
408  call getpoly(cgrib(lpos3),lensec3,jj,kk,mm)
409  if (jj.ne.0 .AND. kk.ne.0 .AND. mm.ne.0) then
410  call specpack(pfld,ndpts,jj,kk,mm,idrstmpl,cpack,lcpack)
411  else
412  print *,'addfield: Cannot pack DRT 5.51.'
413  ierr=9
414  return
415  endif
416 
417  elseif (idrsnum.eq.40 .OR. idrsnum.eq.40000) then ! JPEG2000 encoding
418  if (ibmap.eq.255) then
419  call getdim(cgrib(lpos3),lensec3,width,height,iscan)
420  if (width.eq.0 .OR. height.eq.0) then
421  width=ndpts
422  height=1
423  elseif (width.eq.allones .OR. height.eq.allones) then
424  width=ndpts
425  height=1
426  elseif (ibits(iscan,5,1) .eq. 1) then ! Scanning mode: bit 3
427  itemp=width
428  width=height
429  height=itemp
430  endif
431  else
432  width=ndpts
433  height=1
434  endif
435  if(width<1 .or. height<1) then
436  ! Special case: bitmask off everywhere.
437  write(0,*) 'Warning: bitmask off everywhere.'
438  write(0,*) ' Pretend one point in jpcpack to avoid crash.'
439  width=1
440  height=1
441  endif
442  lcpack=nsize
443  !print *,'w,h=',width,height
444  call jpcpack(pfld,width,height,idrstmpl,cpack,lcpack)
445 
446  elseif (idrsnum.eq.41 .OR. idrsnum.eq.40010) then ! PNG encoding
447  if (ibmap.eq.255) then
448  call getdim(cgrib(lpos3),lensec3,width,height,iscan)
449  if (width.eq.0 .OR. height.eq.0) then
450  width=ndpts
451  height=1
452  elseif (width.eq.allones .OR. height.eq.allones) then
453  width=ndpts
454  height=1
455  elseif (ibits(iscan,5,1) .eq. 1) then ! Scanning mode: bit 3
456  itemp=width
457  width=height
458  height=itemp
459  endif
460  else
461  width=ndpts
462  height=1
463  endif
464  !print *,'png size ',width,height
465  call pngpack(pfld,width,height,idrstmpl,cpack,lcpack)
466  !print *,'png packed'
467  else
468  print *,'addfield: Data Representation Template 5.',idrsnum, &
469  ' not yet implemented.'
470  ierr=7
471  return
472  endif
473  if (ibmap.eq.0 .OR. ibmap.eq.254) then
474  deallocate(pfld)
475  endif
476  if (lcpack .lt. 0) then
477  if(allocated(cpack))deallocate(cpack)
478  ierr=10
479  return
480  endif
481 
482  ! Add Section 5 - Data Representation Section
483  ibeg=iofst ! Calculate offset for beginning of section 5
484  iofst=ibeg+32 ! leave space for length of section
485  call g2_sbytec(cgrib,five,iofst,8) ! Store section number (5)
486  iofst=iofst+8
487  call g2_sbytec(cgrib,ndpts,iofst,32) ! Store num of actual data points
488  iofst=iofst+32
489  call g2_sbytec(cgrib,idrsnum,iofst,16) ! Store Data Repr. Template num.
490  iofst=iofst+16
491 
492  ! Pack up each input value in array idrstmpl into the
493  ! the appropriate number of octets, which are specified in
494  ! corresponding entries in array mapdrs.
495  do i=1,mapdrslen
496  nbits=iabs(mapdrs(i))*8
497  if ((mapdrs(i).ge.0).or.(idrstmpl(i).ge.0)) then
498  call g2_sbytec(cgrib,idrstmpl(i),iofst,nbits)
499  else
500  call g2_sbytec(cgrib,one,iofst,1)
501  call g2_sbytec(cgrib,iabs(idrstmpl(i)),iofst+1,nbits-1)
502  endif
503  iofst=iofst+nbits
504  enddo
505 
506  ! Calculate length of section 5 and store it in octets
507  ! 1-4 of section 5.
508  lensec5=(iofst-ibeg)/8
509  call g2_sbytec(cgrib,lensec5,ibeg,32)
510 
511  ! Add Section 6 - Bit-Map Section
512  ibeg=iofst ! Calculate offset for beginning of section 6
513  iofst=ibeg+32 ! leave space for length of section
514  call g2_sbytec(cgrib,six,iofst,8) ! Store section number (6)
515  iofst=iofst+8
516  call g2_sbytec(cgrib,ibmap,iofst,8) ! Store Bit Map indicator
517  iofst=iofst+8
518 
519  ! Store bitmap, if supplied
520  if (ibmap.eq.0) then
521  call g2_sbytesc(cgrib,intbmap,iofst,1,0,ngrdpts) ! Store BitMap
522  iofst=iofst+ngrdpts
523  endif
524 
525  ! If specifying a previously defined bit-map, make sure
526  ! one already exists in the current GRIB message.
527  if ((ibmap.eq.254).and.(.not.isprevbmap)) then
528  print *,'addfield: Requested previously defined bitmap, ', &
529  ' but one does not exist in the current GRIB message.'
530  ierr=8
531  return
532  endif
533 
534  ! Calculate length of section 6 and store it in octets
535  ! 1-4 of section 6. Pad to end of octect, if necessary.
536  left=8-mod(iofst,8)
537  if (left.ne.8) then
538  call g2_sbytec(cgrib,zero,iofst,left) ! Pad with zeros to fill Octet
539  iofst=iofst+left
540  endif
541  lensec6=(iofst-ibeg)/8
542  call g2_sbytec(cgrib,lensec6,ibeg,32)
543 
544  ! Add Section 7 - Data Section
545  ibeg=iofst ! Calculate offset for beginning of section 7
546  iofst=ibeg+32 ! leave space for length of section
547  call g2_sbytec(cgrib,seven,iofst,8) ! Store section number (7)
548  iofst=iofst+8
549  ! Store Packed Binary Data values, if non-constant field
550  if (lcpack.ne.0) then
551  ioctet=iofst/8
552  cgrib(ioctet+1:ioctet+lcpack)=cpack(1:lcpack)
553  iofst=iofst+(8*lcpack)
554  endif
555 
556  ! Calculate length of section 7 and store it in octets
557  ! 1-4 of section 7.
558  lensec7=(iofst-ibeg)/8
559  call g2_sbytec(cgrib,lensec7,ibeg,32)
560 
561  if(allocated(cpack) )deallocate(cpack)
562 
563  ! Update current byte total of message in Section 0
564  newlen=lencurr+lensec4+lensec5+lensec6+lensec7
565  call g2_sbytec(cgrib,newlen,96,32)
566 
567  return
568 end subroutine addfield
569 
613 subroutine addgrid(cgrib, lcgrib, igds, igdstmpl, igdstmplen, &
614  ideflist, idefnum, ierr)
615  use gridtemplates
616  implicit none
617 
618  character(len = 1), intent(inout) :: cgrib(lcgrib)
619  integer, intent(in) :: igds(*), igdstmpl(*), ideflist(idefnum)
620  integer, intent(in) :: lcgrib, idefnum, igdstmplen
621  integer, intent(out) :: ierr
622 
623  character(len = 4), parameter :: grib = 'GRIB', c7777 = '7777'
624  character(len = 4):: ctemp
625  integer:: mapgrid(igdstmplen)
626  integer, parameter :: ONE = 1, three = 3
627  integer lensec3, iofst, ibeg, lencurr, len, mapgridlen
628  logical needext
629  integer :: i, ilen, iret, isecnum, nbits
630 
631  ierr = 0
632 
633 #ifdef LOGGING
634  print *, 'addgrid lcgrib ', lcgrib, ' igdstmplen ', igdstmplen, ' idefnum ', idefnum
635 #endif
636 
637  ! Check to see if beginning of GRIB message exists.
638  do i = 1, 4
639  if (cgrib(i) /= grib(i:i)) then
640  print *, 'addgrid: GRIB not found in given message.'
641  print *, 'addgrid: Call to routine gribcreate required', &
642  ' to initialize GRIB messge.'
643 10 format('"', 4a1, '" /= "GRIB"')
644  print 10, cgrib(1:4)
645  ierr = 1
646  return
647  endif
648  enddo
649 
650  ! Get current length of GRIB message.
651  call g2_gbytec(cgrib, lencurr, 96, 32)
652 
653  ! Check to see if GRIB message is already complete.
654  ctemp = cgrib(lencurr - 3) // cgrib(lencurr - 2) // cgrib(lencurr &
655  - 1) // cgrib(lencurr)
656  if (ctemp .eq. c7777) then
657  print *, 'addgrid: GRIB message already complete. Cannot', &
658  ' add new section.'
659  ierr = 2
660  return
661  endif
662 
663  ! Loop through all current sections of the GRIB message to find the
664  ! last section number.
665  len = 16 ! length of Section 0
666  do
667  ! Get length and section number of next section.
668  iofst = len * 8
669  call g2_gbytec(cgrib, ilen, iofst, 32)
670  iofst = iofst + 32
671  call g2_gbytec(cgrib, isecnum, iofst, 8)
672  len = len + ilen
673 
674  ! Exit loop if last section reached.
675  if (len .eq. lencurr) exit
676 
677  ! If byte count for each section doesn't match current
678  ! total length, then there is a problem.
679  if (len .gt. lencurr) then
680  print *, 'addgrid: Section byte counts don''t add to total.'
681  print *, 'addgrid: Sum of section byte counts = ', len
682  print *, 'addgrid: Total byte count in Section 0 = ', lencurr
683  ierr = 3
684  return
685  endif
686  enddo
687 
688  ! Section 3 can only be added after sections 1, 2 and 7.
689  if ((isecnum .ne. 1) .and. (isecnum .ne. 2) .and. &
690  (isecnum .ne. 7)) then
691  print *, 'addgrid: Section 3 can only be added after Section', &
692  ' 1, 2 or 7.'
693  print *, 'addgrid: Section ', isecnum, &
694  ' was the last found in given GRIB message.'
695  ierr = 4
696  return
697  endif
698 
699  ! Add Section 3 - Grid Definition Section.
700  ibeg = lencurr * 8 ! Calculate offset for beginning of section 3
701  iofst = ibeg + 32 ! leave space for length of section
702  call g2_sbytec(cgrib, three, iofst, 8) ! Store section number (3)
703  iofst = iofst + 8
704  call g2_sbytec(cgrib, igds(1), iofst, 8) ! Store source of Grid def.
705  iofst = iofst + 8
706  call g2_sbytec(cgrib, igds(2), iofst, 32) ! Store number of data pts.
707  iofst = iofst + 32
708  call g2_sbytec(cgrib, igds(3), iofst, 8) ! Store number of extra octets.
709  iofst = iofst + 8
710  call g2_sbytec(cgrib, igds(4), iofst, 8) ! Store interp. of extra octets.
711  iofst = iofst + 8
712 
713  ! If Octet 6 is not equal to zero, Grid Definition Template may not
714  ! be supplied.
715  if (igds(1) .eq. 0) then
716  call g2_sbytec(cgrib, igds(5), iofst, 16) ! Store Grid Def Template num.
717  else
718  call g2_sbytec(cgrib, 65535, iofst, 16) ! Store missing value as Grid Def Template num.
719  endif
720  iofst = iofst + 16
721 
722  ! Get Grid Definition Template.
723  if (igds(1) .eq. 0) then
724  call getgridtemplate(igds(5), mapgridlen, mapgrid, needext, &
725  iret)
726  if (iret .ne. 0) then
727  ierr = 5
728  return
729  endif
730 
731  ! Extend the Grid Definition Template, if necessary. The number
732  ! of values in a specific template may vary depending on data
733  ! specified in the "static" part of the template.
734  if (needext) then
735  call extgridtemplate(igds(5), igdstmpl, mapgridlen, &
736  mapgrid)
737  endif
738  else
739  mapgridlen = 0
740  endif
741 
742  ! Pack up each input value in array igdstmpl into the the
743  ! appropriate number of octets, which are specified in corresponding
744  ! entries in array mapgrid.
745  do i = 1, mapgridlen
746  nbits = iabs(mapgrid(i)) * 8
747  if ((mapgrid(i) .ge. 0) .or. (igdstmpl(i) .ge. 0)) then
748  call g2_sbytec(cgrib, igdstmpl(i), iofst, nbits)
749  else
750  call g2_sbytec(cgrib, one, iofst, 1)
751  call g2_sbytec(cgrib, iabs(igdstmpl(i)), iofst + 1, nbits &
752  - 1)
753  endif
754  iofst = iofst + nbits
755  enddo
756 
757  ! If requested, insert optional list of numbers defining number of
758  ! points in each row or column. This is used for non regular grids.
759  if (igds(3) .ne. 0) then
760  nbits = igds(3) * 8
761  call g2_sbytesc(cgrib, ideflist, iofst, nbits, 0, idefnum)
762  iofst = iofst + (nbits * idefnum)
763  endif
764 
765  ! Calculate length of section 3 and store it in octets 1-4 of
766  ! section 3.
767  lensec3 = (iofst - ibeg) / 8
768  call g2_sbytec(cgrib, lensec3, ibeg, 32)
769 
770 
771  ! Update current byte total of message in Section 0.
772  call g2_sbytec(cgrib, lencurr + lensec3, 96, 32)
773 end subroutine addgrid
774 
799 subroutine addlocal(cgrib, lcgrib, csec2, lcsec2, ierr)
800  implicit none
801 
802  character(len = 1), intent(inout) :: cgrib(lcgrib)
803  character(len = 1), intent(in) :: csec2(lcsec2)
804  integer, intent(in) :: lcgrib, lcsec2
805  integer, intent(out) :: ierr
806 
807  character(len = 4), parameter :: grib = 'GRIB', c7777 = '7777'
808  character(len = 4):: ctemp
809  integer, parameter :: two = 2
810  integer :: lensec2, iofst, ibeg, lencurr, len
811  integer :: ilen, isecnum, istart
812 
813  ierr = 0
814 
815  ! Check to see if beginning of GRIB message exists.
816  ctemp = cgrib(1) // cgrib(2) // cgrib(3) // cgrib(4)
817  if (ctemp .ne. grib) then
818  print *, 'addlocal: GRIB not found in given message.'
819  print *, 'addlocal: Call to routine gribcreate required', &
820  ' to initialize GRIB messge.'
821  ierr = 1
822  return
823  endif
824 
825  ! Get current length of GRIB message.
826  call g2_gbytec(cgrib, lencurr, 96, 32)
827 
828  ! Check to see if GRIB message is already complete
829  ctemp = cgrib(lencurr - 3) // cgrib(lencurr - 2) // cgrib(lencurr - 1) // cgrib(lencurr)
830  if (ctemp .eq. c7777) then
831  print *, 'addlocal: GRIB message already complete. Cannot add new section.'
832  ierr = 2
833  return
834  endif
835 
836  ! Loop through all current sections of the GRIB message to find the
837  ! last section number.
838  len = 16 ! length of Section 0
839  do
840  ! Get section number and length of next section.
841  iofst = len * 8
842  call g2_gbytec(cgrib, ilen, iofst, 32)
843  iofst = iofst + 32
844  call g2_gbytec(cgrib, isecnum, iofst, 8)
845  len = len + ilen
846  ! Exit loop if last section reached
847  if (len .eq. lencurr) exit
848 
849  ! If byte count for each section doesn't match current
850  ! total length, then there is a problem.
851  if (len .gt. lencurr) then
852  print *, 'addlocal: Section byte counts don''t add to total.'
853  print *, 'addlocal: Sum of section byte counts = ', len
854  print *, 'addlocal: Total byte count in Section 0 = ', lencurr
855  ierr = 3
856  return
857  endif
858  enddo
859 
860  ! Section 2 can only be added after sections 1 and 7.
861  if ((isecnum .ne. 1) .and. (isecnum .ne. 7)) then
862  print *, 'addlocal: Section 2 can only be added after Section 1 or Section 7.'
863  print *, 'addlocal: Section ', isecnum, ' was the last found in given GRIB message.'
864  ierr = 4
865  return
866  endif
867 
868  ! Add Section 2 - Local Use Section.
869  ibeg = lencurr * 8 ! Calculate offset for beginning of section 2
870  iofst = ibeg + 32 ! leave space for length of section
871  call g2_sbytec(cgrib, two, iofst, 8) ! Store section number (2)
872  istart = lencurr + 5
873  cgrib(istart + 1:istart + lcsec2) = csec2(1:lcsec2)
874 
875  ! Calculate length of section 2 and store it in octets 1-4 of
876  ! section 2.
877  lensec2 = lcsec2 + 5 ! bytes
878  call g2_sbytec(cgrib, lensec2, ibeg, 32)
879 
880  ! Update current byte total of message in Section 0.
881  call g2_sbytec(cgrib, lencurr+lensec2, 96, 32)
882 
883 end subroutine addlocal
884 
905 subroutine gribend(cgrib, lcgrib, lengrib, ierr)
906  implicit none
907 
908  character(len = 1), intent(inout) :: cgrib(lcgrib)
909  integer, intent(in) :: lcgrib
910  integer, intent(out) :: lengrib, ierr
911 
912  integer ilen, isecnum
913  character(len = 4), parameter :: grib = 'GRIB'
914  character(len = 1), parameter :: c7777(4) = (/ '7', '7', '7', '7' /)
915  character(len = 4):: ctemp
916  integer iofst, lencurr, len
917 
918  ierr = 0
919 
920  ! Check to see if beginning of GRIB message exists.
921  ctemp = cgrib(1) // cgrib(2) // cgrib(3) // cgrib(4)
922  if (ctemp .ne. grib) then
923  print *, 'gribend: GRIB not found in given message.'
924  ierr = 1
925  return
926  endif
927 
928  ! Get current length of GRIB message.
929  call g2_gbytec(cgrib, lencurr, 96, 32)
930 
931  ! Loop through all current sections of the GRIB message to
932  ! find the last section number.
933  len = 16 ! Length of Section 0
934  do
935  ! Get number and length of next section.
936  iofst = len * 8
937  call g2_gbytec(cgrib, ilen, iofst, 32)
938  iofst = iofst + 32
939  call g2_gbytec(cgrib, isecnum, iofst, 8)
940  len = len + ilen
941 
942  ! Exit loop if last section reached.
943  if (len .eq. lencurr) exit
944 
945  ! If byte count for each section doesn't match current total
946  ! length, then there is a problem.
947  if (len .gt. lencurr) then
948  print *, 'gribend: Section byte counts don''t add ' &
949  ,'to total.'
950  print *, 'gribend: Sum of section byte counts = ', len
951  print *, 'gribend: Total byte count in Section 0 = ', &
952  lencurr
953  ierr = 3
954  return
955  endif
956  enddo
957 
958  ! Can only add End Section (Section 8) after Section 7.
959  if (isecnum .ne. 7) then
960  print *, 'gribend: Section 8 can only be added after Section 7.'
961  print *, 'gribend: Section ', isecnum, &
962  ' was the last found in',' given GRIB message.'
963  ierr = 4
964  return
965  endif
966 
967  ! Add Section 8 - End Section.
968  cgrib(lencurr + 1:lencurr + 4) = c7777
969 
970  ! Update current byte total of message in Section 0.
971  lengrib = lencurr + 4
972  call g2_sbytec(cgrib, lengrib, 96, 32)
973 end subroutine gribend
subroutine cmplxpack(fld, ndpts, idrsnum, idrstmpl, cpack, lcpack)
Pack up a data field using a complex packing algorithm.
Definition: compack.F90:43
subroutine g2_gbytec(in, iout, iskip, nbits)
Extract one arbitrary size big-endian value (up to 32 bits) from a packed bit string into one element...
Definition: g2bytes.F90:21
subroutine mkieee(a, rieee, num)
Copy an array of real to an array of 32-bit IEEE floating points.
Definition: g2bytes.F90:540
subroutine g2_sbytescr(out, rin, iskip, nbits, nskip, n)
Put real values into a packed bit string in big-endian order.
Definition: g2bytes.F90:282
subroutine g2_sbytec(out, in, iskip, nbits)
Put one arbitrary sized (up to 32 bits) value from an integer array, into a packed bit string,...
Definition: g2bytes.F90:238
subroutine g2_sbytesc(out, in, iskip, nbits, nskip, n)
Put arbitrary size (up to 32 bits each) integer values into a packed bit string in big-endian order.
Definition: g2bytes.F90:308
subroutine addgrid(cgrib, lcgrib, igds, igdstmpl, igdstmplen, ideflist, idefnum, ierr)
Add a Grid Definition Section (Section 3) to a GRIB2 message.
Definition: g2create.F90:615
subroutine addlocal(cgrib, lcgrib, csec2, lcsec2, ierr)
Add a Local Use Section (Section 2) to a GRIB2 message.
Definition: g2create.F90:800
subroutine gribcreate(cgrib, lcgrib, listsec0, listsec1, ierr)
Initialize a new GRIB2 message and pack GRIB2 sections 0 (Indicator) and 1 (Identification).
Definition: g2create.F90:54
subroutine addfield(cgrib, lcgrib, ipdsnum, ipdstmpl, ipdstmplen, coordlist, numcoord, idrsnum, idrstmpl, idrstmplen, fld, ngrdpts, ibmap, bmap, ierr)
Pack up Sections 4 through 7 for a field and add them to a GRIB2 message.
Definition: g2create.F90:186
subroutine gribend(cgrib, lcgrib, lengrib, ierr)
Finalize a GRIB2 message after all grids and fields have been added.
Definition: g2create.F90:906
subroutine getdim(csec3, lcsec3, width, height, iscan)
Return the dimensions and scanning mode of a grid definition packed in the Grid Definition Section.
Definition: g2get.F90:1162
subroutine getpoly(csec3, lcsec3, jj, kk, mm)
Return the J, K, and M pentagonal resolution parameters specified in a GRIB2 Grid Definition Section ...
Definition: g2get.F90:1389
subroutine jpcpack(fld, width, height, idrstmpl, cpack, lcpack)
Pack a data field into a JPEG2000 code stream as defined in Data Representation Template 5....
Definition: g2jpc.F90:35
subroutine pngpack(fld, width, height, idrstmpl, cpack, lcpack)
Pack a data field into PNG image format, defined in [Data Representation Template 5....
Definition: g2png.F90:34
subroutine simpack(fld, ndpts, idrstmpl, cpack, lcpack)
Pack a data field using a simple packing algorithm.
Definition: g2sim.F90:27
subroutine specpack(fld, ndpts, JJ, KK, MM, idrstmpl, cpack, lcpack)
Pack a spectral data field using the complex packing algorithm for spherical harmonic data as defined...
Definition: g2spec.F90:25
Handles Data Representation Templates used in Section 5.
subroutine getdrstemplate(number, nummap, map, needext, iret)
Return DRS template information for a specified Data Representation Template.
This Fortran module contains info on all the available GRIB2 Grid Definition Templates used in [Secti...
subroutine getgridtemplate(number, nummap, map, needext, iret)
Get the grid template information for a specified Grid Definition Template.
subroutine extgridtemplate(number, list, nummap, map)
Generate the remaining octet map for a given Grid Definition Template, if required.
Information on all GRIB2 Product Definition Templates used in Section 4 - the Product Definition Sect...
subroutine extpdstemplate(number, list, nummap, map)
This subroutine generates the remaining octet map for a given Product Definition Template,...
subroutine getpdstemplate(number, nummap, map, needext, iret)
This subroutine returns PDS template information for a specified Product Definition Template.