/*@@ @file Startup.c @date Fri May 21 1999 @author Thomas Radke @desc Startup routines for IOFlexIO. @enddesc @version $Id$ @@*/ #include #include #include #include "cctk.h" #include "cctk_Parameters.h" #include "CactusPUGH/PUGH/src/include/pugh.h" #include "CactusBase/IOUtil/src/ioGH.h" #include "CactusBase/IOUtil/src/ioutil_Utils.h" #include "CactusBase/IOUtil/src/ioutil_CheckpointRecovery.h" #include "ioFlexGH.h" /* the rcs ID and its dummy function to use it */ static const char *rcsid = "$Header$"; CCTK_FILEVERSION(CactusPUGHIO_IOFlexIO_Startup_c) /******************************************************************** ******************** External Routines ************************ ********************************************************************/ void IOFlexIO_Startup (void); int IOFlexIO_TerminateGH (const cGH *GH); /******************************************************************** ******************** Internal Routines ************************ ********************************************************************/ static void *SetupGH (tFleshConfig *config, int conv_level, cGH *GH); /*@@ @routine IOFlexIO_Startup @date Fri May 21 1999 @author Thomas Radke @desc The startup registration routine for IOFlexIO. Registers the GH extensions needed for IOFlexIO along with its setup routine. @enddesc @calls CCTK_RegisterGHExtension CCTK_RegisterGHExtensionSetupGH @@*/ void IOFlexIO_Startup (void) { /* check that PUGH was activated */ if (CCTK_GHExtensionHandle ("PUGH") >= 0) { CCTK_RegisterGHExtensionSetupGH (CCTK_RegisterGHExtension ("IOFlexIO"), SetupGH); } else { CCTK_WARN (1, "Thorn PUGH was not activated. " "No IOFlexIO IO methods will be enabled."); } } /*@@ @routine IOFlexIO_TerminateGH @date Tue May 09 2000 @author Thomas Radke @desc The termination routine for IOFlexIO. All open files (stored in the file lists) are closed, and the file lists are freed. Also any created timers are destroyed. @enddesc @calls CCTK_UnregisterGHExtension @var GH @vdesc pointer to grid hierarchy @vtype const cGH * @vio in @endvar @returntype int @returndesc 0 for success @endreturndesc @@*/ int IOFlexIO_TerminateGH (const cGH *GH) { int i; flexioGH *myGH; pNamedData *current; IOFile *IEEEfiles_2D; IEEEfile_t *IEEEfile; DECLARE_CCTK_PARAMETERS /* get the handle for IOFlexIO extensions */ myGH = CCTK_GHExtension (GH, "IOFlexIO"); /* immediately return if IOFlexIO wasn't active */ if (! myGH) { return (0); } /* close any open files by walking through the file lists */ current = myGH->fileList_2D; while (current) { IEEEfiles_2D = (IOFile *) current->data; if (CCTK_Equals (verbose, "full")) { CCTK_VInfo (CCTK_THORNSTRING, "Closing 2D IEEEIO output files " "for variable alias '%s'", current->name); } FLEXIO_ERROR (IOclose (IEEEfiles_2D [0])); FLEXIO_ERROR (IOclose (IEEEfiles_2D [1])); FLEXIO_ERROR (IOclose (IEEEfiles_2D [2])); free (IEEEfiles_2D); current = current->next; } current = myGH->fileList; while (current) { IEEEfile = (IEEEfile_t *) current->data; if (IEEEfile->iofile) { if (CCTK_Equals (verbose, "full")) { CCTK_VInfo (CCTK_THORNSTRING, "Closing IEEEIO output file '%s'", IEEEfile->filename); } IOclose (IEEEfile->iofile); } free (IEEEfile->filename); free (IEEEfile); current = current->next; } /* free the file lists */ DestroyNamedDataList (myGH->fileList_2D); DestroyNamedDataList (myGH->fileList); if (myGH->print_timing_info) { for (i = 0; i < 4; i++) { CCTK_TimerDestroyI (myGH->timers[i]); } } /* finally unregister and free IOFlexIO's GH extension structure */ CCTK_UnregisterGHExtension ("IOFlexIO"); free (myGH); return (0); } /******************************************************************** ******************** Internal Routines ************************ ********************************************************************/ /*@@ @routine SetupGH @date Tue May 09 2000 @author Thomas Radke @desc Allocates and sets up the IOFlexIO GH extension structure. @enddesc @calls CCTK_RegisterIOMethod CCTK_RegisterIOMethodOutputGH CCTK_RegisterIOMethodOutputVarAs CCTK_RegisterIOMethodTimeToOutput CCTK_RegisterIOMethodTriggerOutput IOUtil_CreateDirectory @var config @vdesc flesh configuration structure (unused) @vtype tFleshConfig * @vio in @endvar @var conv_level @vdesc convergence level (unused) @vtype int @vio in @endvar @var GH @vdesc pointer to grid hierarchy @vtype cGH * @vio in @endvar @returntype void * @returndesc pointer to the allocated GH extension structure @endreturndesc @@*/ static void *SetupGH (tFleshConfig *config, int conv_level, cGH *GH) { int i, maxdim, numvars; flexioGH *myGH; const ioGH *ioUtilGH; const char *timer_names[4] = {"IOFlexIO time to dump parameters", "IOFlexIO time to dump datasets", "IOFlexIO total time to checkpoint", "IOFlexIO time to recover"}; DECLARE_CCTK_PARAMETERS /* suppress compiler warnings about unused parameters */ (void) (config + 0); (void) (conv_level + 0); /* register the IOFlexIO routines as I/O methods */ /* the 2D I/O method will only be registered if there are any 2D (or higher dimensional) grid variables defined by thorns */ maxdim = CCTK_MaxDim (); if (maxdim >= 2) { i = CCTK_RegisterIOMethod ("IOFlexIO_2D"); CCTK_RegisterIOMethodOutputGH (i, IOFlexIO_Output2DGH); CCTK_RegisterIOMethodOutputVarAs (i, IOFlexIO_Output2DVarAs); CCTK_RegisterIOMethodTimeToOutput (i, IOFlexIO_TimeFor2D); CCTK_RegisterIOMethodTriggerOutput (i, IOFlexIO_TriggerOutput2D); } i = CCTK_RegisterIOMethod ("IOFlexIO"); CCTK_RegisterIOMethodOutputGH (i, IOFlexIO_OutputGH); CCTK_RegisterIOMethodOutputVarAs (i, IOFlexIO_OutputVarAs); CCTK_RegisterIOMethodTimeToOutput (i, IOFlexIO_TimeFor); CCTK_RegisterIOMethodTriggerOutput (i, IOFlexIO_TriggerOutput); /* register the IOFlexIO recovery routine to thorn IOUtil */ if (IOUtil_RegisterRecover ("IOFlexIO recovery", IOFlexIO_Recover) < 0) { CCTK_WARN (1, "Failed to register IOFlexIO recovery routine"); } /* allocate a new GH extension structure */ numvars = CCTK_NumVars (); myGH = malloc (sizeof (flexioGH)); myGH->requests = calloc (numvars, sizeof (ioRequest *)); myGH->out2D_every = malloc (numvars * sizeof (CCTK_INT)); myGH->out_last = malloc (numvars * sizeof (int)); myGH->out2D_last = malloc (numvars * sizeof (int)); myGH->cp_fileindex = 0; myGH->checkpoint_keep = abs (checkpoint_keep); myGH->cp_filenames = calloc (myGH->checkpoint_keep, sizeof (char *)); myGH->out_vars = strdup (""); myGH->out_every_default = out_every - 1; myGH->out2D_vars = strdup (""); myGH->out2D_every_default = out2D_every - 1; myGH->last_checkpoint_iteration = -1; for (i = 0; i < numvars; i++) { myGH->out2D_last[i] = myGH->out_last[i] = -1; } myGH->fileList_2D = myGH->fileList = NULL; myGH->stop_on_parse_errors = strict_io_parameter_check; if (! CCTK_Equals (verbose, "none")) { CCTK_INFO ("I/O Method 'IOFlexIO' registered: output of grid variables and " "hyperslabs thereof to IEEEIO files"); } IOFlexIO_CheckSteerableParameters (GH, myGH); if (! CCTK_Equals (verbose, "none")) { CCTK_INFO ("I/O Method 'IOFlexIO_2D' registered: 2D output of grid " "functions/arrays to IEEEIO files"); } IOFlexIO_CheckSteerableParameters2D (myGH); myGH->stop_on_parse_errors = 0; /* get the names of output directories */ myGH->out2D_dir = strdup (*out2D_dir ? out2D_dir : io_out_dir); myGH->out_dir = strdup (*out_dir ? out_dir : io_out_dir); /* create the output directories */ ioUtilGH = CCTK_GHExtension (GH, "IO"); if (maxdim >= 2) { i = IOUtil_CreateDirectory (GH, myGH->out2D_dir, ! CCTK_Equals (out_mode, "onefile"), ioUtilGH->ioproc); if (i < 0) { CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, "IOFlexIO_InitGH: problem creating IOFlexIO 2D output" " directory '%s'", myGH->out2D_dir); } else if (i > 0 && CCTK_Equals (verbose, "full")) { CCTK_VInfo (CCTK_THORNSTRING, "IOFlexIO_InitGH: 2D IOFlexIO output directory '%s' " "already exists", myGH->out2D_dir); } } i = IOUtil_CreateDirectory (GH, myGH->out_dir, ! CCTK_Equals (out_mode, "onefile"), ioUtilGH->ioproc); if (i < 0) { CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, "IOFlexIO_InitGH: Problem creating IOFlexIO output" " directory '%s'", myGH->out_dir); } else if (i > 0 && CCTK_Equals (verbose, "full")) { CCTK_VInfo (CCTK_THORNSTRING, "IOFlexIO_InitGH: IOFlexIO output directory '%s' " "already exists", myGH->out_dir); } /* create timers if timing info was requested */ myGH->print_timing_info = print_timing_info; if (myGH->print_timing_info) { for (i = 0; i < 4; i++) { myGH->timers[i] = CCTK_TimerCreate (timer_names[i]); if (myGH->timers[i] < 0) { break; } } if (i != 4) { CCTK_WARN (1, "Could not create timers for checkpoint/recovery ! " "No timer information will be available."); while (--i >= 0) { CCTK_TimerDestroyI (myGH->timers[i]); } myGH->print_timing_info = 0; } else { CCTK_TimerResetI (myGH->timers[2]); CCTK_TimerResetI (myGH->timers[3]); } } return (myGH); }