IFPACK  Development
 All Classes Files Functions Variables Enumerations Friends
globalObjects.c
00001 /*@HEADER
00002 // ***********************************************************************
00003 //
00004 //       Ifpack: Object-Oriented Algebraic Preconditioner Package
00005 //                 Copyright (2002) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 //@HEADER
00041 */
00042 
00043 /* Contains definitions of globally scoped  objects; 
00044  * Also, functions for error handling and message logging.
00045  */
00046 
00047 #include "euclid_common.h"
00048 #include "Parser_dh.h"
00049 #include "Mem_dh.h"
00050 #include "TimeLog_dh.h"
00051 extern void sigRegister_dh ();  /* use sig_dh.h if not for euclid_signals_len */
00052 
00053 /*-------------------------------------------------------------------------
00054  * Globally scoped variables, flags, and objects
00055  *-------------------------------------------------------------------------*/
00056 bool errFlag_dh = false;    /* set to "true" by functions encountering errors */
00057 Parser_dh parser_dh = NULL; /* for setting/getting runtime options */
00058 TimeLog_dh tlog_dh = NULL;  /* internal timing  functionality */
00059 Mem_dh mem_dh = NULL;       /* memory management */
00060 FILE *logFile = NULL;
00061 char msgBuf_dh[MSG_BUF_SIZE_DH];    /* for internal use */
00062 int np_dh = 1;          /* number of processors and subdomains */
00063 int myid_dh = 0;        /* rank of this processor (and subdomain) */
00064 MPI_Comm comm_dh = 0;
00065 
00066 
00067   /* Each processor (may) open a logfile.
00068    * The bools are switches for controlling the amount of informational 
00069    * output, and where it gets written to.  Function logging is only enabled
00070    * when compiled with the debugging (-g) option.
00071    */
00072 FILE *logFile;
00073 void openLogfile_dh (int argc, char *argv[]);
00074 void closeLogfile_dh ();
00075 bool logInfoToStderr = false;
00076 bool logInfoToFile = false;
00077 bool logFuncsToStderr = false;
00078 bool logFuncsToFile = false;
00079 
00080 bool ignoreMe = true;
00081 int ref_counter = 0;
00082 
00083 
00084 /*-------------------------------------------------------------------------
00085  * End of global definitions. 
00086  * Error and info functions follow.
00087  *-------------------------------------------------------------------------*/
00088 
00089 #define MAX_MSG_SIZE 1024
00090 #define MAX_STACK_SIZE 20
00091 
00092 static char errMsg_private[MAX_STACK_SIZE][MAX_MSG_SIZE];
00093 static int errCount_private = 0;
00094 
00095 static char calling_stack[MAX_STACK_SIZE][MAX_MSG_SIZE];
00096 /* static  int  priority_private[MAX_STACK_SIZE]; */
00097 static int calling_stack_count = 0;
00098 
00099 /* static  char errMsg[MAX_MSG_SIZE];    */
00100 
00101 void
00102 openLogfile_dh (int argc, char *argv[])
00103 {
00104   char buf[1024];
00105 
00106   /* this doesn't really belong here, but it's gotta go someplace! */
00107 /*  strcpy(errMsg, "error msg was never set -- ??"); */
00108 
00109   if (logFile != NULL)
00110     return;
00111 
00112   /* set default logging filename */
00113   sprintf (buf, "logFile");
00114 
00115   /* set user supplied logging filename, if one was specified */
00116   if (argc && argv != NULL)
00117     {
00118       int j;
00119       for (j = 1; j < argc; ++j)
00120     {
00121       if (strcmp (argv[j], "-logFile") == 0)
00122         {
00123           if (j + 1 < argc)
00124         {
00125           sprintf (buf, "%s", argv[j + 1]);
00126           break;
00127         }
00128         }
00129     }
00130     }
00131 
00132   /* attempt to open logfile, unless the user entered "-logFile none" */
00133   if (strcmp (buf, "none"))
00134     {
00135       char a[5];
00136       sprintf (a, ".%i", myid_dh);
00137       strcat (buf, a);
00138 
00139       if ((logFile = fopen (buf, "w")) == NULL)
00140     {
00141       fprintf (stderr, "can't open >%s< for writing; continuing anyway\n",
00142            buf);
00143     }
00144     }
00145 }
00146 
00147 void
00148 closeLogfile_dh ()
00149 {
00150   if (logFile != NULL)
00151     {
00152       if (fclose (logFile))
00153     {
00154       fprintf (stderr, "Error closing logFile\n");
00155     }
00156       logFile = NULL;
00157     }
00158 }
00159 
00160 void
00161 setInfo_dh (char *msg, char *function, char *file, int line)
00162 {
00163   if (logInfoToFile && logFile != NULL)
00164     {
00165       fprintf (logFile, "INFO: %s;\n       function= %s  file=%s  line=%i\n",
00166            msg, function, file, line);
00167       fflush (logFile);
00168     }
00169   if (logInfoToStderr)
00170     {
00171       fprintf (stderr, "INFO: %s;\n       function= %s  file=%s  line=%i\n",
00172            msg, function, file, line);
00173     }
00174 }
00175 
00176 /*----------------------------------------------------------------------
00177  *  Error handling stuph follows
00178  *----------------------------------------------------------------------*/
00179 
00180 void
00181 dh_StartFunc (char *function, char *file, int line, int priority)
00182 {
00183   if (priority == 1)
00184     {
00185       sprintf (calling_stack[calling_stack_count],
00186            "[%i]   %s  file= %s  line= %i", myid_dh, function, file,
00187            line);
00188       /* priority_private[calling_stack_count] = priority; */
00189       ++calling_stack_count;
00190 
00191       if (calling_stack_count == MAX_STACK_SIZE)
00192     {
00193       fprintf (stderr,
00194            "_____________ dh_StartFunc: OVERFLOW _____________________\n");
00195       if (logFile != NULL)
00196         {
00197           fprintf (logFile,
00198                "_____________ dh_StartFunc: OVERFLOW _____________________\n");
00199         }
00200       --calling_stack_count;
00201     }
00202     }
00203 }
00204 
00205 void
00206 dh_EndFunc (char *function, int priority)
00207 {
00208   if (priority == 1)
00209     {
00210       --calling_stack_count;
00211 
00212       if (calling_stack_count < 0)
00213     {
00214       calling_stack_count = 0;
00215       fprintf (stderr,
00216            "_____________ dh_EndFunc: UNDERFLOW _____________________\n");
00217       if (logFile != NULL)
00218         {
00219           fprintf (logFile,
00220                "_____________ dh_EndFunc: UNDERFLOW _____________________\n");
00221         }
00222     }
00223     }
00224 }
00225 
00226 
00227 void
00228 setError_dh (char *msg, char *function, char *file, int line)
00229 {
00230   errFlag_dh = true;
00231   if (!strcmp (msg, ""))
00232     {
00233       sprintf (errMsg_private[errCount_private],
00234            "[%i] called from: %s  file= %s  line= %i",
00235            myid_dh, function, file, line);
00236     }
00237   else
00238     {
00239       sprintf (errMsg_private[errCount_private],
00240            "[%i] ERROR: %s\n       %s  file= %s  line= %i\n",
00241            myid_dh, msg, function, file, line);
00242     }
00243   ++errCount_private;
00244 
00245   /* shouldn't do things like this; but we're not building
00246      for the ages: all the world's a stage, this is merely a
00247      prop to be bonfired at play's end.
00248    */
00249   if (errCount_private == MAX_STACK_SIZE)
00250     --errCount_private;
00251 }
00252 
00253 void
00254 printErrorMsg (FILE * fp)
00255 {
00256   if (!errFlag_dh)
00257     {
00258       fprintf (fp, "errFlag_dh is not set; nothing to print!\n");
00259       fflush (fp);
00260     }
00261   else
00262     {
00263       int i;
00264       fprintf (fp,
00265            "\n============= error stack trace ====================\n");
00266       for (i = 0; i < errCount_private; ++i)
00267     {
00268       fprintf (fp, "%s\n", errMsg_private[i]);
00269     }
00270       fprintf (fp, "\n");
00271       fflush (fp);
00272     }
00273 }
00274 
00275 void
00276 printFunctionStack (FILE * fp)
00277 {
00278   int i;
00279   for (i = 0; i < calling_stack_count; ++i)
00280     {
00281       fprintf (fp, "%s\n", calling_stack[i]);
00282     }
00283   fprintf (fp, "\n");
00284   fflush (fp);
00285 }
00286 
00287 
00288 /*----------------------------------------------------------------------
00289  *  function call tracing support follows
00290  *----------------------------------------------------------------------*/
00291 
00292 #define MAX_ERROR_SPACES   200
00293 static char spaces[MAX_ERROR_SPACES];
00294 static int nesting = 0;
00295 static bool initSpaces = true;
00296 #define INDENT_DH 3
00297 
00298 void
00299 Error_dhStartFunc (char *function, char *file, int line)
00300 {
00301   if (initSpaces)
00302     {
00303       memset (spaces, ' ', MAX_ERROR_SPACES * sizeof (char));
00304       initSpaces = false;
00305     }
00306 
00307   /* get rid of string null-terminator from last
00308    * call (if any) to Error_dhStartFunc()
00309    */
00310   spaces[INDENT_DH * nesting] = ' ';
00311 
00312   /* add null-terminator, so the correct number of spaces will be printed */
00313   ++nesting;
00314   if (nesting > MAX_ERROR_SPACES - 1)
00315     nesting = MAX_ERROR_SPACES - 1;
00316   spaces[INDENT_DH * nesting] = '\0';
00317 
00318   if (logFuncsToStderr)
00319     {
00320       fprintf (stderr, "%s(%i) %s  [file= %s  line= %i]\n",
00321            spaces, nesting, function, file, line);
00322     }
00323   if (logFuncsToFile && logFile != NULL)
00324     {
00325       fprintf (logFile, "%s(%i) %s  [file= %s  line= %i]\n",
00326            spaces, nesting, function, file, line);
00327       fflush (logFile);
00328     }
00329 }
00330 
00331 void
00332 Error_dhEndFunc (char *function)
00333 {
00334   nesting -= 1;
00335   if (nesting < 0)
00336     nesting = 0;
00337   spaces[INDENT_DH * nesting] = '\0';
00338 }
00339 
00340 /*----------------------------------------------------------------------
00341  *  Euclid initialization and shutdown
00342  *----------------------------------------------------------------------*/
00343 
00344 static bool EuclidIsActive = false;
00345 
00346 #undef __FUNC__
00347 #define __FUNC__ "EuclidIsInitialized"
00348 bool
00349 EuclidIsInitialized ()
00350 {
00351   return EuclidIsActive;
00352 }
00353 
00354 #undef __FUNC__
00355 #define __FUNC__ "EuclidInitialize"
00356 void
00357 EuclidInitialize (int argc, char *argv[], char *help)
00358 {
00359   if (!EuclidIsActive)
00360     {
00361       MPI_Comm_size (comm_dh, &np_dh);
00362       MPI_Comm_rank (comm_dh, &myid_dh);
00363       openLogfile_dh (argc, argv);
00364       if (mem_dh == NULL)
00365     {
00366       Mem_dhCreate (&mem_dh);
00367       CHECK_V_ERROR;
00368     }
00369       if (tlog_dh == NULL)
00370     {
00371       TimeLog_dhCreate (&tlog_dh);
00372       CHECK_V_ERROR;
00373     }
00374       if (parser_dh == NULL)
00375     {
00376       Parser_dhCreate (&parser_dh);
00377       CHECK_V_ERROR;
00378     }
00379       Parser_dhInit (parser_dh, argc, argv);
00380       CHECK_V_ERROR;
00381       if (Parser_dhHasSwitch (parser_dh, "-sig_dh"))
00382     {
00383       sigRegister_dh ();
00384       CHECK_V_ERROR;
00385     }
00386       if (Parser_dhHasSwitch (parser_dh, "-help"))
00387     {
00388       if (myid_dh == 0)
00389         printf ("%s\n\n", help);
00390       EUCLID_EXIT;
00391     }
00392       if (Parser_dhHasSwitch (parser_dh, "-logFuncsToFile"))
00393     {
00394       logFuncsToFile = true;
00395     }
00396       if (Parser_dhHasSwitch (parser_dh, "-logFuncsToStderr"))
00397     {
00398       logFuncsToStderr = true;
00399     }
00400 
00401       EuclidIsActive = true;
00402     }
00403 
00404 }
00405 
00406 
00407 /* to do: should restore the signal handler that we preempted above! */
00408 #undef __FUNC__
00409 #define __FUNC__ "EuclidFinalize"
00410 void
00411 EuclidFinalize ()
00412 {
00413   if (ref_counter)
00414     return;
00415 
00416   if (EuclidIsActive)
00417     {
00418       if (parser_dh != NULL)
00419     {
00420       Parser_dhDestroy (parser_dh);
00421       CHECK_V_ERROR;
00422     }
00423       if (tlog_dh != NULL)
00424     {
00425       TimeLog_dhDestroy (tlog_dh);
00426       CHECK_V_ERROR;
00427     }
00428       if (logFile != NULL)
00429     {
00430       Mem_dhPrint (mem_dh, logFile, true);
00431       CHECK_V_ERROR;
00432     }
00433 /*  Mem_dhPrint(mem_dh, stderr, false); CHECK_V_ERROR; */
00434       if (mem_dh != NULL)
00435     {
00436       Mem_dhDestroy (mem_dh);
00437       CHECK_V_ERROR;
00438     }
00439       if (logFile != NULL)
00440     {
00441       closeLogfile_dh ();
00442       CHECK_V_ERROR;
00443     }
00444       EuclidIsActive = false;
00445     }
00446 }
00447 
00448 
00449 /*----------------------------------------------------------------------
00450  *  msc. support functions
00451  *----------------------------------------------------------------------*/
00452 
00453 #undef __FUNC__
00454 #define __FUNC__ "printf_dh"
00455 void
00456 printf_dh (char *fmt, ...)
00457 {
00458   START_FUNC_DH va_list args;
00459   char *buf = msgBuf_dh;
00460 
00461   va_start (args, fmt);
00462   vsprintf (buf, fmt, args);
00463   if (myid_dh == 0)
00464     {
00465       fprintf (stdout, "%s", buf);
00466     }
00467   va_end (args);
00468 END_FUNC_DH}
00469 
00470 #undef __FUNC__
00471 #define __FUNC__ "fprintf_dh"
00472 void
00473 fprintf_dh (FILE * fp, char *fmt, ...)
00474 {
00475   START_FUNC_DH va_list args;
00476   char *buf = msgBuf_dh;
00477 
00478   va_start (args, fmt);
00479   vsprintf (buf, fmt, args);
00480   if (myid_dh == 0)
00481     {
00482       fprintf (fp, "%s", buf);
00483     }
00484   va_end (args);
00485 END_FUNC_DH}
00486 
00487 
00488 #undef __FUNC__
00489 #define __FUNC__ "echoInvocation_dh"
00490 void
00491 echoInvocation_dh (MPI_Comm comm, char *prefix, int argc, char *argv[])
00492 {
00493   START_FUNC_DH int i, id;
00494 
00495   MPI_Comm_rank (comm, &id);
00496 
00497   if (prefix != NULL)
00498     {
00499       printf_dh ("\n%s ", prefix);
00500     }
00501   else
00502     {
00503       printf_dh ("\n");
00504     }
00505 
00506   printf_dh ("program invocation: ");
00507   for (i = 0; i < argc; ++i)
00508     {
00509       printf_dh ("%s ", argv[i]);
00510     }
00511   printf_dh ("\n");
00512 END_FUNC_DH}
 All Classes Files Functions Variables Enumerations Friends