HDF5 Real attribute writing in Fortran

883 Views Asked by At

I am trying to write an attribute in my HDF file, my code manages to write the proper value for the attribute if it is of type integer, but not for reals. This is the code

! Number of processes is assumed to be 4

! PROGRAM DATASET_BY_CHUNK

  USE HDF5 ! This module contains all necessary modules 
!     USE MPI

 IMPLICIT NONE

 include 'mpif.h'

 CHARACTER(LEN=7), PARAMETER :: filename = "test.h5"  ! File name
 CHARACTER(LEN=9), PARAMETER :: dsetname = "data_test" ! Dataset name

 INTEGER(HSIZE_T), DIMENSION(1) :: data_dims

 INTEGER(HID_T) :: file_id       ! File identifier 
 INTEGER(HID_T) :: dset_id       ! Dataset identifier 
 INTEGER(HID_T) :: filespace     ! Dataspace identifier in file 
 INTEGER(HID_T) :: memspace      ! Dataspace identifier in memory
 INTEGER(HID_T) :: plist_id      ! Property list identifier
 INTEGER(HID_T) :: attr_id       ! Attribute identifier
 INTEGER(HID_T) :: aspace_id     ! Attribute Dataspace identifier
 INTEGER(HID_T) :: atype_id      ! Attribute Dataspace identifier

 INTEGER(HSIZE_T), DIMENSION(2) :: dimsf = (/4,8/) ! Dataset dimensions
 ! in the file.
 !     INTEGER, DIMENSION(7) :: dimsfi = (/4,8,0,0,0,0,0/) 
 INTEGER(HSIZE_T), DIMENSION (2) :: dimsfi = (/4,8/) 
 INTEGER(HSIZE_T), DIMENSION(2) :: chunk_dims = (/2,4/) ! Chunks dimensions

 INTEGER(HSIZE_T),  DIMENSION(2) :: count  
 INTEGER(HSSIZE_T), DIMENSION(2) :: offset 
 INTEGER(HSIZE_T),  DIMENSION(2) :: stride
 INTEGER(HSIZE_T),  DIMENSION(2) :: block



 INTEGER(HSIZE_T), DIMENSION(1) :: adims ! Attribute dimension
 INTEGER          :: arank = 1     ! Attribure rank
 INTEGER(SIZE_T)  :: attrlen     ! Length of the attribute string

 CHARACTER(LEN=80) ::  attr_data  ! Attribute data


 INTEGER, ALLOCATABLE :: data (:,:)  ! Data to write
 INTEGER :: rank = 2 ! Dataset rank

 real re

 INTEGER :: error, error_n  ! Error flags
 !
 ! MPI definitions and calls.
 !
 INTEGER :: mpierror       ! MPI error flag
 INTEGER :: comm, info
 INTEGER :: mpi_size, mpi_rank

 comm = MPI_COMM_WORLD
 info = MPI_INFO_NULL

 CALL MPI_INIT(mpierror)
 CALL MPI_COMM_SIZE(comm, mpi_size, mpierror)
 CALL MPI_COMM_RANK(comm, mpi_rank, mpierror) 
 ! Quit if mpi_size is not 4 
 if (mpi_size .NE. 4) then
    write(*,*) 'This example is set up to use only 4 processes'
    write(*,*) 'Quitting....'
    goto 100
 endif

 attr_data = "Dataset character attribute"
 !
 ! Initialize HDF5 library and Fortran interfaces.
 !
 CALL h5open_f(error) 

 ! 
 ! Setup file access property list with parallel I/O access.
 !
 CALL h5pcreate_f(H5P_FILE_ACCESS_F, plist_id, error)
 CALL h5pset_fapl_mpio_f(plist_id, comm, info, error)

 !
 ! Create the file collectively.
 ! 
 CALL h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, error, access_prp = plist_id)
 CALL h5pclose_f(plist_id, error)
 !
 ! Create some attribute
 !
 re = 20.0
 !
 ! Create scalar data space for the attribute.
 !
 call h5screate_f(H5S_SCALAR_F,aspace_id,error)
 adims=80
 !     -----------------------------
 !     Reynolds number
 CALL h5acreate_f(file_id,'Re',H5T_NATIVE_DOUBLE,aspace_id, &
      attr_id, error)
 CALL h5awrite_f(attr_id,H5T_NATIVE_DOUBLE,re,adims,error)
 CALL h5aclose_f(attr_id, error)

 !
 ! Terminate access to the data space.
 !
 CALL h5sclose_f(aspace_id, error)

 !
 ! Create the data space for the  dataset. 
 !
 CALL h5screate_simple_f(rank, dimsf, filespace, error)
 CALL h5screate_simple_f(rank, chunk_dims, memspace, error)
 !
 ! Create chunked dataset.
 !
 CALL h5pcreate_f(H5P_DATASET_CREATE_F, plist_id, error)
 CALL h5pset_chunk_f(plist_id, rank, chunk_dims, error)
 CALL h5dcreate_f(file_id, dsetname, H5T_NATIVE_INTEGER, filespace, &
                  dset_id, error, plist_id)
 CALL h5sclose_f(filespace, error)
 !
 ! Each process defines dataset in memory and writes it to the hyperslab
 ! in the file. 
 !
 stride(1) = 1 
 stride(2) = 1 
 count(1) =  1 
 count(2) =  1 
 block(1) = chunk_dims(1)
 block(2) = chunk_dims(2)
 if (mpi_rank .EQ. 0) then
     offset(1) = 0
     offset(2) = 0
 endif
 if (mpi_rank .EQ. 1) then
     offset(1) = chunk_dims(1) 
     offset(2) = 0 
 endif
 if (mpi_rank .EQ. 2) then
     offset(1) = 0 
     offset(2) = chunk_dims(2) 
 endif
 if (mpi_rank .EQ. 3) then
     offset(1) = chunk_dims(1) 
     offset(2) = chunk_dims(2) 
 endif
 ! 
 ! Select hyperslab in the file.
 !
 CALL h5dget_space_f(dset_id, filespace, error)
 CALL h5sselect_hyperslab_f (filespace, H5S_SELECT_SET_F, offset, count, error, &
                             stride, block)
 ! 
 ! Initialize data buffer with trivial data.
 !
 ALLOCATE (data(chunk_dims(1),chunk_dims(2)))
 data = mpi_rank + 1
 !
 ! Create property list for collective dataset write
 !
 CALL h5pcreate_f(H5P_DATASET_XFER_F, plist_id, error) 
 CALL h5pset_dxpl_mpio_f(plist_id, H5FD_MPIO_COLLECTIVE_F, error)

 !
 ! Write the dataset collectively. 
 !
 CALL h5dwrite_f(dset_id, H5T_NATIVE_INTEGER, data, dimsfi, error, &
                 file_space_id = filespace, mem_space_id = memspace, xfer_prp = plist_id)
 !
 ! Write the dataset independently. 
 !
 !    CALL h5dwrite_f(dset_id, H5T_NATIVE_INTEGER, data, dimsfi,error, &
 !                     file_space_id = filespace, mem_space_id = memspace)
 !
 ! Deallocate data buffer.
 !
 DEALLOCATE(data)

 !
 ! Close dataspaces.
 !
 CALL h5sclose_f(filespace, error)
 CALL h5sclose_f(memspace, error)
 !
 ! Close the dataset.
 !
 CALL h5dclose_f(dset_id, error)
 !
 ! Close the property list.
 !
 CALL h5pclose_f(plist_id, error)
 !
 ! Close the file.
 !
 CALL h5fclose_f(file_id, error)

 !
 ! Close FORTRAN interfaces and HDF5 library.
 !
 CALL h5close_f(error)

 100  continue
 CALL MPI_FINALIZE(mpierror)

 END PROGRAM DATASET_BY_CHUNK

The program runs satisfactorily, but when checking in Matlab with h5disp, I get that:
Attributes: 'Re': 0.000000

Any suggestions about how to fix it would be great! Thanks a lot

1

There are 1 best solutions below

0
On

A Minimal, Complete, and Verifiable example (MCVE) would help both yourself (to spot your mistake) and us to figure out what you are really doing.

So in saying that, here's one. Please note there is no error checking, this is bad, bad, bad.

program fa

    use hdf5

    implicit none

    character(len=8), parameter :: filename = "test.h5"

    integer(hid_t) :: file_id
    integer(hid_t) :: attr_id
    integer(hid_t) :: aspace_id
    integer(size_t), dimension(1) :: adims = (/0/)

    integer     :: ierr
    real        :: re

    re = 20.0

    call h5open_f(ierr)
    call h5fcreate_f(trim(filename), H5F_ACC_TRUNC_F, file_id, ierr)
    call h5screate_f(H5S_SCALAR_F, aspace_id, ierr)
    call h5acreate_f(file_id, 'Reynolds number', H5T_NATIVE_REAL, &
                     aspace_id, attr_id, ierr)
    call h5awrite_f(attr_id, H5T_NATIVE_REAL, re, adims, ierr)
    call h5aclose_f(attr_id, ierr)
    call h5sclose_f(aspace_id, ierr)
    call h5fclose_f(file_id, ierr)
    call h5close_f(ierr)

end program fa

If you compile, run then dump the file:

$ h5fc -o fa fa.f90
$ ./fa
$ h5dump test.h5
HDF5 "test.h5" {
GROUP "/" {
    ATTRIBUTE "Reynolds number" {
      DATATYPE  H5T_IEEE_F32LE
      DATASPACE  SCALAR
      DATA {
      (0): 20
      }
    }
}
}

Now the question I have to ask about your code is why is adims set to 80?

I would highly suggest three things

  1. A MCVE.
  2. Error checking.

In regards to using MPI you should always get a serial version (within reason) working then parallelize it. Yes, I know this might near be impossible, but if you do go this route it will make your life easier (at least to begin with).