Dear all,
I have created a minimalistic example using an unlimited dimension for storing time series data. I have followed the Fortran example called h5_extend.f90
. However, I’m struggling at the final step of writing (appending) an additional data portion to the dataset. The code crashes with the following error messages:
HDF5-DIAG: Error detected in HDF5 (1.10.5) thread 0:
#000: ../../src/H5Dio.c line 322 in H5Dwrite(): could not get a validated dataspace from file_space_id
major: Invalid arguments to routine
minor: Bad value
#001: ../../src/H5S.c line 254 in H5S_get_validated_dataspace(): selection + offset not within extent
major: Dataspace
minor: Out of range
The main data structure in my code is a 3D array of “beads”. The first dimension of an array is the Cartesian coordinate, the second—is the bead ID and the third—is the time frame index. I can successfully write this array into a dataset. The second part of the code is creating data for an additional one time frame, extends the existing dataset and attempts to write (append) the new single time frame data into the extended dataset. Would you please point me in the right direction? I suspect I have a mistake in the huperslab selection. Maybe something is wrong with the offset or the count of the elements?
Example code:
PROGRAM H5_ARR_BEADS_EXT
USE HDF5
IMPLICIT NONE
! No. of coordinates, beads, time frames
integer, parameter :: NX = 3, NB = 10, NF = 5
! Beads array
real, allocatable :: beads(:,:,:)
! Coordinate arrays
real, allocatable :: gxx(:), gxy(:), gxz(:)
! File
integer(hid_t) :: fileID
character(len=8) :: fileName = "data.h5"
! Dataspace
integer :: spaceRank = 2
integer(size_t) :: spaceDims(2) = [NF, NB] ! frame, bead
integer(hsize_t) :: maxSpaceDims(2)
integer(hid_t) :: spaceID
! Memory space
integer :: memRank
integer(hsize_t) :: memDims(2)
integer(hid_t) :: memID
! Hyperslab
integer(hsize_t) :: offset(2), count(2)
! Datatype
integer :: arrTypeRank = 1
integer(size_t) :: arrTypeDims(1) = [NX]
integer(hid_t) :: arrTypeID, arrTypeWriteID
! Dataset
integer(size_t) :: dataSetDims(3) = [NF, NB, NX] ! frame, bead, coord
integer(hid_t) :: dataSetID
character(len=64) :: dataSetName
integer(hsize_t) :: dataSetExtDims(3)
! Property
integer(hid_t) :: propID
integer(hsize_t) :: chunkDims(2)
integer :: info ! I/O status
integer :: b, f ! counters
! coord, bead, frame
allocate(beads(dataSetDims(3),dataSetDims(2),dataSetDims(1)), &
gxx(dataSetDims(2)), gxy(dataSetDims(2)), gxz(dataSetDims(2)), &
stat=info)
! Initialise Fortran interface
call H5open_f(info)
! Create new file (with default properties)
call H5Fcreate_f(fileName, H5F_ACC_TRUNC_F, fileID, info)
!-----------------------------------------------------------------------
! Initialise data
! for each time frame
do f = 1, NF
! Initialise data arrays
call random_number(gxx)
call random_number(gxy)
call random_number(gxz)
! for each bead
do b = 1, NB
beads(:,b,f) = [gxx(b), gxy(b), gxz(b)]
print *, "Bead(",b,",",f,"):", beads(:,b,f)
end do
end do
! Create 2D array dataspace (frame, bead) with
! unlimited time frame dimension
! maxSpaceDims = [H5S_UNLIMITED_F, spaceDims(2)]
maxSpaceDims = [H5S_UNLIMITED_F, H5S_UNLIMITED_F]
call H5Screate_simple_f(spaceRank, spaceDims, spaceID, info, maxSpaceDims)
! Enable chunking
! chunkDims = [int(1,8), spaceDims(2)]
chunkDims = [int(1,8), int(1,8)]
call H5Pcreate_f(H5P_DATASET_CREATE_F, propID, info)
call H5Pset_chunk_f(propID, spaceRank, chunkDims, info)
! Create 1D array datatype (coord)
call H5Tarray_create_f(H5T_NATIVE_REAL, arrTypeRank, arrTypeDims, &
arrTypeID, info)
! Create dataset with chunking property
dataSetName = "Beads"
call H5Dcreate_f(fileID, dataSetName, arrTypeID, spaceID, dataSetID, &
info, propID)
! Write data into file
call H5Dwrite_f(dataSetID, arrTypeID, beads, dataSetDims, info)
!-----------------------------------------------------------------------
deallocate(beads, stat=info)
! coord, bead, frame
allocate(beads(dataSetDims(3),dataSetDims(2),1), &
stat=info)
print *, ""
print *, "----- ----- -----"
print *, ""
! Empty data array
beads = 0.0
! Initialise new data portion
! Initialise data arrays
call random_number(gxx)
call random_number(gxy)
call random_number(gxz)
! for each bead
do b = 1, NB
beads(:,b,1) = [gxx(b), gxy(b), gxz(b)]
print *, "Bead(",b,",",1,"):", beads(:,b,1)
end do
! Extend dataset
dataSetExtDims = [NF+1, NB, NX]
call H5Dset_extent_f(dataSetID, dataSetExtDims, info)
! Create 2D array memory space (frame, bead)
memRank = 2; memDims = [1, NB]
call H5Screate_simple_f(memRank, memDims, memID, info)
! Write to extended part of dataset
! Select hyperslab in dataspace
offset = [NF, 0]; count = [1, NB]
call H5Sselect_hyperslab_f(spaceID, H5S_SELECT_SET_F, offset, &
count, info)
! Write data
dataSetDims = [1, NB, NX]
call H5Dwrite_f(dataSetID, arrTypeID, beads(:,:,1), dataSetDims, info, &
memID, spaceID)
! Close dataset
call H5Dclose_f(dataSetID, info)
! Close datatype
call H5Tclose_f(arrTypeID, info)
! Close dataspace
call H5Sclose_f(spaceID, info)
! Close memory space
call H5Sclose_f(memID, info)
!-----------------------------------------------------------------------
! Close file
call h5fclose_f(fileID, info)
! Close Fortran interface
call h5close_f(info)
! Deallocate data arrays
deallocate(beads, gxx, gxy, gxz, stat=info)
END PROGRAM H5_ARR_BEADS_EXT