xref: /petsc/include/petscerror.h (revision 3bbf0e9209c918da710d8f50ca5c48af17a42e60)
1 /*
2     Contains all error handling interfaces for PETSc.
3 */
4 #if !defined(__PETSCERROR_H)
5 #define __PETSCERROR_H
6 
7 /*
8    Defines the function where the compiled source is located; used
9    in printing error messages. This is defined here in case the user
10    does not declare it.
11 */
12 #if !defined(__FUNCT__)
13 #define __FUNCT__ "User provided function"
14 #endif
15 
16 /*
17      These are the generic error codes. These error codes are used
18      many different places in the PETSc source code. The string versions are
19      at src/sys/error/err.c any changes here must also be made there
20      These are also define in include/finclude/petscerror.h any CHANGES here
21      must be also made there.
22 
23 */
24 #define PETSC_ERR_MIN_VALUE        54   /* should always be one less then the smallest value */
25 
26 #define PETSC_ERR_MEM              55   /* unable to allocate requested memory */
27 #define PETSC_ERR_SUP              56   /* no support for requested operation */
28 #define PETSC_ERR_SUP_SYS          57   /* no support for requested operation on this computer system */
29 #define PETSC_ERR_ORDER            58   /* operation done in wrong order */
30 #define PETSC_ERR_SIG              59   /* signal received */
31 #define PETSC_ERR_FP               72   /* floating point exception */
32 #define PETSC_ERR_COR              74   /* corrupted PETSc object */
33 #define PETSC_ERR_LIB              76   /* error in library called by PETSc */
34 #define PETSC_ERR_PLIB             77   /* PETSc library generated inconsistent data */
35 #define PETSC_ERR_MEMC             78   /* memory corruption */
36 #define PETSC_ERR_CONV_FAILED      82   /* iterative method (KSP or SNES) failed */
37 #define PETSC_ERR_USER             83   /* user has not provided needed function */
38 #define PETSC_ERR_SYS              88   /* error in system call */
39 #define PETSC_ERR_POINTER          70   /* pointer does not point to valid address */
40 
41 #define PETSC_ERR_ARG_SIZ          60   /* nonconforming object sizes used in operation */
42 #define PETSC_ERR_ARG_IDN          61   /* two arguments not allowed to be the same */
43 #define PETSC_ERR_ARG_WRONG        62   /* wrong argument (but object probably ok) */
44 #define PETSC_ERR_ARG_CORRUPT      64   /* null or corrupted PETSc object as argument */
45 #define PETSC_ERR_ARG_OUTOFRANGE   63   /* input argument, out of range */
46 #define PETSC_ERR_ARG_BADPTR       68   /* invalid pointer argument */
47 #define PETSC_ERR_ARG_NOTSAMETYPE  69   /* two args must be same object type */
48 #define PETSC_ERR_ARG_NOTSAMECOMM  80   /* two args must be same communicators */
49 #define PETSC_ERR_ARG_WRONGSTATE   73   /* object in argument is in wrong state, e.g. unassembled mat */
50 #define PETSC_ERR_ARG_TYPENOTSET   89   /* the type of the object has not yet been set */
51 #define PETSC_ERR_ARG_INCOMP       75   /* two arguments are incompatible */
52 #define PETSC_ERR_ARG_NULL         85   /* argument is null that should not be */
53 #define PETSC_ERR_ARG_UNKNOWN_TYPE 86   /* type name doesn't match any registered type */
54 
55 #define PETSC_ERR_FILE_OPEN        65   /* unable to open file */
56 #define PETSC_ERR_FILE_READ        66   /* unable to read from file */
57 #define PETSC_ERR_FILE_WRITE       67   /* unable to write to file */
58 #define PETSC_ERR_FILE_UNEXPECTED  79   /* unexpected data in file */
59 
60 #define PETSC_ERR_MAT_LU_ZRPVT     71   /* detected a zero pivot during LU factorization */
61 #define PETSC_ERR_MAT_CH_ZRPVT     81   /* detected a zero pivot during Cholesky factorization */
62 
63 #define PETSC_ERR_INT_OVERFLOW     84   /* should always be one less then the smallest value */
64 
65 #define PETSC_ERR_FLOP_COUNT       90
66 #define PETSC_ERR_NOT_CONVERGED    91  /* solver did not converge */
67 #define PETSC_ERR_MAX_VALUE        92  /* this is always the one more than the largest error code */
68 
69 #define PetscStringizeArg(a) #a
70 #define PetscStringize(a) PetscStringizeArg(a)
71 
72 #if defined(PETSC_USE_ERRORCHECKING)
73 
74 /*MC
75    SETERRQ - Macro that is called when an error has been detected,
76 
77    Synopsis:
78    #include "petscsys.h"
79    PetscErrorCode SETERRQ(MPI_Comm comm,PetscErrorCode errorcode,char *message)
80 
81    Not Collective
82 
83    Input Parameters:
84 +  errorcode - nonzero error code, see the list of standard error codes in include/petscerror.h
85 -  message - error message
86 
87   Level: beginner
88 
89    Notes:
90     Once the error handler is called the calling function is then returned from with the given error code.
91 
92     See SETERRQ1(), SETERRQ2(), SETERRQ3() for versions that take arguments
93 
94     In Fortran MPI_Abort() is always called
95 
96     Experienced users can set the error handler with PetscPushErrorHandler().
97 
98    Concepts: error^setting condition
99 
100 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), PetscError(), CHKERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ2(), SETERRQ3()
101 M*/
102 #define SETERRQ(comm,n,s)              return PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s)
103 
104 /*MC
105    SETERRQ1 - Macro that is called when an error has been detected,
106 
107    Synopsis:
108    #include "petscsys.h"
109    PetscErrorCode SETERRQ1(MPI_Comm comm,PetscErrorCode errorcode,char *formatmessage,arg)
110 
111    Not Collective
112 
113    Input Parameters:
114 +  errorcode - nonzero error code, see the list of standard error codes in include/petscerror.h
115 .  message - error message in the printf format
116 -  arg - argument (for example an integer, string or double)
117 
118   Level: beginner
119 
120    Notes:
121     Once the error handler is called the calling function is then returned from with the given error code.
122 
123    Experienced users can set the error handler with PetscPushErrorHandler().
124 
125    Concepts: error^setting condition
126 
127 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), PetscError(), CHKERRQ(), CHKMEMQ, SETERRQ(), SETERRQ2(), SETERRQ3()
128 M*/
129 #define SETERRQ1(comm,n,s,a1)          return PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s,a1)
130 
131 /*MC
132    SETERRQ2 - Macro that is called when an error has been detected,
133 
134    Synopsis:
135    #include "petscsys.h"
136    PetscErrorCode SETERRQ2(PetscErrorCode errorcode,char *formatmessage,arg1,arg2)
137 
138    Not Collective
139 
140    Input Parameters:
141 +  errorcode - nonzero error code, see the list of standard error codes in include/petscerror.h
142 .  message - error message in the printf format
143 .  arg1 - argument (for example an integer, string or double)
144 -  arg2 - argument (for example an integer, string or double)
145 
146   Level: beginner
147 
148    Notes:
149     Once the error handler is called the calling function is then returned from with the given error code.
150 
151    Experienced users can set the error handler with PetscPushErrorHandler().
152 
153    Concepts: error^setting condition
154 
155 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), PetscError(), CHKERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ3()
156 M*/
157 #define SETERRQ2(comm,n,s,a1,a2)       return PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s,a1,a2)
158 
159 /*MC
160    SETERRQ3 - Macro that is called when an error has been detected,
161 
162    Synopsis:
163    #include "petscsys.h"
164    PetscErrorCode SETERRQ3(PetscErrorCode errorcode,char *formatmessage,arg1,arg2,arg3)
165 
166    Not Collective
167 
168    Input Parameters:
169 +  errorcode - nonzero error code, see the list of standard error codes in include/petscerror.h
170 .  message - error message in the printf format
171 .  arg1 - argument (for example an integer, string or double)
172 .  arg2 - argument (for example an integer, string or double)
173 -  arg3 - argument (for example an integer, string or double)
174 
175   Level: beginner
176 
177    Notes:
178     Once the error handler is called the calling function is then returned from with the given error code.
179 
180     There are also versions for 4, 5, 6 and 7 arguments.
181 
182    Experienced users can set the error handler with PetscPushErrorHandler().
183 
184    Concepts: error^setting condition
185 
186 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), PetscError(), CHKERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ2()
187 M*/
188 #define SETERRQ3(comm,n,s,a1,a2,a3)    return PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s,a1,a2,a3)
189 
190 #define SETERRQ4(comm,n,s,a1,a2,a3,a4) return PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s,a1,a2,a3,a4)
191 #define SETERRQ5(comm,n,s,a1,a2,a3,a4,a5)       return PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s,a1,a2,a3,a4,a5)
192 #define SETERRQ6(comm,n,s,a1,a2,a3,a4,a5,a6)    return PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s,a1,a2,a3,a4,a5,a6)
193 #define SETERRQ7(comm,n,s,a1,a2,a3,a4,a5,a6,a7) return PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s,a1,a2,a3,a4,a5,a6,a7)
194 #define SETERRQ8(comm,n,s,a1,a2,a3,a4,a5,a6,a7,a8) return PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s,a1,a2,a3,a4,a5,a6,a7,a8)
195 #define SETERRABORT(comm,n,s)     do {PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_INITIAL,s);MPI_Abort(comm,n);} while (0)
196 
197 /*MC
198    CHKERRQ - Checks error code, if non-zero it calls the error handler and then returns
199 
200    Synopsis:
201    #include "petscsys.h"
202    PetscErrorCode CHKERRQ(PetscErrorCode errorcode)
203 
204    Not Collective
205 
206    Input Parameters:
207 .  errorcode - nonzero error code, see the list of standard error codes in include/petscerror.h
208 
209   Level: beginner
210 
211    Notes:
212     Once the error handler is called the calling function is then returned from with the given error code.
213 
214     Experienced users can set the error handler with PetscPushErrorHandler().
215 
216     CHKERRQ(n) is fundamentally a macro replacement for
217          if (n) return(PetscError(...,n,...));
218 
219     Although typical usage resembles "void CHKERRQ(PetscErrorCode)" as described above, for certain uses it is
220     highly inappropriate to use it in this manner as it invokes return(PetscErrorCode). In particular,
221     it cannot be used in functions which return(void) or any other datatype.  In these types of functions,
222     you can use CHKERRV() which returns without an error code (bad idea since the error is ignored or
223          if (n) {PetscError(....); return(YourReturnType);}
224     where you may pass back a NULL to indicate an error. You can also call CHKERRABORT(comm,n) to have
225     MPI_Abort() returned immediately.
226 
227     In Fortran MPI_Abort() is always called
228 
229    Concepts: error^setting condition
230 
231 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), PetscError(), SETERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ2(), SETERRQ2()
232 M*/
233 #define CHKERRQ(n)             do {if (PetscUnlikely(n)) return PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_REPEAT," ");} while (0)
234 
235 #define CHKERRV(n)             do {if (PetscUnlikely(n)) {n = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_REPEAT," ");return;}} while(0)
236 #define CHKERRABORT(comm,n)    do {if (PetscUnlikely(n)) {PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_REPEAT," ");MPI_Abort(comm,n);}} while (0)
237 #define CHKERRCONTINUE(n)      do {if (PetscUnlikely(n)) {PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_REPEAT," ");}} while (0)
238 
239 #ifdef PETSC_CLANGUAGE_CXX
240 
241 /*MC
242    CHKERRXX - Checks error code, if non-zero it calls the C++ error handler which throws an exception
243 
244    Synopsis:
245    #include "petscsys.h"
246    void CHKERRXX(PetscErrorCode errorcode)
247 
248    Not Collective
249 
250    Input Parameters:
251 .  errorcode - nonzero error code, see the list of standard error codes in include/petscerror.h
252 
253   Level: beginner
254 
255    Notes:
256     Once the error handler throws a ??? exception.
257 
258     You can use CHKERRV() which returns without an error code (bad idea since the error is ignored)
259     or CHKERRABORT(comm,n) to have MPI_Abort() returned immediately.
260 
261    Concepts: error^setting condition
262 
263 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), PetscError(), SETERRQ(), CHKERRQ(), CHKMEMQ
264 M*/
265 #define CHKERRXX(n)            do {if (PetscUnlikely(n)) {PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,n,PETSC_ERROR_IN_CXX,0);}} while(0)
266 
267 #endif
268 
269 /*MC
270    CHKMEMQ - Checks the memory for corruption, calls error handler if any is detected
271 
272    Synopsis:
273    #include "petscsys.h"
274    CHKMEMQ;
275 
276    Not Collective
277 
278   Level: beginner
279 
280    Notes:
281     Must run with the option -malloc_debug to enable this option
282 
283     Once the error handler is called the calling function is then returned from with the given error code.
284 
285     By defaults prints location where memory that is corrupted was allocated.
286 
287     Use CHKMEMA for functions that return void
288 
289    Concepts: memory corruption
290 
291 .seealso: PetscTraceBackErrorHandler(), PetscPushErrorHandler(), PetscError(), SETERRQ(), CHKMEMQ, SETERRQ1(), SETERRQ2(), SETERRQ3(),
292           PetscMallocValidate()
293 M*/
294 #define CHKMEMQ do {PetscErrorCode _7_ierr = PetscMallocValidate(__LINE__,PETSC_FUNCTION_NAME,__FILE__);CHKERRQ(_7_ierr);} while(0)
295 
296 #define CHKMEMA PetscMallocValidate(__LINE__,PETSC_FUNCTION_NAME,__FILE__)
297 
298 #else /* PETSC_USE_ERRORCHECKING */
299 
300 /*
301     These are defined to be empty for when error checking is turned off, with ./configure --with-errorchecking=0
302 */
303 
304 #define SETERRQ(c,n,s)
305 #define SETERRQ1(c,n,s,a1)
306 #define SETERRQ2(c,n,s,a1,a2)
307 #define SETERRQ3(c,n,s,a1,a2,a3)
308 #define SETERRQ4(c,n,s,a1,a2,a3,a4)
309 #define SETERRQ5(c,n,s,a1,a2,a3,a4,a5)
310 #define SETERRQ6(c,n,s,a1,a2,a3,a4,a5,a6)
311 #define SETERRQ7(c,n,s,a1,a2,a3,a4,a5,a6,a7)
312 #define SETERRQ8(c,n,s,a1,a2,a3,a4,a5,a6,a7,a8)
313 #define SETERRABORT(comm,n,s)
314 
315 #define CHKERRQ(n)     ;
316 #define CHKERRABORT(comm,n) ;
317 #define CHKERRCONTINUE(n) ;
318 #define CHKMEMQ        ;
319 
320 #ifdef PETSC_CLANGUAGE_CXX
321 #define CHKERRXX(n) ;
322 #endif
323 
324 #endif /* PETSC_USE_ERRORCHECKING */
325 
326 /*E
327   PetscErrorType - passed to the PETSc error handling routines indicating if this is the first or a later call to the error handlers
328 
329   Level: advanced
330 
331   PETSC_ERROR_IN_CXX indicates the error was detected in C++ and an exception should be generated
332 
333   Developer Notes: This is currently used to decide when to print the detailed information about the run in PetscTraceBackErrorHandling()
334 
335 .seealso: PetscError(), SETERRXX()
336 E*/
337 typedef enum {PETSC_ERROR_INITIAL=0,PETSC_ERROR_REPEAT=1,PETSC_ERROR_IN_CXX = 2} PetscErrorType;
338 
339 PETSC_EXTERN PetscErrorCode PetscErrorPrintfInitialize(void);
340 PETSC_EXTERN PetscErrorCode PetscErrorMessage(int,const char*[],char **);
341 PETSC_EXTERN PetscErrorCode PetscTraceBackErrorHandler(MPI_Comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*);
342 PETSC_EXTERN PetscErrorCode PetscIgnoreErrorHandler(MPI_Comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*);
343 PETSC_EXTERN PetscErrorCode PetscEmacsClientErrorHandler(MPI_Comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*);
344 PETSC_EXTERN PetscErrorCode PetscMPIAbortErrorHandler(MPI_Comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*);
345 PETSC_EXTERN PetscErrorCode PetscAbortErrorHandler(MPI_Comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*);
346 PETSC_EXTERN PetscErrorCode PetscAttachDebuggerErrorHandler(MPI_Comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*);
347 PETSC_EXTERN PetscErrorCode PetscReturnErrorHandler(MPI_Comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*);
348 PETSC_EXTERN PetscErrorCode PetscError(MPI_Comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,...);
349 PETSC_EXTERN PetscErrorCode PetscPushErrorHandler(PetscErrorCode (*handler)(MPI_Comm,int,const char*,const char*,PetscErrorCode,PetscErrorType,const char*,void*),void*);
350 PETSC_EXTERN PetscErrorCode PetscPopErrorHandler(void);
351 PETSC_EXTERN PetscErrorCode PetscSignalHandlerDefault(int,void*);
352 PETSC_EXTERN PetscErrorCode PetscPushSignalHandler(PetscErrorCode (*)(int,void *),void*);
353 PETSC_EXTERN PetscErrorCode PetscPopSignalHandler(void);
354 
355 /*MC
356     PetscErrorPrintf - Prints error messages.
357 
358    Synopsis:
359     #include "petscsys.h"
360      PetscErrorCode (*PetscErrorPrintf)(const char format[],...);
361 
362     Not Collective
363 
364     Input Parameters:
365 .   format - the usual printf() format string
366 
367    Options Database Keys:
368 +    -error_output_stdout - cause error messages to be printed to stdout instead of the
369          (default) stderr
370 -    -error_output_none to turn off all printing of error messages (does not change the way the
371           error is handled.)
372 
373    Notes: Use
374 $     PetscErrorPrintf = PetscErrorPrintfNone; to turn off all printing of error messages (does not change the way the
375 $                        error is handled.) and
376 $     PetscErrorPrintf = PetscErrorPrintfDefault; to turn it back on
377 $        of you can use your own function
378 
379           Use
380      PETSC_STDERR = FILE* obtained from a file open etc. to have stderr printed to the file.
381      PETSC_STDOUT = FILE* obtained from a file open etc. to have stdout printed to the file.
382 
383           Use
384       PetscPushErrorHandler() to provide your own error handler that determines what kind of messages to print
385 
386    Level: developer
387 
388     Fortran Note:
389     This routine is not supported in Fortran.
390 
391     Concepts: error messages^printing
392     Concepts: printing^error messages
393 
394 .seealso: PetscFPrintf(), PetscSynchronizedPrintf(), PetscHelpPrintf(), PetscPrintf(), PetscErrorHandlerPush(), PetscVFPrintf(), PetscHelpPrintf()
395 M*/
396 PETSC_EXTERN PetscErrorCode (*PetscErrorPrintf)(const char[],...);
397 
398 typedef enum {PETSC_FP_TRAP_OFF=0,PETSC_FP_TRAP_ON=1} PetscFPTrap;
399 PETSC_EXTERN PetscErrorCode PetscSetFPTrap(PetscFPTrap);
400 PETSC_EXTERN PetscErrorCode PetscFPTrapPush(PetscFPTrap);
401 PETSC_EXTERN PetscErrorCode PetscFPTrapPop(void);
402 
403 /*  Linux functions CPU_SET and others don't work if sched.h is not included before
404     including pthread.h. Also, these functions are active only if either _GNU_SOURCE
405     or __USE_GNU is not set (see /usr/include/sched.h and /usr/include/features.h), hence
406     set these first.
407 */
408 #if defined(PETSC_HAVE_PTHREADCLASSES) || defined (PETSC_HAVE_OPENMP)
409 #if defined(PETSC_HAVE_SCHED_H)
410 #ifndef _GNU_SOURCE
411 #define _GNU_SOURCE
412 #endif
413 #include <sched.h>
414 #endif
415 #include <pthread.h>
416 #endif
417 
418 /*
419      This code is for managing thread local global variables. Each of Linux, Microsoft WINDOWS, OpenMP, and Apple OS X have
420    different ways to indicate this. On OS X each thread local global is accessed by using a pthread_key_t for that variable.
421    Thus we have functions for creating destroying and using the keys. Except for OS X these access functions merely directly
422    acess the thread local variable.
423 */
424 
425 #if defined(PETSC_HAVE_PTHREADCLASSES) && !defined(PETSC_PTHREAD_LOCAL)
426 typedef pthread_key_t PetscThreadKey;
427 /* Get the value associated with key */
428 PETSC_STATIC_INLINE void* PetscThreadLocalGetValue(PetscThreadKey key)
429 {
430   return pthread_getspecific(key);
431 }
432 
433 /* Set the value for key */
434 PETSC_STATIC_INLINE void PetscThreadLocalSetValue(PetscThreadKey *key,void* value)
435 {
436   pthread_setspecific(*key,(void*)value);
437 }
438 
439 /* Create pthread thread local key */
440 PETSC_STATIC_INLINE void PetscThreadLocalRegister(PetscThreadKey *key)
441 {
442   pthread_key_create(key,NULL);
443 }
444 
445 /* Delete pthread thread local key */
446 PETSC_STATIC_INLINE void PetscThreadLocalDestroy(PetscThreadKey key)
447 {
448   pthread_key_delete(key);
449 }
450 #else
451 typedef void* PetscThreadKey;
452 PETSC_STATIC_INLINE void* PetscThreadLocalGetValue(PetscThreadKey key)
453 {
454   return key;
455 }
456 
457 PETSC_STATIC_INLINE void PetscThreadLocalSetValue(PetscThreadKey *key,void* value)
458 {
459   *key = value;
460 }
461 
462 PETSC_STATIC_INLINE void PetscThreadLocalRegister(PETSC_UNUSED PetscThreadKey *key)
463 {
464 }
465 
466 PETSC_STATIC_INLINE void PetscThreadLocalDestroy(PETSC_UNUSED PetscThreadKey key)
467 {
468 }
469 #endif
470 
471 /*
472       Allows the code to build a stack frame as it runs
473 */
474 #if defined(PETSC_USE_DEBUG)
475 
476 #define PETSCSTACKSIZE 64
477 
478 typedef struct  {
479   const char      *function[PETSCSTACKSIZE];
480   const char      *file[PETSCSTACKSIZE];
481         int       line[PETSCSTACKSIZE];
482         PetscBool petscroutine[PETSCSTACKSIZE];
483         int       currentsize;
484 } PetscStack;
485 
486 #if defined(PETSC_HAVE_PTHREADCLASSES)
487 #if defined(PETSC_PTHREAD_LOCAL)
488 PETSC_EXTERN PETSC_PTHREAD_LOCAL PetscStack *petscstack;
489 #else
490 PETSC_EXTERN PetscThreadKey petscstack;
491 #endif
492 #elif defined(PETSC_HAVE_OPENMP)
493 PETSC_EXTERN PetscStack *petscstack;
494 #pragma omp threadprivate(petscstack)
495 #else
496 PETSC_EXTERN PetscStack *petscstack;
497 #endif
498 
499 PETSC_EXTERN PetscErrorCode PetscStackCopy(PetscStack*,PetscStack*);
500 PETSC_EXTERN PetscErrorCode PetscStackPrint(PetscStack*,FILE* fp);
501 
502 PETSC_STATIC_INLINE PetscBool PetscStackActive(void)
503 {
504   return(PetscThreadLocalGetValue(petscstack) ? PETSC_TRUE : PETSC_FALSE);
505 }
506 
507 /* Stack handling is based on the following two "NoCheck" macros.  These should only be called directly by other error
508  * handling macros.  We record the line of the call, which may or may not be the location of the definition.  But is at
509  * least more useful than "unknown" because it can distinguish multiple calls from the same function.
510  */
511 
512 #define PetscStackPushNoCheck(funct,petsc_routine)                            \
513   do {                                                                        \
514     PetscStack* petscstackp;                                                  \
515     PetscStackAMSTakeAccess();                                                \
516     petscstackp = (PetscStack*)PetscThreadLocalGetValue(petscstack);          \
517     if (petscstackp && (petscstackp->currentsize < PETSCSTACKSIZE)) {         \
518       petscstackp->function[petscstackp->currentsize]  = funct;               \
519       petscstackp->file[petscstackp->currentsize]      = __FILE__;            \
520       petscstackp->line[petscstackp->currentsize]      = __LINE__;            \
521       petscstackp->petscroutine[petscstackp->currentsize] = petsc_routine;    \
522       petscstackp->currentsize++;                                             \
523     }                                                                         \
524     PetscStackAMSGrantAccess();                                               \
525   } while (0)
526 
527 #define PetscStackPopNoCheck                                            \
528   do {PetscStack* petscstackp;                                          \
529     PetscStackAMSTakeAccess();                                          \
530     petscstackp = (PetscStack*)PetscThreadLocalGetValue(petscstack);    \
531     if (petscstackp && petscstackp->currentsize > 0) {                  \
532       petscstackp->currentsize--;                                       \
533       petscstackp->function[petscstackp->currentsize]  = 0;             \
534       petscstackp->file[petscstackp->currentsize]      = 0;             \
535       petscstackp->line[petscstackp->currentsize]      = 0;             \
536       petscstackp->petscroutine[petscstackp->currentsize] = PETSC_FALSE;\
537     }                                                                   \
538     PetscStackAMSGrantAccess();                                         \
539   } while (0)
540 
541 /*MC
542    PetscFunctionBegin - First executable line of each PETSc function
543         used for error handling.
544 
545    Synopsis:
546    #include "petscsys.h"
547    void PetscFunctionBegin;
548 
549    Not Collective
550 
551    Usage:
552 .vb
553      int something;
554 
555      PetscFunctionBegin;
556 .ve
557 
558    Notes:
559      Not available in Fortran
560 
561    Level: developer
562 
563 .seealso: PetscFunctionReturn()
564 
565 .keywords: traceback, error handling
566 M*/
567 #define PetscFunctionBegin do {                                   \
568     PetscStackPushNoCheck(PETSC_FUNCTION_NAME,PETSC_TRUE);        \
569     PetscCheck__FUNCT__();                                        \
570     PetscRegister__FUNCT__();                                     \
571   } while (0)
572 
573 /*MC
574    PetscFunctionBeginUser - First executable line of user provided PETSc routine
575 
576    Synopsis:
577    #include "petscsys.h"
578    void PetscFunctionBeginUser;
579 
580    Not Collective
581 
582    Usage:
583 .vb
584      int something;
585 
586      PetscFunctionBegin;
587 .ve
588 
589    Notes:
590      Not available in Fortran
591 
592    Level: developer
593 
594 .seealso: PetscFunctionReturn()
595 
596 .keywords: traceback, error handling
597 M*/
598 #define PetscFunctionBeginUser                                          \
599   do {                                                                  \
600     PetscStackPushNoCheck(PETSC_FUNCTION_NAME,PETSC_FALSE);             \
601     PetscCheck__FUNCT__();                                              \
602     PetscRegister__FUNCT__();                                           \
603   } while (0)
604 
605 
606 #if defined(PETSC_SERIALIZE_FUNCTIONS)
607 #include <petsc-private/petscfptimpl.h>
608 /*
609    Registers the current function into the global function pointer to function name table
610 
611    Have to fix this to handle errors but cannot return error since used in PETSC_VIEWER_DRAW_() etc
612 */
613 #define PetscRegister__FUNCT__() do { \
614   static PetscBool __chked = PETSC_FALSE; \
615   if (!__chked) {\
616   void *ptr; PetscDLSym(NULL,__FUNCT__,&ptr);\
617   __chked = PETSC_TRUE;\
618   }} while (0)
619 #else
620 #define PetscRegister__FUNCT__()
621 #endif
622 
623 #define PetscCheck__FUNCT__() do { PetscBool _sc1,_sc2;                  \
624     PetscStrcmpNoError(PETSC_FUNCTION_NAME,__FUNCT__,&_sc1);\
625     PetscStrcmpNoError(__FUNCT__,"User provided function",&_sc2);\
626     if (!_sc1 && !_sc2) { \
627       printf("%s:%d: __FUNCT__=\"%s\" does not agree with %s=\"%s\"\n",__FILE__,__LINE__,__FUNCT__,PetscStringize(PETSC_FUNCTION_NAME),PETSC_FUNCTION_NAME); \
628     }                                                                   \
629   } while (0)
630 
631 #define PetscStackPush(n) \
632   do {                                                                  \
633     PetscStackPushNoCheck(n,PETSC_FALSE);                               \
634     CHKMEMQ;                                                            \
635   } while (0)
636 
637 #define PetscStackPop                           \
638     do {                                        \
639       CHKMEMQ;                                  \
640       PetscStackPopNoCheck;                     \
641     } while (0)
642 
643 /*MC
644    PetscFunctionReturn - Last executable line of each PETSc function
645         used for error handling. Replaces return()
646 
647    Synopsis:
648    #include "petscsys.h"
649    void PetscFunctionReturn(0);
650 
651    Not Collective
652 
653    Usage:
654 .vb
655     ....
656      PetscFunctionReturn(0);
657    }
658 .ve
659 
660    Notes:
661      Not available in Fortran
662 
663    Level: developer
664 
665 .seealso: PetscFunctionBegin()
666 
667 .keywords: traceback, error handling
668 M*/
669 #define PetscFunctionReturn(a) \
670   do {                                                                \
671     PetscStackPopNoCheck;                                             \
672     return(a);} while (0)
673 
674 #define PetscFunctionReturnVoid() \
675   do {                                                                \
676     PetscStackPopNoCheck;                                             \
677     return;} while (0)
678 
679 #else
680 
681 #if defined(PETSC_HAVE_PTHREADCLASSES)
682 #if defined(PETSC_PTHREAD_LOCAL)
683 PETSC_EXTERN PETSC_PTHREAD_LOCAL void *petscstack;
684 #else
685 PETSC_EXTERN PetscThreadKey petscstack;
686 #endif
687 #elif defined(PETSC_HAVE_OPENMP)
688 PETSC_EXTERN void *petscstack;
689 #pragma omp threadprivate(petscstack)
690 #else
691 PETSC_EXTERN void *petscstack;
692 #endif
693 
694 #define PetscStackPushNoCheck(funct,petsc_routine) do {} while (0)
695 #define PetscStackPopNoCheck                       do {} while (0)
696 #define PetscFunctionBegin
697 #define PetscFunctionBeginUser
698 #define PetscFunctionReturn(a)    return(a)
699 #define PetscFunctionReturnVoid() return
700 #define PetscStackPop             CHKMEMQ
701 #define PetscStackPush(f)         CHKMEMQ
702 #define PetscStackActive          PETSC_FALSE
703 
704 #endif
705 
706 /*
707     PetscStackCall - Calls an external library routine or user function after pushing the name of the routine on the stack.
708 
709    Input Parameters:
710 +   name - string that gives the name of the function being called
711 -   routine - actual call to the routine, including ierr = and CHKERRQ(ierr);
712 
713    Note: Often one should use PetscStackCallStandard() instead. This routine is intended for external library routines that DO NOT return error codes
714 
715    Developer Note: this is so that when a user or external library routine results in a crash or corrupts memory, they get blamed instead of PETSc.
716 
717 
718 
719 */
720 #define PetscStackCall(name,routine) do { PetscStackPush(name);routine;PetscStackPop; } while(0)
721 
722 /*
723     PetscStackCallStandard - Calls an external library routine after pushing the name of the routine on the stack.
724 
725    Input Parameters:
726 +   func-  name of the routine
727 -   args - arguments to the routine surrounded by ()
728 
729    Notes: This is intended for external package routines that return error codes. Use PetscStackCall() for those that do not.
730 
731    Developer Note: this is so that when an external packge routine results in a crash or corrupts memory, they get blamed instead of PETSc.
732 
733 */
734 #define PetscStackCallStandard(func,args) do {                        \
735     PetscStackPush(#func);ierr = func args;PetscStackPop; if (ierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in %s()",#func); \
736   } while (0)
737 
738 PETSC_EXTERN PetscErrorCode PetscStackCreate(void);
739 PETSC_EXTERN PetscErrorCode PetscStackView(FILE*);
740 PETSC_EXTERN PetscErrorCode PetscStackDestroy(void);
741 
742 #endif
743