在hdf5 fortran中扩展复合数据类型

时间:2013-06-13 16:07:04

标签: data-structures fortran90 hdf5

我正在尝试做一些应该相当普遍的事情。将复合数据类型的数组写入hdf5文件,扩展文件并将数组的新值写出,依此类推。我想在一个循环中做这个。我将我的数据集初始化为零长度,然后根据需要在循环中扩展它。 如果循环是1次旅行,它可以正常工作:

  HDF5 "mydata_1trip.h5" {
  GROUP "/" {
  DATASET "MYDATA" {
  DATATYPE  H5T_COMPOUND {
     H5T_STD_I32LE "i4_name";
     H5T_STD_I16LE "i21_name";
     H5T_STD_I16LE "i22_name";
     H5T_IEEE_F64LE "r8_name";
  }
  DATASPACE  SIMPLE { ( 2 ) / ( H5S_UNLIMITED ) }
  DATA {
  (0): {
        -100,
        -1,
        0,
        1e+06
     },
  (1): {
        -100,
        -1,
        0,
        1e+06
     }      }      }      }      }

使用2个循环循环,数据集正确扩展,但第二次写入 覆盖原始数据(并将垃圾放入第二个数据集)。所以问题似乎与偏移量有关吗?

HDF5 "mydata_2trip.h5" {
GROUP "/" {
DATASET "MYDATA" {
  DATATYPE  H5T_COMPOUND {
     H5T_STD_I32LE "i4_name";
     H5T_STD_I16LE "i21_name";
     H5T_STD_I16LE "i22_name";
     H5T_IEEE_F64LE "r8_name";
  }
  DATASPACE  SIMPLE { ( 4 ) / ( H5S_UNLIMITED ) }
  DATA {
  (0): {
        -200,
        -2,
        0,
        2e+06
     },
  (1): {
        -200,
        -2,
        0,
        2e+06
     },
  (2): {
        107382520,
        1,
        0,
        0
     },
  (3): {
        107375576,
        1,
        0,
        4.94066e-324
     }
  }
  }
  }
  }

这是代码

      program read_test
  USE hdf5
  USE ISO_C_BINDING
  implicit none

KIND参数

  INTEGER, PARAMETER :: int_k1 = SELECTED_INT_KIND(1) ! This should map to INTEGER*1 on most modern processors
  INTEGER, PARAMETER :: int_k2 = SELECTED_INT_KIND(4) ! This should map to INTEGER*2 on most modern processors
  INTEGER, PARAMETER :: int_k4 = SELECTED_INT_KIND(8) ! This should map to INTEGER*4 on most modern processors
  INTEGER, PARAMETER :: int_k8 = SELECTED_INT_KIND(16) ! This should map to INTEGER*8 on most modern processors

  INTEGER, PARAMETER :: r_k4 = SELECTED_REAL_KIND(5) ! This should map to REAL*4 on most modern processors
  INTEGER, PARAMETER :: r_k8 = SELECTED_REAL_KIND(10) ! This should map to REAL*8 on most modern processors

文件

  CHARACTER(LEN=*), PARAMETER ::
 &   H5FILE_NAME="mydata.h5"
  CHARACTER(LEN=*), PARAMETER :: DATASETNAME = "MYDATA"

  type my_data
  sequence
  integer(kind=int_k4) :: i4
  integer(kind=int_k2) :: i1_2,i2_2
  real (kind=r_k8) :: r8
  end type

  integer(kind=int_k4) :: nsize=2,i
  type(my_data),allocatable :: iblock(:)


  INTEGER, PARAMETER :: RANK = 1



  TYPE(my_data), pointer :: s1(:)
  INTEGER(hid_t) :: s1_tid  ! File datatype identifier
  INTEGER(HID_T) :: file_id ! File identifier 
  INTEGER(HID_T) :: dset_id ! Dataset identifier 
  INTEGER(HID_T) :: dataspace ! Dataspace identifier 
  INTEGER(HID_T) :: memspace ! Memory dataspace identifier 
  INTEGER(HID_T) :: crp_list ! Dataset creation property identifier 


  INTEGER(hsize_t) :: DIMS(1) ! Dataspace dimensions
  INTEGER(SIZE_T) :: type_size ! Size of the datatype
  INTEGER(SIZE_T) :: compound_offset, sizeof_compound
  INTEGER(HSIZE_T), DIMENSION(1) :: chunk_dims,size
  INTEGER :: hdferr
  TYPE(C_PTR) :: f_ptr

最大尺寸

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

  INTEGER(HSIZE_T), DIMENSION(1) :: offset
  INTEGER(HSIZE_T), DIMENSION(1) :: count 

分配缓冲区:

  allocate(iblock(nsize))
  dims(1) = nsize
  allocate(s1(dims(1)))

初始化FORTRAN接口。

  CALL h5open_f(hdferr)

使用默认属性创建新文件。

 CALL h5fcreate_f(h5file_name, H5F_ACC_TRUNC_F, file_id, hdferr)

我们最初将其设置为0.我们 可以在每个步骤扩展数据集。

  maxdims = (/H5S_UNLIMITED_F/)
  dims(1) = 0
  write(*,*)" dims = ",dims

创建无限维度的数据空间。

  CALL H5Screate_simple_f(RANK, dims, dataspace, hdferr,maxdims)

然后创建数据集创建属性列表。数据集的布局 使用无限尺寸时必须分块。的选择 块大小会影响性能,包括时间和磁盘空间。如果 块很小,你会有很多开销。如果它们是 太大了,您可能会分配不需要的空间和文件 可能最终会变得太大。这是一个玩具示例,所以我们会选择 一行的大块。

修改数据集创建属性,即启用分块

  CALL h5pcreate_f(H5P_DATASET_CREATE_F, crp_list, hdferr)
  chunk_dims(1) = nsize
  CALL h5pset_chunk_f(crp_list, RANK, chunk_dims, hdferr)

创建内存数据类型。

  CALL H5Tcreate_f(H5T_COMPOUND_F, H5OFFSETOF(C_LOC(s1(1)),
 &   C_LOC(s1(2))), s1_tid, hdferr)

  CALL H5Tinsert_f(s1_tid, "i4_name",
 &   H5OFFSETOF(C_LOC(s1(1)),C_LOC(s1(1)%i4)),
 &   h5kind_to_type(int_k4,H5_INTEGER_KIND), hdferr)
  CALL H5Tinsert_f(s1_tid, "i21_name",
 &   H5OFFSETOF(C_LOC(s1(1)),C_LOC(s1(1)%i1_2)),
 &   h5kind_to_type(int_k2,H5_INTEGER_KIND), hdferr)
  CALL H5Tinsert_f(s1_tid, "i22_name",
 &   H5OFFSETOF(C_LOC(s1(1)),C_LOC(s1(1)%i2_2)),
 &   h5kind_to_type(int_k2,H5_INTEGER_KIND), hdferr)
  CALL H5Tinsert_f(s1_tid, "r8_name",
 &   H5OFFSETOF(C_LOC(s1(1)),C_LOC(s1(1)%r8)),
 &   h5kind_to_type(r_k8,H5_REAL_KIND), hdferr)

创建数据集。

  CALL H5Dcreate_f(file_id, datasetname, s1_tid, dataspace, 
 &   dset_id, hdferr,crp_list)

关闭资源。现在创建了数据集,因此我们不需要 物业清单了。我们不再需要文件数据空间了,因为 当数据集将被扩展时,它将变为无效 仍然保持以前的程度。所以我们必须抓住更新的 无论如何都是文件数据空间。

  call h5pclose_f(crp_list,hdferr)
  CALL h5sclose_f(dataspace, hdferr)

我们创建一个内存数据空间来指示缓冲区的大小 记忆。

  dims(1) = nsize
  CALL h5screate_simple_f(RANK, dims, dataspace, hdferr)

设置输入数据

  do i=1,2
   iblock(:)%i4 = -100*i
   iblock(:)%i1_2 = i
   iblock(:)%i2_2 = -i
   iblock(:)%r8 = 1.d6*i 

将数据写入memtype

   s1(:) = iblock(:)

我们创建一个内存数据空间来指示缓冲区的大小 记忆。 dims(1)已经是nsize

我们现在需要扩展数据集。我们设置了初始大小 数据集为0,因此我们需要首先扩展它。请注意,我们扩展 数据集本身,而不是数据空间。

  size(1) = i*nsize
  CALL h5dset_extent_f(dset_id, size, hdferr)
  dims(1) = nsize
  CALL h5screate_simple_f (rank, dims, memspace, hdferr)
  CALL h5dget_space_f(dset_id, dataspace, hdferr)
  offset(1) = (i-1)*nsize ! if this is in chunks
  count(1)  = nsize

  CALL h5sselect_hyperslab_f(dataspace, H5S_SELECT_SET_F, 
 &   offset, count, hdferr)

将数据数组写入数据集

  f_ptr = C_LOC(s1(1))
  CALL H5Dwrite_f(dset_id, s1_tid, f_ptr, hdferr)

  CALL h5sclose_f(dataspace,hdferr)

  enddo

发布资源

  CALL H5Tclose_f(s1_tid, hdferr)
  CALL h5sclose_f(memspace, hdferr)
  CALL h5dclose_f(dset_id, hdferr)
  CALL h5fclose_f(file_id, hdferr)
  end program read_test

0 个答案:

没有答案