xref: /petsc/src/sys/error/err.c (revision 61cc744836451fb4d1d6f02ab6992be430960ed1)
1 
2 /*
3       Code that allows one to set the error handlers
4       Portions of this code are under:
5       Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
6 */
7 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
8 #include <petscviewer.h>
9 
10 typedef struct _EH *EH;
11 struct _EH {
12   PetscErrorCode (*handler)(MPI_Comm, int, const char *, const char *, PetscErrorCode, PetscErrorType, const char *, void *);
13   void *ctx;
14   EH    previous;
15 };
16 
17 /* This is here to allow the traceback error handler (or potentially other error handlers)
18    to certify that PETSCABORT is being called on all MPI processes, and that it should be possible to call
19    MPI_Finalize() and exit().  This should only be used when `PetscCIEnabledPortabeErrorOutput == PETSC_TRUE`
20    to allow testing of error messages.  Do not rely on this for clean exit in production. */
21 PetscBool petscabortmpifinalize = PETSC_FALSE;
22 
23 static EH eh = NULL;
24 
25 /*@C
26   PetscEmacsClientErrorHandler - Error handler that uses the emacsclient program to
27   load the file where the error occurred. Then calls the "previous" error handler.
28 
29   Not Collective
30 
31   Input Parameters:
32 + comm - communicator over which error occurred
33 . line - the line number of the error (indicated by __LINE__)
34 . file - the file in which the error was detected (indicated by __FILE__)
35 . fun  - the function name
36 . mess - an error text string, usually just printed to the screen
37 . n    - the generic error number
38 . p    - specific error number
39 - ctx  - error handler context
40 
41   Options Database Key:
42 . -on_error_emacs <machinename> - will contact machinename to open the Emacs client there
43 
44   Level: developer
45 
46   Note:
47   You must put (server-start) in your .emacs file for the emacsclient software to work
48 
49   Developer Notes:
50   Since this is an error handler it cannot call `PetscCall()`; thus we just return if an error is detected.
51   But some of the functions it calls do perform error checking that may not be appropriate in a error handler call.
52 
53 .seealso: `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`,
54           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscReturnErrorHandler()`
55  @*/
56 PetscErrorCode PetscEmacsClientErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx)
57 {
58   PetscErrorCode ierr;
59   char           command[PETSC_MAX_PATH_LEN];
60   const char    *pdir;
61   FILE          *fp;
62 
63   ierr = PetscGetPetscDir(&pdir);
64   if (ierr) return ierr;
65   ierr = PetscSNPrintf(command, PETSC_STATIC_ARRAY_LENGTH(command), "cd %s; emacsclient --no-wait +%d %s\n", pdir, line, file);
66   if (ierr) return ierr;
67 #if defined(PETSC_HAVE_POPEN)
68   ierr = PetscPOpen(MPI_COMM_WORLD, (char *)ctx, command, "r", &fp);
69   if (ierr) return ierr;
70   ierr = PetscPClose(MPI_COMM_WORLD, fp);
71   if (ierr) return ierr;
72 #else
73   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
74 #endif
75   ierr = PetscPopErrorHandler();
76   if (ierr) return ierr; /* remove this handler from the stack of handlers */
77   if (!eh) {
78     ierr = PetscTraceBackErrorHandler(comm, line, fun, file, n, p, mess, NULL);
79     if (ierr) return ierr;
80   } else {
81     ierr = (*eh->handler)(comm, line, fun, file, n, p, mess, eh->ctx);
82     if (ierr) return ierr;
83   }
84   return PETSC_SUCCESS;
85 }
86 
87 /*@C
88   PetscPushErrorHandler - Sets a routine to be called on detection of errors.
89 
90   Not Collective
91 
92   Input Parameters:
93 + handler - error handler routine
94 - ctx     - optional handler context that contains information needed by the handler (for
95             example file pointers for error messages etc.)
96 
97   Calling sequence of `handler`:
98 + comm - communicator over which error occurred
99 . line - the line number of the error (indicated by __LINE__)
100 . file - the file in which the error was detected (indicated by __FILE__)
101 . fun  - the function name
102 . n    - the generic error number (see list defined in include/petscerror.h)
103 . p    - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
104 . mess - an error text string, usually just printed to the screen
105 - ctx  - the error handler context
106 
107   Options Database Keys:
108 + -on_error_attach_debugger <noxterm,gdb or dbx> - starts up the debugger if an error occurs
109 - -on_error_abort                                - aborts the program if an error occurs
110 
111   Level: intermediate
112 
113   Note:
114   The currently available PETSc error handlers include `PetscTraceBackErrorHandler()`,
115   `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, and `PetscMPIAbortErrorHandler()`, `PetscReturnErrorHandler()`.
116 
117   Fortran Notes:
118   You can only push one error handler from Fortran before popping it.
119 
120 .seealso: `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscPushSignalHandler()`
121 @*/
122 PetscErrorCode PetscPushErrorHandler(PetscErrorCode (*handler)(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx), void *ctx)
123 {
124   EH neweh;
125 
126   PetscFunctionBegin;
127   PetscCall(PetscNew(&neweh));
128   if (eh) neweh->previous = eh;
129   else neweh->previous = NULL;
130   neweh->handler = handler;
131   neweh->ctx     = ctx;
132   eh             = neweh;
133   PetscFunctionReturn(PETSC_SUCCESS);
134 }
135 
136 /*@
137   PetscPopErrorHandler - Removes the latest error handler that was
138   pushed with `PetscPushErrorHandler()`.
139 
140   Not Collective
141 
142   Level: intermediate
143 
144 .seealso: `PetscPushErrorHandler()`
145 @*/
146 PetscErrorCode PetscPopErrorHandler(void)
147 {
148   EH tmp;
149 
150   PetscFunctionBegin;
151   if (!eh) PetscFunctionReturn(PETSC_SUCCESS);
152   tmp = eh;
153   eh  = eh->previous;
154   PetscCall(PetscFree(tmp));
155   PetscFunctionReturn(PETSC_SUCCESS);
156 }
157 
158 /*@C
159   PetscReturnErrorHandler - Error handler that causes a return without printing an error message.
160 
161   Not Collective
162 
163   Input Parameters:
164 + comm - communicator over which error occurred
165 . line - the line number of the error (indicated by __LINE__)
166 . fun  - the function name
167 . file - the file in which the error was detected (indicated by __FILE__)
168 . mess - an error text string, usually just printed to the screen
169 . n    - the generic error number
170 . p    - specific error number
171 - ctx  - error handler context
172 
173   Level: developer
174 
175   Notes:
176   Most users need not directly employ this routine and the other error
177   handlers, but can instead use the simplified interface `SETERRQ()`, which has
178   the calling sequence
179 $     SETERRQ(comm, number, mess)
180 
181   `PetscIgnoreErrorHandler()` does the same thing as this function, but is deprecated, you should use this function.
182 
183   Use `PetscPushErrorHandler()` to set the desired error handler.
184 
185 .seealso: `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscError()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscTraceBackErrorHandler()`,
186           `PetscAttachDebuggerErrorHandler()`, `PetscEmacsClientErrorHandler()`
187  @*/
188 PetscErrorCode PetscReturnErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx)
189 {
190   (void)comm;
191   (void)line;
192   (void)fun;
193   (void)file;
194   (void)p;
195   (void)mess;
196   (void)ctx;
197   return n;
198 }
199 
200 static char PetscErrorBaseMessage[1024];
201 /*
202        The numerical values for these are defined in include/petscerror.h; any changes
203    there must also be made here
204 */
205 static const char *PetscErrorStrings[] = {
206   /*55 */ "Out of memory",
207   "No support for this operation for this object type",
208   "No support for this operation on this system",
209   /*58 */ "Operation done in wrong order",
210   /*59 */ "Signal received",
211   /*60 */ "Nonconforming object sizes",
212   "Argument aliasing not permitted",
213   "Invalid argument",
214   /*63 */ "Argument out of range",
215   "Corrupt argument: https://petsc.org/release/faq/#valgrind",
216   "Unable to open file",
217   "Read from file failed",
218   "Write to file failed",
219   "Invalid pointer",
220   /*69 */ "Arguments must have same type",
221   /*70 */ "Attempt to use a pointer that does not point to a valid accessible location",
222   /*71 */ "Zero pivot in LU factorization: https://petsc.org/release/faq/#zeropivot",
223   /*72 */ "Floating point exception",
224   /*73 */ "Object is in wrong state",
225   "Corrupted Petsc object",
226   "Arguments are incompatible",
227   "Error in external library",
228   /*77 */ "Petsc has generated inconsistent data",
229   "Memory corruption: https://petsc.org/release/faq/#valgrind",
230   "Unexpected data in file",
231   /*80 */ "Arguments must have same communicators",
232   /*81 */ "Zero pivot in Cholesky factorization: https://petsc.org/release/faq/#zeropivot",
233   "",
234   "",
235   "Overflow in integer operation: https://petsc.org/release/faq/#64-bit-indices",
236   /*85 */ "Null argument, when expecting valid pointer",
237   /*86 */ "Unknown type. Check for miss-spelling or missing package: https://petsc.org/release/install/install/#external-packages",
238   /*87 */ "MPI library at runtime is not compatible with MPI used at compile time",
239   /*88 */ "Error in system call",
240   /*89 */ "Object Type not set: https://petsc.org/release/faq/#object-type-not-set",
241   /*90 */ "",
242   /*   */ "",
243   /*92 */ "See https://petsc.org/release/overview/linear_solve_table/ for possible LU and Cholesky solvers",
244   /*93 */ "You cannot overwrite this option since that will conflict with other previously set options",
245   /*94 */ "Example/application run with number of MPI ranks it does not support",
246   /*95 */ "Missing or incorrect user input",
247   /*96 */ "GPU resources unavailable",
248   /*97 */ "GPU error",
249   /*98 */ "General MPI error",
250   /*99 */ "PetscError() incorrectly returned an error code of 0"};
251 
252 /*@C
253   PetscErrorMessage - Returns the text string associated with a PETSc error code.
254 
255   Not Collective
256 
257   Input Parameter:
258 . errnum - the error code
259 
260   Output Parameters:
261 + text     - the error message (`NULL` if not desired)
262 - specific - the specific error message that was set with `SETERRQ()` or
263              `PetscError()`. (`NULL` if not desired)
264 
265   Level: developer
266 
267 .seealso: `PetscErrorCode`, `PetscPushErrorHandler()`, `PetscAttachDebuggerErrorHandler()`,
268 `PetscError()`, `SETERRQ()`, `PetscCall()` `PetscAbortErrorHandler()`,
269 `PetscTraceBackErrorHandler()`
270 @*/
271 PetscErrorCode PetscErrorMessage(PetscErrorCode errnum, const char *text[], char **specific)
272 {
273   PetscFunctionBegin;
274   if (text) {
275     if (errnum > PETSC_ERR_MIN_VALUE && errnum < PETSC_ERR_MAX_VALUE) {
276       size_t len;
277 
278       *text = PetscErrorStrings[errnum - PETSC_ERR_MIN_VALUE - 1];
279       PetscCall(PetscStrlen(*text, &len));
280       if (!len) *text = NULL;
281     } else if (errnum == PETSC_ERR_BOOLEAN_MACRO_FAILURE) {
282       /* this "error code" arises from failures in boolean macros, where the || operator is
283          used to short-circuit the macro call in case of error. This has the side effect of
284          "returning" either 0 (PETSC_SUCCESS) or 1 (PETSC_ERR_UNKNONWN):
285 
286          #define PETSC_FOO(x) ((PetscErrorCode)(PetscBar(x) || PetscBaz(x)))
287 
288          If PetscBar() fails (returns nonzero) PetscBaz() is not executed but the result of
289          this expression is boolean false, hence PETSC_ERR_UNNOWN
290        */
291       *text = "Error occurred in boolean shortcuit in macro";
292     } else {
293       *text = NULL;
294     }
295   }
296   if (specific) *specific = PetscErrorBaseMessage;
297   PetscFunctionReturn(PETSC_SUCCESS);
298 }
299 
300 #if defined(PETSC_CLANGUAGE_CXX)
301   /* C++ exceptions are formally not allowed to propagate through extern "C" code. In practice, far too much software
302  * would be broken if implementations did not handle it it some common cases. However, keep in mind
303  *
304  *   Rule 62. Don't allow exceptions to propagate across module boundaries
305  *
306  * in "C++ Coding Standards" by Sutter and Alexandrescu. (This accounts for part of the ongoing C++ binary interface
307  * instability.) Having PETSc raise errors as C++ exceptions was probably misguided and should eventually be removed.
308  *
309  * Here is the problem: You have a C++ function call a PETSc function, and you would like to maintain the error message
310  * and stack information from the PETSc error. You could make everyone write exactly this code in their C++, but that
311  * seems crazy to me.
312  */
313   #include <sstream>
314   #include <stdexcept>
315 static void PetscCxxErrorThrow()
316 {
317   const char *str;
318   if (eh && eh->ctx) {
319     std::ostringstream *msg;
320     msg = (std::ostringstream *)eh->ctx;
321     str = msg->str().c_str();
322   } else str = "Error detected in C PETSc";
323 
324   throw std::runtime_error(str);
325 }
326 #endif
327 
328 /*@C
329   PetscError - Routine that is called when an error has been detected, usually called through the macro SETERRQ(PETSC_COMM_SELF,).
330 
331   Collective
332 
333   Input Parameters:
334 + comm - communicator over which error occurred.  ALL ranks of this communicator MUST call this routine
335 . line - the line number of the error (indicated by __LINE__)
336 . func - the function name in which the error was detected
337 . file - the file in which the error was detected (indicated by __FILE__)
338 . n    - the generic error number
339 . p    - `PETSC_ERROR_INITIAL` indicates the error was initially detected, `PETSC_ERROR_REPEAT` indicates this is a traceback from a previously detected error
340 - mess - formatted message string - aka printf
341 
342   Options Database Keys:
343 + -error_output_stdout - output the error messages to stdout instead of the default stderr
344 - -error_output_none   - do not output the error messages
345 
346   Level: intermediate
347 
348   Notes:
349   PETSc error handling is done with error return codes. A non-zero return indicates an error
350   was detected. The return-value of this routine is what is ultimately returned by
351   `SETERRQ()`.
352 
353   Note that numerical errors (potential divide by zero, for example) are not managed by the
354   error return codes; they are managed via, for example, `KSPGetConvergedReason()` that
355   indicates if the solve was successful or not. The option `-ksp_error_if_not_converged`, for
356   example, turns numerical failures into hard errors managed via `PetscError()`.
357 
358   PETSc provides a rich supply of error handlers, see the list below, and users can also
359   provide their own error handlers.
360 
361   If the user sets their own error handler (via `PetscPushErrorHandler()`) they may return any
362   arbitrary value from it, but are encouraged to return nonzero values. If the return value is
363   zero, `SETERRQ()` will ignore the value and return `PETSC_ERR_RETURN` (a nonzero value)
364   instead.
365 
366   Most users need not directly use this routine and the error handlers, but can instead use
367   the simplified interface `PetscCall()` or `SETERRQ()`.
368 
369   Fortran Notes:
370   This routine is used differently from Fortran
371 $    PetscError(MPI_Comm comm, PetscErrorCode n, PetscErrorType p, char *message)
372 
373   Developer Notes:
374   Since this is called after an error condition it should not be calling any error handlers (currently it ignores any error codes)
375   BUT this routine does call regular PETSc functions that may call error handlers, this is problematic and could be fixed by never calling other PETSc routines
376   but this annoying.
377 
378 .seealso: `PetscErrorCode`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`,
379           `PetscReturnErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscEmacsClientErrorHandler()`,
380           `SETERRQ()`, `PetscCall()`, `CHKMEMQ`, `PetscErrorMessage()`, `PETSCABORT()`
381 @*/
382 PetscErrorCode PetscError(MPI_Comm comm, int line, const char *func, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, ...)
383 {
384   va_list        Argp;
385   size_t         fullLength;
386   char           buf[2048], *lbuf = NULL;
387   PetscBool      ismain;
388   PetscErrorCode ierr;
389 
390   if (!PetscErrorHandlingInitialized) return n;
391   if (comm == MPI_COMM_NULL) comm = PETSC_COMM_SELF;
392 
393   /* Compose the message evaluating the print format */
394   if (mess) {
395     va_start(Argp, mess);
396     ierr = PetscVSNPrintf(buf, 2048, mess, &fullLength, Argp);
397     va_end(Argp);
398     lbuf = buf;
399     if (p == PETSC_ERROR_INITIAL) ierr = PetscStrncpy(PetscErrorBaseMessage, lbuf, sizeof(PetscErrorBaseMessage));
400   }
401 
402   if (p == PETSC_ERROR_INITIAL && n != PETSC_ERR_MEMC) ierr = PetscMallocValidate(__LINE__, PETSC_FUNCTION_NAME, __FILE__);
403 
404   if (!eh) ierr = PetscTraceBackErrorHandler(comm, line, func, file, n, p, lbuf, NULL);
405   else ierr = (*eh->handler)(comm, line, func, file, n, p, lbuf, eh->ctx);
406   PetscStackClearTop;
407 
408   /*
409       If this is called from the main() routine we abort the program.
410       We cannot just return because them some MPI processes may continue to attempt to run
411       while this process simply exits.
412   */
413   if (func) {
414     PetscErrorCode cmp_ierr = PetscStrncmp(func, "main", 4, &ismain);
415     if (ismain) {
416       if (petscwaitonerrorflg) cmp_ierr = PetscSleep(1000);
417       (void)cmp_ierr;
418       PETSCABORT(comm, ierr);
419     }
420   }
421 #if defined(PETSC_CLANGUAGE_CXX)
422   if (p == PETSC_ERROR_IN_CXX) PetscCxxErrorThrow();
423 #endif
424   return ierr;
425 }
426 
427 /* -------------------------------------------------------------------------*/
428 
429 /*@C
430   PetscIntView - Prints an array of integers; useful for debugging.
431 
432   Collective
433 
434   Input Parameters:
435 + N      - number of integers in array
436 . idx    - array of integers
437 - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
438 
439   Level: intermediate
440 
441   Note:
442   This may be called from within the debugger
443 
444   Developer Notes:
445   idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done
446 
447 .seealso: `PetscViewer`, `PetscRealView()`
448 @*/
449 PetscErrorCode PetscIntView(PetscInt N, const PetscInt idx[], PetscViewer viewer)
450 {
451   PetscMPIInt rank, size;
452   PetscInt    j, i, n = N / 20, p = N % 20;
453   PetscBool   iascii, isbinary;
454   MPI_Comm    comm;
455 
456   PetscFunctionBegin;
457   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
458   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3);
459   if (N) PetscAssertPointer(idx, 2);
460   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
461   PetscCallMPI(MPI_Comm_size(comm, &size));
462   PetscCallMPI(MPI_Comm_rank(comm, &rank));
463 
464   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
465   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
466   if (iascii) {
467     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
468     for (i = 0; i < n; i++) {
469       if (size > 1) {
470         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * i));
471       } else {
472         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * i));
473       }
474       for (j = 0; j < 20; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[i * 20 + j]));
475       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
476     }
477     if (p) {
478       if (size > 1) {
479         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * n));
480       } else {
481         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * n));
482       }
483       for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[20 * n + i]));
484       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
485     }
486     PetscCall(PetscViewerFlush(viewer));
487     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
488   } else if (isbinary) {
489     PetscMPIInt *sizes, Ntotal, *displs, NN;
490     PetscInt    *array;
491 
492     PetscCall(PetscMPIIntCast(N, &NN));
493 
494     if (size > 1) {
495       if (rank) {
496         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
497         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, NULL, NULL, NULL, MPIU_INT, 0, comm));
498       } else {
499         PetscCall(PetscMalloc1(size, &sizes));
500         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
501         Ntotal = sizes[0];
502         PetscCall(PetscMalloc1(size, &displs));
503         displs[0] = 0;
504         for (i = 1; i < size; i++) {
505           Ntotal += sizes[i];
506           displs[i] = displs[i - 1] + sizes[i - 1];
507         }
508         PetscCall(PetscMalloc1(Ntotal, &array));
509         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, array, sizes, displs, MPIU_INT, 0, comm));
510         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_INT));
511         PetscCall(PetscFree(sizes));
512         PetscCall(PetscFree(displs));
513         PetscCall(PetscFree(array));
514       }
515     } else {
516       PetscCall(PetscViewerBinaryWrite(viewer, idx, N, PETSC_INT));
517     }
518   } else {
519     const char *tname;
520     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
521     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
522   }
523   PetscFunctionReturn(PETSC_SUCCESS);
524 }
525 
526 /*@C
527   PetscRealView - Prints an array of doubles; useful for debugging.
528 
529   Collective
530 
531   Input Parameters:
532 + N      - number of `PetscReal` in array
533 . idx    - array of `PetscReal`
534 - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
535 
536   Level: intermediate
537 
538   Note:
539   This may be called from within the debugger
540 
541   Developer Notes:
542   idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done
543 
544 .seealso: `PetscViewer`, `PetscIntView()`
545 @*/
546 PetscErrorCode PetscRealView(PetscInt N, const PetscReal idx[], PetscViewer viewer)
547 {
548   PetscMPIInt rank, size;
549   PetscInt    j, i, n = N / 5, p = N % 5;
550   PetscBool   iascii, isbinary;
551   MPI_Comm    comm;
552 
553   PetscFunctionBegin;
554   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
555   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3);
556   PetscAssertPointer(idx, 2);
557   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
558   PetscCallMPI(MPI_Comm_size(comm, &size));
559   PetscCallMPI(MPI_Comm_rank(comm, &rank));
560 
561   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
562   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
563   if (iascii) {
564     PetscInt tab;
565 
566     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
567     PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
568     for (i = 0; i < n; i++) {
569       PetscCall(PetscViewerASCIISetTab(viewer, tab));
570       if (size > 1) {
571         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * i));
572       } else {
573         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * i));
574       }
575       PetscCall(PetscViewerASCIISetTab(viewer, 0));
576       for (j = 0; j < 5; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 5 + j]));
577       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
578     }
579     if (p) {
580       PetscCall(PetscViewerASCIISetTab(viewer, tab));
581       if (size > 1) {
582         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * n));
583       } else {
584         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * n));
585       }
586       PetscCall(PetscViewerASCIISetTab(viewer, 0));
587       for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[5 * n + i]));
588       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
589     }
590     PetscCall(PetscViewerFlush(viewer));
591     PetscCall(PetscViewerASCIISetTab(viewer, tab));
592     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
593   } else if (isbinary) {
594     PetscMPIInt *sizes, *displs, Ntotal, NN;
595     PetscReal   *array;
596 
597     PetscCall(PetscMPIIntCast(N, &NN));
598 
599     if (size > 1) {
600       if (rank) {
601         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
602         PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, NULL, NULL, NULL, MPIU_REAL, 0, comm));
603       } else {
604         PetscCall(PetscMalloc1(size, &sizes));
605         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
606         Ntotal = sizes[0];
607         PetscCall(PetscMalloc1(size, &displs));
608         displs[0] = 0;
609         for (i = 1; i < size; i++) {
610           Ntotal += sizes[i];
611           displs[i] = displs[i - 1] + sizes[i - 1];
612         }
613         PetscCall(PetscMalloc1(Ntotal, &array));
614         PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, array, sizes, displs, MPIU_REAL, 0, comm));
615         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_REAL));
616         PetscCall(PetscFree(sizes));
617         PetscCall(PetscFree(displs));
618         PetscCall(PetscFree(array));
619       }
620     } else {
621       PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_REAL));
622     }
623   } else {
624     const char *tname;
625     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
626     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
627   }
628   PetscFunctionReturn(PETSC_SUCCESS);
629 }
630 
631 /*@C
632   PetscScalarView - Prints an array of `PetscScalar`; useful for debugging.
633 
634   Collective
635 
636   Input Parameters:
637 + N      - number of scalars in array
638 . idx    - array of scalars
639 - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
640 
641   Level: intermediate
642 
643   Note:
644   This may be called from within the debugger
645 
646   Developer Notes:
647   idx cannot be const because may be passed to binary viewer where byte swapping may be done
648 
649 .seealso: `PetscViewer`, `PetscIntView()`, `PetscRealView()`
650 @*/
651 PetscErrorCode PetscScalarView(PetscInt N, const PetscScalar idx[], PetscViewer viewer)
652 {
653   PetscMPIInt rank, size;
654   PetscInt    j, i, n = N / 3, p = N % 3;
655   PetscBool   iascii, isbinary;
656   MPI_Comm    comm;
657 
658   PetscFunctionBegin;
659   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
660   PetscValidHeader(viewer, 3);
661   if (N) PetscAssertPointer(idx, 2);
662   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
663   PetscCallMPI(MPI_Comm_size(comm, &size));
664   PetscCallMPI(MPI_Comm_rank(comm, &rank));
665 
666   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
667   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
668   if (iascii) {
669     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
670     for (i = 0; i < n; i++) {
671       if (size > 1) {
672         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * i));
673       } else {
674         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * i));
675       }
676       for (j = 0; j < 3; j++) {
677 #if defined(PETSC_USE_COMPLEX)
678         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[i * 3 + j]), (double)PetscImaginaryPart(idx[i * 3 + j])));
679 #else
680         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 3 + j]));
681 #endif
682       }
683       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
684     }
685     if (p) {
686       if (size > 1) {
687         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * n));
688       } else {
689         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * n));
690       }
691       for (i = 0; i < p; i++) {
692 #if defined(PETSC_USE_COMPLEX)
693         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[n * 3 + i]), (double)PetscImaginaryPart(idx[n * 3 + i])));
694 #else
695         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[3 * n + i]));
696 #endif
697       }
698       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
699     }
700     PetscCall(PetscViewerFlush(viewer));
701     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
702   } else if (isbinary) {
703     PetscMPIInt *sizes, Ntotal, *displs, NN;
704     PetscScalar *array;
705 
706     PetscCall(PetscMPIIntCast(N, &NN));
707 
708     if (size > 1) {
709       if (rank) {
710         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
711         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, NULL, NULL, NULL, MPIU_SCALAR, 0, comm));
712       } else {
713         PetscCall(PetscMalloc1(size, &sizes));
714         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
715         Ntotal = sizes[0];
716         PetscCall(PetscMalloc1(size, &displs));
717         displs[0] = 0;
718         for (i = 1; i < size; i++) {
719           Ntotal += sizes[i];
720           displs[i] = displs[i - 1] + sizes[i - 1];
721         }
722         PetscCall(PetscMalloc1(Ntotal, &array));
723         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, array, sizes, displs, MPIU_SCALAR, 0, comm));
724         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_SCALAR));
725         PetscCall(PetscFree(sizes));
726         PetscCall(PetscFree(displs));
727         PetscCall(PetscFree(array));
728       }
729     } else {
730       PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_SCALAR));
731     }
732   } else {
733     const char *tname;
734     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
735     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
736   }
737   PetscFunctionReturn(PETSC_SUCCESS);
738 }
739 
740 #if defined(PETSC_HAVE_CUDA)
741   #include <petscdevice_cuda.h>
742 PETSC_EXTERN const char *PetscCUBLASGetErrorName(cublasStatus_t status)
743 {
744   switch (status) {
745   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
746   case CUBLAS_STATUS_SUCCESS:
747     return "CUBLAS_STATUS_SUCCESS";
748   case CUBLAS_STATUS_NOT_INITIALIZED:
749     return "CUBLAS_STATUS_NOT_INITIALIZED";
750   case CUBLAS_STATUS_ALLOC_FAILED:
751     return "CUBLAS_STATUS_ALLOC_FAILED";
752   case CUBLAS_STATUS_INVALID_VALUE:
753     return "CUBLAS_STATUS_INVALID_VALUE";
754   case CUBLAS_STATUS_ARCH_MISMATCH:
755     return "CUBLAS_STATUS_ARCH_MISMATCH";
756   case CUBLAS_STATUS_MAPPING_ERROR:
757     return "CUBLAS_STATUS_MAPPING_ERROR";
758   case CUBLAS_STATUS_EXECUTION_FAILED:
759     return "CUBLAS_STATUS_EXECUTION_FAILED";
760   case CUBLAS_STATUS_INTERNAL_ERROR:
761     return "CUBLAS_STATUS_INTERNAL_ERROR";
762   case CUBLAS_STATUS_NOT_SUPPORTED:
763     return "CUBLAS_STATUS_NOT_SUPPORTED";
764   case CUBLAS_STATUS_LICENSE_ERROR:
765     return "CUBLAS_STATUS_LICENSE_ERROR";
766   #endif
767   default:
768     return "unknown error";
769   }
770 }
771 PETSC_EXTERN const char *PetscCUSolverGetErrorName(cusolverStatus_t status)
772 {
773   switch (status) {
774   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
775   case CUSOLVER_STATUS_SUCCESS:
776     return "CUSOLVER_STATUS_SUCCESS";
777   case CUSOLVER_STATUS_NOT_INITIALIZED:
778     return "CUSOLVER_STATUS_NOT_INITIALIZED";
779   case CUSOLVER_STATUS_INVALID_VALUE:
780     return "CUSOLVER_STATUS_INVALID_VALUE";
781   case CUSOLVER_STATUS_ARCH_MISMATCH:
782     return "CUSOLVER_STATUS_ARCH_MISMATCH";
783   case CUSOLVER_STATUS_INTERNAL_ERROR:
784     return "CUSOLVER_STATUS_INTERNAL_ERROR";
785     #if (CUDART_VERSION >= 9000) /* CUDA 9.0 had these defined on June 2021 */
786   case CUSOLVER_STATUS_ALLOC_FAILED:
787     return "CUSOLVER_STATUS_ALLOC_FAILED";
788   case CUSOLVER_STATUS_MAPPING_ERROR:
789     return "CUSOLVER_STATUS_MAPPING_ERROR";
790   case CUSOLVER_STATUS_EXECUTION_FAILED:
791     return "CUSOLVER_STATUS_EXECUTION_FAILED";
792   case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
793     return "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
794   case CUSOLVER_STATUS_NOT_SUPPORTED:
795     return "CUSOLVER_STATUS_NOT_SUPPORTED ";
796   case CUSOLVER_STATUS_ZERO_PIVOT:
797     return "CUSOLVER_STATUS_ZERO_PIVOT";
798   case CUSOLVER_STATUS_INVALID_LICENSE:
799     return "CUSOLVER_STATUS_INVALID_LICENSE";
800     #endif
801   #endif
802   default:
803     return "unknown error";
804   }
805 }
806 PETSC_EXTERN const char *PetscCUFFTGetErrorName(cufftResult result)
807 {
808   switch (result) {
809   case CUFFT_SUCCESS:
810     return "CUFFT_SUCCESS";
811   case CUFFT_INVALID_PLAN:
812     return "CUFFT_INVALID_PLAN";
813   case CUFFT_ALLOC_FAILED:
814     return "CUFFT_ALLOC_FAILED";
815   case CUFFT_INVALID_TYPE:
816     return "CUFFT_INVALID_TYPE";
817   case CUFFT_INVALID_VALUE:
818     return "CUFFT_INVALID_VALUE";
819   case CUFFT_INTERNAL_ERROR:
820     return "CUFFT_INTERNAL_ERROR";
821   case CUFFT_EXEC_FAILED:
822     return "CUFFT_EXEC_FAILED";
823   case CUFFT_SETUP_FAILED:
824     return "CUFFT_SETUP_FAILED";
825   case CUFFT_INVALID_SIZE:
826     return "CUFFT_INVALID_SIZE";
827   case CUFFT_UNALIGNED_DATA:
828     return "CUFFT_UNALIGNED_DATA";
829   case CUFFT_INCOMPLETE_PARAMETER_LIST:
830     return "CUFFT_INCOMPLETE_PARAMETER_LIST";
831   case CUFFT_INVALID_DEVICE:
832     return "CUFFT_INVALID_DEVICE";
833   case CUFFT_PARSE_ERROR:
834     return "CUFFT_PARSE_ERROR";
835   case CUFFT_NO_WORKSPACE:
836     return "CUFFT_NO_WORKSPACE";
837   case CUFFT_NOT_IMPLEMENTED:
838     return "CUFFT_NOT_IMPLEMENTED";
839   case CUFFT_LICENSE_ERROR:
840     return "CUFFT_LICENSE_ERROR";
841   case CUFFT_NOT_SUPPORTED:
842     return "CUFFT_NOT_SUPPORTED";
843   default:
844     return "unknown error";
845   }
846 }
847 #endif
848 
849 #if defined(PETSC_HAVE_HIP)
850   #include <petscdevice_hip.h>
851 PETSC_EXTERN const char *PetscHIPBLASGetErrorName(hipblasStatus_t status)
852 {
853   switch (status) {
854   case HIPBLAS_STATUS_SUCCESS:
855     return "HIPBLAS_STATUS_SUCCESS";
856   case HIPBLAS_STATUS_NOT_INITIALIZED:
857     return "HIPBLAS_STATUS_NOT_INITIALIZED";
858   case HIPBLAS_STATUS_ALLOC_FAILED:
859     return "HIPBLAS_STATUS_ALLOC_FAILED";
860   case HIPBLAS_STATUS_INVALID_VALUE:
861     return "HIPBLAS_STATUS_INVALID_VALUE";
862   case HIPBLAS_STATUS_ARCH_MISMATCH:
863     return "HIPBLAS_STATUS_ARCH_MISMATCH";
864   case HIPBLAS_STATUS_MAPPING_ERROR:
865     return "HIPBLAS_STATUS_MAPPING_ERROR";
866   case HIPBLAS_STATUS_EXECUTION_FAILED:
867     return "HIPBLAS_STATUS_EXECUTION_FAILED";
868   case HIPBLAS_STATUS_INTERNAL_ERROR:
869     return "HIPBLAS_STATUS_INTERNAL_ERROR";
870   case HIPBLAS_STATUS_NOT_SUPPORTED:
871     return "HIPBLAS_STATUS_NOT_SUPPORTED";
872   default:
873     return "unknown error";
874   }
875 }
876 PETSC_EXTERN const char *PetscHIPSPARSEGetErrorName(hipsparseStatus_t status)
877 {
878   switch (status) {
879   case HIPSPARSE_STATUS_SUCCESS:
880     return "HIPSPARSE_STATUS_SUCCESS";
881   case HIPSPARSE_STATUS_NOT_INITIALIZED:
882     return "HIPSPARSE_STATUS_NOT_INITIALIZED";
883   case HIPSPARSE_STATUS_ALLOC_FAILED:
884     return "HIPSPARSE_STATUS_ALLOC_FAILED";
885   case HIPSPARSE_STATUS_INVALID_VALUE:
886     return "HIPSPARSE_STATUS_INVALID_VALUE";
887   case HIPSPARSE_STATUS_ARCH_MISMATCH:
888     return "HIPSPARSE_STATUS_ARCH_MISMATCH";
889   case HIPSPARSE_STATUS_MAPPING_ERROR:
890     return "HIPSPARSE_STATUS_MAPPING_ERROR";
891   case HIPSPARSE_STATUS_EXECUTION_FAILED:
892     return "HIPSPARSE_STATUS_EXECUTION_FAILED";
893   case HIPSPARSE_STATUS_INTERNAL_ERROR:
894     return "HIPSPARSE_STATUS_INTERNAL_ERROR";
895   case HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
896     return "HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
897   case HIPSPARSE_STATUS_ZERO_PIVOT:
898     return "HIPSPARSE_STATUS_ZERO_PIVOT";
899   case HIPSPARSE_STATUS_NOT_SUPPORTED:
900     return "HIPSPARSE_STATUS_NOT_SUPPORTED";
901   case HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES:
902     return "HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES";
903   default:
904     return "unknown error";
905   }
906 }
907 PETSC_EXTERN const char *PetscHIPSolverGetErrorName(hipsolverStatus_t status)
908 {
909   switch (status) {
910   case HIPSOLVER_STATUS_SUCCESS:
911     return "HIPSOLVER_STATUS_SUCCESS";
912   case HIPSOLVER_STATUS_NOT_INITIALIZED:
913     return "HIPSOLVER_STATUS_NOT_INITIALIZED";
914   case HIPSOLVER_STATUS_ALLOC_FAILED:
915     return "HIPSOLVER_STATUS_ALLOC_FAILED";
916   case HIPSOLVER_STATUS_MAPPING_ERROR:
917     return "HIPSOLVER_STATUS_MAPPING_ERROR";
918   case HIPSOLVER_STATUS_INVALID_VALUE:
919     return "HIPSOLVER_STATUS_INVALID_VALUE";
920   case HIPSOLVER_STATUS_EXECUTION_FAILED:
921     return "HIPSOLVER_STATUS_EXECUTION_FAILED";
922   case HIPSOLVER_STATUS_INTERNAL_ERROR:
923     return "HIPSOLVER_STATUS_INTERNAL_ERROR";
924   case HIPSOLVER_STATUS_NOT_SUPPORTED:
925     return "HIPSOLVER_STATUS_NOT_SUPPORTED ";
926   case HIPSOLVER_STATUS_ARCH_MISMATCH:
927     return "HIPSOLVER_STATUS_ARCH_MISMATCH";
928   case HIPSOLVER_STATUS_HANDLE_IS_NULLPTR:
929     return "HIPSOLVER_STATUS_HANDLE_IS_NULLPTR";
930   case HIPSOLVER_STATUS_INVALID_ENUM:
931     return "HIPSOLVER_STATUS_INVALID_ENUM";
932   case HIPSOLVER_STATUS_UNKNOWN:
933   default:
934     return "HIPSOLVER_STATUS_UNKNOWN";
935   }
936 }
937 #endif
938 
939 /*@C
940   PetscMPIErrorString - Given an MPI error code returns the `MPI_Error_string()` appropriately
941   formatted for displaying with the PETSc error handlers.
942 
943   Input Parameter:
944 . err - the MPI error code
945 
946   Output Parameter:
947 . string - the MPI error message, should declare its length to be larger than `MPI_MAX_ERROR_STRING`
948 
949   Level: developer
950 
951   Note:
952   Does not return an error code or do error handling because it may be called from inside an error handler
953 
954 .seealso: `PetscErrorCode` `PetscErrorMessage()`
955 @*/
956 void PetscMPIErrorString(PetscMPIInt err, char *string)
957 {
958   char        errorstring[MPI_MAX_ERROR_STRING];
959   PetscMPIInt len, j = 0;
960 
961   MPI_Error_string(err, (char *)errorstring, &len);
962   for (PetscMPIInt i = 0; i < len; i++) {
963     string[j++] = errorstring[i];
964     if (errorstring[i] == '\n') {
965       for (PetscMPIInt k = 0; k < 16; k++) string[j++] = ' ';
966     }
967   }
968   string[j] = 0;
969 }
970