/*@@ @file Write.c @date Fri Feb 21 15:27:03 1997 @author John Shalf, Gabrielle Allen, Tom Goodale, Thomas Radke @desc File handling routines for IOFlexIO. @enddesc @version $Id$ @@*/ #include #include #include #include "cctk.h" #include "cctk_Parameters.h" #include "CactusBase/IOUtil/src/ioGH.h" #include "CactusBase/IOUtil/src/ioutil_Utils.h" #include "ioFlexGH.h" /* the rcs ID and its dummy funtion to use it */ static const char *rcsid = "$Header$"; CCTK_FILEVERSION(CactusPUGHIO_IOFlexIO_Write_c) /******************************************************************** ******************** Internal Routines ************************ ********************************************************************/ static IEEEfile_t *OpenFile (const cGH *GH, int vindex, const char *alias, int *is_new_file); /*@@ @routine IOFlexIO_Write @author Paul Walker @date Feb 1997 @desc Opens the IOFlexIO output file, calls the dump routine, and closes it again. @enddesc @calls OpenFile IOFlexIO_DumpVar @var GH @vdesc Pointer to CCTK GH @vtype const cGH * @vio in @endvar @var vindex @vdesc index of variable @vtype int @vio in @endvar @var alias @vdesc alias name of variable to output @vtype const char * @vio in @endvar @returntype int @returndesc return code of @seeroutine IOFlexIO_DumpVar, or
-1 if no storage was assigned to variable
-2 if file couldn't be opened @endreturndesc @@*/ int IOFlexIO_Write (const cGH *GH, int vindex, const char *alias) { const flexioGH *myGH; const ioGH *ioUtilGH; int myproc, len, is_new_file, retval; char buffer[128]; char *fullname; IEEEfile_t *file; 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 IOFlexIO output for '%s' (no storage)", fullname); free (fullname); return (-1); } if (CCTK_Equals (verbose, "full")) { CCTK_VInfo (CCTK_THORNSTRING, "IOFlexIO output of variable '%s', " "alias '%s'", CCTK_VarName (vindex), alias); } myGH = CCTK_GHExtension (GH, "IOFlexIO"); ioUtilGH = CCTK_GHExtension (GH, "IO"); /* get the filename and descriptor for output */ file = OpenFile (GH, vindex, alias, &is_new_file); /* nothing to do for an already opened file which is kept open all the time */ myproc = CCTK_MyProc (GH); if (myproc == ioUtilGH->ioproc && (CCTK_GroupTypeFromVarI (vindex) != CCTK_SCALAR || myproc == 0)) { if (is_new_file || reuse_filehandles) { if (CCTK_Equals (verbose, "full")) { CCTK_VInfo (CCTK_THORNSTRING, "%s IEEEIO output file '%s'", is_new_file ? "Opening" : "Resuming", file->filename); } /* first time through or one file per slice: open anew */ if (is_new_file) { file->iofile = IEEEopen (file->filename, "w"); if (! IOisValid (file->iofile)) { CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, "Couldn't " "create IEEEIO output file '%s'", file->filename); } /* 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); FLEXIO_ERROR (IOwriteAttribute (file->iofile, "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); FLEXIO_ERROR (IOwriteAttribute (file->iofile, "creation date", CHAR, strlen (buffer) + 1, buffer)); } } else { /* resume the file (reopen descriptor) This allows descriptor reuse without requiring expensive destruction and reallocation of the associated datastructures */ FLEXIO_ERROR (IOresume (file->iofile)); } /* turn on buffer cache (with default size chosen by IEEEIO lib) */ if (file->iofile) { IEEEbufferOn (file->iofile, 0); } } if (! file->iofile) { CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, "Invalid file descriptor for IEEEIO ouput file '%s'", file->filename); return (-2); } } else { file->iofile = (IOFile) 0; } /* output the data */ retval = IOFlexIO_DumpVar (GH, myGH->requests[vindex], file->iofile); /* output the GH extensions and parameters */ if (file->iofile) { /* output parameters necessary for filereader datafiles */ if (is_new_file) { IOFlexIOi_DumpGHExtensions (GH, file->iofile); if (! CCTK_Equals (out_save_parameters, "no")) { IOFlexIOi_DumpParameters (GH, CCTK_Equals (out_save_parameters, "all"), file->iofile); } } /* close the file */ if (out_timesteps_per_file > 0 || reuse_filehandles) { if (CCTK_Equals (verbose, "full")) { CCTK_VInfo (CCTK_THORNSTRING, "%s IEEEIO output file '%s'", out_timesteps_per_file > 0 ? "Closing" : "Pausing", file->filename); } IEEEbufferOff (file->iofile); if (out_timesteps_per_file > 0) { FLEXIO_ERROR (IOclose (file->iofile)); } else { FLEXIO_ERROR (IOpause (file->iofile)); } } } if (out_timesteps_per_file > 0) { free (file->filename); free (file); } return (retval); } /******************************************************************** ******************** Internal Routines ************************ ********************************************************************/ /* generate the filename for the given alias and creates/opens the file */ static IEEEfile_t *OpenFile (const cGH *GH, int vindex, const char *alias, int *is_new_file) { const ioGH *ioUtilGH; flexioGH *myGH; int myproc, nprocs, vdim, result; char extra[256], extradir[256]; char *outputdir, *tmp; IEEEfile_t *file; DECLARE_CCTK_PARAMETERS /* get the GH extensions for IOUtil, and IOFlexIO */ ioUtilGH = CCTK_GHExtension (GH, "IO"); myGH = CCTK_GHExtension (GH, "IOFlexIO"); file = GetNamedData (myGH->fileList, alias); if (file != NULL) { /* set flag to indicate that file should be opened in append mode */ *is_new_file = 0; return (file); } extra[0] = extradir[0] = '\0'; nprocs = CCTK_nProcs (GH); myproc = CCTK_MyProc (GH); vdim = CCTK_GroupDimFromVarI (vindex); if (out_timesteps_per_file > 0) { tmp = extra; sprintf (extra, ".time_%7.3f", GH->cctk_time); /* be sure to replace any spaces in the filename with an _ */ do { if (*tmp == ' ') { *tmp = '_'; } } while (*++tmp); } /* * OUTPUT ONE FILE FOR EACH N PROCESSORS * ------------------------------------- * * If only one output file, the single file for each GV is written * in the default output directory (ie. extradir = ""). Otherwise * a directory is created for each output GV to hold the multiple files. */ if (ioUtilGH->ioproc_every < nprocs && CCTK_GroupTypeFromVarI (vindex) != CCTK_SCALAR) { /* add the output processor number to the extra string */ sprintf (extra, "%s.file_%d", extra, myproc / ioUtilGH->ioproc_every); /* if necessary create the output directory */ outputdir = malloc (strlen (myGH->out_dir) + strlen (alias) + 5); sprintf (outputdir, "%s/%s_%dd", myGH->out_dir, alias, vdim); result = IOUtil_CreateDirectory (GH, outputdir, ! CCTK_Equals (out_mode, "onefile"), ioUtilGH->ioproc); if (result < 0) { CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, "Problem creating IOFlexIO output directory '%s'", outputdir); } else if (result > 0 && CCTK_Equals (verbose, "full")) { CCTK_VInfo (CCTK_THORNSTRING, "IOFlexIO output directory '%s' already exists", outputdir); } free (outputdir); #ifdef CCTK_MPI /* wait for all processors to catch up */ CCTK_Barrier (GH); #endif /* extradir is the relative output directory */ sprintf (extradir, "%s_%dd/", alias, vdim); } /* CREATE THE COMPLETE OUTPUT FILENAME ----------------------------------- */ file = malloc (sizeof (IEEEfile_t)); file->filename = malloc (strlen (myGH->out_dir) + strlen (extradir) + strlen (alias) + strlen (extra) + strlen (GH->identity) + 10); sprintf (file->filename, "%s/%s%s%s%s.ieee", myGH->out_dir, extradir, alias, extra, GH->identity); /* no need to store file info if used only once */ *is_new_file = 1; if (out_timesteps_per_file < 0) { if (myproc == ioUtilGH->ioproc) { if (! IO_TruncateOutputFiles (GH)) { file->iofile = IEEEopen (file->filename, "a"); *is_new_file = ! IOisValid (file->iofile); } } StoreNamedData (&myGH->fileList, alias, file); } return (file); }