/*@@ @routine WriteGF @date Tue Apr 1 16:45:35 1997 @author Paul Walker @desc Dumps the "0D" data. @enddesc @calls @calledby @history @hauthor Thomas Radke @hdate 17 Mar 1999 @hdesc included "cctk_Comm.h" to overload CCTK_GetMyProc() properly @hendhistory @@*/ #include #include #include "cctk.h" #include "cctk_parameters.h" #include "iobasicGH.h" void IOBasic_WriteGF (cGH *GH, int index, const char *alias) { DECLARE_CCTK_PARAMETERS int i; iobasicGH *myGH; FILE *file; char *openmode; char *filename; char title_start_char; int reduction_handle; 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) */ const struct { char *operator; char *label; char *extension; } reductions [] = { {"minimum", "min", "min"}, {"maximum", "max", "max"}, {"norm1", "norm1", "nm1"}, {"norm2", "norm2", "nm2"}, }; #define NUM_REDUCTIONS (sizeof (reductions) / sizeof (reductions [0])) /* first, check if variable has storage assigned */ if (! CCTK_QueryGroupStorageI (GH, CCTK_GroupIndexFromVarI (index))) { char *msg, *fullname; fullname = CCTK_FullName (index); msg = (char *) malloc (200 * sizeof (char) + strlen (fullname)); sprintf (msg, "No 0D output for '%s' (no storage)", fullname); CCTK_WARN (2, msg); free (fullname); free (msg); return; } if (CCTK_Equals (outScalar_style, "gnuplot")) title_start_char = '#'; else title_start_char = 34; /* this is for xgraph */ myGH = (iobasicGH *) GH->extensions [CCTK_GHExtensionHandle ("IOBasic")]; /* the extra characters should be sufficient for the longest filename extension */ filename = (char *) malloc (strlen (myGH->outdirScalar) + strlen (alias) + 20); /* now loop over all IOBasic reduction operations */ for (i = 0; i < NUM_REDUCTIONS; i++) { /* get the reduction handle from the reduction operator */ reduction_handle = CCTK_ReductionHandle (reductions [i].operator); if (reduction_handle < 0) { char *msg = (char *) malloc (100 + strlen (reductions [i].operator)); sprintf (msg, "Invalid reduction operator '%s'", reductions [i].operator); CCTK_WARN (3, msg); free (msg); continue; } /* do the reduction (all processors) */ CCTK_Reduce (GH, 0, reduction_handle, 1, CCTK_VARIABLE_REAL, &reduction_value, 1, index); /* dump the reduction value to file by processor 0 */ if (CCTK_MyProc (GH) == 0) { /* build the filename */ sprintf (filename, "%s/%s_%s.tl", myGH->outdirScalar, alias, reductions [i].extension); /* see if output files for this alias name were already created */ if (GetNamedData (myGH->filenameListScalar, filename) == NULL) openmode = "w"; else openmode = "a"; file = fopen (filename, openmode); if (file == NULL) { char *msg = (char *) malloc (100 + strlen (filename)); sprintf (msg, "Could not open output file '%s'", filename); CCTK_WARN (3, msg); free (msg); continue; } /* when creating the file, write the header and also save the filename in the database */ if (*openmode == 'w') { fprintf (file, "%c%s %s v time\n", title_start_char, alias, reductions [i].label); /* just store a non-NULL pointer in database */ StoreNamedData (&myGH->filenameListScalar, filename, (void *) 1); } /* write the data and close the file */ fprintf (file, "%f %25.13f\n", GH->cctk_time, reduction_value); fclose (file); } } free (filename); USE_CCTK_PARAMETERS }