diff options
Diffstat (limited to 'src/Output.c')
-rw-r--r-- | src/Output.c | 670 |
1 files changed, 670 insertions, 0 deletions
diff --git a/src/Output.c b/src/Output.c new file mode 100644 index 0000000..4bb6a86 --- /dev/null +++ b/src/Output.c @@ -0,0 +1,670 @@ + /*@@ + @file Output.c + @date 01 Oct 1999 + @author Jonghyun Lee + @desc + Functions to deal with IOPanda output of grid variables + @enddesc + @version $Id$ + @@*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "CactusBase/IOUtil/src/ioGH.h" +#include "CactusPUGH/PUGH/src/include/pugh.h" + +#include "ioPandaGH.h" +#include "Panda/c_interface.h" + +/* the rcs ID and its dummy funtion to use it */ +static const char *rcsid = "$Header$"; +CCTK_FILEVERSION(BetaThorns_IOPanda_Output_c) + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static int CheckOutputVar (int vindex); +static void CheckSteerableParameters (pandaGH *myGH); +static void SetOutputFlag (int vindex, const char *optstring, void *arg); +static int IOPanda_Timestep (const cGH *GH, int vindex, const char *alias); +static void IOPanda_IEEEIOStructDump (const cGH *GH, const char *fname); +static void IOPanda_AddCommonAttributes (const cGH *GH, int vindex, int timelevel, int global_size[3], char *fname); +static void IOPanda_AddChunkAttributes (const cGH *GH, int vindex, CCTK_INT4 *geom, char *fname); + + +/*@@ + @routine IOPanda_OutputGH + @date Sat March 6 1999 + @author Gabrielle Allen + @desc + Loops over all variables and outputs them if necessary + @enddesc + + @calls IOPanda_TimeFor + IOPanda_Timestep + + @var GH + @vdesc Pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + + @returntype int + @returndesc + the number of variables which were output at this iteration + (or 0 if it wasn't time to output yet) + @endreturndesc +@@*/ +int IOPanda_OutputGH (const cGH *GH) +{ + int vindex, retval; + pandaGH *myGH; + char *fullname; + const char *name; + DECLARE_CCTK_PARAMETERS + + + /* Get the GH extension for IOPanda */ + myGH = (pandaGH *) CCTK_GHExtension (GH, "IOPanda"); + + CheckSteerableParameters (myGH); + + if (myGH->out_every <= 0) + { + return (0); + } + + /* Loop over all variables */ + for (vindex = retval = 0; vindex < CCTK_NumVars (); vindex++) + { + if (IOPanda_TimeFor (GH, vindex)) + { + name = CCTK_VarName (vindex); + + if (verbose) + { + fullname = CCTK_FullName (vindex); + CCTK_VInfo (CCTK_THORNSTRING, "IOPanda_OutputGH: " + "(fullname, name) = (%s, %s)", fullname, name); + free (fullname); + } + + /* Do the output */ + if (IOPanda_Timestep (GH, vindex, name) == 0) + { + /* Register variable as having output this iteration */ + myGH->out_last [vindex] = GH->cctk_iteration; + retval++; + } + } + } + + return (retval); +} + + +/*@@ + @routine IOPanda_OutputVarAs + @date Sat March 6 1999 + @author Gabrielle Allen + @desc + Unconditional output of a variable using the IOPanda I/O method + @enddesc + + @calls IOPanda_Timestep + + @var GH + @vdesc Pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var fullname + @vdesc complete name of variable to output + @vtype const char * + @vio in + @endvar + @var alias + @vdesc alias name of variable to output + (used to generate output filename) + @vtype const char * + @vio in + @endvar + + @returntype int + @returndesc + return code of @seeroutine IOPanda_Timestep + @endreturndesc +@@*/ +int IOPanda_OutputVarAs (const cGH *GH, const char *fullname, const char *alias) +{ + int vindex, retval; + DECLARE_CCTK_PARAMETERS + + + vindex = CCTK_VarIndex (fullname); + if (verbose) + { + CCTK_VInfo (CCTK_THORNSTRING, "IOPanda_OutputVarAs: " + "(fullname, alias, index) = (%s, %s, %d)", + fullname, alias, vindex); + } + + /* Do the output */ + retval = IOPanda_Timestep (GH, vindex, alias); + + return (retval); +} + + +/*@@ + @routine IOPanda_TimeFor + @date Sat March 6 1999 + @author Gabrielle Allen + @desc + Decides if it is time to output a variable + using the IOPanda output method + @enddesc + + @calls CheckSteerableParameters + + @var GH + @vdesc Pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var vindex + @vdesc index of variable + @vtype int + @vio in + @endvar + + @returntype int + @returndesc + 1 if output should take place at this iteration, or<BR> + 0 if not + @endreturndesc +@@*/ +int IOPanda_TimeFor (const cGH *GH, int vindex) +{ + pandaGH *myGH; + char *fullname; + + + /* Get the GH extension for IOPanda */ + myGH = (pandaGH *) CCTK_GHExtension (GH, "IOPanda"); + + CheckSteerableParameters (myGH); + + /* Check if any output was requested */ + if (myGH->out_every <= 0) + { + return (0); + } + + /* Check this variable should be output */ + if (! (myGH->do_out[vindex] && GH->cctk_iteration % myGH->out_every == 0)) + { + return (0); + } + + /* Check variable not already output this iteration */ + if (myGH->out_last [vindex] == GH->cctk_iteration) + { + fullname = CCTK_FullName (vindex); + CCTK_VWarn (5, __LINE__, __FILE__, CCTK_THORNSTRING, + "Already done IOPanda output for variable '%s' in current " + "iteration (probably via triggers)", fullname); + free (fullname); + return (0); + } + + return (1); +} + + +/*@@ + @routine IOPanda_TriggerOutput + @date Sat March 6 1999 + @author Gabrielle Allen + @desc + Triggers the output a variable using the IOPanda output method + @enddesc + + @calls IOPanda_Timestep + + @var GH + @vdesc Pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var vindex + @vdesc index of variable to output + @vtype int + @vio in + @endvar + + @returntype int + @returndesc + return code of @seeroutine IOPanda_Timestep + @endreturndesc +@@*/ +int IOPanda_TriggerOutput (const cGH *GH, int vindex) +{ + int retval; + pandaGH *myGH; + const char *varname; + DECLARE_CCTK_PARAMETERS + + + varname = CCTK_VarName (vindex); + + /* Get the GH extension for IOPanda */ + myGH = (pandaGH *) CCTK_GHExtension (GH, "IOPanda"); + + if (verbose) + { + CCTK_VInfo (CCTK_THORNSTRING, "TriggerOutput: " + "name, index = %s, %d", varname, vindex); + } + + /* Do the output */ + retval = IOPanda_Timestep (GH, vindex, varname); + + if (retval == 0) + { + /* Register variable as having output this iteration */ + myGH->out_last [vindex] = GH->cctk_iteration; + } + + return (retval); +} + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +/*@@ + @routine CheckSteerableParameters + @date Mon Oct 10 2000 + @author Thomas Radke + @desc + Checks if IOPanda steerable parameters were changed + and does appropriate re-evaluation. + @enddesc + + @calls CCTK_TraverseString + + @var myGH + @vdesc Pointer to IOPanda GH + @vtype pandaGH * + @vio in + @endvar +@@*/ +static void CheckSteerableParameters (pandaGH *myGH) +{ + int times_set; + static int out_vars_lastset = -1; + DECLARE_CCTK_PARAMETERS + + + /* how often to output */ + myGH->out_every = out_every; + if (myGH->out_every < 0) + { + myGH->out_every = *(const CCTK_INT *) + CCTK_ParameterGet ("out_every", + CCTK_ImplementationThorn ("IO"), NULL); + } + + /* re-parse the 'out_vars' parameter if it was changed */ + times_set = CCTK_ParameterQueryTimesSet ("out_vars", CCTK_THORNSTRING); + if (times_set != out_vars_lastset) + { + memset (myGH->do_out, 0, CCTK_NumVars ()); + CCTK_TraverseString (out_vars, SetOutputFlag, myGH->do_out, + CCTK_GROUP_OR_VAR); + + /* Save the last setting of 'out_vars' parameter */ + out_vars_lastset = times_set; + } +} + + +/* check if this variable can be output (static conditions) */ +static int CheckOutputVar (int vindex) +{ + char *errormsg, *fullname; + + + errormsg = NULL; + +/*** FIXME: IEEEIO doesn't provide a COMPLEX datatype + so somehow CCTK_COMPLEX has to be mapped onto REALs or so. + We have to check this already here because if an IEEEIO file + is created and nothing is written to, it crashes at re-opening. ***/ + if (CCTK_VarTypeI (vindex) == CCTK_VARIABLE_COMPLEX) + { + errormsg = "IOPanda output for complex variable '%s' not yet supported"; + } + else if (CCTK_GroupTypeFromVarI (vindex) == CCTK_SCALAR) + { + errormsg = "IOPanda output for scalar variable '%s' not supported"; + } + + if (errormsg) + { + fullname = CCTK_FullName (vindex); + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + errormsg, fullname); + free (fullname); + } + + return (errormsg != NULL); +} + + +/* callback for CCTK_TraverseString() to set the output flag + for the given variable */ +static void SetOutputFlag (int vindex, const char *optstring, void *arg) +{ + char *flags = (char *) arg; + + + /* Check the variable type */ + flags[vindex] = CheckOutputVar (vindex) == 0; + + if (optstring) + { + CCTK_VWarn (5, __LINE__, __FILE__, CCTK_THORNSTRING, + "Optional string '%s' in variable name ignored", optstring); + } +} + + +static int IOPanda_Timestep (const cGH *GH, int vindex, const char *alias) +{ + void *data; + int tmp[1], tmp1[3], tmp2[3]; + Distribution dist1[3], dist2[3]; + CCTK_INT4 bnd[9]; + int free_flag, timelevel; + ArrayInfo ainfo; + ioGH *ioUtilGH; + pGH *pughGH; + char *fullname; + union + { + char *non_const_char; + const char *const_char; + } cast_to_const; + DECLARE_CCTK_PARAMETERS + + + /* check if variable has storage assigned */ + if (! CCTK_QueryGroupStorageI (GH, CCTK_GroupIndexFromVarI (vindex))) + { + fullname = CCTK_FullName (vindex); + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "No IOPanda output for '%s' (no storage)", fullname); + free (fullname); + return (-1); + } + + /* get the handles for PUGH and IOUtil GH extensions */ + pughGH = PUGH_pGH (GH); + ioUtilGH = (ioGH *) CCTK_GHExtension (GH, "IO"); + + /* prevent compiler warning "cast discards `const' from pointer target type"*/ + cast_to_const.const_char = alias; + ainfo.name_ = cast_to_const.non_const_char; + + ainfo.rank_ = 3; + tmp1[0] = GH->cctk_gsh[2]; + tmp1[1] = GH->cctk_gsh[1]; + tmp1[2] = GH->cctk_gsh[0]; + ainfo.size_ = tmp1; + + switch (CCTK_VarTypeI (vindex)) + { + case CCTK_VARIABLE_CHAR: + ainfo.esize_ = CHAR; + break; + + case CCTK_VARIABLE_INT: +#ifdef CCTK_INTEGER_PRECISION_8 + ainfo.esize_ = INT64; +#elif CCTK_INTEGER_PRECISION_4 + ainfo.esize_ = INT32; +#elif CCTK_INTEGER_PRECISION_2 + ainfo.esize_ = INT16; +#endif + break; + + case CCTK_VARIABLE_REAL: + if (ioUtilGH->out_single) + { + ainfo.esize_ = FLOAT32; + } + else + { +#ifdef CCTK_REAL_PRECISION_8 + ainfo.esize_ = FLOAT64; +#elif CCTK_REAL_PRECISION_4 + ainfo.esize_ = FLOAT32; +#endif + } + } + + /* FIXME: rank */ + ainfo.mem_rank_ = 3; + tmp2[0] = pughGH->Connectivity [2]->nprocs [2]; + tmp2[1] = pughGH->Connectivity [2]->nprocs [1]; + tmp2[2] = pughGH->Connectivity [2]->nprocs [0]; + ainfo.mem_layout_ = tmp2; + dist1[0] = dist1[1] = dist1[2] = BLOCK; + ainfo.mem_dist_ = dist1; + + ainfo.disk_rank_ = 1; + dist2[0] = BLOCK; dist2[1] = dist2[2] = NONE; + tmp[0]= ((CCTK_nProcs(GH) - 1) / ioUtilGH->ioproc_every + 1); + + ainfo.disk_layout_ = tmp; + ainfo.disk_dist_ = dist2; + + timelevel = 0; + + IOPanda_getDumpData(GH, vindex, timelevel, &data, &free_flag, bnd, ainfo.esize_); + ainfo.data_ = (char *)data; + + /*** FIXME: asymmetric ghostzones */ + ainfo.stencil_width_ = GH->cctk_nghostzones [0]; + + PandaTimestep(&ainfo); + if (free_flag) + { + free (data); + } + + IOPanda_AddCommonAttributes(GH, vindex, timelevel, ainfo.size_, ainfo.name_); + + if (! ioUtilGH->unchunked) + { + /* Write chunk attributes */ + IOPanda_AddChunkAttributes (GH, vindex, bnd, ainfo.name_); + } + + if (PandaIsNewFile(ainfo.name_)) + { + IOPanda_IEEEIOStructDump(GH, ainfo.name_); + } + + return (0); +} + + +static void IOPanda_AddCommonAttributes (const cGH *GH, + int vindex, + int timelevel, + int global_size[3], + char *fname) +{ + DECLARE_CCTK_PARAMETERS + CCTK_REAL d3_to_IO [6]; /* buffer for writing doubles to IEEEIO */ + CCTK_INT4 i_to_IO; /* buffer for writing an int to IEEEIO */ + CCTK_INT4 i3_to_IO[3]; /* buffer for writing ints to IEEEIO */ + CCTK_REAL dummy; + char *name, *gname; + ioGH *ioUtilGH; + + + /* Get the handle for IO extensions */ + ioUtilGH = (ioGH *) CCTK_GHExtension (GH, "IO"); + + name = CCTK_FullName (vindex); + Panda_WriteAttribute (fname, "name", BYTE, strlen (name) + 1, name); + free (name); + + gname = CCTK_GroupNameFromVarI (vindex); + Panda_WriteAttribute (fname, "groupname", BYTE, strlen (gname) + 1, gname); + free (gname); + + i_to_IO = CCTK_GroupTypeFromVarI (vindex); + Panda_WriteAttribute (fname, "grouptype", INT32, 1, &i_to_IO); + + i_to_IO = CCTK_NumTimeLevelsFromVarI (vindex); + Panda_WriteAttribute (fname, "ntimelevels", INT32, 1, &i_to_IO); + + i_to_IO = timelevel; + Panda_WriteAttribute (fname, "timelevel", INT32, 1, &i_to_IO); + + Panda_WriteAttribute (fname, "time", FLOAT64, 1,&GH->cctk_time); + + d3_to_IO [0] = CCTK_CoordRange (GH, &d3_to_IO [0], &dummy, -1, "x", "cart3d"); + d3_to_IO [1] = CCTK_CoordRange (GH, &d3_to_IO [1], &dummy, -1, "y", "cart3d"); + d3_to_IO [2] = CCTK_CoordRange (GH, &d3_to_IO [2], &dummy, -1, "z", "cart3d"); + Panda_WriteAttribute (fname, "origin", FLOAT64,3,d3_to_IO); + CCTK_CoordRange (GH, &d3_to_IO [0], &d3_to_IO [3], -1, "x", "cart3d"); + CCTK_CoordRange (GH, &d3_to_IO [1], &d3_to_IO [4], -1, "y", "cart3d"); + CCTK_CoordRange (GH, &d3_to_IO [2], &d3_to_IO [5], -1, "z", "cart3d"); + Panda_WriteAttribute (fname, "min_ext", FLOAT64, 3, d3_to_IO); + Panda_WriteAttribute (fname, "max_ext", FLOAT64, 3, d3_to_IO+3); + + /* FIXME: dimension */ + d3_to_IO [0] = GH->cctk_delta_space [0] * ioUtilGH->downsample[0]; + d3_to_IO [1] = GH->cctk_delta_space [1] * ioUtilGH->downsample[1]; + d3_to_IO [2] = GH->cctk_delta_space [2] * ioUtilGH->downsample[2]; + Panda_WriteAttribute (fname, "delta", FLOAT64, 3, d3_to_IO); + + if (ioUtilGH->downsample[0] > 1 || + ioUtilGH->downsample[1] > 1 || + ioUtilGH->downsample[2] > 1) + { + d3_to_IO [0] = GH->cctk_delta_space [0]; + d3_to_IO [1] = GH->cctk_delta_space [1]; + d3_to_IO [2] = GH->cctk_delta_space [2]; + Panda_WriteAttribute (fname, "evolution_delta", FLOAT64, 3, d3_to_IO); + } + + i3_to_IO[0] = global_size[0]; + i3_to_IO[1] = global_size[1]; + i3_to_IO[2] = global_size[2]; + Panda_WriteAttribute (fname, "global_size", INT32, 3, i3_to_IO); + + i_to_IO = CCTK_nProcs (GH); + Panda_WriteAttribute (fname, "nprocs", INT32, 1, &i_to_IO); + + i_to_IO = ioUtilGH->ioproc_every; + Panda_WriteAttribute (fname, "ioproc_every", INT32, 1, &i_to_IO); + + i_to_IO = ioUtilGH->unchunked; + Panda_WriteAttribute (fname, "unchunked", INT32, 1, &i_to_IO); + + i_to_IO = GH->cctk_iteration; + Panda_WriteAttribute (fname, "iteration", INT32, 1, &i_to_IO); +} + + +static void IOPanda_AddChunkAttributes (const cGH *GH, + int vindex, + CCTK_INT4 *geom, + char *fname) +{ + int dim; + char *name; + CCTK_INT4 i_to_IO; + + + /* there is nothing to do for a serial run */ + if (CCTK_nProcs (GH) == 1) + { + return; + } + + /* get the dimension of the variable */ + dim = CCTK_GroupDimI (CCTK_GroupIndexFromVarI (vindex)); + + Panda_WriteAttribute (fname, "chunk_origin", INT32, dim, &geom[0]); + Panda_WriteAttribute (fname, "subchunk_lb", INT32, dim, &geom[0]); + Panda_WriteAttribute (fname, "global_size", INT32, dim, &geom[2*dim]); + + i_to_IO = GH->cctk_iteration; + Panda_WriteAttribute (fname, "chunk_dataset", INT32, 1, &i_to_IO); + + name = CCTK_FullName (vindex); + Panda_WriteAttribute (fname, "name", CHAR, strlen (name)+1, name); + free (name); +} + + +static void IOPanda_IEEEIOStructDump (const cGH *GH, + const char *fname) +{ + DECLARE_CCTK_PARAMETERS + int len; + CCTK_INT4 i_temp; + CCTK_REAL d_temp; + ioGH *ioUtilGH; + char buffer[128]; + + + ioUtilGH = (ioGH *) CCTK_GHExtension (GH, "IO"); + + i_temp = GH->cctk_iteration; + Panda_WriteAttribute (fname, "GH$iteration", INT32, 1, &i_temp); + + i_temp = ioUtilGH->ioproc_every; + Panda_WriteAttribute (fname, "GH$ioproc_every", INT32, 1, &i_temp); + + i_temp = CCTK_nProcs (GH); + Panda_WriteAttribute (fname, "GH$nprocs", INT32, 1, &i_temp); + + d_temp = GH->cctk_time; + Panda_WriteAttribute (fname, "GH$time", FLOAT64, 1, &d_temp); + + /* 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); + Panda_WriteAttribute (fname, "parameter file", CHAR, + strlen (buffer) + 1, buffer); + } + if (CCTK_Equals (out_fileinfo, "creation date") || + CCTK_Equals (out_fileinfo, "all")) + { + buffer[0] = 0; + Util_CurrentDate (sizeof (buffer), buffer); + len = strlen (buffer) + 1; + buffer[len-1] = ' '; + Util_CurrentTime (sizeof (buffer) - len, buffer + len); + Panda_WriteAttribute (fname, "creation date", CHAR, + strlen (buffer) + 1, buffer); + } +} |