From 6b661bbe7e32f6769d1fd24dc30f99e186d70f03 Mon Sep 17 00:00:00 2001 From: tradke Date: Fri, 26 Apr 2002 15:40:31 +0000 Subject: Moved the I/O request description and parsing routines from IOHDF5Util to IOUtil so that they can be shared by all I/O thorns now. git-svn-id: http://svn.cactuscode.org/arrangements/CactusBase/IOUtil/trunk@158 b32723a9-ab3a-4a60-88e2-2e5d99d7c17a --- src/Utils.c | 415 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/ioGH.h | 52 ++----- src/ioutil_Utils.h | 50 ++++++- 3 files changed, 468 insertions(+), 49 deletions(-) diff --git a/src/Utils.c b/src/Utils.c index 7abec4d..c6a1c98 100644 --- a/src/Utils.c +++ b/src/Utils.c @@ -3,7 +3,7 @@ @date Tue 4th July 2000 @author Gabrielle Allen @desc - Utility routines which may be called by other IO thorns + Utility routines which may be called by other I/O thorns. @enddesc @version $Id$ @@*/ @@ -15,6 +15,9 @@ #include "cctk.h" #include "cctk_Parameters.h" +#include "cctk_GNU.h" +#include "util_String.h" +#include "ioGH.h" #include "ioutil_Utils.h" #include "ioutil_CheckpointRecovery.h" @@ -23,10 +26,109 @@ static const char *rcsid = "$Header$"; CCTK_FILEVERSION(CactusBase_IOUtil_Utils_c) +/******************************************************************** + ******************** Macro Definitions ************************ + ********************************************************************/ /* uncomment this if you want some debugging output */ /* #define DEBUG_IOUTIL 1 */ +/******************************************************************** + ******************** Internal Typedefs ************************ + ********************************************************************/ +typedef struct +{ + const cGH *GH; + ioRequest **request_list; +} info_t; + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static void SetOutputVar (int vindex, const char *optstring, void *arg); + + +/******************************************************************** + ******************** External Routines ************************ + ********************************************************************/ +int CCTK_RegexMatch (const char *string, const char *pattern, const int nmatch, + regmatch_t *pmatch); + + + /*@@ + @routine IOUtil_ParseVarsForOutput + @date Fri 26 April 2002 + @author Thomas Radke + @desc + Parses the given 'out_vars' string as a list of variable and/or + groupnames. If an option string is appended to a name this will + be parsed for I/O request options. + @enddesc + + @calls CCTK_TraverseString + + @var GH + @vdesc pointer to CCTK grid hierarchy + @vtype const cGH * + @vio in + @endvar + @var out_vars + @vdesc string with list of variables and/or group names to parse + @vtype const char * + @vio in + @endvar + @var request_list + @vdesc list of I/O requests to fill out + @vtype ioRequest *[] + @vio out + @endvar +@@*/ +void IOUtil_ParseVarsForOutput (const cGH *GH, const char *out_vars, + ioRequest *request_list[]) +{ + int i; + info_t info; + + + /* free current list of I/O requests */ + for (i = CCTK_NumVars () - 1; i >= 0; i--) + { + if (request_list[i]) + { + IOUtil_FreeIORequest (&request_list[i]); + } + } + + /* generate new list of I/O requests */ + info.GH = GH; + info.request_list = request_list; + CCTK_TraverseString (out_vars, SetOutputVar, &info, CCTK_GROUP_OR_VAR); +} + + + /*@@ + @routine IOUtil_FreeIORequest + @date Fri 26 April 2002 + @author Thomas Radke + @desc + Frees an I/O request description. + @enddesc + + @var request + @vdesc pointer to the I/O request structure + @vtype ioRequest ** + @vio inout + @endvar +@@*/ +void IOUtil_FreeIORequest (ioRequest **request) +{ + free ((*request)->vectors); + free (*request); + *request = NULL; +} + + /*@@ @routine IOUtil_1DLines @date July 4 2000 @@ -474,3 +576,314 @@ int IOUtil_CreateDirectory (const cGH *GH, const char *dirname, return (retval); } + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static void SetOutputVar (int vindex, const char *optstring, void *arg) +{ + info_t *info; + regmatch_t gmatch[6], *dmatch; + int i, j, bytes, matched; + char *token, *separator, *fullname; + char *substring, *parsestring, *regexstring; + ioRequest *request; + DECLARE_CCTK_PARAMETERS + + + info = (info_t *) arg; + + /* allocate a new I/O request structure and initialize it with defaults */ + request = IOUtil_DefaultIORequest (info->GH, vindex); + + if (! optstring) + { + info->request_list[vindex] = request; + return; + } + + fullname = CCTK_FullName (vindex); + + /* parse the I/O request information */ + matched = CCTK_RegexMatch (optstring, + "\\{([0-9]*)\\}" /* dimension */ + "\\{([0-9,()]+)*\\}" /* direction */ + "\\{([0-9,]+)*\\}" /* origin */ + "\\{([-0-9,]+)*\\}" /* extent */ + "\\{([0-9,]+)*\\}", /* downsample */ + 6, gmatch); + if (matched <= 0) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "Couldn't parse I/O request options '%s' for variable '%s'", + optstring, fullname); + free (fullname); free (request); + return; + } + + /* SLAB DIMENSION */ + bytes = (int) (gmatch[1].rm_eo - gmatch[1].rm_so); + if (gmatch[1].rm_so != -1 && bytes > 0) + { + request->hdim = atoi (optstring + gmatch[1].rm_so); + if (request->hdim <= 0 || request->hdim > request->vdim) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "Invalid dimension given %d in I/O request options '%s' " + "for variable '%s'", request->hdim, optstring, fullname); + free (fullname); free (request); + return; + } + } + + /* DIRECTION */ + bytes = (int) (gmatch[2].rm_eo - gmatch[2].rm_so); + if (gmatch[2].rm_so != -1 && bytes > 0) + { + substring = strdup (optstring + gmatch[2].rm_so); + substring[bytes] = 0; + + dmatch = (regmatch_t *) malloc ((request->hdim + 1) * + sizeof (regmatch_t)); + regexstring = (char *) malloc (request->hdim * sizeof ("\\(([0-9,]+)\\)")); + regexstring[0] = 0; + for (i = 0; i < request->hdim; i++) + { + strcat (regexstring, "\\(([0-9,]+)\\)"); + } + matched = CCTK_RegexMatch (substring, regexstring, request->hdim + 1, + dmatch); + free (regexstring); + if (matched <= 0) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "Couldn't parse direction vectors in I/O request options '%s' " + "for variable '%s'.", optstring, fullname); + free (fullname); free (dmatch); free (request); + return; + } + + for (j = 0; j < request->hdim; j++) + { + i = 0; + bytes = (int) (dmatch[j + 1].rm_eo - dmatch[j + 1].rm_so); + if (dmatch[j + 1].rm_so != -1 && bytes > 0) + { + parsestring = strdup (substring + dmatch[j + 1].rm_so); + parsestring[bytes] = 0; + + token = parsestring; + while ((separator = strchr (token, ',')) != NULL) + { + *separator = 0; + request->direction[j * request->vdim + i] = atoi (token); + if (++i >= request->vdim) + { + break; + } + token = separator + 1; + } + request->direction[j * request->vdim + i++] = atoi (token); + free (parsestring); + } + free (substring); + if (i < request->vdim) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "Direction vectors are incomplete or missing in I/O request " + "options '%s' for variable '%s'.", optstring, fullname); + free (fullname); free (request); + return; + } + } + } + + /* ORIGIN */ + bytes = (int) (gmatch[3].rm_eo - gmatch[3].rm_so); + if (gmatch[3].rm_so != -1 && bytes > 0) + { + substring = strdup (optstring + gmatch[3].rm_so); + substring[bytes] = 0; + + i = 0; + token = substring; + while ((separator = strchr (token, ',')) != NULL) + { + *separator = 0; + request->origin[i] = atoi (token); + if (++i >= request->vdim) + { + break; + } + token = separator + 1; + } + request->origin[i++] = atoi (token); + free (substring); + + if (i < request->vdim) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "Origin vector is incomplete or missing in I/O request " + "options '%s' for variable '%s'.", optstring, fullname); + free (fullname); free (request); + return; + } + } + + /* LENGTH */ + bytes = (int) (gmatch[4].rm_eo - gmatch[4].rm_so); + if(gmatch[4].rm_so != -1 && bytes > 0) + { + substring = strdup (optstring + gmatch[4].rm_so); + substring[bytes] = 0; + + i = 0; + token = substring; + while ((separator = strchr (token, ',')) != NULL) + { + *separator = 0; + request->extent[i] = atoi (token); + if (++i >= request->hdim) + { + break; + } + token = separator + 1; + } + request->extent[i++] = atoi (token); + free (substring); + + if (i < request->hdim) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "Length vector is incomplete or missing in I/O request " + "options '%s' for variable '%s'.", optstring, fullname); + free (fullname); free (request); + return; + } + } + + /* DOWNSAMPLING */ + bytes = (int) (gmatch[5].rm_eo - gmatch[5].rm_so); + if(gmatch[5].rm_so != -1 && bytes > 0) + { + substring = strdup (optstring + gmatch[5].rm_so); + substring[bytes] = 0; + + i = 0; + token = substring; + while ((separator = strchr (token, ',')) != NULL) + { + *separator = 0; + request->downsample[i] = atoi (token); + if (++i >= request->hdim) + { + break; + } + token = separator + 1; + } + request->downsample[i++] = atoi (token); + free (substring); + + if (i < request->hdim) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "Downsampling vector is incomplete or missing in I/O request " + "options '%s' for variable '%s'.", optstring, fullname); + free (fullname); free (request); + return; + } + } + + /* assign the new I/O request */ + info->request_list[vindex] = request; + + /* clean up */ + free (fullname); +} + + +ioRequest *IOUtil_DefaultIORequest (const cGH *GH, int vindex) +{ + ioRequest *request; + int *extent_int; + const ioGH *myGH; + DECLARE_CCTK_PARAMETERS + + + myGH = (const ioGH *) CCTK_GHExtension (GH, "IO"); + + /* allocate a new I/O request structure */ + request = (ioRequest *) malloc (sizeof (ioRequest)); + + /* fill out the basics */ + request->vindex = vindex; + request->timelevel = 0; + request->check_exist = myGH->recovered; + + /* get the I/O request datatype (will be single-precision if requested) */ + request->hdatatype = CCTK_VarTypeI (vindex); + if (myGH->out_single) + { + if (request->hdatatype == CCTK_VARIABLE_REAL) + { + request->hdatatype = CCTK_VARIABLE_REAL4; + } + else if (request->hdatatype == CCTK_VARIABLE_COMPLEX) + { + request->hdatatype = CCTK_VARIABLE_COMPLEX8; + } +#ifdef CCTK_INT2 + else if (request->hdatatype == CCTK_VARIABLE_INT) + { + request->hdatatype = CCTK_VARIABLE_INT2; + } +#endif + } + + /* get the variable's dimension and extents */ + request->vdim = CCTK_GroupDimFromVarI (vindex); + extent_int = (int *) malloc (request->vdim * sizeof (int)); + CCTK_GroupgshVI (GH, request->vdim, extent_int, vindex); + + /* allocate the arrays all in one go + only initialize those which are mandatory for the Hyperslab API */ + request->vectors = (CCTK_INT *) calloc ((request->vdim + 6) * request->vdim + 1, + sizeof (CCTK_INT)); + request->hoffset = request->vectors + 0*request->vdim; + request->hsize = request->vectors + 1*request->vdim; + request->hsize_chunk = request->vectors + 2*request->vdim; + request->origin = request->vectors + 3*request->vdim + 1; + request->extent = request->vectors + 4*request->vdim + 1; + request->downsample = request->vectors + 5*request->vdim + 1; + request->direction = request->vectors + 6*request->vdim + 1; + + for (request->hdim = 0; request->hdim < request->vdim; request->hdim++) + { + request->extent[request->hdim] = extent_int[request->hdim]; + request->direction[request->hdim * (request->vdim + 1)] = 1; + + /* take the downsampling parameters from IOUtil */ + if (request->hdim == 0) + { + request->downsample[request->hdim] = out3D_downsample_x; + } + else if (request->hdim == 1) + { + request->downsample[request->hdim] = out3D_downsample_y; + } + else if (request->hdim == 2) + { + request->downsample[request->hdim] = out3D_downsample_z; + } + else + { + request->downsample[request->hdim] = 1; + } + } + + /* clean up */ + free (extent_int); + + return (request); +} diff --git a/src/ioGH.h b/src/ioGH.h index c77c7b9..150e4da 100644 --- a/src/ioGH.h +++ b/src/ioGH.h @@ -2,22 +2,14 @@ @header ioGH.h @date Tue 9th Jan 1999 @author Gabrielle Allen - @desc - The extensions to the GH structure from IOUtil. - @history - @hauthor Thomas Radke @hdate 16 Mar 1999 - @hdesc Added parameters for 2D and 3D output - @hauthor Thomas Radke @hdate 17 Mar 1999 - @hdesc Changed naming: IEEEIO -> FlexIO - @hauthor Thomas Radke @hdate 30 Mar 1999 - @hdesc Undefined DI macro - @endhistory - @version $Header$ + @desc + The extensions to the GH structure from IOUtil. + @enddesc + @version $Header$ @@*/ -#ifndef _IOGH_H_ -#define _IOGH_H_ 1 - +#ifndef _IOUTIL_IOGH_H_ +#define _IOUTIL_IOGH_H_ 1 #ifdef __cplusplus extern "C" @@ -26,34 +18,11 @@ extern "C" /* IOUtil's GH extension structure */ -typedef struct IOGH +typedef struct { - -#if 0 - /* TR: commented these things out because they were moved into the other - IO thorns' GH extensions - But maybe someday we want them back here, eg. if the user - wants to say how often to do 3D output in general for all IO thorns - that can produce 3D output; of course they should still be able - override this with their own parameters. - */ - /* How often to output */ - int infoevery; - int IO_0Devery; - int IO_1Devery; - int IO_2Devery; - int IO_3Devery; - - /* Directory in which to output */ - char *outpfx_0D; - char *outpfx_1D; - char *outpfx_2D; - char *outpfx_3D; -#endif - /* for 3D output */ - int ioproc; /* the IO processor each proc belongs to */ - int nioprocs; /* total number of IO processors */ + int ioproc; /* the I/O processor each proc belongs to */ + int nioprocs; /* total number of I/O processors */ int ioproc_every; /* output by every N'th processor */ int unchunked; /* if true generate unchunked output file */ int *downsample; /* downsampling parameters array of size cctk_maxdim */ @@ -72,5 +41,4 @@ typedef struct IOGH } #endif -#endif /* _IOGH_H_ */ - +#endif /* _IOUTIL_IOGH_H_ */ diff --git a/src/ioutil_Utils.h b/src/ioutil_Utils.h index 519f6ee..83831dc 100644 --- a/src/ioutil_Utils.h +++ b/src/ioutil_Utils.h @@ -4,13 +4,12 @@ @author Thomas Radke @desc Function prototypes for setting up slice centers. - @history - @endhistory - @version $Header$ + @enddesc + @version $Header$ @@*/ -#ifndef _IOUTIL_UTILS_H_ -#define _IOUTIL_UTILS_H_ +#ifndef _IOUTIL_IOUTIL_UTILS_H_ +#define _IOUTIL_IOUTIL_UTILS_H_ 1 #ifdef __cplusplus extern "C" @@ -18,6 +17,44 @@ extern "C" #endif +/* structure describing an I/O request (including hyperslab parameters) */ +typedef struct +{ + /* index and timelevel of the variable */ + int vindex, timelevel; + + /* dimensionality of the variable and the hyperslab */ + int vdim, hdim; + + /* CCTK datatype for the hyperslab */ + int hdatatype; + + /* flag indicating wheter check whether an object to be written already + exists (and remove it in that case) */ + int check_exist; + + /* pointer to allocated buffers */ + CCTK_INT *vectors; + + /* hyperslab mapping parameters */ + CCTK_INT *origin, *direction, *extent, *downsample; + + /* offset and sizes of hyperslab into the variable's dataspace */ + CCTK_INT *hoffset, *hsize, *hsize_chunk; + +} ioRequest; + + +/* parse a given 'out_vars' parameter string */ +void IOUtil_ParseVarsForOutput (const cGH *GH, const char *out_vars, + ioRequest *request_list[]); + +/* return the default I/O request description structure for a variable */ +ioRequest *IOUtil_DefaultIORequest (const cGH *GH, int vindex); + +/* free an I/O request description */ +void IOUtil_FreeIORequest (ioRequest **request); + /* set the slice center for 1D lines */ int IOUtil_1DLines (const cGH *GH, int num_dims, @@ -32,6 +69,7 @@ int IOUtil_2DPlanes (const cGH *GH, const CCTK_REAL *origin_phys, int *slice_center); +/* create an output directory on all I/O processors */ int IOUtil_CreateDirectory (const cGH *GH, const char *dirname, int multiple_io_procs, @@ -41,4 +79,4 @@ int IOUtil_CreateDirectory (const cGH *GH, } #endif -#endif /* _IOUTIL_UTILS_H_ */ +#endif /* _IOUTIL_IOUTIL_UTILS_H_ */ -- cgit v1.2.3