Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

moving grb2index core code into g2 library #615

Merged
merged 25 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6f426d7
moving grb2index core code into g2 library
edwardhartnett Feb 15, 2024
7530344
moving grb2index code into g2 library
edwardhartnett Feb 15, 2024
0524c87
moving grb2index code into g2 library
edwardhartnett Feb 15, 2024
6f881f9
moved code to create index into library
edwardhartnett Feb 15, 2024
b3fbb61
cleanup
edwardhartnett Feb 15, 2024
3fe79ec
working on test
edwardhartnett Feb 15, 2024
78fe876
working on test
edwardhartnett Feb 15, 2024
9080c8e
working on test
edwardhartnett Feb 15, 2024
ca5d26e
working on test
edwardhartnett Feb 15, 2024
d6cadd2
fixed leak in test
edwardhartnett Feb 15, 2024
7553e3b
more index testing
edwardhartnett Feb 15, 2024
c115288
more index testing
edwardhartnett Feb 15, 2024
489bdb6
working on index test
edwardhartnett Feb 15, 2024
0e01790
working on index test
edwardhartnett Feb 15, 2024
40a6c4e
commented out all test code in test_create_index.F90
edwardhartnett Feb 16, 2024
6075c25
uncommented out some test code in test_create_index.F90
edwardhartnett Feb 16, 2024
e22a12a
uncommented out some more test code in test_create_index.F90
edwardhartnett Feb 16, 2024
b8a479b
adding intents
edwardhartnett Feb 16, 2024
33c1cc5
more testing
edwardhartnett Feb 16, 2024
cfa229d
changed filename in index header record
edwardhartnett Feb 16, 2024
d2800b2
initialized variables
edwardhartnett Feb 16, 2024
05dbcf6
uncommented more test code, again
edwardhartnett Feb 16, 2024
2ce20d6
uncommented more test code, again
edwardhartnett Feb 16, 2024
264cc2b
fixed test
edwardhartnett Feb 16, 2024
fbbe2d8
test working
edwardhartnett Feb 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 148 additions & 4 deletions src/g2index.F90
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,150 @@
!> @brief Subroutines for dealing with indexes.
!> @author Edward Hartnett @date Jan 31, 2024

!> Create a version 1 or 2 index file for a GRIB2 file.
!>
!> @param[in] lugb Logical unit of opened GRIB2 file.
!> @param[in] lugi Logical unit file opened to write index to.
!> @param[in] idxver Index version.
!> @param[in] filename Name of GRIB2 file.
!> @param[out] iret Return code:
!> - 0 success
!> - 90 problem opening GRIB2 file.
!> - 91 problem opening index file.
!> - 92 no messages found in GRIB2 file.
!>
!> @author Ed Hartnett, Mark Iredell @date Feb 15, 2024
subroutine g2_create_index(lugb, lugi, idxver, filename, iret)
implicit none

integer, intent(in) :: lugb, lugi, idxver
character*(*) :: filename
integer, intent(out) :: iret

integer (kind = 8) :: msk1, msk2
parameter(msk1 = 32000_8, msk2 = 4000_8)
character(len=1), pointer, dimension(:) :: cbuf
integer :: numtot, nnum, nlen, mnum, kw
integer :: irgi, iw, nmess

interface
subroutine getg2i2r(lugb, msk1, msk2, mnum, idxver, cbuf, &
nlen, nnum, nmess, iret)
integer, intent(in) :: lugb
integer (kind = 8), intent(in) :: msk1, msk2
integer, intent(in) :: mnum, idxver
character(len = 1), pointer, dimension(:) :: cbuf
integer, intent(out) :: nlen, nnum, nmess, iret
end subroutine getg2i2r
end interface

! Assume success.
iret = 0
numtot = 0
nlen = 0

! Generate index records for all messages in file, or until memory
! runs out.
mnum = 0
call getg2i2r(lugb, msk1, msk2, mnum, idxver, cbuf, &
nlen, nnum, nmess, irgi)
if (irgi .gt. 1 .or. nnum .eq. 0 .or. nlen .eq. 0) then
iret = 92
return
endif
numtot = numtot + nnum
mnum = mnum + nmess

! Write headers.
call g2_write_index_headers(lugi, nlen, numtot, filename)
iw = 162

! Write the index data we have so far.
call bawrite(lugi, iw, nlen, kw, cbuf)
iw = iw + nlen

! Extend index file if index buffer length too large to hold in memory.
if (irgi .eq. 1) then
do while (irgi .eq. 1 .and. nnum .gt. 0)
if (associated(cbuf)) then
deallocate(cbuf)
nullify(cbuf)
endif
call getg2i2r(11, msk1, msk2, mnum, idxver, cbuf, &
nlen, nnum, nmess, irgi)
if (irgi .le. 1 .and. nnum .gt. 0) then
numtot = numtot + nnum
mnum = mnum + nmess
call bawrite(lugi, iw, nlen, kw, cbuf)
iw = iw + nlen
endif
enddo
! Go back and overwrite headers with new info.
call g2_write_index_headers(lugi, iw, numtot, filename)
endif
deallocate(cbuf)

end subroutine g2_create_index

!> Write index headers.
!>
!> @param[in] lugi integer logical unit of output index file
!> @param[in] nlen integer total length of index records
!> @param[in] nnum integer number of index records
!> @param[in] filename character name of GRIB file
!>
!> @author Iredell @date 93-11-22
subroutine g2_write_index_headers(lugi, nlen, nnum, filename)
implicit none

integer, intent(in) :: lugi, nlen, nnum
character, intent(in) :: filename*(*)

character cd8*8, ct10*10, hostname*15
#ifdef __GFORTRAN__
integer istat
#else
character hostnam*15
integer hostnm
#endif
character chead(2)*81
integer :: kw

! fill first 81-byte header
call date_and_time(cd8, ct10)
chead(1) = '!GFHDR!'
chead(1)(9:10) = ' 1'
chead(1)(12:14) = ' 1'
write(chead(1)(16:20),'(i5)') 162
chead(1)(22:31) = cd8(1:4) // '-' // cd8(5:6) // '-' // cd8(7:8)
chead(1)(33:40) = ct10(1:2) // ':' // ct10(3:4) // ':' // ct10(5:6)
chead(1)(42:47) = 'GB2IX1'
chead(1)(49:54) = ' '
#ifdef __GFORTRAN__
istat = hostnm(hostname)
if (istat .eq. 0) then
chead(1)(56:70) = '0000'
else
chead(1)(56:70) = '0001'
endif
#else
chead(1)(56:70) = hostnam(hostname)
#endif
chead(1)(72:80) = 'grb2index'
chead(1)(81:81) = char(10)

! fill second 81-byte header
chead(2) = 'IX1FORM:'
write(chead(2)(9:38),'(3i10)') 162, nlen, nnum
chead(2)(41:80) = filename
chead(2)(81:81) = char(10)

! write headers at beginning of index file
call bawrite(lugi, 0, 162, kw, chead)

return
end subroutine g2_write_index_headers

!> Find, read or generate a version 1 GRIB2 index for a GRIB2 file
!> (which must be < 2 GB).
!>
Expand Down Expand Up @@ -363,7 +507,6 @@ subroutine getg2i2(lugi, cbuf, idxver, nlen, nnum, iret)
iret = 4
call baread(lugi, 0, 162, lhead, chead)
if (lhead .eq. 162 .and. chead(42:47) .eq. 'GB2IX1') then
! read(chead(82:162), '(8x, 3i10, 2x, a40)', iostat = ios) nskp, nlen, nnum
read(chead(82:162), '(2x, i1, 5x, 3i10, 2x, a40)', iostat = ios) idxver, nskp, nlen, nnum
if (ios .eq. 0) then
allocate(cbuf(nlen), stat = istat) ! Allocate space for cbuf.
Expand All @@ -378,7 +521,7 @@ subroutine getg2i2(lugi, cbuf, idxver, nlen, nnum, iret)
endif
end subroutine getg2i2

!> Generate an index record for a message in a GRIB2 file.
!> Generate a version 1 index record for each message in a GRIB2 file.
!>
!> The index record contains byte offsets to the message, it's length,
!> and byte offsets within the message to each section. The index file
Expand Down Expand Up @@ -438,7 +581,8 @@ end subroutine getg2i2r
call getg2i2r(lugb, msk1_8, msk2_8, mnum, 1, cbuf, nlen, nnum, nmess, iret)
end subroutine getg2ir

!> Generate an index record for a message in a GRIB2 file.
!> Generate a version 1 or 2 index record for each message in a GRIB2
!> file.
!>
!> The index record contains byte offsets to the message, it's length,
!> and byte offsets within the message to each section. The index file
Expand Down Expand Up @@ -816,7 +960,7 @@ end subroutine gf_unpack5
endif

! Search for request.
do while(iret.ne.0 .and. k.lt.nnum)
do while(iret .ne. 0 .and. k .lt. nnum)
k = k + 1
! Get length of current index record.
call g2_gbytec(cbuf, inlen, ipos * 8, 4 * 8)
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ foreach(kind ${kinds})
create_test(test_mkieee ${kind})
create_test(test_getlocal ${kind})
create_test(test_index_gdas ${kind} index_rec.F90)
create_test(test_create_index ${kind})
create_test(test_getgb2p_gdas ${kind})
set_tests_properties(test_getgb2p_gdas_${kind} PROPERTIES LABELS noMemcheck)
create_test(test_realloc ${kind})
Expand Down
133 changes: 133 additions & 0 deletions tests/test_create_index.F90
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
! This is a test program for NCEPLIBS-g2.
!
! This program tests index file functionality with g2_create_index().
!
! Ed Hartnett 2/15/24
program test_create_index
use grib_mod
implicit none

! These are the test files we will use.
character(*) :: TEST_FILE_GDAS
parameter (TEST_FILE_GDAS = 'gdaswave.t00z.wcoast.0p16.f000.grib2')
character(*) :: TEST_FILE_GDAS_INDEX
parameter (TEST_FILE_GDAS_INDEX = 'test_create_index_gdaswave.grb2index')
character(len=1), pointer, dimension(:) :: cbuf(:)
integer :: idxver = 1, nlen, nnum, lugi = 31, lugb = 11
integer :: j, jdisc, jpdtn, jgdtn
integer :: jids(13), jpdt(100), jgdt(250)
integer :: i
integer :: k, lpos, iret
type(gribfield) :: gfld
integer :: expected_idsect(13) = (/ 7, 0, 2, 1, 1, 2021, 11, 30, 0, 0, 0, 0, 1 /)
integer :: expected_igdtmpl(19) = (/ 6, 0, 0, 0, 0, 0, 0, 241, 151, 0, 0, 50000000, &
210000000, 48, 25000000, 250000000, 166667, 166667, 0 /)
integer :: expected_ipdtmpl(15) = (/ 2, 1, 2, 0, 11, 0, 0, 1, 0, 1, 0, 1, 255, 0, 0 /)
integer :: expected_idrtmpl(7) = (/ 1092616192, 0, 2, 11, 0, 0, 255 /)
integer :: ios

interface
subroutine getg2i2(lugi, cbuf, idxver, nlen, nnum, iret)
integer, intent(in) :: lugi
character(len=1), pointer, dimension(:) :: cbuf
integer, intent(out) :: idxver, nlen, nnum, iret
end subroutine getg2i2
subroutine g2_create_index(lugb, lugi, idxver, filename, iret)
integer, intent(in) :: lugb, lugi, idxver
character*(*) :: filename
integer, intent(out) :: iret
end subroutine g2_create_index
end interface

print *, 'Testing index creation and reading.'
print *, 'testing g2_create_index on ', TEST_FILE_GDAS

! Open GRIB2 file for reading.
call baopenr(lugb, TEST_FILE_GDAS, ios)
if (ios .ne. 0) stop 2

! Open output file where index will be written.
call baopen(lugi, TEST_FILE_GDAS_INDEX, ios)
if (ios .ne. 0) stop 3

call g2_create_index(lugb, lugi, idxver, TEST_FILE_GDAS, iret)
if (iret .ne. 0) stop 10

call baclose(lugb, ios)
if (ios .ne. 0) stop 11
call baclose(lugi, ios)
if (ios .ne. 0) stop 12

print *, 'OK!'
print *, 'testing that index file can be read with getg2i2()...'

! Open the index file.
call baopen(lugi, TEST_FILE_GDAS_INDEX, iret)
if (iret .ne. 0) stop 20

! Read the index file.
call getg2i2(lugi, cbuf, idxver, nlen, nnum, iret)
if (nlen .ne. 3800 .or. nnum .ne. 19 .or. iret .ne. 0) stop 80

! Close the index file.
call baclose(lugi, iret)
if (iret .ne. 0) stop 100

print *, 'OK!'
print *, 'testing that index buffer can be understood by getgb2s2()...'

! Parse the index info in cbuf, and fill gfld with the info about
! the first message.
j = 0
jdisc = -1
do i = 1, 13
jids(i) = -9999
end do
jpdtn = -1
do i = 1, 100
jpdt(i) = -9999
end do
jgdtn = -1
do i = 1, 250
jgdt(i) = -9999
end do
call getgb2s2(cbuf, idxver, nlen, nnum, j, jdisc, jids, jpdtn, jpdt, jgdtn, &
jgdt, k, gfld, lpos, iret)
if (iret .ne. 0) stop 101

! Check that the information is correct for the first record.
if (gfld%version .ne. 2 .or. gfld%discipline .ne. 0) stop 102
if (gfld%idsectlen .ne. 13) stop 103
if (gfld%ifldnum .ne. 1) stop 105
if (gfld%griddef .ne. 0) stop 106
if (gfld%ngrdpts .ne. 36391) stop 107
if (gfld%numoct_opt .ne. 0 .or. gfld%interp_opt .ne. 0 .or. gfld%num_opt .ne. 0) stop 108
if (gfld%igdtnum .ne. 0 .or. gfld%igdtlen .ne. 19) stop 109
if (gfld%ipdtnum .ne. 0 .or. gfld%ipdtlen .ne. 15 .or. gfld%num_coord .ne. 0) stop 110
if (gfld%unpacked .neqv. .FALSE.) stop 112
if (gfld%ibmap .ne. 0) stop 113
do i = 1, gfld%idsectlen
if (gfld%idsect(i) .ne. expected_idsect(i)) stop 200
end do
do i = 1, gfld%igdtlen
if (gfld%igdtmpl(i) .ne. expected_igdtmpl(i)) stop 201
end do
do i = 1, gfld%ipdtlen
if (gfld%ipdtmpl(i) .ne. expected_ipdtmpl(i)) stop 202
end do
do i = 1, gfld%idrtlen
if (gfld%idrtmpl(i) .ne. expected_idrtmpl(i)) stop 203
end do

! Free memory.
call gf_free(gfld)

print *, 'OK!'

! Clean up.
deallocate(cbuf)
call gf_finalize(iret)
if (iret .ne. 0) stop 200

print *, 'SUCCESS!...'
end program test_create_index
Loading