/*@@ @file Output.c @date Mon 21 September @author Gabrielle Allen @desc Functions to deal with scalar output of grid variables @enddesc @@*/ /* #define IOBASIC_DEBUG 1 */ #include #include #include #include "cctk.h" #include "cctk_Parameters.h" #include "util_String.h" #include "iobasicGH.h" static const char *rcsid = "$Header$"; CCTK_FILEVERSION(CactusBase_IOBasic_OutputScalar_c) /******************************************************************** ******************** Internal Routines ************************ ********************************************************************/ static void CheckSteerableParameters (iobasicGH *myGH); /*@@ @routine IOBasic_ScalarOutputGH @date Sat March 6 1999 @author Gabrielle Allen @desc Loops over all variables and outputs them if necessary @enddesc @calls IOBasic_TimeForScalarOutput IOBasic_WriteScalar @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 IOBasic_ScalarOutputGH (const cGH *GH) { int vindex, retval; const char *name; iobasicGH *myGH; /* Get the GH extensions for IOBasic */ myGH = (iobasicGH *) CCTK_GHExtension (GH, "IOBasic"); CheckSteerableParameters (myGH); /* Return if no output is required */ if (myGH->outScalar_every <= 0) { return (0); } /* Loop over all variables */ for (vindex = retval = 0; vindex < CCTK_NumVars (); vindex++) { /* Is it time for output ? */ if (! IOBasic_TimeForScalarOutput (GH, vindex)) { continue; } /* Get the variable name for this index (for filename) */ name = CCTK_VarName (vindex); #ifdef IOBASIC_DEBUG printf("\nIn IOBasic_ScalarOutputGH\n----------------\n"); printf(" Index = %d\n",vindex); printf(" Variable = -%s-\n",name); printf(" Last output iteration was = %d\n",myGH->outScalar_last[vindex]); #endif /* Make the IO call */ if (IOBasic_WriteScalar (GH, vindex, name) == 0) { /* Register GF as having 0D output this iteration */ myGH->outScalar_last [vindex] = GH->cctk_iteration; retval++; } } /* end of loop over all variables */ return (retval); } /*@@ @routine IOBasic_TimeForScalarOutput @date Sat March 6 1999 @author Gabrielle Allen @desc Decides if it is time to do Scalar output. @enddesc @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
0 if not @endreturndesc @@*/ int IOBasic_TimeForScalarOutput (const cGH *GH, int vindex) { int retval; char *fullname; iobasicGH *myGH; /* Get the GH extension for IOBasic */ myGH = (iobasicGH *) CCTK_GHExtension (GH, "IOBasic"); CheckSteerableParameters (myGH); /* check if any output was requested */ if (myGH->outScalar_every <= 0 || GH->cctk_iteration % myGH->outScalar_every || myGH->scalar_reductions[vindex].num_reductions == 0) { retval = 0; } else { /* Check if variable wasn't already output this iteration */ retval = myGH->outScalar_last [vindex] != GH->cctk_iteration; if (! retval) { fullname = CCTK_FullName (vindex); CCTK_VWarn (5, __LINE__, __FILE__, CCTK_THORNSTRING, "Already done scalar output for '%s' in current iteration " "(probably via triggers)", fullname); free (fullname); } } return (retval); } /*@@ @routine IOBasic_TriggerScalarOutput @date Sat March 6 1999 @author Gabrielle Allen @desc Triggers the output of a variable using IOBasic's Scalar output method @enddesc @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 IOBasic_WriteScalar @endreturndesc @@*/ int IOBasic_TriggerScalarOutput (const cGH *GH, int vindex) { int retval; const char *name; iobasicGH *myGH; /* Get the GH extension for IOBasic */ myGH = (iobasicGH *) CCTK_GHExtension (GH, "IOBasic"); name = CCTK_VarName (vindex); #ifdef IOBASIC_DEBUG printf ("\nIn IOBasic_TriggerScalarOutput\n---------------------\n"); printf (" Index = %d\n", vindex); printf (" Variable = -%s-\n", name); #endif /* Do the Scalar output */ retval = IOBasic_WriteScalar (GH, vindex, name); if (retval == 0) { /* Register variable as having Scalar output this iteration */ myGH->outScalar_last [vindex] = GH->cctk_iteration; } return (retval); } /******************************************************************** ******************** Internal Routines ************************ ********************************************************************/ /*@@ @routine CheckSteerableParameters @date Tue 31 Jul 2001 @author Thomas Radke @desc Re-evaluates 'IOBasic::outScalar_every' and/or 'IO::out_every' resp. to set myGH->outScalar_every to the frequency of scalar output. Re-evaluates 'IOBasic::outScalar_vars' and 'IOBasic::outScalar_reductions'. @enddesc @calls CCTK_ParameterQueryTimesSet @var myGH @vdesc Pointer to IOBasic's GH extension @vtype iobasicGH * @vio in @endvar @@*/ static void CheckSteerableParameters (iobasicGH *myGH) { int vindex, out_old, times_set, update_reductions_list, num_vars; iobasic_reduction_t *reduction, *next; static int outScalar_vars_lastset = -1; static int outScalar_reductions_lastset = -1; iobasic_parseinfo_t info; char *msg, *oldmsg, *fullname; DECLARE_CCTK_PARAMETERS /* how often to output */ out_old = myGH->outScalar_every; myGH->outScalar_every = outScalar_every >= 0 ? outScalar_every : out_every; /* report if frequency changed */ if (myGH->outScalar_every != out_old && ! CCTK_Equals (newverbose, "none")) { if (myGH->outScalar_every > 0) { CCTK_VInfo (CCTK_THORNSTRING, "Scalar: Periodic output every %d " "iterations", myGH->outScalar_every); } else { CCTK_INFO ("Scalar: Periodic output turned off"); } } /* return if there's nothing to do */ if (myGH->outScalar_every <= 0) { return; } /* check if the 'outScalar_reductions' parameter if it was changed */ times_set = CCTK_ParameterQueryTimesSet ("outScalar_reductions", CCTK_THORNSTRING); update_reductions_list = times_set != outScalar_reductions_lastset; outScalar_reductions_lastset = times_set; /* check if the 'outScalar_vars' parameter if it was changed */ times_set = CCTK_ParameterQueryTimesSet ("outScalar_vars", CCTK_THORNSTRING); update_reductions_list |= times_set != outScalar_vars_lastset; outScalar_vars_lastset = times_set; if (update_reductions_list) { /* free old reduction lists ... */ num_vars = CCTK_NumVars (); for (vindex = 0; vindex < num_vars; vindex++) { if (myGH->scalar_reductions[vindex].num_reductions > 0) { myGH->scalar_reductions[vindex].num_reductions = 0; reduction = myGH->scalar_reductions[vindex].reductions; while (reduction) { next = reduction->next; free (reduction->name); free (reduction); reduction = next; } } } /* ... and create new ones */ info.reduction_list = myGH->scalar_reductions; info.reductions_string = outScalar_reductions; if (CCTK_TraverseString (outScalar_vars, IOBasic_AssignReductionList, &info, CCTK_GROUP_OR_VAR) < 0) { CCTK_WARN (1, "Failed to parse 'IOBasic::outScalar_vars' parameter"); } else if (! CCTK_Equals (newverbose, "none")) { msg = NULL; for (vindex = 0; vindex < num_vars; vindex++) { if (myGH->scalar_reductions[vindex].num_reductions) { fullname = CCTK_FullName (vindex); if (! msg) { Util_asprintf (&msg, "Scalar: Periodic output requested for '%s'", fullname); } else { oldmsg = msg; Util_asprintf (&msg, "%s, '%s'", oldmsg, fullname); free (oldmsg); } free (fullname); } } if (msg) { CCTK_INFO (msg); free (msg); } } } }