/*@@ @routine WriteGF @date Tue Apr 1 16:45:35 1997 @author Paul Walker @desc Dumps the scalar data of CCTK_ARRAY and CCTK_GF variables. @enddesc @version $Id$ @@*/ #include #include #include /* strlen(3) */ #include /* isalpha(3) */ #include #include /* stat(2) */ #include "cctk.h" #include "cctk_Parameters.h" #include "CactusBase/IOUtil/src/ioutil_AdvertisedFiles.h" #include "CactusBase/IOUtil/src/ioutil_CheckpointRecovery.h" #include "iobasicGH.h" /* the rcs ID and its dummy function to use it */ static char *rcsid = "$Id$"; CCTK_FILEVERSION(CactusBase_IOBasic_WriteGF_c) /*@@ @routine IOBasic_WriteGF @date Mon Jun 19 2000 @author Thomas Radke @desc Apply the given reduction operators on the CCTK_ARRAY or CCTK_GF variable and output the result into a text file suitable for postprocessing by either gluplot or xgraph. @enddesc @calls CCTK_QueryGroupStorageI CCTK_Reduce CCTK_ReductionHandle IOUtil_RestartFromRecovery IOUtil_AdvertiseFile @var GH @vdesc Pointer to CCTK grid hierarchy @vtype cGH * @vio in @endvar @var vindex @vdesc CCTK index of the variable to output @vtype int @vio in @endvar @var alias @vdesc alias name to use for building the output filename @vtype const char * @vio in @endvar @@*/ void IOBasic_WriteGF (cGH *GH, int vindex, const char *alias) { DECLARE_CCTK_PARAMETERS int ierr; int reduction_handle; iobasicGH *myGH; FILE *file; char *openmode; char *filename; char *reduction_op; char *string_start; char *string_end; char comment_char; char format_str[15]; const char *file_extension; char *fullname, buffer[128]; struct stat fileinfo; ioAdvertisedFileDesc advertised_file; CCTK_REAL reduction_value; /* add more reductions to this table if you want, telling it - the reduction operator - the label for the file header - the filename extension (suffixed by ".tl" for trace line) */ /* first, check if variable has storage assigned */ if (! CCTK_QueryGroupStorageI (GH, CCTK_GroupIndexFromVarI (vindex))) { fullname = CCTK_FullName (vindex); CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, "IOBasic_WriteGF: No scalar output for '%s' (no storage)", fullname); free (fullname); return; } /* set output format */ sprintf (format_str, "%%%s\t%%%s\n", out_format, out_format); /* set the output file extension and the output style */ if (CCTK_Equals (outScalar_style, "gnuplot")) { file_extension = ".asc"; comment_char = '#'; } else { file_extension = ".xg"; comment_char = '"'; } /* get the GH extension handle for IOBasic */ myGH = (iobasicGH *) CCTK_GHExtension (GH, "IOBasic"); /* allocate strings for the filename and the reduction operator */ filename = (char *) malloc (strlen (myGH->outdirScalar) + strlen (alias) + strlen (outScalar_reductions) + strlen (file_extension) + 3); reduction_op = (char *) malloc (strlen (outScalar_reductions) + 1); /* now loop over all reduction operators */ string_start = outScalar_reductions; while (string_start && *string_start) { /* skip leading spaces */ while (isspace (*string_start)) { string_start++; } if (! *string_start) { break; } /* advance to end of the operator string */ string_end = string_start + 1; while (*string_end && ! isspace (*string_end)) { string_end++; } /* copy the operator string */ strncpy (reduction_op, string_start, string_end - string_start); reduction_op[string_end - string_start] = 0; string_start = string_end; /* get the reduction handle from the reduction operator */ reduction_handle = CCTK_ReductionHandle (reduction_op); if (reduction_handle < 0) { CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, "IOBasic_WriteGF: Invalid reduction operator '%s'", reduction_op); continue; } /* do the reduction (all processors) */ ierr = CCTK_Reduce (GH, 0, reduction_handle, 1, CCTK_VARIABLE_REAL, &reduction_value, 1, vindex); /* dump the reduction value to file by processor 0 */ if (ierr == 0 && CCTK_MyProc (GH) == 0) { /* build the filename */ if (new_filename_scheme) { sprintf (filename, "%s/%s_%s%s", myGH->outdirScalar, alias, reduction_op, file_extension); } else { /* FIXME: this check can go if we switch to the new filename scheme */ if (strcmp (reduction_op, "minimum") == 0) { file_extension = "min"; } else if (strcmp (reduction_op, "maximum") == 0) { file_extension = "max"; } else if (strcmp (reduction_op, "norm1") == 0) { file_extension = "nm1"; } else if (strcmp (reduction_op, "norm2") == 0) { file_extension = "nm2"; } else { file_extension = "unknown"; } sprintf (filename, "%s/%s_%s.tl", myGH->outdirScalar, alias, file_extension); } /* see if output files for this alias name were already created */ if (GetNamedData (myGH->filenameListScalar, filename) == NULL) { /* if restart from recovery, all existing files are opened in append mode */ if (IOUtil_RestartFromRecovery (GH)) { openmode = stat (filename, &fileinfo) == 0 ? "a" : "w"; } else { openmode = "w"; } } else { openmode = "a"; } file = fopen (filename, openmode); if (file == NULL) { CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, "IOBasic_WriteGF: Could not open output file '%s'", filename); continue; } /* when creating the file, advertise it for downloading, write the header and the file info, and save the filename in the database */ if (*openmode == 'w') { /* advertise the file for downloading */ advertised_file.slice = reduction_op; advertised_file.thorn = CCTK_THORNSTRING; advertised_file.varname = CCTK_FullName (vindex); advertised_file.description = "Reduction on Grid Functions"; advertised_file.mimetype = CCTK_Equals (outScalar_style, "gnuplot") ? "application/gnuplot" : "application/x-graph"; IOUtil_AdvertiseFile (GH, filename, &advertised_file); CCTK_ParameterFilename (sizeof (buffer), buffer); fprintf (file, "%cParameter file %s\n", comment_char, buffer); Util_CurrentDate (sizeof (buffer), buffer); fprintf (file, "%cCreated %s ", comment_char, buffer); Util_CurrentTime (sizeof (buffer), buffer); fprintf (file, "%s\n", buffer); fprintf (file, "%cx-label time\n", comment_char); fprintf (file, "%cy-label %s\n", comment_char, advertised_file.varname); fprintf (file, "%c%s %s v time\n", comment_char, alias, reduction_op); free (advertised_file.varname); /* just store a non-NULL pointer in database */ StoreNamedData (&myGH->filenameListScalar, filename, (void *) 1); } /* write the data and close the file */ fprintf (file, format_str, GH->cctk_time, reduction_value); fclose (file); } } /* free allocated resources */ free (reduction_op); free (filename); }