Dear All,
I am using parallel hdf5 to write compound dataset from biological
simulations. I am trying to use compound datatype with an array element
whose size is known at runtime (I see similar question which is not answered
<http://hdf-forum.184993.n3.nabble.com/C-or-C-create-a-compound-datatype-of-double-arrays-with-runtime-size-determination-td4025678.html>).
I have searched mailing list but didn't see any solution. I am providing
all info with the complete example. Let me know if I am making any mistake
below:
The compound datatype example
<https://www.hdfgroup.org/ftp/HDF5/examples/examples-by-api/hdf5-examples/1_8/C/H5T/h5ex_t_cmpd.c>
in the tutorial write below dataset (this is simple *serial* test example):
typedef struct {
double temperature;
double pressure;
char *location;
int serial_no;
} sensor_t;
I am slightly modifying this example to write:
typedef struct {
double temperature;
double pressure;
int *location; // note that compile time fixed
size array (e.g. *int location[38]*) works fine!
int serial_no;
} sensor_t;
Note that the length of location array is known at runtime and *same for
all instances of sensor_t (so I assume I don't need variable length
datatype which is not supported by parallel hdf5 anyway)*.
So I create compound datatype as:
// first create datatype for an array element
locdims[0] = nloc; //nloc is size of location array,
strtype = H5Tarray_create(H5T_NATIVE_INT, 1, locdims);
// I add size of location array otherwise I get an error: H5T__insert():
member extends past end of compound type
memtype = H5Tcreate (H5T_COMPOUND, sizeof (sensor_t) +
nloc*sizeof(int));
status = H5Tinsert (memtype, "Temperature (F)",
HOFFSET (sensor_t, temperature), H5T_NATIVE_DOUBLE);
status = H5Tinsert (memtype, "Pressure (inHg)",
HOFFSET (sensor_t, pressure), H5T_NATIVE_DOUBLE);
status = H5Tinsert (memtype, "Location", HOFFSET (sensor_t, location),
strtype);
/* for serial_no field I can't use HOFFSET (sensor_t, serial_no)
because location
* is pointer to 1-d array. So I manually calculate offset as:
*/
int serial_no_offset = HOFFSET (sensor_t, location) + nloc*sizeof(int);
status = H5Tinsert (memtype, "Serial number",
serial_no_offset, H5T_NATIVE_INT);
Now if I write and read above dataset through program I get correct values!
But if I try to look at the generated hdf5 file with hdf5dump, it shows
invalid values :
*$ ./a.out *
Dynamic Allocating nlocs 4
DS1[0]:
Serial number : 1153
Location : 0
Location : 10
Location : 20
Location : 30
Temperature (F) : 53.230000
Pressure (inHg) : 24.570000
DS1[1]:
Serial number : 1184
Location : 0
Location : 10
Location : 20
Location : 30
Temperature (F) : 55.120000
Pressure (inHg) : 22.950000
*$ h5dump h5ex_t_cmpd.h5*
HDF5 "h5ex_t_cmpd.h5" {
GROUP "/" {
DATASET "DS1" {
DATATYPE H5T_COMPOUND {
H5T_IEEE_F64LE "Temperature (F)";
H5T_IEEE_F64LE "Pressure (inHg)";
H5T_ARRAY { [4] H5T_STD_I32LE } "Location";
H5T_STD_I32LE "Serial number";
}
DATASPACE SIMPLE { ( 2 ) / ( 2 ) }
DATA {
(0): {
53.23,
24.57,
[ -515879600, 32684, 1153, 32767 ],
687194767
},
(1): {
6.93572e-310,
5.84974e-321,
[ 0, 0, 4, 0 ],
2
}
}
}
}
}
I have attached test program with this email. The fixed size array example
works fine and you can compile the attached test as:
gcc h5ex_t_cmpd.c -DSTATIC -I/include path lib_link
*To reproduce the above issue with (dynamically allocated array) : *
gcc h5ex_t_cmpd.c -I/include path lib_link
Any help will be appreciated!
Regards,
Pramod
/************************************************************
This example shows how to read and write compound
datatypes to a dataset. The program first writes
compound structures to a dataset with a dataspace of DIM0,
then closes the file. Next, it reopens the file, reads
back the data, and outputs it to the screen.
This file is intended for use with HDF5 Library version 1.8
************************************************************/
#include "hdf5.h"
#include <stdio.h>
#include <stdlib.h>
#define FILE "h5ex_t_cmpd.h5"
#define DATASET "DS1"
#define DIM0 2
#define NVEC 4
typedef struct {
double temperature;
double pressure;
#ifndef STATIC
int *location;
#else
int location[NVEC];
#endif
int serial_no;
} sensor_t; /* Compound type */
int
main (int argc, char *argv[])
{
hid_t file, memtype, strtype, space, dset;
/* Handles */
herr_t status;
hsize_t dims[1] = {DIM0};
hsize_t locdims[1];
sensor_t wdata[DIM0], /* Write buffer */
*rdata; /* Read buffer */
int ndims,
i;
int nloc = NVEC;
if(argc>1)
nloc = atoi(argv[1]);
#ifndef STATIC
printf("\n Dynamic Allocating array %d ", nloc);
#endif
/*
* Initialize data.
*/
#ifndef STATIC
wdata[0].location = (int *) malloc(sizeof(int)*nloc);
wdata[1].location = (int *) malloc(sizeof(int)*nloc);
#endif
wdata[0].serial_no = 1153;
wdata[0].temperature = 53.23;
wdata[0].pressure = 24.57;
wdata[1].serial_no = 1184;
wdata[1].temperature = 55.12;
wdata[1].pressure = 22.95;
for(i=0; i<nloc; i++) {
wdata[0].location[i] = i * 10;
wdata[1].location[i] = i * 10;
}
/*
* Create a new file using the default properties.
*/
file = H5Fcreate (FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
/*
* Create variable-length string datatype.
*/
locdims[0] = nloc;
strtype = H5Tarray_create(H5T_NATIVE_INT, 1, locdims);
/*
* Create the compound datatype for memory.
*/
#ifndef STATIC
//include size of location array otherwise I get an error: H5T__insert(): member extends past end of compound type
memtype = H5Tcreate (H5T_COMPOUND, sizeof (sensor_t) + nloc*sizeof(int));
#else
memtype = H5Tcreate (H5T_COMPOUND, sizeof (sensor_t));
#endif
status = H5Tinsert (memtype, "Temperature (F)",
HOFFSET (sensor_t, temperature), H5T_NATIVE_DOUBLE);
status = H5Tinsert (memtype, "Pressure (inHg)",
HOFFSET (sensor_t, pressure), H5T_NATIVE_DOUBLE);
status = H5Tinsert (memtype, "Location", HOFFSET (sensor_t, location),
strtype);
/* for serial_no field I can't use HOFFSET (sensor_t, serial_no) because location
* is pointer to 1-d array. So I manually calculate offset
*/
int serial_no_offset = HOFFSET (sensor_t, location) + nloc*sizeof(int);
status = H5Tinsert (memtype, "Serial number",
serial_no_offset, H5T_NATIVE_INT);
//HOFFSET (sensor_t, serial_no), H5T_NATIVE_INT);
/*
* Create dataspace. Setting maximum size to NULL sets the maximum
* size to be the current size.
*/
space = H5Screate_simple (1, dims, NULL);
/*
* Create the dataset and write the compound data to it.
*/
dset = H5Dcreate (file, DATASET, memtype, space, H5P_DEFAULT, H5P_DEFAULT,
H5P_DEFAULT);
status = H5Dwrite (dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata);
/*
* Close and release resources.
*/
status = H5Dclose (dset);
status = H5Sclose (space);
status = H5Fclose (file);
/*
* Now we begin the read section of this example. Here we assume
* the dataset has the same name and rank, but can have any size.
* Therefore we must allocate a new array to read in data using
* malloc(). For simplicity, we do not rebuild memtype.
*/
/*
* Open file and dataset.
*/
file = H5Fopen (FILE, H5F_ACC_RDONLY, H5P_DEFAULT);
dset = H5Dopen (file, DATASET, H5P_DEFAULT);
/*
* Get dataspace and allocate memory for read buffer.
*/
space = H5Dget_space (dset);
ndims = H5Sget_simple_extent_dims (space, dims, NULL);
rdata = (sensor_t *) malloc (dims[0] * sizeof (sensor_t));
#ifndef STATIC
rdata[0].location = (int *) malloc(sizeof(int)*nloc);
rdata[1].location = (int *) malloc(sizeof(int)*nloc);
#endif
/*
* Read the data.
*/
status = H5Dread (dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata);
/*
* Output the data to the screen.
*/
for (i=0; i<dims[0]; i++) {
printf ("%s[%d]:\n", DATASET, i);
printf ("Serial number : %d\n", rdata[i].serial_no);
for(int j=0; j<nloc; j++)
printf ("Location : %d\n", rdata[i].location[j]);
printf ("Temperature (F) : %f\n", rdata[i].temperature);
printf ("Pressure (inHg) : %f\n\n", rdata[i].pressure);
}
/*
* Close and release resources. H5Dvlen_reclaim will automatically
* traverse the structure and free any vlen data (strings in this
* case).
*/
status = H5Dvlen_reclaim (memtype, space, H5P_DEFAULT, rdata);
free (rdata);
status = H5Dclose (dset);
status = H5Sclose (space);
status = H5Tclose (memtype);
status = H5Tclose (strtype);
status = H5Fclose (file);
#ifndef STATIC
free(wdata[0].location);
free(wdata[1].location);
#endif
return 0;
}
_______________________________________________
Hdf-forum is for HDF software users discussion.
[email protected]
http://lists.hdfgroup.org/mailman/listinfo/hdf-forum_lists.hdfgroup.org
Twitter: https://twitter.com/hdf5