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

Data structures 在hdf5 fortran中扩展复合数据类型,data-structures,fortran90,hdf5,Data Structures,Fortran90,Hdf5,我正在尝试做一些应该相当普遍的事情。将复合数据类型的数组写入hdf5文件,扩展该文件并将数组的新值写入,依此类推。我想在一个循环中做这个。我将数据集初始化为零长度,然后根据需要在循环中扩展它。 如果回路为1跳闸,则工作正常: HDF5 "mydata_1trip.h5" { GROUP "/" { DATASET "MYDATA" { DATATYPE H5T_COMPOUND { H5T_STD_I32LE "i4_name"; H5T_STD_I16LE

我正在尝试做一些应该相当普遍的事情。将复合数据类型的数组写入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
     }      }      }      }      }
使用两次循环,数据集正确扩展,但第二次写入 覆盖原始数据并将垃圾放入第二个数据集中。那么问题似乎在于偏移量

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
种类参数

  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
档案

最大尺寸

  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(:)
我们创建一个内存数据空间,以指示内存中缓冲区的大小 记忆力 dims1已经过nsize

我们现在需要扩展数据集。我们设置了该文件的初始大小 dataset为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

所以主要的问题是调用H5Dwrite\u fdset\u id、s1\u tid、f\u ptr、hdferr应该是:调用H5Dwrite\u fdset\id、s1\u tid、f\u ptr、hdferr、memspace、dataspace。还有一些其他的小错误。
  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