aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreschnett <eschnett@fb53df36-e548-4a1e-8150-ab98cbd5e786>2011-02-01 16:10:41 +0000
committereschnett <eschnett@fb53df36-e548-4a1e-8150-ab98cbd5e786>2011-02-01 16:10:41 +0000
commite744b60750abd5a3e4d1f364a170790e2a8ee69f (patch)
treeeb29e13f5d633f8f0ec299d1772ee4094ae5f732
parent843647b42b132d851f16c7d2da798b4d7d6ce24a (diff)
Add utilities from CactusExternal/HDF5
git-svn-id: http://svn.cactuscode.org/projects/ExternalLibraries/HDF5/trunk@29 fb53df36-e548-4a1e-8150-ab98cbd5e786
-rw-r--r--src/make.configuration.defn4
-rw-r--r--src/make.configuration.deps21
-rw-r--r--src/util/hdf5_double_to_single.c340
-rw-r--r--src/util/hdf5_extract.c418
-rw-r--r--src/util/hdf5_merge.c373
5 files changed, 1156 insertions, 0 deletions
diff --git a/src/make.configuration.defn b/src/make.configuration.defn
new file mode 100644
index 0000000..86f52ea
--- /dev/null
+++ b/src/make.configuration.defn
@@ -0,0 +1,4 @@
+# make.configuration.defn file for thorn HDF5
+
+# Define this thorn's utilities
+ALL_UTILS += hdf5_merge hdf5_extract hdf5_double_to_single
diff --git a/src/make.configuration.deps b/src/make.configuration.deps
new file mode 100644
index 0000000..402c629
--- /dev/null
+++ b/src/make.configuration.deps
@@ -0,0 +1,21 @@
+# make.configuration.deps file for thorn HDF5
+
+HDF5_BUILD_DIR = $(BUILD_DIR)/HDF5
+HDF5_SRC_DIR = $(PACKAGE_DIR)/ExternalLibraries/HDF5/src/util
+
+HDF5_CFLAGS = -DCCODE $(CFLAGS) -I$(CONFIG) -I$(BINDINGS_DIR)/include -I$(FLESH_DIR)/include $(HDF5_INC_DIRS:%=-I%)
+HDF5_LDFLAGS = $(DEBUG_LD) $(LDFLAGS) $(EXTRAFLAGS) $(GENERAL_LIBRARIES)
+
+
+
+# Compile
+$(HDF5_BUILD_DIR)/%.o: $(HDF5_SRC_DIR)/%.c
+ @echo "Compiling $<"
+ -$(MKDIR) $(MKDIRFLAGS) $(HDF5_BUILD_DIR) 2> /dev/null
+ $(CC) $< $(HDF5_CFLAGS) -c -o $@
+
+# Link
+$(UTIL_DIR)/%: $(HDF5_BUILD_DIR)/%.o
+ @echo "Creating $* in $(UTIL_DIR) from $<"
+ -$(MKDIR) $(MKDIRFLAGS) $(UTIL_DIR) 2> /dev/null
+ $(LD) $< $(HDF5_LDFLAGS) -o $@
diff --git a/src/util/hdf5_double_to_single.c b/src/util/hdf5_double_to_single.c
new file mode 100644
index 0000000..870ccc7
--- /dev/null
+++ b/src/util/hdf5_double_to_single.c
@@ -0,0 +1,340 @@
+ /*@@
+ @file hdf5_double_to_single.c
+ @date Thu 10 Jan 2002
+ @author Thomas Radke
+ @desc
+ This utility program copies a Cactus HDF5 datafile reverting
+ double-precision datasets into single-precision.
+ @enddesc
+ @version $Id: hdf5_double_to_single.c,v 1.3 2009/09/29 14:38:14 schnetter Exp $
+ @@*/
+
+#include "cctk.h"
+
+#define H5_USE_16_API 1
+#include <hdf5.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* the rcs ID and its dummy function to use it */
+static const char *rcsid = "$Header: /cactusdevcvs/CactusExternal/HDF5/src/util/hdf5_double_to_single.c,v 1.3 2009/09/29 14:38:14 schnetter Exp $";
+CCTK_FILEVERSION(CactusExternal_HDF5_util_hdf5_double_to_single_c)
+
+
+/*****************************************************************************/
+/* macro definitions */
+/*****************************************************************************/
+/* macro to do an HDF5 call, check its return code, and print a warning
+ in case of an error */
+#define CHECK_ERROR(hdf5_call) \
+ do \
+ { \
+ int _error_code = hdf5_call; \
+ \
+ \
+ if (_error_code < 0) \
+ { \
+ fprintf (stderr, "WARNING: line %d: HDF5 call '%s' returned " \
+ "error code %d\n", \
+ __LINE__, #hdf5_call, _error_code); \
+ nerrors++; \
+ } \
+ } while (0)
+
+
+/*****************************************************************************/
+/* global variables */
+/*****************************************************************************/
+/* NOTE: although it isn't good programming practice
+ we make these variables global for convenience
+ since they are accessed from recursively or
+ indirectly called routines which only get passed
+ a single user-supplied argument */
+static char *pathname = NULL; /* pathname of the current object */
+static unsigned int nerrors = 0; /* global error counter */
+
+/*****************************************************************************/
+/* local function prototypes */
+/*****************************************************************************/
+static herr_t CopyObject (hid_t copy_from, const char *objectname, void *arg);
+static herr_t CopyAttribute (hid_t src, const char *attr_name, void *arg);
+
+
+ /*@@
+ @routine main
+ @date Thu 10 Jan 2002
+ @author Thomas Radke
+ @desc
+ Main routine of the HDF5 double-to-single converter
+ @enddesc
+
+ @calls CopyObject
+
+ @var argc
+ @vdesc number of command line arguments
+ @vtype int
+ @vio in
+ @endvar
+ @var argv
+ @vdesc command line arguments
+ @vtype char *[]
+ @vio in
+ @endvar
+
+ @returntype int
+ @returndesc
+ 0 for success, negative return values indicate an error
+ @endreturndesc
+@@*/
+int main (int argc, char *argv[])
+{
+ hid_t infile, outfile;
+
+
+ /* give some help if called with incorrect number of parameters */
+ if (argc != 3)
+ {
+ fprintf (stderr, "Usage: %s <infile> <outfile>\n", argv[0]);
+ fprintf (stderr, " eg, %s alp.h5 alp_single.h5\n\n", argv[0]);
+ return (0);
+ }
+
+ H5E_BEGIN_TRY
+ {
+ /* open the input file */
+ infile = H5Fopen (argv[1], H5F_ACC_RDONLY, H5P_DEFAULT);
+ if (infile < 0)
+ {
+ fprintf (stderr, "ERROR: Cannot open HDF5 input file '%s' !\n\n",argv[1]);
+ return (-1);
+ }
+
+ /* create output file */
+ outfile = H5Fcreate (argv[2], H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ if (outfile < 0)
+ {
+ fprintf (stderr, "ERROR: Cannot create HDF5 output file '%s' !\n\n",
+ argv[2]);
+ return (-1);
+ }
+ } H5E_END_TRY
+
+ printf ("\n --------------------------------------------------\n"
+ " Cactus 4 HDF5 double-to-single precision Converter\n"
+ " --------------------------------------------------\n");
+
+ /* do the copying by iterating over all objects */
+ pathname = "";
+ CHECK_ERROR (H5Giterate (infile, "/", NULL, CopyObject, &outfile));
+
+ /* finally, close all open files */
+ CHECK_ERROR (H5Fclose (infile));
+ CHECK_ERROR (H5Fclose (outfile));
+
+ /* report status */
+ if (nerrors == 0)
+ {
+ printf ("\n\n *** All Cactus data successfully converted. ***\n\n");
+ }
+ else
+ {
+ fprintf (stderr, "\n\n *** WARNING: %u errors occured during "
+ "conversion. ***\n\n", nerrors);
+ }
+
+ return (0);
+}
+
+
+/*****************************************************************************/
+/* local routines */
+/*****************************************************************************/
+ /*@@
+ @routine CopyObject
+ @date Thu 10 Jan 2002
+ @author Thomas Radke
+ @desc
+ Iterator recursively called by H5Giterate() for every object
+ in the input file
+ @enddesc
+
+ @calls CopyAttribute
+
+ @var from
+ @vdesc identifier for the group the current object belongs to
+ @vtype hid_t
+ @vio in
+ @endvar
+ @var objectname
+ @vdesc name of the current object
+ @vtype const char *
+ @vio in
+ @endvar
+ @var _to
+ @vdesc user-supplied argument indicating the output object identifier
+ @vtype hid_t
+ @vio in
+ @endvar
+
+ @returntype int
+ @returndesc
+ 0 - continue the iteration for following group objects
+ 1 - short-curcuit, no further iteration of this group
+ @endreturndesc
+@@*/
+static herr_t CopyObject (hid_t from,
+ const char *objectname,
+ void *_to)
+{
+ hid_t to, datatype, dataspace;
+ H5G_stat_t objectinfo;
+ char *current_pathname;
+ size_t objectsize;
+ char *data;
+
+
+ /* build the full pathname for the current to object to process */
+ current_pathname = pathname;
+ pathname = (char *) malloc (strlen (current_pathname) +
+ strlen (objectname) + 2);
+ sprintf (pathname, "%s/%s", current_pathname, objectname);
+
+ /* get the output object identifier */
+ to = *(hid_t *) _to;
+
+ /* check the type of the current object */
+ CHECK_ERROR (H5Gget_objinfo (from, objectname, 0, &objectinfo));
+ if (objectinfo.type == H5G_GROUP)
+ {
+ printf (" copying group '%s'\n", pathname);
+
+ CHECK_ERROR (from = H5Gopen (from, objectname));
+ CHECK_ERROR (to = H5Gcreate (to, objectname, 0));
+ /* iterate over all objects in the (first) input file */
+ CHECK_ERROR (H5Giterate (from, ".", NULL, CopyObject, &to));
+ CHECK_ERROR (H5Aiterate (from, NULL, CopyAttribute, &to));
+ CHECK_ERROR (H5Gclose (to));
+ CHECK_ERROR (H5Gclose (from));
+ }
+ else if (objectinfo.type == H5G_DATASET)
+ {
+ CHECK_ERROR (from = H5Dopen (from, objectname));
+ CHECK_ERROR (dataspace = H5Dget_space (from));
+ CHECK_ERROR (datatype = H5Dget_type (from));
+ if (H5Tget_class (datatype) == H5T_FLOAT)
+ {
+ CHECK_ERROR (H5Tclose (datatype));
+ CHECK_ERROR (datatype = H5Tcopy (H5T_NATIVE_FLOAT));
+ printf (" converting dataset '%s'\n", pathname);
+ }
+ else
+ {
+ printf (" copying dataset '%s'\n", pathname);
+ }
+ CHECK_ERROR (to = H5Dcreate (to, objectname, datatype, dataspace,
+ H5P_DEFAULT));
+ objectsize = H5Tget_size (datatype);
+ if (H5Sis_simple (dataspace))
+ {
+ objectsize *= H5Sget_simple_extent_npoints (dataspace);
+ }
+ if (objectsize > 0)
+ {
+ data = (char *) malloc (objectsize);
+ CHECK_ERROR (H5Dread (from, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ data));
+ CHECK_ERROR (H5Dwrite (to, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT,data));
+ free (data);
+ }
+ CHECK_ERROR (H5Aiterate (from, NULL, CopyAttribute, &to));
+ CHECK_ERROR (H5Dclose (to));
+ CHECK_ERROR (H5Dclose (from));
+ CHECK_ERROR (H5Sclose (dataspace));
+ CHECK_ERROR (H5Tclose (datatype));
+ }
+ else
+ {
+ fprintf (stderr, "WARNING: Found object '%s' which is neither a group "
+ "nor a dataset ! Object will not be copied.\n", pathname);
+ nerrors++;
+ }
+
+ /* reset the pathname */
+ free (pathname);
+ pathname = current_pathname;
+
+ return (0);
+}
+
+
+ /*@@
+ @routine CopyAttribute
+ @date Thu 10 Jan 2002
+ @author Thomas Radke
+ @desc
+ Iterator recursively called by H5Aiterate() for every attribute
+ of an object (dataset or group)
+ @enddesc
+
+ @var from
+ @vdesc identifier for the group or dataset to read the attribute from
+ @vtype hid_t
+ @vio in
+ @endvar
+ @var attrname
+ @vdesc name of the current attribute
+ @vtype const char *
+ @vio in
+ @endvar
+ @var _to
+ @vdesc user-supplied argument indicating the group or dataset
+ to copy the attribute to
+ @vtype hid_t
+ @vio in
+ @endvar
+
+ @returntype int
+ @returndesc
+ 0 - continue the iteration for following attributes
+ @endreturndesc
+@@*/
+static herr_t CopyAttribute (hid_t from,
+ const char *attrname,
+ void *_to)
+{
+ hid_t attr, datatype, dataspace, to;
+ size_t attrsize;
+ void *value;
+
+
+ /* get the target group/dataset identifier */
+ to = *(hid_t *) _to;
+
+ /* open the attribute given by its name, get type, dataspace, and value
+ and just copy it */
+ CHECK_ERROR (attr = H5Aopen_name (from, attrname));
+ CHECK_ERROR (datatype = H5Aget_type (attr));
+ CHECK_ERROR (dataspace = H5Aget_space (attr));
+ attrsize = H5Tget_size (datatype);
+ if (H5Sis_simple (dataspace) > 0)
+ {
+ attrsize *= H5Sget_simple_extent_npoints (dataspace);
+ }
+ if (attrsize > 0)
+ {
+ value = malloc (attrsize);
+ CHECK_ERROR (H5Aread (attr, datatype, value));
+ CHECK_ERROR (H5Aclose (attr));
+ CHECK_ERROR (attr = H5Acreate (to, attrname, datatype, dataspace,
+ H5P_DEFAULT));
+ CHECK_ERROR (H5Awrite (attr, datatype, value));
+ free (value);
+ }
+ CHECK_ERROR (H5Aclose (attr));
+ CHECK_ERROR (H5Sclose (dataspace));
+ CHECK_ERROR (H5Tclose (datatype));
+
+ return (0);
+}
diff --git a/src/util/hdf5_extract.c b/src/util/hdf5_extract.c
new file mode 100644
index 0000000..75de6bd
--- /dev/null
+++ b/src/util/hdf5_extract.c
@@ -0,0 +1,418 @@
+ /*@@
+ @file hdf5_extract.c
+ @date Thu 19 Feb 2002
+ @author Thomas Radke
+ @desc
+ This utility program extracts objects from an HDF5 file and writes
+ them into a new one.
+ @enddesc
+ @version $Id: hdf5_extract.c,v 1.3 2009/09/29 14:38:14 schnetter Exp $
+ @@*/
+
+#include "cctk.h"
+
+#define H5_USE_16_API 1
+#include <hdf5.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* the rcs ID and its dummy function to use it */
+static const char *rcsid = "$Header: /cactusdevcvs/CactusExternal/HDF5/src/util/hdf5_extract.c,v 1.3 2009/09/29 14:38:14 schnetter Exp $";
+CCTK_FILEVERSION(CactusExternal_HDF5_util_hdf5_extract_c)
+
+
+/*****************************************************************************/
+/* macro definitions */
+/*****************************************************************************/
+/* macro to do an HDF5 call, check its return code, and print a warning
+ in case of an error */
+#define CHECK_ERROR(hdf5_call) \
+ do \
+ { \
+ int _error_code = hdf5_call; \
+ \
+ \
+ if (_error_code < 0) \
+ { \
+ fprintf (stderr, "WARNING: line %d: HDF5 call '%s' returned " \
+ "error code %d\n", \
+ __LINE__, #hdf5_call, _error_code); \
+ nerrors++; \
+ } \
+ } while (0)
+
+
+/*****************************************************************************/
+/* global variables */
+/*****************************************************************************/
+/* NOTE: although it isn't good programming practice
+ we make these variables global for convenience
+ since they are accessed from recursively or
+ indirectly called routines which only get passed
+ a single user-supplied argument */
+static char *pathname = NULL; /* pathname of the current object */
+static unsigned int nerrors = 0; /* global error counter */
+static unsigned int check_parents = 0; /* flag to check for parent groups */
+
+/*****************************************************************************/
+/* local function prototypes */
+/*****************************************************************************/
+static herr_t CopyObject (hid_t from, const char *objectname, void *_to);
+static herr_t CopyAttribute (hid_t src, const char *attr_name, void *arg);
+
+
+ /*@@
+ @routine main
+ @date Thu 19 Feb 2002
+ @author Thomas Radke
+ @desc
+ Main routine of the HDF5 file extractor
+ @enddesc
+
+ @calls CopyObject
+
+ @var argc
+ @vdesc number of command line arguments
+ @vtype int
+ @vio in
+ @endvar
+ @var argv
+ @vdesc command line arguments
+ @vtype char *[]
+ @vio in
+ @endvar
+
+ @returntype int
+ @returndesc
+ 0 for success, negative return values indicate an error
+ @endreturndesc
+@@*/
+int main (int argc, char *argv[])
+{
+ char objectname[256];
+ FILE *listfile;
+ hid_t infile, outfile;
+
+
+ /* give some help if called with incorrect number of parameters */
+ if (argc != 4)
+ {
+ fprintf (stderr, "Usage: %s <listfile> <infile> <outfile>\n", argv[0]);
+ fprintf (stderr, " where <listfile> can be created from the output of the h5ls command\n\n");
+ fprintf (stderr, " eg, h5ls alp.h5 > listfile\n"
+ " # now edit listfile to select all datasets to be extracted\n"
+ " # (don't forget to remove backslashes and the trailing 'Dataset {...}')\n"
+ " %s extract_list alp.h5 alp_extract.h5\n\n", argv[0]);
+
+ return (0);
+ }
+
+ /* open the list file */
+ listfile = fopen (argv[1], "r");
+ if (listfile == NULL)
+ {
+ fprintf (stderr, "ERROR: Cannot open list file '%s' !\n\n", argv[1]);
+ return (-1);
+ }
+
+ H5E_BEGIN_TRY
+ {
+ /* open the input file */
+ infile = H5Fopen (argv[2], H5F_ACC_RDONLY, H5P_DEFAULT);
+ if (infile < 0)
+ {
+ fprintf (stderr, "ERROR: Cannot open HDF5 input file '%s' !\n\n",argv[2]);
+ return (-1);
+ }
+
+ /* try to open an existing outfile file in append mode,
+ if this fails create it as a new file */
+ outfile = H5Fopen (argv[3], H5F_ACC_RDWR, H5P_DEFAULT);
+ if (outfile < 0)
+ {
+ outfile = H5Fcreate (argv[3], H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ }
+ if (outfile < 0)
+ {
+ fprintf (stderr, "ERROR: Cannot create HDF5 output file '%s' !\n\n",
+ argv[3]);
+ return (-1);
+ }
+ } H5E_END_TRY
+
+ printf ("\n ----------------------------\n"
+ " Cactus 4 HDF5 File Extractor\n"
+ " ----------------------------\n");
+
+ /* do the copying by iterating over all objects */
+ while (fgets (objectname, sizeof (objectname), listfile))
+ {
+ /* get rid of the trailing newline */
+ objectname[strlen (objectname) - 1] = 0;
+ pathname = "";
+
+ check_parents = 1;
+ CopyObject (infile, objectname, &outfile);
+ }
+
+ /* finally, close all open files */
+ CHECK_ERROR (H5Fclose (infile));
+ CHECK_ERROR (H5Fclose (outfile));
+ fclose (listfile);
+
+ /* report status */
+ if (nerrors == 0)
+ {
+ printf ("\n\n *** All objects successfully extracted. ***\n\n");
+ }
+ else
+ {
+ fprintf (stderr, "\n\n *** WARNING: %u errors occured during "
+ "data extraction. ***\n\n", nerrors);
+ }
+
+ return (0);
+}
+
+
+/*****************************************************************************/
+/* local routines */
+/*****************************************************************************/
+ /*@@
+ @routine CopyObject
+ @date Thu 19 Feb 2002
+ @author Thomas Radke
+ @desc
+ Copies an object with given name from the input file into the
+ output file.
+ @enddesc
+
+ @calls CopyAttribute
+
+ @var from
+ @vdesc input group handle
+ @vtype hid_t
+ @vio in
+ @endvar
+ @var objectname
+ @vdesc name of the object to extract
+ @vtype const char *
+ @vio in
+ @endvar
+ @var _to
+ @vdesc output group handle
+ @vtype void *
+ @vio in
+ @endvar
+
+ @returntype herr_t
+ @returndesc
+ 0 - continue the iteration for following group objects
+ 1 - short-curcuit, no further iteration of this group
+ @endreturndesc
+@@*/
+static herr_t CopyObject (hid_t from,
+ const char *objectname,
+ void *_to)
+{
+ hid_t to, datatype, dataspace, from_group, to_group;
+ H5G_stat_t objectinfo;
+ char *current_pathname;
+ size_t objectsize;
+ herr_t result;
+ char *data, *slash;
+
+
+ /* get the output object identifier */
+ to = *(hid_t *) _to;
+
+ /* check whether the requested object was already extracted */
+ H5E_BEGIN_TRY
+ {
+ result = H5Gget_objinfo (to, objectname, 0, &objectinfo);
+ } H5E_END_TRY
+ if (result >= 0)
+ {
+ fprintf (stderr, "WARNING: object '%s' was already extracted\n",objectname);
+ return (0);
+ }
+
+ /* check whether the requested object exists */
+ H5E_BEGIN_TRY
+ {
+ result = H5Gget_objinfo (from, objectname, 0, &objectinfo);
+ } H5E_END_TRY
+ if (result < 0)
+ {
+ fprintf (stderr, "WARNING: object '%s' will not be extracted (object "
+ "doesn't exist)\n", objectname);
+ nerrors++;
+ return (0);
+ }
+
+ /* make sure that all parent groups exist */
+ if (check_parents)
+ {
+ slash = pathname;
+ /* skip leading slashes */
+ while (*slash == '/')
+ {
+ slash++;
+ }
+
+ /* now go through all groups (separated by slashes) */
+ while ((slash = strchr (slash, '/')) != NULL)
+ {
+ *slash = 0;
+
+ /* try to create the group */
+ H5E_BEGIN_TRY
+ {
+ to_group = H5Gcreate (to, pathname, 0);
+ } H5E_END_TRY
+ if (to_group >= 0)
+ {
+ /* copy all attributes */
+ CHECK_ERROR (from_group = H5Gopen (from, pathname));
+ CHECK_ERROR (H5Aiterate (from_group, NULL, CopyAttribute, &to_group));
+ CHECK_ERROR (H5Gclose (from_group));
+ CHECK_ERROR (H5Gclose (to_group));
+ }
+ *slash++ = '/';
+ }
+ check_parents = 0;
+ }
+
+ /* build the full pathname for the current to object to process */
+ current_pathname = pathname;
+ pathname = (char *) malloc (strlen (current_pathname) +
+ strlen (objectname) + 2);
+ sprintf (pathname, "%s/%s", current_pathname, objectname);
+
+ /* check the type of the current object */
+ if (objectinfo.type == H5G_GROUP)
+ {
+ printf (" copying group '%s'\n", pathname);
+
+ CHECK_ERROR (from = H5Gopen (from, objectname));
+ CHECK_ERROR (to = H5Gcreate (to, objectname, 0));
+ /* iterate over all objects in the (first) input file */
+ CHECK_ERROR (H5Giterate (from, ".", NULL, CopyObject, &to));
+ CHECK_ERROR (H5Aiterate (from, NULL, CopyAttribute, &to));
+ CHECK_ERROR (H5Gclose (to));
+ CHECK_ERROR (H5Gclose (from));
+ }
+ else if (objectinfo.type == H5G_DATASET)
+ {
+ CHECK_ERROR (from = H5Dopen (from, objectname));
+ CHECK_ERROR (dataspace = H5Dget_space (from));
+ CHECK_ERROR (datatype = H5Dget_type (from));
+
+ printf (" copying dataset '%s'\n", pathname);
+ CHECK_ERROR (to = H5Dcreate (to, objectname, datatype, dataspace,
+ H5P_DEFAULT));
+ objectsize = H5Tget_size (datatype);
+ if (H5Sis_simple (dataspace))
+ {
+ objectsize *= H5Sget_simple_extent_npoints (dataspace);
+ }
+ if (objectsize > 0)
+ {
+ data = (char *) malloc (objectsize);
+ CHECK_ERROR (H5Dread (from, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ data));
+ CHECK_ERROR (H5Dwrite (to, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT,data));
+ free (data);
+ }
+ CHECK_ERROR (H5Aiterate (from, NULL, CopyAttribute, &to));
+ CHECK_ERROR (H5Dclose (to));
+ CHECK_ERROR (H5Dclose (from));
+ CHECK_ERROR (H5Sclose (dataspace));
+ CHECK_ERROR (H5Tclose (datatype));
+ }
+ else
+ {
+ fprintf (stderr, "WARNING: Found object '%s' which is neither a group "
+ "nor a dataset ! Object will not be copied.\n", pathname);
+ nerrors++;
+ }
+
+ /* reset the pathname */
+ free (pathname);
+ pathname = current_pathname;
+
+ return (0);
+}
+
+
+ /*@@
+ @routine CopyAttribute
+ @date Thu 19 Feb 2002
+ @author Thomas Radke
+ @desc
+ Iterator recursively called by H5Aiterate() for every attribute
+ of an object (dataset or group)
+ @enddesc
+
+ @var from
+ @vdesc identifier for the group or dataset to read the attribute from
+ @vtype hid_t
+ @vio in
+ @endvar
+ @var attrname
+ @vdesc name of the current attribute
+ @vtype const char *
+ @vio in
+ @endvar
+ @var _to
+ @vdesc user-supplied argument indicating the group or dataset
+ to copy the attribute to
+ @vtype hid_t
+ @vio in
+ @endvar
+
+ @returntype int
+ @returndesc
+ 0 - continue the iteration for following attributes
+ @endreturndesc
+@@*/
+static herr_t CopyAttribute (hid_t from,
+ const char *attrname,
+ void *_to)
+{
+ hid_t attr, datatype, dataspace, to;
+ size_t attrsize;
+ void *value;
+
+
+ /* get the target group/dataset identifier */
+ to = *(hid_t *) _to;
+
+ /* open the attribute given by its name, get type, dataspace, and value
+ and just copy it */
+ CHECK_ERROR (attr = H5Aopen_name (from, attrname));
+ CHECK_ERROR (datatype = H5Aget_type (attr));
+ CHECK_ERROR (dataspace = H5Aget_space (attr));
+ attrsize = H5Tget_size (datatype);
+ if (H5Sis_simple (dataspace) > 0)
+ {
+ attrsize *= H5Sget_simple_extent_npoints (dataspace);
+ }
+ if (attrsize > 0)
+ {
+ value = malloc (attrsize);
+ CHECK_ERROR (H5Aread (attr, datatype, value));
+ CHECK_ERROR (H5Aclose (attr));
+ CHECK_ERROR (attr = H5Acreate (to, attrname, datatype, dataspace,
+ H5P_DEFAULT));
+ CHECK_ERROR (H5Awrite (attr, datatype, value));
+ free (value);
+ }
+ CHECK_ERROR (H5Aclose (attr));
+ CHECK_ERROR (H5Sclose (dataspace));
+ CHECK_ERROR (H5Tclose (datatype));
+
+ return (0);
+}
diff --git a/src/util/hdf5_merge.c b/src/util/hdf5_merge.c
new file mode 100644
index 0000000..2d6a0fd
--- /dev/null
+++ b/src/util/hdf5_merge.c
@@ -0,0 +1,373 @@
+ /*@@
+ @file hdf5_merge.c
+ @date Thu 10 Jan 2002
+ @author Thomas Radke
+ @desc
+ This utility program takes a list of Cactus HDF5 datafiles,
+ merges them at the group hierarchy level and dumps the resulting
+ tree to a new HDF5 file.
+ @enddesc
+ @version $Id: hdf5_merge.c,v 1.3 2009/09/29 14:38:14 schnetter Exp $
+ @@*/
+
+#include "cctk.h"
+
+#define H5_USE_16_API 1
+#include <hdf5.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* the rcs ID and its dummy function to use it */
+static const char *rcsid = "$Header: /cactusdevcvs/CactusExternal/HDF5/src/util/hdf5_merge.c,v 1.3 2009/09/29 14:38:14 schnetter Exp $";
+CCTK_FILEVERSION(CactusExternal_HDF5_util_hdf5_merge_c)
+
+
+/*****************************************************************************/
+/* macro definitions */
+/*****************************************************************************/
+/* macro to do an HDF5 call, check its return code, and print a warning
+ in case of an error */
+#define CHECK_ERROR(hdf5_call) \
+ do \
+ { \
+ int _error_code = hdf5_call; \
+ \
+ \
+ if (_error_code < 0) \
+ { \
+ fprintf (stderr, "WARNING: line %d: HDF5 call '%s' returned " \
+ "error code %d\n", \
+ __LINE__, #hdf5_call, _error_code); \
+ nerrors++; \
+ } \
+ } while (0)
+
+
+/*****************************************************************************/
+/* global variables */
+/*****************************************************************************/
+/* NOTE: although it isn't good programming practice
+ we make these variables global for convenience
+ since they are accessed from recursively or
+ indirectly called routines which only get passed
+ a single user-supplied argument */
+static char *pathname = NULL; /* pathname of the current object */
+static unsigned int nerrors = 0; /* global error counter */
+
+/*****************************************************************************/
+/* local function prototypes */
+/*****************************************************************************/
+static herr_t CopyObject (hid_t copy_from, const char *objectname, void *arg);
+static herr_t CopyAttribute (hid_t src, const char *attr_name, void *arg);
+
+
+ /*@@
+ @routine main
+ @date Sat 24 Feb 2001
+ @author Thomas Radke
+ @desc
+ Main routine of the HDF5 file merger
+ @enddesc
+
+ @calls CopyObject
+
+ @var argc
+ @vdesc number of command line arguments
+ @vtype int
+ @vio in
+ @endvar
+ @var argv
+ @vdesc command line arguments
+ @vtype char *[]
+ @vio in
+ @endvar
+
+ @returntype int
+ @returndesc
+ 0 for success, negative return values indicate an error
+ @endreturndesc
+@@*/
+int main (int argc, char *argv[])
+{
+ int i;
+ hid_t *infiles, outfile;
+
+
+ /* give some help if called with incorrect number of parameters */
+ if (argc < 3)
+ {
+ fprintf (stderr, "Usage: %s <infile1> [<infile2> ...] <outfile>\n",argv[0]);
+ fprintf (stderr, " eg, %s alp.time*.h5 alp.h5"
+ "\n\n", argv[0]);
+ return (0);
+ }
+
+ H5E_BEGIN_TRY
+ {
+ /* open the input files */
+ infiles = (hid_t *) malloc ((argc - 2) * sizeof (hid_t));
+ for (i = 0; i < argc - 2; i++)
+ {
+ infiles[i] = H5Fopen (argv[i + 1], H5F_ACC_RDONLY, H5P_DEFAULT);
+ if (infiles[i] < 0)
+ {
+ fprintf (stderr, "ERROR: Cannot open HDF5 input file '%s' !\n\n",
+ argv[i + 1]);
+ return (-1);
+ }
+ }
+
+ /* try to open an existing outfile file in append mode,
+ if this fails create it as a new file */
+ outfile = H5Fopen (argv[argc-1], H5F_ACC_RDWR, H5P_DEFAULT);
+ if (outfile < 0)
+ {
+ outfile = H5Fcreate (argv[argc-1], H5F_ACC_TRUNC, H5P_DEFAULT,
+ H5P_DEFAULT);
+ }
+ if (outfile < 0)
+ {
+ fprintf (stderr, "ERROR: Cannot open HDF5 output file '%s' !\n\n",
+ argv[argc - 1]);
+ return (-1);
+ }
+ } H5E_END_TRY
+
+ printf ("\n -------------------------\n"
+ " Cactus 4 HDF5 File Merger\n"
+ " -------------------------\n");
+
+ /* do the copying by iterating over all objects */
+ for (i = 0; i < argc - 2; i++)
+ {
+ printf ("\n Merging objects from input file '%s' into output file '%s'\n",
+ argv[i + 1], argv[argc-1]);
+ pathname = "";
+ CHECK_ERROR (H5Giterate (infiles[i], "/", NULL, CopyObject, &outfile));
+ }
+
+ /* finally, close all open files */
+ for (i = 0; i < argc - 2; i++)
+ {
+ CHECK_ERROR (H5Fclose (infiles[i]));
+ }
+ CHECK_ERROR (H5Fclose (outfile));
+ free (infiles);
+
+ /* report status */
+ if (nerrors == 0)
+ {
+ printf ("\n\n *** All input files successfully merged. ***\n\n");
+ }
+ else
+ {
+ fprintf (stderr, "\n\n *** WARNING: %u errors occured during "
+ "file merging. ***\n\n", nerrors);
+ }
+
+ return (0);
+}
+
+
+/*****************************************************************************/
+/* local routines */
+/*****************************************************************************/
+ /*@@
+ @routine CopyObject
+ @date Sat 24 Feb 2001
+ @author Thomas Radke
+ @desc
+ Iterator recursively called by H5Giterate() for every object
+ in the input file
+ It copies the current object to the output file if it didn't
+ already exist there.
+ @enddesc
+
+ @calls CopyAttribute
+
+ @var from
+ @vdesc identifier for the group the current object belongs to
+ @vtype hid_t
+ @vio in
+ @endvar
+ @var objectname
+ @vdesc name of the current object
+ @vtype const char *
+ @vio in
+ @endvar
+ @var _to
+ @vdesc user-supplied argument indicating the output object identifier
+ @vtype hid_t
+ @vio in
+ @endvar
+
+ @returntype int
+ @returndesc
+ 0 - continue the iteration for following group objects
+ 1 - short-curcuit, no further iteration of this group
+ @endreturndesc
+@@*/
+static herr_t CopyObject (hid_t from,
+ const char *objectname,
+ void *_to)
+{
+ int i;
+ hid_t to, datatype, dataspace;
+ H5G_stat_t objectinfo;
+ char *current_pathname;
+ size_t objectsize;
+ void *data;
+
+
+ /* get the output object identifier */
+ to = *(hid_t *) _to;
+
+ /* check whether an object by that name already exists */
+ H5E_BEGIN_TRY
+ {
+ i = H5Gget_objinfo (to, objectname, 0, &objectinfo) >= 0;
+ } H5E_END_TRY
+ if (i)
+ {
+ printf (" object '%s/%s' will not be copied (already exists)\n",
+ pathname, objectname);
+ return (0);
+ }
+
+ /* build the full pathname for the current to object to process */
+ current_pathname = pathname;
+ pathname = (char *) malloc (strlen (current_pathname) +
+ strlen (objectname) + 2);
+ sprintf (pathname, "%s/%s", current_pathname, objectname);
+
+ /* check the type of the current object */
+ CHECK_ERROR (H5Gget_objinfo (from, objectname, 0, &objectinfo));
+ if (objectinfo.type == H5G_GROUP)
+ {
+ printf (" copying group '%s'\n", pathname);
+
+ CHECK_ERROR (from = H5Gopen (from, objectname));
+ CHECK_ERROR (to = H5Gcreate (to, objectname, 0));
+ /* iterate over all objects in the (first) input file */
+ CHECK_ERROR (H5Giterate (from, ".", NULL, CopyObject, &to));
+ CHECK_ERROR (H5Aiterate (from, NULL, CopyAttribute, &to));
+ CHECK_ERROR (H5Gclose (to));
+ CHECK_ERROR (H5Gclose (from));
+ }
+ else if (objectinfo.type == H5G_DATASET)
+ {
+ printf (" copying dataset '%s'\n", pathname);
+
+ CHECK_ERROR (from = H5Dopen (from, objectname));
+ CHECK_ERROR (datatype = H5Dget_type (from));
+ CHECK_ERROR (dataspace = H5Dget_space (from));
+ CHECK_ERROR (to = H5Dcreate (to, objectname, datatype, dataspace,
+ H5P_DEFAULT));
+ objectsize = H5Sget_select_npoints (dataspace) * H5Tget_size (datatype);
+ if (objectsize > 0)
+ {
+ data = malloc (objectsize);
+ if (data == NULL)
+ {
+ fprintf (stderr, "failled to allocate %d bytes of memory, giving up\n",
+ (int) objectsize);
+ exit (-1);
+ }
+ CHECK_ERROR (H5Dread (from, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+ data));
+ CHECK_ERROR (H5Dwrite (to, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT,data));
+ free (data);
+ }
+ CHECK_ERROR (H5Aiterate (from, NULL, CopyAttribute, &to));
+ CHECK_ERROR (H5Dclose (to));
+ CHECK_ERROR (H5Dclose (from));
+ CHECK_ERROR (H5Sclose (dataspace));
+ CHECK_ERROR (H5Tclose (datatype));
+ }
+ else
+ {
+ fprintf (stderr, "WARNING: Found object '%s' which is not neither a "
+ "group nor a dataset ! Object will not be copied.\n",
+ pathname);
+ nerrors++;
+ }
+
+ /* reset the pathname */
+ free (pathname);
+ pathname = current_pathname;
+
+ return (0);
+}
+
+
+ /*@@
+ @routine CopyAttribute
+ @date Sat 24 Feb 2001
+ @author Thomas Radke
+ @desc
+ Iterator recursively called by H5Aiterate() for every attribute
+ of an object (dataset or group)
+ @enddesc
+
+ @var from
+ @vdesc identifier for the group or dataset to read the attribute from
+ @vtype hid_t
+ @vio in
+ @endvar
+ @var attrname
+ @vdesc name of the current attribute
+ @vtype const char *
+ @vio in
+ @endvar
+ @var _to
+ @vdesc user-supplied argument indicating the group or dataset
+ to copy the attribute to
+ @vtype hid_t
+ @vio in
+ @endvar
+
+ @returntype int
+ @returndesc
+ 0 - continue the iteration for following attributes
+ @endreturndesc
+@@*/
+static herr_t CopyAttribute (hid_t from,
+ const char *attrname,
+ void *_to)
+{
+ hid_t attr, datatype, dataspace, to;
+ size_t attrsize;
+ void *value;
+
+
+ /* get the target group/dataset identifier */
+ to = *(hid_t *) _to;
+
+ /* open the attribute given by its name, get type, dataspace, and value
+ and just copy it */
+ CHECK_ERROR (attr = H5Aopen_name (from, attrname));
+ CHECK_ERROR (datatype = H5Aget_type (attr));
+ CHECK_ERROR (dataspace = H5Aget_space (attr));
+ attrsize = H5Tget_size (datatype);
+ if (H5Sis_simple (dataspace) > 0)
+ {
+ attrsize *= H5Sget_simple_extent_npoints (dataspace);
+ }
+ if (attrsize > 0)
+ {
+ value = malloc (attrsize);
+ CHECK_ERROR (H5Aread (attr, datatype, value));
+ CHECK_ERROR (H5Aclose (attr));
+ CHECK_ERROR (attr = H5Acreate (to, attrname, datatype, dataspace,
+ H5P_DEFAULT));
+ CHECK_ERROR (H5Awrite (attr, datatype, value));
+ free (value);
+ }
+ CHECK_ERROR (H5Aclose (attr));
+ CHECK_ERROR (H5Sclose (dataspace));
+ CHECK_ERROR (H5Tclose (datatype));
+
+ return (0);
+}