1
0
mirror of https://github.com/TREX-CoE/trexio.git synced 2025-04-27 10:54:44 +02:00
trexio/src/templates_hdf5/templator_hdf5.org

9.2 KiB

Templator for HDF5 backend

Constant file prefixes (not used by generator) for HDF5   noxport 

#+NAME:header

/* This file was generated from the org-mode file.
 To generate it, open templator_hdf5.org file in Emacs and execute
 M-x org-babel-tangle
*/
<<header>>
#ifndef _TREXIO_HDF5_H
#define _TREXIO_HDF5_H

#include "trexio.h"
#include "trexio_s.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/stat.h>

#include "hdf5.h"
#include "hdf5_hl.h" // needed for high-level APIs like H5LT, requires additional linking in Makefile
<<header>>
#include "trexio_hdf5.h"

Template for HDF5 definitions

  #define $GROUP$_GROUP_NAME          "$group$"
  #define $GROUP_NUM$_NAME            "$group_num$"
  #define $GROUP$_$GROUP_DSET$_NAME   "$group_dset$"

Template for HDF5 structures

typedef struct trexio_hdf5_s {
trexio_t     parent ;
hid_t      file_id;
hid_t      $group$_group;
const char* file_name;
} trexio_hdf5_t;

Template for HDF5 init/deinit

trexio_exit_code trexio_hdf5_init(trexio_t* file) {

trexio_hdf5_t* f = (trexio_hdf5_t*) file;

/* If file doesn't exist, create it */
int f_exists = 0;
struct stat st;

if (stat(file->file_name, &st) == 0) f_exists = 1;

if (f_exists == 1) {

  switch (file->mode) {
  case 'r': 
    // reading the existing file -> open as RDONLY
    f->file_id = H5Fopen(file->file_name, H5F_ACC_RDONLY, H5P_DEFAULT);
    break;
  case 'a': 
    // appending the existing file -> open as RDWR
    f->file_id = H5Fopen(file->file_name, H5F_ACC_RDWR, H5P_DEFAULT);
    break;
  case 'w': 
    // writing the existing file -> overwrite it (_TRUNC) [_EXCL | H5F_ACC_DEBUG as an alternative]
    f->file_id = H5Fcreate(file->file_name, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
    break;
  }  

} else {

  switch (file->mode) {
  case 'r': 
  case 'a': 
    // reading or appending non-existing file -> error
    return TREXIO_FAILURE;
  case 'w': 
    // writing non-existing file -> create it
    f->file_id = H5Fcreate(file->file_name, H5F_ACC_EXCL, H5P_DEFAULT, H5P_DEFAULT);
    break;
  }  

}  

/* Create or open groups in the hdf5 file assuming that they exist if file exists */    
switch (file->mode) {
  // the switch for 'r'/'a' is reached only if file exists
  case 'r':
  case 'a': 
    f->$group$_group = H5Gopen(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT);
    //f->electron_group = H5Gopen(f->file_id, ELECTRON_GROUP_NAME, H5P_DEFAULT); 
    break;
  case 'w':
    f->$group$_group = H5Gcreate(f->file_id, $GROUP$_GROUP_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
    //f->electron_group = H5Gcreate(f->file_id, ELECTRON_GROUP_NAME, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
    break;
}
assert (f->$group$_group > 0L);
//assert (f->electron_group > 0L);

return TREXIO_SUCCESS;
}

trexio_exit_code trexio_hdf5_finalize(trexio_t* file) {

trexio_hdf5_t* f = (trexio_hdf5_t*) file;

H5Gclose(f->$group$_group);
f->$group$_group = 0;

/*
H5Gclose(f->electron_group);
f->electron_group = 0; 
*/

H5Fclose(f->file_id);
f->file_id = 0;

return TREXIO_SUCCESS;
}

Template for HDF5 read/write a number

trexio_exit_code trexio_hdf5_read_$group_num$(const trexio_t* file, uint64_t* num);
trexio_exit_code trexio_hdf5_write_$group_num$(const trexio_t* file, const uint64_t num);
trexio_exit_code trexio_hdf5_read_$group_num$const trexio_t* file, uint64_t* num) {

assert (file != NULL);
assert (num  != NULL);

trexio_hdf5_t* f = (trexio_hdf5_t*) file;
/* Quit if the dimensioning attribute is missing in the file */
if (H5Aexists(f->$group$_group, $GROUP_NUM$_NAME) == 0) return TREXIO_FAILURE;

/* Read the nucleus_num attribute of nucleus group */
hid_t num_id = H5Aopen(f->$group$_group, $GROUP_NUM$_NAME, H5P_DEFAULT);
if (num_id <= 0) return TREXIO_INVALID_ID;

herr_t status = H5Aread(num_id, H5T_NATIVE_ULLONG, num);
if (status < 0) return TREXIO_FAILURE;

return TREXIO_SUCCESS;
}
trexio_exit_code trexio_hdf5_write_$group_num$(const trexio_t* file, const uint64_t num) {

assert (file != NULL);
assert (num > 0L);

trexio_hdf5_t* f = (trexio_hdf5_t*) file;
hid_t num_id;
herr_t status;
/* Write the dimensioning variables */
hid_t dtype = H5Tcopy(H5T_NATIVE_ULLONG);

if (H5Aexists(f->$group$_group, $GROUP_NUM$_NAME) == 0) {
 
  hid_t dspace = H5Screate(H5S_SCALAR);

  num_id = H5Acreate(f->$group$_group, $GROUP_NUM$_NAME, dtype, dspace,
                   H5P_DEFAULT, H5P_DEFAULT);
  if (num_id <= 0) return TREXIO_INVALID_ID;

  status = H5Awrite(num_id, dtype, &(num));
  if (status < 0) return TREXIO_FAILURE;

  H5Sclose(dspace);
  
} else {

  uint64_t infile_num;
  trexio_exit_code rc = trexio_hdf5_read_$group_num$(file, &(infile_num));
  if (rc != TREXIO_SUCCESS) return rc;

  if (infile_num != num) {

    if (infile_num != 0) {
printf("%ld -> %ld %s \n", num, infile_num, 
      "This variable already exists. Overwriting it is not supported");
      H5Tclose(dtype);
  	return TREXIO_FAILURE;

    } else {
  
      num_id = H5Aopen(f->$group$_group, $GROUP_NUM$_NAME, H5P_DEFAULT);
      if (num_id <= 0) return TREXIO_INVALID_ID;
     
      status = H5Awrite(num_id, dtype, &(num));
      if (status < 0) return TREXIO_FAILURE;

    }
  }
}

H5Aclose(num_id);
H5Tclose(dtype);
return TREXIO_SUCCESS;

}

Template for HDF5 read/write a dataset

trexio_exit_code trexio_hdf5_read_$group$_$group_dset$(const trexio_t* file, double* $group_dset$, const uint32_t rank, const uint64_t* dims);
trexio_exit_code trexio_hdf5_write_$group$_$group_dset$(const trexio_t* file, const double* $group_dset$, const uint32_t rank, const uint64_t* dims);
trexio_exit_code trexio_hdf5_read_$group$_$group_dset$(const trexio_t* file, $group_dset_dtype$* $group_dset$, const uint32_t rank, const uint64_t* dims) {

assert (file != NULL);
assert ($group_dset$ != NULL);

trexio_hdf5_t* f = (trexio_hdf5_t*) file;

herr_t status;
int rrank;
// get the rank of the dataset in a file
status = H5LTget_dataset_ndims (f->$group$_group, $GROUP$_$GROUP_DSET$_NAME, 
                               &rrank);

if (status < 0) return TREXIO_FAILURE;

if (rrank != (int) rank) return TREXIO_INVALID_ARG_3;

// open the dataset to get its dimensions  
hid_t dset_id = H5Dopen(f->$group$_group, $GROUP$_$GROUP_DSET$_NAME,  H5P_DEFAULT);
if (dset_id <= 0) return TREXIO_INVALID_ID; 

// allocate space for the dimensions to be read
hsize_t* ddims = (hsize_t*) calloc( (int) rank, sizeof(hsize_t));
if (ddims == NULL) return TREXIO_FAILURE;

// read dimensions from the existing dataset
status = H5LDget_dset_dims(dset_id, ddims);

H5Dclose(dset_id);
if (status < 0) {
 free(ddims);
 return TREXIO_FAILURE;
}

for (uint32_t i=0; i<rank; i++){
  if (ddims[i] != dims[i]) {
    free(ddims);
    return TREXIO_INVALID_ARG_4;
  }
}
free(ddims);

/* High-level H5LT API. No need to deal with dataspaces and datatypes */
status = H5LTread_dataset_double(f->$group$_group,
                                 $GROUP$_$GROUP_DSET$_NAME,
                                 $group_dset$);				   
if (status < 0) return TREXIO_FAILURE;

return TREXIO_SUCCESS;
}
trexio_exit_code trexio_hdf5_write_$group$_$group_dset$(const trexio_t* file, const $group_dset_dtype$* $group_dset$, const uint32_t rank, const uint64_t* dims) {

assert (file != NULL);
assert ($group_dset$ != NULL);
 
uint64_t $group_dset_dim$;
trexio_exit_code rc = trexio_hdf5_read_$group_dset_dim$(file, &($group_dset_dim$));
if (rc != TREXIO_SUCCESS) return rc;
if ($group_dset_dim$ <= 0L) return TREXIO_INVALID_NUM;

trexio_hdf5_t* f = (trexio_hdf5_t*) file; 

herr_t status;
if ( H5LTfind_dataset(f->$group$_group, $GROUP$_$GROUP_DSET$_NAME) != 1) { 
 
 status = H5LTmake_dataset_$group_dset_dtype$ (f->$group$_group, $GROUP$_$GROUP_DSET$_NAME, 
                                   (int) rank, (hsize_t*) dims, $group_dset$);
 if (status < 0) return TREXIO_FAILURE;

} else {   

 hid_t dset_id = H5Dopen(f->$group$_group, $GROUP$_$GROUP_DSET$_NAME, H5P_DEFAULT);
 if (dset_id <= 0) return TREXIO_INVALID_ID;
 
 status = H5Dwrite(dset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, $group_dset$);
 
 H5Dclose(dset_id);
 if (status < 0) return TREXIO_FAILURE;

}

return TREXIO_SUCCESS;
}

Constant file suffixes (not used by generator) for HDF5   noxport 

#endif