From 51c706da529214743a0eafaf95f2d97cfb6727b6 Mon Sep 17 00:00:00 2001 From: tradke Date: Mon, 2 Jul 2007 12:08:00 +0000 Subject: added utility program to convert CarpetIOHDF5 output data into PUGH's IOHDF5 format git-svn-id: http://svn.cactuscode.org/arrangements/CactusPUGHIO/IOHDF5/trunk@231 4825ed28-b72c-4eae-9704-e50c059e567d --- src/make.configuration.defn | 2 +- src/util/hdf5_convert_from_carpetiohdf5.c | 435 ++++++++++++++++++++++++++++++ 2 files changed, 436 insertions(+), 1 deletion(-) create mode 100644 src/util/hdf5_convert_from_carpetiohdf5.c diff --git a/src/make.configuration.defn b/src/make.configuration.defn index aba91f8..7e9ca9d 100644 --- a/src/make.configuration.defn +++ b/src/make.configuration.defn @@ -2,7 +2,7 @@ # $Header$ # add the recombiner and the IEEEIO converter to the Cactus utitlity tools -ALL_UTILS += hdf5_recombiner hdf5_merge hdf5_extract hdf5_double_to_single +ALL_UTILS += hdf5_recombiner hdf5_merge hdf5_extract hdf5_double_to_single hdf5_convert_from_carpetiohdf5 ifneq ($(strip $(HAVE_FLEXIO)), ) ALL_UTILS += hdf5_convert_from_ieeeio diff --git a/src/util/hdf5_convert_from_carpetiohdf5.c b/src/util/hdf5_convert_from_carpetiohdf5.c new file mode 100644 index 0000000..74e7c7c --- /dev/null +++ b/src/util/hdf5_convert_from_carpetiohdf5.c @@ -0,0 +1,435 @@ + /*@@ + @file hdf5_convert_from_carpetiohdf5.c + @date Tue 11 October 2005 + @author Thomas Radke + @desc + Utility program to convert CarpetIOHDF5 datafiles + into IOHDF5 datafiles. + @enddesc + @version $Id$ + @@*/ + +#define MAXDIM 3 +#define MAXNAMESIZE 100 + +#include +#include + + +/* Cactus includes (defines CCTK_FILEVERSION) */ +#include "cctk.h" +#include "cctk_Version.h" + +/* IOHDF5 includes */ +#include "../../../IOHDF5Util/src/ioHDF5UtilGH.h" + +/* the rcs ID and its dummy function to use it */ +static const char *rcsid = "$Header$"; +CCTK_FILEVERSION(CactusPUGHIO_IOHDF5_util_hdf5_convert_from_carpetiohdf5_c) + + +/*****************************************************************************/ +/* macro definitions */ +/*****************************************************************************/ +/* uncomment the following to get some debugging output */ +/* #define IOHDF5_DEBUG 1 */ + +/* metadata group in CarpetIOHDF5 files */ +/* FIXME: should rather include the proper CarpetIOHDF5 header file */ +#define METADATA_GROUP "Parameters and Global Attributes" + +/* 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); \ + exit (-1); \ + } \ + } while (0) + +/*****************************************************************************/ +/* global variables */ +/*****************************************************************************/ +static int nprocs = 0; /* number of processors for IOHDF5 chunked data */ +static int unchunked = 0; /* flag indicating chunked/unchunked data */ +static char *pathname = NULL; /* pathname of the current object */ +static int ntimelevels = 1; /* value of the timelevel attribute */ +static const char *groupname = NULL; /* value of the groupname attribute */ + +/*****************************************************************************/ +/* 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 Tue 11 October 2005 + @author Thomas Radke + @desc + Main routine of the CarpetIOHDF5-to-IOHDF5 converter + @enddesc + + @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, j; + int rank; + int *dims; + double timestep; + char *varname, *coordname, *tag; + double *coords, *data, *bbox, *origin, *delta; + hid_t infile, outfile, dataset, dataspace, attr, attrDataspace; + hid_t group, hdf5String; + hsize_t hdf5Dims[MAXDIM]; + int iteration, timelevel; + char hdf5DatasetName[2 * MAXNAMESIZE]; + const char *cactus_version = "Cactus Beta16"; /* CCTK_FullVersion (); */ + + + if (argc != 6) + { + fprintf (stderr, "Usage: %s \n", argv[0]); + fprintf (stderr, " eg. %s grid::coordinates 1 4 gxx-CarpetIOHDF5.h5 gxx-IOHDF5.h5\n", argv[0]); + return (0); + } + + groupname = argv[1]; + ntimelevels = atoi (argv[2]); + nprocs = atoi (argv[3]); + + infile = H5Fopen (argv[4], H5F_ACC_RDONLY, H5P_DEFAULT); + if (infile < 0) + { + fprintf (stderr, "Could not open CarpetIOHDF5 input file '%s'\n", argv[4]); + return (-1); + } + + outfile = H5Fcreate (argv[5], H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + if (outfile < 0) + { + fprintf (stderr, "Could not create HDF5 output file '%s'\n", argv[5]); + return (-1); + } + + printf ("\n ---------------------------------------\n" + " Cactus CarpetIOHDF5-to-IOHDF5 Converter\n" + " ---------------------------------------\n"); + + CHECK_ERROR (hdf5String = H5Tcopy (H5T_C_S1)); + +#if 0 + /* read the metadata group from the CarpetIOHDF5 file */ + CHECK_ERROR (group = H5Gopen (infile, METADATA_GROUP)); + + CHECK_ERROR (attr = H5Aopen_name (group, "nioprocs")); + CHECK_ERROR (H5Aread (attr, H5T_NATIVE_INT, &nprocs)); + CHECK_ERROR (H5Aclose (attr)); + + CHECK_ERROR (H5Gclose (group)); +#endif + + /* create the metadata group in the IOHDF5 file */ + CHECK_ERROR (group = H5Gcreate (outfile, GLOBAL_ATTRIBUTES_GROUP, 0)); + CHECK_ERROR (attrDataspace = H5Screate (H5S_SCALAR)); + + CHECK_ERROR (attr = H5Acreate (group, "nprocs", H5T_NATIVE_INT, + attrDataspace, H5P_DEFAULT)); + CHECK_ERROR (H5Awrite (attr, H5T_NATIVE_INT, &nprocs)); + CHECK_ERROR (H5Aclose (attr)); + + CHECK_ERROR (attr = H5Acreate (group, "ioproc_every", H5T_NATIVE_INT, + attrDataspace, H5P_DEFAULT)); + CHECK_ERROR (H5Awrite (attr, H5T_NATIVE_INT, &nprocs)); + CHECK_ERROR (H5Aclose (attr)); + + CHECK_ERROR (attr = H5Acreate (group, "unchunked", H5T_NATIVE_INT, + attrDataspace, H5P_DEFAULT)); + unchunked = nprocs == 1; + CHECK_ERROR (H5Awrite (attr, H5T_NATIVE_INT, &unchunked)); + CHECK_ERROR (H5Aclose (attr)); + + CHECK_ERROR (H5Tset_size (hdf5String, strlen (cactus_version))); + CHECK_ERROR (attr = H5Acreate (group, "Cactus version", hdf5String, + attrDataspace, H5P_DEFAULT)); + CHECK_ERROR (H5Awrite (attr, hdf5String, cactus_version)); + CHECK_ERROR (H5Aclose (attr)); + + CHECK_ERROR (H5Gclose (group)); + + /* copy datasets as we traverse through the input file */ + pathname = ""; + CHECK_ERROR (H5Giterate (infile, "/", NULL, CopyObject, &outfile)); + + CHECK_ERROR (H5Sclose (attrDataspace)); + CHECK_ERROR (H5Tclose (hdf5String)); + CHECK_ERROR (H5Fclose (outfile)); + CHECK_ERROR (H5Fclose (infile)); + + 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, attr, attr_dataspace, attr_datatype, datatype, dataspace, dataset; + H5G_stat_t objectinfo; + char *current_pathname, *name; + size_t objectsize; + int i, iteration, timelevel; + char *data; + + + /* skip the CarpetIOHDF5 metadata group */ + if (! strcmp (objectname, METADATA_GROUP)) + { + return (0); + } + + /* check the type of the current object */ + CHECK_ERROR (H5Gget_objinfo (from, objectname, 0, &objectinfo)); + if (objectinfo.type != H5G_DATASET) + { + fprintf (stderr, "WARNING: Found object '%s/%s' which is not a dataset ! " + "Object will not be copied.\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); + printf (" copying dataset '%s'\n", pathname); + + /* get the output object identifier */ + to = *(hid_t *) _to; + + CHECK_ERROR (from = H5Dopen (from, objectname)); + CHECK_ERROR (attr = H5Aopen_name (from, "name")); + CHECK_ERROR (datatype = H5Aget_type (attr)); + CHECK_ERROR (objectsize = H5Tget_size (datatype)); + data = malloc (objectsize + 1); + CHECK_ERROR (H5Aread (attr, datatype, data)); + data[objectsize] = 0; + CHECK_ERROR (H5Tclose (datatype)); + CHECK_ERROR (H5Aclose (attr)); + + CHECK_ERROR (attr = H5Aopen_name (from, "timestep")); + CHECK_ERROR (H5Aread (attr, H5T_NATIVE_INT, &iteration)); + CHECK_ERROR (H5Aclose (attr)); + + CHECK_ERROR (attr = H5Aopen_name (from, "group_timelevel")); + CHECK_ERROR (H5Aread (attr, H5T_NATIVE_INT, &timelevel)); + CHECK_ERROR (H5Aclose (attr)); + + /* build the new name for the PUGH dataset */ + name = malloc (objectsize + 100); + sprintf (name, "%s timelevel %d at iteration %d", data, timelevel, iteration); + free (data); + + CHECK_ERROR (dataspace = H5Dget_space (from)); + CHECK_ERROR (datatype = H5Dget_type (from)); + objectsize = H5Tget_size (datatype); + if (H5Sis_simple (dataspace)) { + objectsize *= H5Sget_simple_extent_npoints (dataspace); + } + + data = malloc (objectsize); + CHECK_ERROR (H5Dread (from, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, data)); + + if (! unchunked) { + CHECK_ERROR (to = H5Gcreate (to, name, 0)); + } + for (i = 0; i < nprocs; i++) { + char chunkname[20]; + sprintf (chunkname, "chunk%d", i); + CHECK_ERROR (dataset = H5Dcreate (to, unchunked ? name : chunkname, + datatype, dataspace, H5P_DEFAULT)); + CHECK_ERROR (H5Dwrite (dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, + data)); + if (i + 1 < nprocs) { + CHECK_ERROR (H5Dclose (dataset)); + } + } + free (name); + free (data); + CHECK_ERROR (H5Sclose (dataspace)); + CHECK_ERROR (H5Tclose (datatype)); + + to = unchunked ? dataset : to; + + /* copy Carpet attributes */ + CHECK_ERROR (H5Aiterate (from, NULL, CopyAttribute, &to)); + CHECK_ERROR (H5Dclose (from)); + + /* add attributes which aren't stored by Carpet but needed by PUGH */ + CHECK_ERROR (dataspace = H5Screate (H5S_SCALAR)); + + const int grouptype = 403; /* CCTK_ARRAY */ + CHECK_ERROR (attr = H5Acreate (to, "grouptype", H5T_NATIVE_INT, + dataspace, H5P_DEFAULT)); + CHECK_ERROR (H5Awrite (attr, H5T_NATIVE_INT, &grouptype)); + CHECK_ERROR (H5Aclose (attr)); + + CHECK_ERROR (attr = H5Acreate (to, "ntimelevels", H5T_NATIVE_INT, + dataspace, H5P_DEFAULT)); + CHECK_ERROR (H5Awrite (attr, H5T_NATIVE_INT, &ntimelevels)); + CHECK_ERROR (H5Aclose (attr)); + + CHECK_ERROR (datatype = H5Tcopy (H5T_C_S1)); + CHECK_ERROR (H5Tset_size (datatype, strlen (groupname))); + CHECK_ERROR (attr = H5Acreate (to, "groupname", datatype, + dataspace, H5P_DEFAULT)); + CHECK_ERROR (H5Awrite (attr, datatype, groupname)); + CHECK_ERROR (H5Aclose (attr)); + CHECK_ERROR (H5Tclose (datatype)); + + CHECK_ERROR (H5Sclose (dataspace)); + + if (unchunked) { + CHECK_ERROR (H5Dclose (to)); + } else { + CHECK_ERROR (H5Gclose (to)); + } + + /* 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); +} -- cgit v1.2.3