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