NCEPLIBS-g2  3.4.9
g2index.F90
Go to the documentation of this file.
1 
4 
20 subroutine g2_create_index(lugb, lugi, idxver, filename, iret)
21  implicit none
22 
23  integer, intent(in) :: lugb, lugi, idxver
24  character*(*) :: filename
25  integer, intent(out) :: iret
26 
27  integer (kind = 8) :: msk1, msk2
28  parameter(msk1 = 32000_8, msk2 = 4000_8)
29  character(len=1), pointer, dimension(:) :: cbuf
30  integer :: numtot, nnum, nlen, mnum, kw
31  integer :: irgi, iw, nmess
32 
33  interface
34  subroutine getg2i2r(lugb, msk1, msk2, mnum, idxver, cbuf, &
35  nlen, nnum, nmess, iret)
36  integer, intent(in) :: lugb
37  integer (kind = 8), intent(in) :: msk1, msk2
38  integer, intent(in) :: mnum, idxver
39  character(len = 1), pointer, dimension(:) :: cbuf
40  integer, intent(out) :: nlen, nnum, nmess, iret
41  end subroutine getg2i2r
42  end interface
43 
44  ! Assume success.
45  iret = 0
46  numtot = 0
47  nlen = 0
48 
49  ! Generate index records for all messages in file, or until memory
50  ! runs out.
51  mnum = 0
52  call getg2i2r(lugb, msk1, msk2, mnum, idxver, cbuf, &
53  nlen, nnum, nmess, irgi)
54  if (irgi .gt. 1 .or. nnum .eq. 0 .or. nlen .eq. 0) then
55  iret = 92
56  return
57  endif
58  numtot = numtot + nnum
59  mnum = mnum + nmess
60 
61  ! Write headers.
62  call g2_write_index_headers(lugi, nlen, numtot, idxver, filename)
63  iw = 162
64 
65  ! Write the index data we have so far.
66  call bawrite(lugi, iw, nlen, kw, cbuf)
67  iw = iw + nlen
68 
69  ! Extend index file if index buffer length too large to hold in memory.
70  if (irgi .eq. 1) then
71  do while (irgi .eq. 1 .and. nnum .gt. 0)
72  if (associated(cbuf)) then
73  deallocate(cbuf)
74  nullify(cbuf)
75  endif
76  call getg2i2r(11, msk1, msk2, mnum, idxver, cbuf, &
77  nlen, nnum, nmess, irgi)
78  if (irgi .le. 1 .and. nnum .gt. 0) then
79  numtot = numtot + nnum
80  mnum = mnum + nmess
81  call bawrite(lugi, iw, nlen, kw, cbuf)
82  iw = iw + nlen
83  endif
84  enddo
85  ! Go back and overwrite headers with new info.
86  call g2_write_index_headers(lugi, iw, numtot, idxver, filename)
87  endif
88  deallocate(cbuf)
89 
90 end subroutine g2_create_index
91 
102 subroutine g2_write_index_headers(lugi, nlen, nnum, idxver, filename)
103  implicit none
104 
105  integer, intent(in) :: lugi, nlen, nnum, idxver
106  character, intent(in) :: filename*(*)
107 
108  character cd8*8, ct10*10, hostname*15
109 #ifdef __GFORTRAN__
110  integer istat
111 #else
112  character hostnam*15
113  integer hostnm
114 #endif
115  character chead(2)*81
116  integer :: kw
117 
118  ! fill first 81-byte header
119  call date_and_time(cd8, ct10)
120  chead(1) = '!GFHDR!'
121  chead(1)(9:10) = ' 1'
122  chead(1)(12:14) = ' 1'
123  write(chead(1)(16:20),'(i5)') 162
124  chead(1)(22:31) = cd8(1:4) // '-' // cd8(5:6) // '-' // cd8(7:8)
125  chead(1)(33:40) = ct10(1:2) // ':' // ct10(3:4) // ':' // ct10(5:6)
126  chead(1)(42:47) = 'GB2IX1'
127  chead(1)(49:54) = ' '
128 #ifdef __GFORTRAN__
129  istat = hostnm(hostname)
130  if (istat .eq. 0) then
131  chead(1)(56:70) = '0000'
132  else
133  chead(1)(56:70) = '0001'
134  endif
135 #else
136  chead(1)(56:70) = hostnam(hostname)
137 #endif
138  chead(1)(72:80) = 'grb2index'
139  chead(1)(81:81) = char(10)
140 
141  ! fill second 81-byte header
142  if (idxver .eq. 1) then
143  chead(2) = 'IX1FORM:'
144  else
145  chead(2) = 'IX2FORM:'
146  endif
147  write(chead(2)(9:38),'(3i10)') 162, nlen, nnum
148  chead(2)(41:80) = filename
149  chead(2)(81:81) = char(10)
150 
151  ! write headers at beginning of index file
152  call bawrite(lugi, 0, 162, kw, chead)
153 
154  return
155 end subroutine g2_write_index_headers
156 
197 subroutine getidx(lugb, lugi, cindex, nlen, nnum, iret)
198  implicit none
199 
200  integer, intent(in) :: lugb, lugi
201  character(len = 1), pointer, dimension(:) :: cindex
202  integer, intent(out) :: nlen, nnum, iret
203  integer :: idxver
204 
205  interface
206  subroutine getidx2(lugb, lugi, idxver, cindex, nlen, nnum, iret)
207  integer, intent(in) :: lugb, lugi
208  integer, intent(inout) :: idxver
209  character(len = 1), pointer, dimension(:) :: cindex
210  integer, intent(out) :: nlen, nnum, iret
211  end subroutine getidx2
212  end interface
213 
214  ! When getidx() is called, always use index version 1. Call
215  ! getidx2() for a chance to set the index version.
216  idxver = 1
217  call getidx2(lugb, lugi, idxver, cindex, nlen, nnum, iret)
218 
219  ! If index version 2 is being used, return error.
220  if (iret .eq. 0 .and. idxver .eq. 2) iret = 97
221 
222 end subroutine getidx
223 
265 subroutine getidx2(lugb, lugi, idxver, cindex, nlen, nnum, iret)
266  implicit none
267 
268  integer, intent(in) :: lugb, lugi
269  integer, intent(inout) :: idxver
270  character(len = 1), pointer, dimension(:) :: cindex
271  integer, intent(out) :: nlen, nnum, iret
272 
273  integer, parameter :: maxidx = 10000
274  integer (kind = 8), parameter :: msk1 = 32000_8, msk2 = 4000_8
275  integer :: lux
276  integer :: irgi, mskp, nmess, i
277 
278  type gindex
279  integer :: nlen
280  integer :: nnum
281  integer :: idxver
282  character(len = 1), pointer, dimension(:) :: cbuf
283  end type gindex
284 
285  type(gindex), save :: idxlist(10000)
286 
287  data lux/0/
288 
289  ! declare interfaces (required for cbuf pointer)
290  interface
291  subroutine getg2i2(lugi, cbuf, idxver, nlen, nnum, iret)
292  integer, intent(in) :: lugi
293  character(len=1), pointer, dimension(:) :: cbuf
294  integer, intent(out) :: idxver, nlen, nnum, iret
295  end subroutine getg2i2
296  subroutine getg2i2r(lugb, msk1, msk2, mnum, idxver, cbuf, &
297  nlen, nnum, nmess, iret)
298  integer, intent(in) :: lugb
299  integer (kind = 8), intent(in) :: msk1, msk2
300  integer, intent(in) :: mnum, idxver
301  character(len = 1), pointer, dimension(:) :: cbuf
302  integer, intent(out) :: nlen, nnum, nmess, iret
303  end subroutine getg2i2r
304  end interface
305 
306  ! Free all associated memory and exit.
307  if (lugb .eq. 0) then
308  !print *, 'getidx: Freeing all memory'
309  do i = 1, 10000
310  if (associated(idxlist(i)%cbuf)) then
311  !print *, 'deallocating ', loc(idxlist(i)%cbuf)
312  deallocate(idxlist(i)%cbuf)
313  nullify(idxlist(i)%cbuf)
314  endif
315  end do
316  iret = 0
317  return
318  endif
319 
320  ! Determine whether index buffer needs to be initialized.
321  lux = 0
322  iret = 0
323  if (lugb .le. 0 .or. lugb .gt. 9999) then
324  print *, ' file unit number out of range'
325  print *, ' use unit numbers in range: 0 - 9999 '
326  iret = 90
327  return
328  endif
329 
330  ! Force regeneration of index from GRIB2 file.
331  if (lugi .eq. lugb) then
332  if (associated(idxlist(lugb)%cbuf)) &
333  deallocate(idxlist(lugb)%cbuf)
334  !print *, 'Force regeneration'
335  nullify(idxlist(lugb)%cbuf)
336  idxlist(lugb)%nlen = 0
337  idxlist(lugb)%nnum = 0
338  lux = 0
339  endif
340 
341  ! Force re-read of index from indexfile.
342  if (lugi .lt. 0) then
343  ! associated with unit abs(lugi)
344  if (associated(idxlist(lugb)%cbuf)) &
345  deallocate(idxlist(lugb)%cbuf)
346  !print *, 'Force re-read'
347  nullify(idxlist(lugb)%cbuf)
348  idxlist(lugb)%nlen = 0
349  idxlist(lugb)%nnum = 0
350  lux = abs(lugi)
351  endif
352 
353  ! Check if index already exists in memory.
354  if (associated(idxlist(lugb)%cbuf)) then
355  !print *, 'Index exists in memory!'
356  cindex => idxlist(lugb)%cbuf
357  nlen = idxlist(lugb)%nlen
358  nnum = idxlist(lugb)%nnum
359  idxver = idxlist(lugb)%idxver
360  return
361  endif
362 
363  ! Either read index from index file, or generate it from the GRIB2
364  ! file. This is an index for all messages in the file, each message
365  ! gets an index record, all stuffed into idxlist(lugbb)%cbuf.
366  irgi = 0
367  if (lux .gt. 0) then
368  call getg2i2(lux, idxlist(lugb)%cbuf, idxver, nlen, nnum, irgi)
369  elseif (lux .le. 0) then
370  mskp = 0
371  call getg2i2r(lugb, msk1, msk2, mskp, idxver, idxlist(lugb)%cbuf, &
372  nlen, nnum, nmess, irgi)
373  endif
374 
375  ! Handle errors.
376  if (irgi .ne. 0) then
377  nlen = 0
378  nnum = 0
379  print *, ' error reading index file '
380  iret = 96
381  return
382  endif
383 
384  ! Fill these values.
385  cindex => idxlist(lugb)%cbuf
386  idxlist(lugb)%nlen = nlen
387  idxlist(lugb)%nnum = nnum
388  idxlist(lugb)%idxver = idxver
389 
390 end subroutine getidx2
391 
421 subroutine getg2i(lugi, cbuf, nlen, nnum, iret)
422  implicit none
423 
424  integer, intent(in) :: lugi
425  character(len=1), pointer, dimension(:) :: cbuf
426  integer, intent(out) :: nlen, nnum, iret
427  integer :: idxver
428 
429  interface
430  subroutine getg2i2(lugi, cbuf, idxver, nlen, nnum, iret)
431  integer, intent(in) :: lugi
432  character(len=1), pointer, dimension(:) :: cbuf
433  integer, intent(out) :: idxver, nlen, nnum, iret
434  end subroutine getg2i2
435  end interface
436 
437  ! Call the version of this subroutine that handles version 1 and
438  ! version 2. If getg2i() is called on a version 2 index, return
439  ! error.
440  call getg2i2(lugi, cbuf, idxver, nlen, nnum, iret)
441  if (idxver .eq. 2) iret = 5
442 
443 end subroutine getg2i
444 
503 subroutine getg2i2(lugi, cbuf, idxver, nlen, nnum, iret)
504  implicit none
505 
506  integer, intent(in) :: lugi
507  character(len=1), pointer, dimension(:) :: cbuf
508  integer, intent(out) :: idxver, nlen, nnum, iret
509 
510  character chead*162
511  integer :: ios, istat, lbuf, lhead, nskp
512 
513  nullify(cbuf)
514  nlen = 0
515  nnum = 0
516  iret = 4
517  call baread(lugi, 0, 162, lhead, chead)
518  if (lhead .eq. 162 .and. chead(42:47) .eq. 'GB2IX1') then
519  read(chead(82:162), '(2x, i1, 5x, 3i10, 2x, a40)', iostat = ios) idxver, nskp, nlen, nnum
520  if (ios .eq. 0) then
521  allocate(cbuf(nlen), stat = istat) ! Allocate space for cbuf.
522  if (istat .ne. 0) then
523  iret = 2
524  return
525  endif
526  iret = 0
527  call baread(lugi, nskp, nlen, lbuf, cbuf)
528  if (lbuf .ne. nlen) iret = 3
529  endif
530  endif
531 end subroutine getg2i2
532 
565 subroutine getg2ir(lugb, msk1, msk2, mnum, cbuf, nlen, nnum, nmess, iret)
566  use re_alloc ! needed for subroutine realloc
567  implicit none
568 
569  integer, intent(in) :: lugb
570  integer, intent(in) :: msk1, msk2
571  integer, intent(in) :: mnum
572  character(len = 1), pointer, dimension(:) :: cbuf
573  integer, intent(out) :: nlen, nnum, nmess, iret
574 
575  integer (kind = 8) :: msk1_8, msk2_8
576 
577  interface
578  subroutine getg2i2r(lugb, msk1, msk2, mnum, idxver, cbuf, &
579  nlen, nnum, nmess, iret)
580  integer, intent(in) :: lugb
581  integer (kind = 8), intent(in) :: msk1, msk2
582  integer, intent(in) :: mnum, idxver
583  character(len = 1), pointer, dimension(:) :: cbuf
584  integer, intent(out) :: nlen, nnum, nmess, iret
585  end subroutine getg2i2r
586  end interface
587 
588  msk1_8 = msk1
589  msk2_8 = msk2
590  call getg2i2r(lugb, msk1_8, msk2_8, mnum, 1, cbuf, nlen, nnum, nmess, iret)
591 end subroutine getg2ir
592 
626 subroutine getg2i2r(lugb, msk1, msk2, mnum, idxver, cbuf, nlen, nnum, nmess, iret)
627  use re_alloc ! needed for subroutine realloc
628  implicit none
629 
630  integer, intent(in) :: lugb
631  integer (kind = 8), intent(in) :: msk1, msk2
632  integer, intent(in) :: mnum, idxver
633  character(len = 1), pointer, dimension(:) :: cbuf
634  integer, intent(out) :: nlen, nnum, nmess, iret
635 
636  character(len = 1), pointer, dimension(:) :: cbuftmp
637  integer :: nbytes, newsize, next, numfld, m, mbuf
638  integer (kind = 8) :: iseek, lskip, lgrib
639  integer :: istat, init, iret1, lgrib4
640  parameter(init = 50000, next = 10000)
641 
642  interface ! required for cbuf pointer
643  subroutine ix2gb2(lugb, lskip8, idxver, lgrib, cbuf, numfld, mlen, iret)
644  integer :: lugb
645  integer (kind = 8) :: lskip8
646  integer :: idxver, lgrib
647  character(len = 1), pointer, dimension(:) :: cbuf
648  integer :: numfld, mlen, iret
649  end subroutine ix2gb2
650  end interface
651 
652  ! Initialize.
653  iret = 0
654  nullify(cbuf)
655  mbuf = init
656  allocate(cbuf(mbuf), stat = istat) ! allocate initial space for cbuf.
657  if (istat .ne. 0) then
658  iret = 2
659  return
660  endif
661 
662  ! Search for first grib message.
663  iseek = 0_8
664  call skgb8(lugb, iseek, msk1, lskip, lgrib)
665  do m = 1, mnum
666  if (lgrib .gt. 0) then
667  iseek = lskip + lgrib
668  call skgb8(lugb, iseek, msk2, lskip, lgrib)
669  endif
670  enddo
671 
672  ! Get index records for every grib message found.
673  nlen = 0
674  nnum = 0
675  nmess = mnum
676  do while (iret .eq. 0 .and. lgrib .gt. 0)
677  lgrib4 = int(lgrib, kind(4))
678  call ix2gb2(lugb, lskip, idxver, lgrib4, cbuftmp, numfld, nbytes, iret1)
679  if (iret1 .ne. 0) print *, ' SAGT ', numfld, nbytes, iret1
680  if((nbytes + nlen) .gt. mbuf) then ! Allocate more space, if necessary.
681  newsize = max(mbuf + next, mbuf + nbytes)
682  call realloc(cbuf, nlen, newsize, istat)
683  if (istat .ne. 0) then
684  iret = 1
685  return
686  endif
687  mbuf = newsize
688  endif
689 
690  ! If index records were returned in cbuftmp from ixgb2,
691  ! copy cbuftmp into cbuf, then deallocate cbuftmp when done.
692  if (associated(cbuftmp)) then
693  cbuf(nlen + 1 : nlen + nbytes) = cbuftmp(1 : nbytes)
694  deallocate(cbuftmp, stat = istat)
695  if (istat .ne. 0) then
696  print *, ' deallocating cbuftmp ... ', istat
697  iret = 3
698  return
699  endif
700  nullify(cbuftmp)
701  nnum = nnum + numfld
702  nlen = nlen + nbytes
703  nmess = nmess + 1
704  endif
705 
706  ! Look for next grib message.
707  iseek = lskip + lgrib
708  call skgb8(lugb, iseek, msk2, lskip, lgrib)
709  enddo
710 end subroutine getg2i2r
711 
784 subroutine getgb2s(cbuf, nlen, nnum, j, jdisc, jids, jpdtn, jpdt, jgdtn, &
785  jgdt, k, gfld, lpos, iret)
786  use grib_mod
787  implicit none
788 
789  character(len = 1), intent(in) :: cbuf(nlen)
790  integer, intent(in) :: nlen, nnum, j, jdisc
791  integer, dimension(:) :: jids(*)
792  integer, intent(in) :: jpdtn
793  integer, dimension(:) :: jpdt(*)
794  integer, intent(in) :: jgdtn
795  integer, dimension(:) :: jgdt(*)
796  integer, intent(out) :: k
797  type(gribfield), intent(out) :: gfld
798  integer, intent(out) :: lpos, iret
799 
800  interface
801  subroutine getgb2s2(cbuf, idxver, nlen, nnum, j, jdisc, jids, jpdtn, jpdt, jgdtn, &
802  jgdt, k, gfld, lpos, iret)
803  import gribfield
804  character(len = 1), intent(in) :: cbuf(nlen)
805  integer, intent(in) :: idxver, nlen, nnum, j, jdisc
806  integer, dimension(:) :: jids(*)
807  integer, intent(in) :: jpdtn
808  integer, dimension(:) :: jpdt(*)
809  integer, intent(in) :: jgdtn
810  integer, dimension(:) :: jgdt(*)
811  integer, intent(out) :: k
812  type(gribfield), intent(out) :: gfld
813  integer, intent(out) :: lpos, iret
814  end subroutine getgb2s2
815  end interface
816 
817  ! When getgb2s() is called, always use index version 1. Call
818  ! getgb2s2() to handle version 1 or 2.
819  call getgb2s2(cbuf, 1, nlen, nnum, j, jdisc, jids, jpdtn, jpdt, jgdtn, &
820  jgdt, k, gfld, lpos, iret)
821 
822 end subroutine getgb2s
823 
897 subroutine getgb2s2(cbuf, idxver, nlen, nnum, j, jdisc, jids, jpdtn, jpdt, jgdtn, &
898  jgdt, k, gfld, lpos, iret)
899  use grib_mod
900  implicit none
901 
902  character(len = 1), intent(in) :: cbuf(nlen)
903  integer, intent(in) :: idxver, nlen, nnum, j, jdisc
904  integer, dimension(:) :: jids(*)
905  integer, intent(in) :: jpdtn
906  integer, dimension(:) :: jpdt(*)
907  integer, intent(in) :: jgdtn
908  integer, dimension(:) :: jgdt(*)
909  integer, intent(out) :: k
910  type(gribfield), intent(out) :: gfld
911  integer, intent(out) :: lpos, iret
912 
913  integer :: kgds(5)
914  logical :: match1, match3, match4
915  integer :: i, icnd, inlen, iof, ipos, jpos, lsec1, lsec3, lsec4, lsec5, numgdt, numpdt, inc
916 
917  interface
918  subroutine gf_unpack1(cgrib, lcgrib, iofst, ids, idslen, ierr)
919  character(len = 1), intent(in) :: cgrib(lcgrib)
920  integer, intent(in) :: lcgrib
921  integer, intent(inout) :: iofst
922  integer, pointer, dimension(:) :: ids
923  integer, intent(out) :: ierr, idslen
924  end subroutine gf_unpack1
925  subroutine gf_unpack3(cgrib, lcgrib, iofst, igds, igdstmpl, &
926  mapgridlen, ideflist, idefnum, ierr)
927  character(len = 1), intent(in) :: cgrib(lcgrib)
928  integer, intent(in) :: lcgrib
929  integer, intent(inout) :: iofst
930  integer, pointer, dimension(:) :: igdstmpl, ideflist
931  integer, intent(out) :: igds(5)
932  integer, intent(out) :: ierr, idefnum
933  end subroutine gf_unpack3
934  subroutine gf_unpack4(cgrib, lcgrib, iofst, ipdsnum, ipdstmpl, &
935  mappdslen, coordlist, numcoord, ierr)
936  character(len = 1), intent(in) :: cgrib(lcgrib)
937  integer, intent(in) :: lcgrib
938  integer, intent(inout) :: iofst
939  real, pointer, dimension(:) :: coordlist
940  integer, pointer, dimension(:) :: ipdstmpl
941  integer, intent(out) :: ipdsnum
942  integer, intent(out) :: ierr, numcoord
943  end subroutine gf_unpack4
944  subroutine gf_unpack5(cgrib, lcgrib, iofst, ndpts, idrsnum, &
945  idrstmpl, mapdrslen, ierr)
946  character(len = 1), intent(in) :: cgrib(lcgrib)
947  integer, intent(in) :: lcgrib
948  integer, intent(inout) :: iofst
949  integer, intent(out) :: ndpts, idrsnum
950  integer, pointer, dimension(:) :: idrstmpl
951  integer, intent(out) :: ierr
952  end subroutine gf_unpack5
953  end interface
954 
955  ! Initialize.
956  k = 0
957  lpos = 0
958  iret = 1
959  ipos = 0
960  nullify(gfld%idsect, gfld%local)
961  nullify(gfld%list_opt, gfld%igdtmpl, gfld%ipdtmpl)
962  nullify(gfld%coord_list, gfld%idrtmpl, gfld%bmap, gfld%fld)
963  if (idxver .eq. 1) then
964  inc = 0
965  else
966  ! Add the extra 4 bytes in the version 2 index record, starting
967  ! at byte 9.
968  inc = 4
969  endif
970 
971  ! Search for request.
972  do while(iret .ne. 0 .and. k .lt. nnum)
973  k = k + 1
974  ! Get length of current index record.
975  call g2_gbytec(cbuf, inlen, ipos * 8, 4 * 8)
976  if (k .le. j) then ! skip this index
977  ipos = ipos + inlen
978  cycle
979  endif
980 
981  ! Check if grib2 discipline is a match.
982  call g2_gbytec(cbuf, gfld%discipline, (ipos + inc + 41) * 8, 1 * 8)
983  if (jdisc .ne. -1 .and. jdisc .ne. gfld%discipline) then
984  ipos = ipos + inlen
985  cycle
986  endif
987 
988  ! Check if identification section is a match.
989  match1 = .false.
990  ! Get length of ids.
991  call g2_gbytec(cbuf, lsec1, (ipos + inc + 44) * 8, 4 * 8)
992  iof = 0
993  call gf_unpack1(cbuf(ipos + inc + 45), lsec1, iof, gfld%idsect, gfld%idsectlen, icnd)
994  if (icnd .eq. 0) then
995  match1 = .true.
996  do i = 1, gfld%idsectlen
997  if (jids(i) .ne. -9999 .and. jids(i) .ne. gfld%idsect(i)) then
998  match1 = .false.
999  exit
1000  endif
1001  enddo
1002  endif
1003  if (.not. match1) then
1004  deallocate(gfld%idsect)
1005  ipos = ipos + inlen
1006  cycle
1007  endif
1008 
1009  ! Check if grid definition template is a match.
1010  jpos = ipos + 44 + inc + lsec1
1011  match3 = .false.
1012  call g2_gbytec(cbuf, lsec3, jpos * 8, 4 * 8) ! get length of gds
1013  if (jgdtn .eq. -1) then
1014  match3 = .true.
1015  else
1016  call g2_gbytec(cbuf, numgdt, (jpos + 12) * 8, 2 * 8) ! get gdt template no.
1017  if (jgdtn .eq. numgdt) then
1018  iof = 0
1019  call gf_unpack3(cbuf(jpos + 1), lsec3, iof, kgds, gfld%igdtmpl, &
1020  gfld%igdtlen, gfld%list_opt, gfld%num_opt, icnd)
1021  if (icnd .eq. 0) then
1022  match3 = .true.
1023  do i = 1, gfld%igdtlen
1024  if (jgdt(i) .ne. -9999 .and. jgdt(i).ne.gfld%igdtmpl(i)) then
1025  match3 = .false.
1026  exit
1027  endif
1028  enddo
1029  endif
1030  endif
1031  endif
1032  if (.not. match3) then
1033  if (associated(gfld%idsect)) deallocate(gfld%idsect)
1034  if (associated(gfld%igdtmpl)) deallocate(gfld%igdtmpl)
1035  if (associated(gfld%list_opt)) deallocate(gfld%list_opt)
1036  ipos = ipos + inlen
1037  cycle
1038  else
1039  gfld%griddef = kgds(1)
1040  gfld%ngrdpts = kgds(2)
1041  gfld%numoct_opt = kgds(3)
1042  gfld%interp_opt = kgds(4)
1043  gfld%igdtnum = kgds(5)
1044  endif
1045 
1046  ! Check if product definition template is a match.
1047  jpos = jpos + lsec3
1048  match4 = .false.
1049 
1050  ! Get length of pds.
1051  call g2_gbytec(cbuf, lsec4, jpos * 8, 4 * 8)
1052  if (jpdtn .eq. -1) then
1053  match4 = .true.
1054  else
1055  ! Get pdt template no.
1056  call g2_gbytec(cbuf, numpdt, (jpos + 7) * 8, 2 * 8)
1057  if (jpdtn .eq. numpdt) then
1058  iof = 0
1059  call gf_unpack4(cbuf(jpos + 1), lsec4, iof, gfld%ipdtnum, &
1060  gfld%ipdtmpl, gfld%ipdtlen, gfld%coord_list, gfld%num_coord, icnd)
1061  if (icnd .eq. 0) then
1062  match4 = .true.
1063  do i = 1, gfld%ipdtlen
1064  if (jpdt(i) .ne. -9999 .and. jpdt(i) .ne. gfld%ipdtmpl(i)) then
1065  match4 = .false.
1066  exit
1067  endif
1068  enddo
1069  endif
1070  endif
1071  endif
1072  if (.not. match4) then
1073  if (associated(gfld%idsect)) deallocate(gfld%idsect)
1074  if (associated(gfld%ipdtmpl)) deallocate(gfld%ipdtmpl)
1075  if (associated(gfld%coord_list)) deallocate(gfld%coord_list)
1076  endif
1077 
1078  ! If request is found set values for derived type gfld and return.
1079  if (match1 .and. match3 .and. match4) then
1080  lpos = ipos + 1
1081  call g2_gbytec(cbuf, gfld%version, (ipos + inc + 40) * 8, 1 * 8)
1082  call g2_gbytec(cbuf, gfld%ifldnum, (ipos + inc + 42) * 8, 2 * 8)
1083  gfld%unpacked = .false.
1084  jpos = ipos + 44 + inc + lsec1
1085  if (jgdtn .eq. -1) then ! unpack gds, if not done before
1086  iof = 0
1087  call gf_unpack3(cbuf(jpos + 1), lsec3, iof, kgds, gfld%igdtmpl, &
1088  gfld%igdtlen, gfld%list_opt, gfld%num_opt, icnd)
1089  gfld%griddef = kgds(1)
1090  gfld%ngrdpts = kgds(2)
1091  gfld%numoct_opt = kgds(3)
1092  gfld%interp_opt = kgds(4)
1093  gfld%igdtnum = kgds(5)
1094  endif
1095  jpos = jpos + lsec3
1096  if (jpdtn .eq. -1) then ! unpack pds, if not done before
1097  iof = 0
1098  call gf_unpack4(cbuf(jpos + 1), lsec4, iof, gfld%ipdtnum, &
1099  gfld%ipdtmpl, gfld%ipdtlen, gfld%coord_list, gfld%num_coord, icnd)
1100  endif
1101  jpos = jpos + lsec4
1102  call g2_gbytec(cbuf, lsec5, jpos * 8, 4 * 8) ! get length of drs
1103  iof = 0
1104  call gf_unpack5(cbuf(jpos + 1), lsec5, iof, gfld%ndpts, &
1105  gfld%idrtnum, gfld%idrtmpl, gfld%idrtlen, icnd)
1106  jpos = jpos + lsec5
1107  call g2_gbytec(cbuf, gfld%ibmap, (jpos + 5) * 8, 1 * 8) ! get ibmap
1108  iret = 0
1109  else ! pdt did not match
1110  ipos = ipos + inlen
1111  endif
1112  enddo
1113 end subroutine getgb2s2
1114 
1148 subroutine ixgb2(lugb, lskip, lgrib, cbuf, numfld, mlen, iret)
1149  use re_alloc ! needed for subroutine realloc
1150  implicit none
1151 
1152  integer :: lugb, lskip, lgrib
1153  character(len = 1), pointer, dimension(:) :: cbuf
1154  integer :: numfld, mlen, iret
1155  integer (kind = 8) :: lskip8
1156 
1157  interface
1158  subroutine ix2gb2(lugb, lskip8, idxver, lgrib, cbuf, numfld, mlen, iret)
1159  integer :: lugb
1160  integer (kind = 8) :: lskip8
1161  integer :: idxver, lgrib
1162  character(len = 1), pointer, dimension(:) :: cbuf
1163  integer :: numfld, mlen, iret
1164  end subroutine ix2gb2
1165  end interface
1166 
1167  ! Always use index version 1 from this subroutine.
1168  lskip8 = lskip
1169  call ix2gb2(lugb, lskip8, 1, lgrib, cbuf, numfld, mlen, iret)
1170 end subroutine ixgb2
1171 
1207 subroutine ix2gb2(lugb, lskip8, idxver, lgrib, cbuf, numfld, mlen, iret)
1208  use re_alloc ! needed for subroutine realloc
1209  implicit none
1210 
1211  integer :: lugb
1212  integer (kind = 8) :: lskip8
1213  integer :: idxver, lgrib
1214  character(len = 1), pointer, dimension(:) :: cbuf
1215  integer :: numfld, mlen, iret
1216 
1217  character cver, cdisc
1218  character(len = 4) :: ctemp
1219  integer loclus, locgds, locbms
1220  integer :: indbmp, numsec, next, newsize, g2_mova2i, mbuf, lindex
1221  integer :: linmax, ixskp
1222  integer :: mxspd, mxskp, mxsgd, mxsdr, mxsbm, mxlus
1223  integer :: mxlen, mxds, mxfld, mxbms
1224  integer :: init, ixlus, lskip
1225  integer :: ixsgd, ilndrs, ilnpds, istat, ixds
1226  integer (kind = 8) :: ibread8, lbread8, ibskip8, lengds8
1227  integer (kind = 8) :: ilnpds8, ilndrs8
1228  integer :: ixspd, ixfld, ixids, ixlen, ixsbm, ixsdr
1229  integer :: lensec, lensec1
1230  parameter(linmax = 5000, init = 50000, next = 10000)
1231  parameter(ixskp = 4, ixlus = 8, ixsgd = 12, ixspd = 16, ixsdr = 20, ixsbm = 24, &
1232  ixds = 28, ixlen = 36, ixfld = 42, ixids = 44)
1233  parameter(mxskp = 4, mxlus = 4, mxsgd = 4, mxspd = 4, mxsdr = 4, mxsbm = 4, &
1234  mxds = 4, mxlen = 4, mxfld = 2, mxbms = 6)
1235  character cbread(linmax), cindex(linmax)
1236  character cids(linmax), cgds(linmax)
1237  integer :: INT1_BITS, INT2_BITS, INT4_BITS, INT8_BITS
1238  parameter(int1_bits = 8, int2_bits = 16, int4_bits = 32, int8_bits = 64)
1239  integer :: mypos, inc
1240 
1241  if (idxver .eq. 1) then
1242  inc = 0
1243  else
1244  ! Add the extra 4 bytes in the version 2 index record, starting
1245  ! at byte 9.
1246  inc = 4
1247  endif
1248 
1249  loclus = 0
1250  iret = 0
1251  mlen = 0
1252  numfld = 0
1253  nullify(cbuf)
1254  mbuf = init
1255  allocate(cbuf(mbuf), stat = istat) ! allocate initial space for cbuf
1256  if (istat .ne. 0) then
1257  iret = 1
1258  return
1259  endif
1260 
1261  ! Read sections 0 and 1 for GRIB version number and discipline.
1262  ibread8 = min(lgrib, linmax)
1263  call bareadl(lugb, lskip8, ibread8, lbread8, cbread)
1264  if (lbread8 .ne. ibread8) then
1265  iret = 2
1266  return
1267  endif
1268  if(cbread(8) .ne. char(2)) then ! not grib edition 2
1269  iret = 3
1270  return
1271  endif
1272  cver = cbread(8)
1273  cdisc = cbread(7)
1274  call g2_gbytec(cbread, lensec1, 16 * 8, int4_bits)
1275  lensec1 = min(lensec1, int(ibread8, kind(lensec1)))
1276  cids(1:lensec1) = cbread(17:16 + lensec1)
1277  ibskip8 = lskip8 + 16_8 + int(lensec1, kind(8))
1278 
1279  ! Loop through remaining sections creating an index for each field.
1280  ibread8 = max(5, mxbms)
1281  do
1282  call bareadl(lugb, ibskip8, ibread8, lbread8, cbread)
1283  ctemp = cbread(1)//cbread(2)//cbread(3)//cbread(4)
1284  if (ctemp .eq. '7777') return ! end of message found
1285  if (lbread8 .ne. ibread8) then
1286  iret = 2
1287  return
1288  endif
1289  call g2_gbytec(cbread, lensec, 0, int4_bits)
1290  call g2_gbytec(cbread, numsec, int4_bits, int1_bits)
1291 
1292  if (numsec .eq. 2) then ! save local use location
1293  loclus = int(ibskip8 - lskip8, kind(4))
1294  elseif (numsec .eq. 3) then ! save gds info
1295  lengds8 = lensec
1296  cgds = char(0)
1297  call bareadl(lugb, ibskip8, lengds8, lbread8, cgds)
1298  if (lbread8 .ne. lengds8) then
1299  iret = 2
1300  return
1301  endif
1302  locgds = int(ibskip8 - lskip8, kind(4))
1303  elseif (numsec .eq. 4) then ! found pds
1304  cindex = char(0)
1305  mypos = int4_bits
1306  if (idxver .eq. 1) then
1307  lskip = int(lskip8, kind(4))
1308  call g2_sbytec(cindex, lskip, mypos, int4_bits) ! bytes to skip
1309  mypos = mypos + int4_bits
1310  else
1311  call g2_sbytec8(cindex, lskip8, mypos, int8_bits) ! bytes to skip
1312  mypos = mypos + int8_bits
1313  endif
1314  call g2_sbytec(cindex, loclus, mypos, int4_bits) ! location of local use
1315  mypos = mypos + int4_bits
1316  call g2_sbytec(cindex, locgds, mypos, int4_bits) ! location of gds
1317  mypos = mypos + int4_bits
1318  call g2_sbytec(cindex, int(ibskip8 - lskip8, kind(4)), mypos, int4_bits) ! location of pds
1319  mypos = mypos + int4_bits * 4 ! skip ahead in cbuf
1320  call g2_sbytec(cindex, lgrib, mypos, int8_bits) ! len of grib2
1321  mypos = mypos + int8_bits
1322  cindex((mypos / 8) + 1) = cver
1323  mypos = mypos + int1_bits
1324  cindex((mypos / 8) + 1) = cdisc
1325  mypos = mypos + int1_bits
1326  call g2_sbytec(cindex, numfld + 1, mypos, int2_bits) ! field num
1327  mypos = mypos + int2_bits
1328  cindex(ixids + 1 + inc:ixids + lensec1 + inc) = cids(1:lensec1)
1329  lindex = ixids + lensec1 + inc
1330  cindex(lindex + 1:lindex + lengds8) = cgds(1:lengds8)
1331  lindex = lindex + int(lengds8, kind(lindex))
1332  ilnpds = lensec
1333  ilnpds8 = ilnpds
1334  call bareadl(lugb, ibskip8, ilnpds8, lbread8, cindex(lindex + 1))
1335  if (lbread8 .ne. ilnpds8) then
1336  iret = 2
1337  return
1338  endif
1339  lindex = lindex + ilnpds
1340  elseif (numsec .eq. 5) then ! found drs
1341  mypos = (ixsdr + inc) * int1_bits
1342  call g2_sbytec(cindex, int(ibskip8 - lskip8, kind(4)), mypos, int4_bits) ! location of drs
1343  ilndrs = lensec
1344  ilndrs8 = ilndrs
1345  call bareadl(lugb, ibskip8, ilndrs8, lbread8, cindex(lindex + 1))
1346  if (lbread8 .ne. ilndrs8) then
1347  iret = 2
1348  return
1349  endif
1350  lindex = lindex + ilndrs
1351  elseif (numsec .eq. 6) then ! found bms
1352  indbmp = g2_mova2i(cbread(6))
1353  mypos = (ixsbm + inc) * int1_bits
1354  if (indbmp.lt.254) then
1355  locbms = int(ibskip8 - lskip8, kind(4))
1356  call g2_sbytec(cindex, locbms, mypos, int4_bits) ! loc. of bms
1357  elseif (indbmp.eq.254) then
1358  call g2_sbytec(cindex, locbms, mypos, int4_bits) ! loc. of bms
1359  elseif (indbmp.eq.255) then
1360  call g2_sbytec(cindex, int(ibskip8 - lskip8, kind(4)), mypos, int4_bits) ! loc. of bms
1361  endif
1362  cindex(lindex + 1:lindex + mxbms) = cbread(1:mxbms)
1363  lindex = lindex + mxbms
1364  call g2_sbytec(cindex, lindex, 0, int4_bits) ! num bytes in index record
1365  elseif (numsec .eq. 7) then ! found data section
1366  mypos = (ixds + inc) * int1_bits
1367  call g2_sbytec(cindex, int(ibskip8 - lskip8, kind(4)), mypos, int4_bits) ! loc. of data sec.
1368  numfld = numfld + 1
1369  if ((lindex + mlen) .gt. mbuf) then ! allocate more space if necessary
1370  newsize = max(mbuf + next, mbuf + lindex)
1371  call realloc(cbuf, mlen, newsize, istat)
1372  if (istat .ne. 0) then
1373  numfld = numfld-1
1374  iret = 4
1375  return
1376  endif
1377  mbuf = newsize
1378  endif
1379  cbuf(mlen + 1:mlen + lindex) = cindex(1:lindex)
1380  mlen = mlen + lindex
1381  else ! unrecognized section
1382  iret = 5
1383  return
1384  endif
1385  ibskip8 = ibskip8 + lensec
1386  enddo
1387 end subroutine ix2gb2
1388 
1395 subroutine gf_finalize(iret)
1396  implicit none
1397 
1398  integer, intent(out) :: iret
1399  character(len = 1), pointer, dimension(:) :: cindex
1400  integer :: nlen, nnum
1401 
1402  ! Declare interfaces (required for cbuf pointer).
1403  interface
1404  subroutine getidx(lugb, lugi, cbuf, nlen, nnum, irgi)
1405  character(len = 1), pointer, dimension(:) :: cbuf
1406  integer, intent(in) :: lugb, lugi
1407  integer, intent(out) :: nlen, nnum, irgi
1408  end subroutine getidx
1409  end interface
1410 
1411  ! Call getidx with 0 for the first parameter, ensuring that the
1412  ! internal memory is freed.
1413  call getidx(0, 0, cindex, nlen, nnum, iret)
1414 
1415 end subroutine gf_finalize
1416 
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 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_sbytec8(out, in, iskip, nbits)
Put one arbitrary sized (up to 64 bits) values into a packed bit string, taking the low order bits fr...
Definition: g2bytes.F90:380
subroutine ix2gb2(lugb, lskip8, idxver, lgrib, cbuf, numfld, mlen, iret)
Generate a version 1 or 2 index record for each field in a GRIB2 message.
Definition: g2index.F90:1208
subroutine g2_create_index(lugb, lugi, idxver, filename, iret)
Create a version 1 or 2 index file for a GRIB2 file.
Definition: g2index.F90:21
subroutine getgb2s(cbuf, nlen, nnum, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, k, gfld, lpos, iret)
Find information about a GRIB field from the index and fill a grib_mod::gribfield.
Definition: g2index.F90:786
subroutine getidx(lugb, lugi, cindex, nlen, nnum, iret)
Find, read or generate a version 1 GRIB2 index for a GRIB2 file (which must be < 2 GB).
Definition: g2index.F90:198
subroutine g2_write_index_headers(lugi, nlen, nnum, idxver, filename)
Write index headers.
Definition: g2index.F90:103
subroutine getg2i2r(lugb, msk1, msk2, mnum, idxver, cbuf, nlen, nnum, nmess, iret)
Generate a version 1 or 2 index record for each message in a GRIB2 file.
Definition: g2index.F90:627
subroutine getg2ir(lugb, msk1, msk2, mnum, cbuf, nlen, nnum, nmess, iret)
Generate a version 1 index record for each message in a GRIB2 file.
Definition: g2index.F90:566
subroutine ixgb2(lugb, lskip, lgrib, cbuf, numfld, mlen, iret)
Generate a version 1 index record for each field in a GRIB2 message.
Definition: g2index.F90:1149
subroutine getidx2(lugb, lugi, idxver, cindex, nlen, nnum, iret)
Find, read or generate a version 1 or 2 GRIB2 index for a GRIB2 file (which may be > 2 GB).
Definition: g2index.F90:266
subroutine gf_finalize(iret)
Free all memory associated with the library.
Definition: g2index.F90:1396
subroutine getg2i(lugi, cbuf, nlen, nnum, iret)
Read a version 1 index file and return its contents.
Definition: g2index.F90:422
subroutine getg2i2(lugi, cbuf, idxver, nlen, nnum, iret)
Read a version 1 or 2 index file and return its contents.
Definition: g2index.F90:504
subroutine getgb2s2(cbuf, idxver, nlen, nnum, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, k, gfld, lpos, iret)
Find information about a GRIB field from the index and fill a grib_mod::gribfield.
Definition: g2index.F90:899
subroutine gf_unpack1(cgrib, lcgrib, iofst, ids, idslen, ierr)
Unpack Section 1 (Identification Section) of a GRIB2 message, starting at octet 6 of that Section.
Definition: g2unpack.F90:42
subroutine gf_unpack5(cgrib, lcgrib, iofst, ndpts, idrsnum, idrstmpl, mapdrslen, ierr)
Unpack Section 5 (Data Representation Section) of a GRIB2 message, starting at octet 6 of that Sectio...
Definition: g2unpack.F90:467
subroutine gf_unpack4(cgrib, lcgrib, iofst, ipdsnum, ipdstmpl, mappdslen, coordlist, numcoord, ierr)
Unpack Section 4 (Product Definition Section) of a GRIB2 message, starting at octet 6 of that Section...
Definition: g2unpack.F90:334
subroutine gf_unpack3(cgrib, lcgrib, iofst, igds, igdstmpl, mapgridlen, ideflist, idefnum, ierr)
Unpack Section 3 (Grid Definition Section) of a GRIB2 message, starting at octet 6 of that Section.
Definition: g2unpack.F90:184
This Fortran module contains the declaration of derived type gribfield.
Definition: gribmod.F90:10
Reallocate memory, preserving contents.
Definition: realloc.F90:12
subroutine skgb8(lugb, iseek8, mseek8, lskip8, lgrib8)
Search a file for the next GRIB1 or GRIB2 message.
Definition: skgb.F90:53