/*@@ @file DumpUtils.c @date Fri Oct 6 2000 @author Thomas Radke @desc Utility routines for dumping data into HDF5 files. @enddesc @version $Id$ @@*/ #include #include "cctk.h" #include "cctk_Version.h" #include "cctk_Parameters.h" #include "CactusBase/IOUtil/src/ioGH.h" #include "CactusBase/IOUtil/src/ioutil_CheckpointRecovery.h" #include "ioHDF5UtilGH.h" /* the rcs ID and its dummy function to use it */ static const char *rcsid = "$Header$"; CCTK_FILEVERSION(CactusPUGHIO_IOHDF5Util_DumpUtils_c) /*@@ @routine IOHDF5Util_DumpGH @date Tue Oct 10 2000 @author Thomas Radke @desc Dump all variables of the given GH along with the global attributes and parameters to the given HDF5 checkpoint file. @enddesc @var GH @vdesc pointer to CCTK grid hierarchy @vtype const cGH * @vio in @endvar @var timers @vdesc array of timers for timing the checkpointing @vtype const int * @vio in @endvar @var file @vdesc HDF5 file handle @vtype hid_t @vio in @endvar @returntype int @returndesc the accumulated return code from @seeroutine IOHDF5Util_DumpVar (should be 0 for success, or negative if some error occured) @endreturndesc @@*/ int IOHDF5Util_DumpGH (const cGH *GH, const int *timers, hid_t file) { int first_vindex, gindex, retval; cGroup gdata; char *fullname; ioRequest *request; DECLARE_CCTK_PARAMETERS retval = 0; /* start CP_PARAMETERS_TIMER timer */ if (timers) { CCTK_TimerResetI (timers[CP_PARAMETERS_TIMER]); CCTK_TimerStartI (timers[CP_PARAMETERS_TIMER]); } /* now start dumping away */ if (file >= 0) { /* all GH extension variables and parameter stuff which is not specific to any dataset goes into dedicated groups */ IOHDF5Util_DumpParameters (GH, 1, file); IOHDF5Util_DumpGHExtensions (GH, file); } if (CCTK_Equals (verbose, "full")) { CCTK_INFO ("Dumping Grid Variables ..."); } /* stop CP_PARAMETERS_TIMER timer and start CP_VARIABLES_TIMER */ if (timers) { CCTK_TimerStopI (timers[CP_PARAMETERS_TIMER]); CCTK_TimerResetI (timers[CP_VARIABLES_TIMER]); CCTK_TimerStartI (timers[CP_VARIABLES_TIMER]); } /* ... now the variables, sorted by groups */ for (gindex = CCTK_NumGroups () - 1; gindex >= 0; gindex--) { /* only dump groups which have storage assigned */ if (CCTK_QueryGroupStorageI (GH, gindex) <= 0) { continue; } /* get the number of allocated timelevels */ CCTK_GroupData (gindex, &gdata); gdata.numtimelevels = 0; gdata.numtimelevels = CCTK_GroupStorageIncrease (GH, 1, &gindex, &gdata.numtimelevels,NULL); /* dump all timelevels except the oldest (for multi-level groups) */ if (gdata.numtimelevels > 1) { gdata.numtimelevels--; } first_vindex = CCTK_FirstVarIndexI (gindex); /* get the default I/O request for this group */ request = IOUtil_DefaultIORequest (GH, first_vindex, 1); /* disable checking for old data objects, disable datatype conversion and downsampling, request hyperslab output including ghostzones */ request->check_exist = 0; request->hdatatype = gdata.vartype; for (request->hdim = 0; request->hdim < request->vdim; request->hdim++) { request->downsample[request->hdim] = 1; } request->with_ghostzones = 1; /* loop over all variables in this group */ for (request->vindex = first_vindex; request->vindex < first_vindex + gdata.numvars; request->vindex++) { /* loop over all allocated timelevels of this variable */ for (request->timelevel = 0; request->timelevel < gdata.numtimelevels; request->timelevel++) { if (CCTK_Equals (verbose, "full") && file >= 0) { fullname = CCTK_FullName (request->vindex); CCTK_VInfo (CCTK_THORNSTRING, " %s (timelevel %d)", fullname, request->timelevel); free (fullname); } retval += IOHDF5Util_DumpVar (GH, request, file); } } /* end of loop over all variables */ } /* end of loop over all groups */ /* stop CP_VARIABLES_TIMER timer */ if (timers) { CCTK_TimerStopI (timers[CP_VARIABLES_TIMER]); } /* free I/O request */ IOUtil_FreeIORequest (&request); return (retval); } /*@@ @routine IOHDF5Util_DumpCommonAttributes @date May 21 1999 @author Thomas Radke @desc Add "Common" attributes to the given dataset, these are: @enddesc @var GH @vdesc pointer to CCTK grid hierarchy @vtype const cGH * @vio in @endvar @var request @vdesc reference to the I/O request description @vtype const ioRequest * @vio in @endvar @var dataset @vdesc the object handle where the attributes should be attached to @vtype hid_t @vio in @endvar @@*/ void IOHDF5Util_DumpCommonAttributes (const cGH *GH, const ioRequest *request, hid_t object) { int dim, vdim; char *groupname; CCTK_INT attr_int; CCTK_REAL *attr_real; const ioHDF5UtilGH *myGH; char coord_system_name[20]; DECLARE_CCTK_PARAMETERS myGH = CCTK_GHExtension (GH, "IOHDF5Util"); /* attributes describing the variable */ groupname = CCTK_GroupNameFromVarI (request->vindex); WRITE_ATTRIBUTE ("groupname", groupname, object, myGH, 0, myGH->HDF5_STRING); free (groupname); attr_int = CCTK_GroupTypeFromVarI (request->vindex); WRITE_ATTRIBUTE ("grouptype", &attr_int, object, myGH, 0, HDF5_INT); attr_int = CCTK_MaxTimeLevelsVI (request->vindex); WRITE_ATTRIBUTE ("ntimelevels", &attr_int, object, myGH, 0, HDF5_INT); WRITE_ATTRIBUTE ("global_size", request->hsize, object, myGH, request->hdim, HDF5_INT); WRITE_ATTRIBUTE ("time", &GH->cctk_time, object, myGH, 0, HDF5_REAL); /* attributes describing the underlying grid These are only stored for CCTK_GF variables if they are associated with coordinates. */ /* FIXME: This is hardcoded for cartesian coordinate systems. A better solution would be to be able to query the coordinate system which is associated with the variable. */ vdim = CCTK_GroupDimFromVarI (request->vindex); sprintf (coord_system_name, "cart%dd", vdim); if (CCTK_GroupTypeFromVarI (request->vindex) == CCTK_GF && CCTK_CoordSystemHandle (coord_system_name) >= 0) { attr_real = malloc (3 * vdim * sizeof (CCTK_REAL)); for (dim = 0; dim < vdim; dim++) { CCTK_CoordRange (GH, &attr_real[dim], &attr_real[dim + vdim], dim + 1, NULL, coord_system_name); attr_real[dim + 0*vdim] += request->origin[dim] * GH->cctk_delta_space[dim]; attr_real[dim + 2*vdim] = GH->cctk_delta_space[dim] * request->downsample[dim]; attr_real[dim + 1*vdim] = attr_real[dim + 0*vdim] + ((request->extent[dim] + request->downsample[dim]-1) / request->downsample[dim] - 1) * attr_real[dim + 2*vdim]; } WRITE_ATTRIBUTE ("origin", attr_real, object, myGH, vdim, HDF5_REAL); WRITE_ATTRIBUTE ("min_ext", attr_real, object, myGH, vdim, HDF5_REAL); WRITE_ATTRIBUTE ("max_ext", attr_real + vdim, object, myGH, vdim,HDF5_REAL); WRITE_ATTRIBUTE ("delta", attr_real + 2*vdim, object, myGH, vdim,HDF5_REAL); free (attr_real); } } /*@@ @routine IOHDF5Util_DumpParameters @date Thu Jan 20 2000 @author Thomas Radke @desc Collects the parameters of all active implementations into a single string and writes it as an attribute attached to the CACTUS_PARAMETERS_GROUP group in the HDF5 file. @enddesc @var GH @vdesc pointer to CCTK grid hierarchy @vtype const cGH * @vio in @endvar @var all @vdesc flag indicating whether to save all parameters or just the ones which have been set before @vtype int @vio in @endvar @var file @vdesc the HDF5 file handle @vtype hid_t @vio in @endvar @@*/ void IOHDF5Util_DumpParameters (const cGH *GH, int all, hid_t file) { ioHDF5UtilGH *myGH; char *parameters; hid_t group; DECLARE_CCTK_PARAMETERS if (CCTK_Equals (verbose, "full")) { CCTK_INFO ("Dumping Parameters ..."); } /* get the parameter string buffer */ parameters = IOUtil_GetAllParameters (GH, all); if (parameters) { myGH = CCTK_GHExtension (GH, "IOHDF5Util"); HDF5_ERROR (group = H5Gcreate (file, CACTUS_PARAMETERS_GROUP, 0)); WRITE_ATTRIBUTE (ALL_PARAMETERS, parameters, group, myGH, 0, myGH->HDF5_STRING); HDF5_ERROR (H5Gclose (group)); free (parameters); } } /*@@ @routine IOHDF5Util_DumpGHExtensions @date Thu Jan 20 2000 @author Thomas Radke @desc Attaches the current values of important flesh and IO variables as attributes to the GLOBAL_ATTRIBUTES_GROUP group in the HDF5 file. @enddesc @var GH @vdesc pointer to CCTK grid hierarchy @vtype const cGH * @vio in @endvar @var file @vdesc the HDF5 file handle @vtype hid_t @vio in @endvar @@*/ void IOHDF5Util_DumpGHExtensions (const cGH *GH, hid_t file) { int value; hid_t group; char buffer[128]; const char *version; const ioGH *ioUtilGH; const ioHDF5UtilGH *myGH; DECLARE_CCTK_PARAMETERS if (CCTK_Equals (verbose, "full")) { CCTK_INFO ("Dumping GH extensions ..."); } ioUtilGH = CCTK_GHExtension (GH, "IO"); myGH = CCTK_GHExtension (GH, "IOHDF5Util"); HDF5_ERROR (group = H5Gcreate (file, GLOBAL_ATTRIBUTES_GROUP, 0)); value = CCTK_MainLoopIndex (); WRITE_ATTRIBUTE ("main_loop_index", &value, group, myGH, 0, H5T_NATIVE_INT); value = CCTK_nProcs (GH); WRITE_ATTRIBUTE ("nprocs", &value, group, myGH, 0, H5T_NATIVE_INT); WRITE_ATTRIBUTE ("ioproc_every", &ioUtilGH->ioproc_every, group, myGH, 0, H5T_NATIVE_INT); WRITE_ATTRIBUTE ("unchunked", &ioUtilGH->unchunked, group, myGH, 0, H5T_NATIVE_INT); WRITE_ATTRIBUTE ("cctk_time", &GH->cctk_time, group, myGH, 0, HDF5_REAL); WRITE_ATTRIBUTE ("cctk_iteration", &GH->cctk_iteration, group, myGH, 0, H5T_NATIVE_INT); version = CCTK_FullVersion (); WRITE_ATTRIBUTE ("Cactus version", version, group, myGH, 0,myGH->HDF5_STRING); /* add the parameter filename and the creation date as file identification attributes */ if (CCTK_Equals (out_fileinfo, "parameter filename") || CCTK_Equals (out_fileinfo, "all")) { buffer[0] = 0; CCTK_ParameterFilename (sizeof (buffer), buffer); WRITE_ATTRIBUTE ("parameter file", buffer, group, myGH,0,myGH->HDF5_STRING); } if (CCTK_Equals (out_fileinfo, "creation date") || CCTK_Equals (out_fileinfo, "all")) { buffer[0] = 0; Util_CurrentDate (sizeof (buffer), buffer); value = strlen (buffer) + 1; buffer[value-1] = ' '; Util_CurrentTime (sizeof (buffer) - value, buffer + value); WRITE_ATTRIBUTE ("creation date", buffer, group, myGH, 0,myGH->HDF5_STRING); } HDF5_ERROR (H5Gclose (group)); } /*@@ @routine IOHDF5Util_DataType @author Thomas Radke @date Mon 11 June 2001 @desc Returns the HDF5 datatype for a given CCTK datatype @enddesc @var myGH @vdesc pointer to IOHDF5Util's GH extensions @vtype ioHDF5UtilGH * @vio in @endvar @var cctk_type @vdesc CCTK datatype @vtype int @vio in @endvar @returntype hid_t @returndesc the appropriate HDF5 datatype for success, or -1 otherwise @endreturndesc @@*/ hid_t IOHDF5Util_DataType (const ioHDF5UtilGH *myGH, int cctk_type) { hid_t retval; switch (cctk_type) { case CCTK_VARIABLE_CHAR: retval = HDF5_CHAR; break; case CCTK_VARIABLE_INT: retval = HDF5_INT; break; case CCTK_VARIABLE_REAL: retval = HDF5_REAL; break; case CCTK_VARIABLE_COMPLEX: retval = myGH->HDF5_COMPLEX; break; #ifdef CCTK_INT1 case CCTK_VARIABLE_INT1: retval = HDF5_INT1; break; #endif #ifdef CCTK_INT2 case CCTK_VARIABLE_INT2: retval = HDF5_INT2; break; #endif #ifdef CCTK_INT4 case CCTK_VARIABLE_INT4: retval = HDF5_INT4; break; #endif #ifdef CCTK_INT8 case CCTK_VARIABLE_INT8: retval = HDF5_INT8; break; #endif #ifdef CCTK_REAL4 case CCTK_VARIABLE_REAL4: retval = HDF5_REAL4; break; case CCTK_VARIABLE_COMPLEX8: retval = myGH->HDF5_COMPLEX8; break; #endif #ifdef CCTK_REAL8 case CCTK_VARIABLE_REAL8: retval = HDF5_REAL8; break; case CCTK_VARIABLE_COMPLEX16: retval = myGH->HDF5_COMPLEX16; break; #endif #ifdef CCTK_REAL16 case CCTK_VARIABLE_REAL16: retval = HDF5_REAL16; break; case CCTK_VARIABLE_COMPLEX32: retval = myGH->HDF5_COMPLEX32; break; #endif default: CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, "Unsupported CCTK variable datatype %d", cctk_type); retval = -1; } return (retval); }