'Saving Armadillo matrix/cube into HDF5 file

I'm trying to save a struct with multiple arma::vec, arma:mat and arma::cube.

struct rdb_struct{
    string info;
    vec rng_vec;
    vec azvec;
    cube TSAP;
    cube CONV;
    cube TVSAP;
    mat rd_maxbeam;
    mat rd_maxbeam2;
    mat rd_maxbeam3;
    umat rd_maxbeam_index;
    umat rd_maxbeam2_index;
    umat rd_maxbeam3_index;
    mat rd_maxbeam_azdeg;
    mat rd_maxbeam2_azdeg;
    mat rd_maxbeam3_azdeg;
};

For the string and vectors, it was somewhat simple to save:

#define ARMA_DONT_USE_WRAPPER
#include <armadillo>
#include <string>
#include <iostream>
#include "H5Cpp.h"
#define ARMA_ALLOW_FAKE_GCC  //allows the use of GCC compiled armadillo with ICC compiler

using namespace std;
using namespace arma;

struct rdb_struct{
    string info;
    //params_struct params;
    vec rng_vec;

    vec azvec;
    
    cube TSAP;
    cube CONV;
    cube TVSAP;
    
    mat rd_maxbeam;
    mat rd_maxbeam2;
    mat rd_maxbeam3;
    umat rd_maxbeam_index;
    umat rd_maxbeam2_index;
    umat rd_maxbeam3_index;
    mat rd_maxbeam_azdeg;
    mat rd_maxbeam2_azdeg;
    mat rd_maxbeam3_azdeg;
};

struct rdb_struct_hdf5{
    string info;
    // params_struct params;
    hvl_t rng_vec;
    hvl_t azvec;
    hid_t mem_TSAP;
    
};

int main(void)
{
    rdb_struct rdb_data;
    rdb_struct_hdf5 rdb_hdf5;

    long long unsigned int NR=256;
    long long unsigned int ND=450;
    long long unsigned int NE=64;

    hid_t vlen_double = H5Tvlen_create(H5T_NATIVE_DOUBLE);

    rdb_data.info="testing woohoo";
    rdb_data.rng_vec=2*ones<vec>(32);
    rdb_data.azvec=3*ones<vec>(32);
    rdb_data.TSAP=4*ones<cube>(NR,ND,NE);
    rdb_data.CONV=5*ones<cube>(NR,ND,NE);
    rdb_data.TVSAP=6*ones<cube>(NR,ND,NE);
    rdb_data.rd_maxbeam=7*ones<mat>(NR,ND);
    rdb_data.rd_maxbeam2=8*ones<mat>(NR,ND);
    rdb_data.rd_maxbeam3=9*ones<mat>(NR,ND);
    rdb_data.rd_maxbeam_index=10*ones<umat>(NR,ND);
    rdb_data.rd_maxbeam2_index=11*ones<umat>(NR,ND);
    rdb_data.rd_maxbeam3_index=12*ones<umat>(NR,ND);
    rdb_data.rd_maxbeam_azdeg=13*ones<mat>(NR,ND);
    rdb_data.rd_maxbeam2_azdeg=14*ones<mat>(NR,ND);
    rdb_data.rd_maxbeam3_azdeg=15*ones<mat>(NR,ND);

    rdb_hdf5.info=rdb_data.info;
    rdb_hdf5.rng_vec.p=rdb_data.rng_vec.memptr();
    rdb_hdf5.rng_vec.len=rdb_data.rng_vec.size();
    rdb_hdf5.azvec.p=rdb_data.azvec.memptr();
    rdb_hdf5.azvec.len=rdb_data.azvec.size();
    

    // the array of each length of multidimentional data.
    hsize_t dim_rdb[1];

    dim_rdb[0] = sizeof(rdb_hdf5) / sizeof(rdb_struct_hdf5);

    // the length of dim
    int rank_rdb = sizeof(dim_rdb) / sizeof(hsize_t);


    // defining the datatype to pass HDF55
    H5::CompType h5_rdb(sizeof(rdb_struct_hdf5));
    h5_rdb.insertMember("info", HOFFSET(rdb_struct_hdf5, info), H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
    h5_rdb.insertMember("rng_vec", HOFFSET(rdb_struct_hdf5, rng_vec), vlen_double);
    h5_rdb.insertMember("azvec", HOFFSET(rdb_struct_hdf5, azvec), vlen_double);
    h5_rdb.insertMember("TSAP", HOFFSET(rdb_struct_hdf5, mem_TSAP), cube_double);
    
    // preparation of a dataset and a file.
    H5::DataSpace space_rdb(rank_rdb, dim_rdb);
    H5::H5File *file = new H5::H5File("data_test.h5", H5F_ACC_TRUNC);
    H5::DataSet *dataset_rdb = new H5::DataSet(file->createDataSet("rdb_data", h5_rdb, space_rdb));
    // Write
    dataset_rdb->write(&rdb_hdf5, h5_rdb);
    
    delete dataset_rdb;
    delete file;
    return 0;
}

But the mat and cubes have been giving me trouble, mainly because I have no idea what I'm doing with HDF5. It looks like to do what I want, I need to create a H5Tarray_create and insert it into the 'cpmp_type h5_rdb' but everything I have tried has failed to run (it does compile) with the following message:

HDF5-DIAG: Error detected in HDF5 (1.10.4) thread 139735682275136:
  #000: ../../../src/H5Tcompound.c line 354 in H5Tinsert(): unable to insert member
    major: Datatype
    minor: Unable to insert object
  #001: ../../../src/H5Tcompound.c line 446 in H5T__insert(): member extends past end of compound type
    major: Datatype
    minor: Unable to insert object
terminate called after throwing an instance of 'H5::DataTypeIException'
Aborted (core dumped)

This code seems to work but when I try to merge it with my original code it doesn't work, mainly from me not understanding how/why hid_t is used for everything...

#include <armadillo>
#include <string>
#include <iostream>
#include "H5Cpp.h"
#define ARMA_ALLOW_FAKE_GCC  //allows the use of GCC compiled armadillo with ICC compiler

using namespace std;
using namespace arma;

int
main (void)
{
    long long unsigned int NR=64;
    long long unsigned int ND=64;
    long long unsigned int NE=64;
        hsize_t dims_of_int_array[] = {NR,ND,NE};
    hsize_t dims_of_int_dataspace[] = {1};

    // int *data = (int *)malloc(4*4*4*sizeof(int));
    // int i;
    // for (i=0; i<(4*4*4); i++) data[i] = i;
    cube data = 4*ones<cube>(NR,ND,NE);

    hid_t file = H5Fcreate("multset.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

    hid_t mem_h5t = H5Tarray_create(H5T_NATIVE_DOUBLE, 2, dims_of_int_array);
    hid_t dataspace = H5Screate_simple(2, dims_of_int_dataspace, NULL);
    hid_t dataset = H5Dcreate(file, "data_data", mem_h5t, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
    H5Dwrite(dataset, mem_h5t, H5S_ALL, H5S_ALL, H5P_DEFAULT, data.memptr()); 

    H5Dclose(dataset);
    H5Sclose(dataspace);
    H5Tclose(mem_h5t);
    // free(data);
 
    return 0;
}  

I did notice the code that is work only works until the cube size becomes too large and starts spitting out errors about contiguous write failed but I think that's a problem for another day. I'm mainly looking for help on how to insert a array datatype into a composite datatype. Any help would be greatly appreciated.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source