aboutsummaryrefslogtreecommitdiff
path: root/src/Utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Utils.c')
-rw-r--r--src/Utils.c415
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);
+}