diff options
Diffstat (limited to 'src/Utils.c')
-rw-r--r-- | src/Utils.c | 415 |
1 files changed, 414 insertions, 1 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); +} |