xref: /petsc/src/sys/error/err.c (revision 27f49a208b01d2e827ab9db411a2d16003fe9262)
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 poping 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 call MPI_Abort() instead of
395     return to allow the parallel program to be properly shutdown.
396 
397     Does not call PETSCABORT() since that would provide the wrong source file and line number information
398   */
399   if (func) {
400     PetscErrorCode cmp_ierr = PetscStrncmp(func, "main", 4, &ismain);
401     if (ismain) {
402       if (petscwaitonerrorflg) cmp_ierr = PetscSleep(1000);
403       (void)cmp_ierr;
404       PETSCABORT(comm, ierr);
405     }
406   }
407 #if defined(PETSC_CLANGUAGE_CXX)
408   if (p == PETSC_ERROR_IN_CXX) PetscCxxErrorThrow();
409 #endif
410   return ierr;
411 }
412 
413 /* -------------------------------------------------------------------------*/
414 
415 /*@C
416     PetscIntView - Prints an array of integers; useful for debugging.
417 
418     Collective
419 
420     Input Parameters:
421 +   N - number of integers in array
422 .   idx - array of integers
423 -   viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
424 
425   Level: intermediate
426 
427     Note:
428     This may be called from within the debugger
429 
430     Developer Note:
431     idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done
432 
433 .seealso: `PetscViewer`, `PetscRealView()`
434 @*/
435 PetscErrorCode PetscIntView(PetscInt N, const PetscInt idx[], PetscViewer viewer)
436 {
437   PetscMPIInt rank, size;
438   PetscInt    j, i, n = N / 20, p = N % 20;
439   PetscBool   iascii, isbinary;
440   MPI_Comm    comm;
441 
442   PetscFunctionBegin;
443   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
444   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3);
445   if (N) PetscValidIntPointer(idx, 2);
446   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
447   PetscCallMPI(MPI_Comm_size(comm, &size));
448   PetscCallMPI(MPI_Comm_rank(comm, &rank));
449 
450   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
451   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
452   if (iascii) {
453     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
454     for (i = 0; i < n; i++) {
455       if (size > 1) {
456         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * i));
457       } else {
458         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * i));
459       }
460       for (j = 0; j < 20; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[i * 20 + j]));
461       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
462     }
463     if (p) {
464       if (size > 1) {
465         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * n));
466       } else {
467         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * n));
468       }
469       for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[20 * n + i]));
470       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
471     }
472     PetscCall(PetscViewerFlush(viewer));
473     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
474   } else if (isbinary) {
475     PetscMPIInt *sizes, Ntotal, *displs, NN;
476     PetscInt    *array;
477 
478     PetscCall(PetscMPIIntCast(N, &NN));
479 
480     if (size > 1) {
481       if (rank) {
482         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
483         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, NULL, NULL, NULL, MPIU_INT, 0, comm));
484       } else {
485         PetscCall(PetscMalloc1(size, &sizes));
486         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
487         Ntotal = sizes[0];
488         PetscCall(PetscMalloc1(size, &displs));
489         displs[0] = 0;
490         for (i = 1; i < size; i++) {
491           Ntotal += sizes[i];
492           displs[i] = displs[i - 1] + sizes[i - 1];
493         }
494         PetscCall(PetscMalloc1(Ntotal, &array));
495         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, array, sizes, displs, MPIU_INT, 0, comm));
496         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_INT));
497         PetscCall(PetscFree(sizes));
498         PetscCall(PetscFree(displs));
499         PetscCall(PetscFree(array));
500       }
501     } else {
502       PetscCall(PetscViewerBinaryWrite(viewer, idx, N, PETSC_INT));
503     }
504   } else {
505     const char *tname;
506     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
507     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
508   }
509   PetscFunctionReturn(PETSC_SUCCESS);
510 }
511 
512 /*@C
513     PetscRealView - Prints an array of doubles; useful for debugging.
514 
515     Collective
516 
517     Input Parameters:
518 +   N - number of `PetscReal` in array
519 .   idx - array of `PetscReal`
520 -   viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
521 
522   Level: intermediate
523 
524     Note:
525     This may be called from within the debugger
526 
527     Developer Note:
528     idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done
529 
530 .seealso: `PetscViewer`, `PetscIntView()`
531 @*/
532 PetscErrorCode PetscRealView(PetscInt N, const PetscReal idx[], PetscViewer viewer)
533 {
534   PetscMPIInt rank, size;
535   PetscInt    j, i, n = N / 5, p = N % 5;
536   PetscBool   iascii, isbinary;
537   MPI_Comm    comm;
538 
539   PetscFunctionBegin;
540   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
541   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3);
542   PetscValidRealPointer(idx, 2);
543   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
544   PetscCallMPI(MPI_Comm_size(comm, &size));
545   PetscCallMPI(MPI_Comm_rank(comm, &rank));
546 
547   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
548   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
549   if (iascii) {
550     PetscInt tab;
551 
552     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
553     PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
554     for (i = 0; i < n; i++) {
555       PetscCall(PetscViewerASCIISetTab(viewer, tab));
556       if (size > 1) {
557         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * i));
558       } else {
559         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * i));
560       }
561       PetscCall(PetscViewerASCIISetTab(viewer, 0));
562       for (j = 0; j < 5; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 5 + j]));
563       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
564     }
565     if (p) {
566       PetscCall(PetscViewerASCIISetTab(viewer, tab));
567       if (size > 1) {
568         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * n));
569       } else {
570         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * n));
571       }
572       PetscCall(PetscViewerASCIISetTab(viewer, 0));
573       for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[5 * n + i]));
574       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
575     }
576     PetscCall(PetscViewerFlush(viewer));
577     PetscCall(PetscViewerASCIISetTab(viewer, tab));
578     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
579   } else if (isbinary) {
580     PetscMPIInt *sizes, *displs, Ntotal, NN;
581     PetscReal   *array;
582 
583     PetscCall(PetscMPIIntCast(N, &NN));
584 
585     if (size > 1) {
586       if (rank) {
587         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
588         PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, NULL, NULL, NULL, MPIU_REAL, 0, comm));
589       } else {
590         PetscCall(PetscMalloc1(size, &sizes));
591         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
592         Ntotal = sizes[0];
593         PetscCall(PetscMalloc1(size, &displs));
594         displs[0] = 0;
595         for (i = 1; i < size; i++) {
596           Ntotal += sizes[i];
597           displs[i] = displs[i - 1] + sizes[i - 1];
598         }
599         PetscCall(PetscMalloc1(Ntotal, &array));
600         PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, array, sizes, displs, MPIU_REAL, 0, comm));
601         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_REAL));
602         PetscCall(PetscFree(sizes));
603         PetscCall(PetscFree(displs));
604         PetscCall(PetscFree(array));
605       }
606     } else {
607       PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_REAL));
608     }
609   } else {
610     const char *tname;
611     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
612     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
613   }
614   PetscFunctionReturn(PETSC_SUCCESS);
615 }
616 
617 /*@C
618     PetscScalarView - Prints an array of `PetscScalar`; useful for debugging.
619 
620     Collective
621 
622     Input Parameters:
623 +   N - number of scalars in array
624 .   idx - array of scalars
625 -   viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
626 
627   Level: intermediate
628 
629     Note:
630     This may be called from within the debugger
631 
632     Developer Note:
633     idx cannot be const because may be passed to binary viewer where byte swapping may be done
634 
635 .seealso: `PetscViewer`, `PetscIntView()`, `PetscRealView()`
636 @*/
637 PetscErrorCode PetscScalarView(PetscInt N, const PetscScalar idx[], PetscViewer viewer)
638 {
639   PetscMPIInt rank, size;
640   PetscInt    j, i, n = N / 3, p = N % 3;
641   PetscBool   iascii, isbinary;
642   MPI_Comm    comm;
643 
644   PetscFunctionBegin;
645   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
646   PetscValidHeader(viewer, 3);
647   if (N) PetscValidScalarPointer(idx, 2);
648   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
649   PetscCallMPI(MPI_Comm_size(comm, &size));
650   PetscCallMPI(MPI_Comm_rank(comm, &rank));
651 
652   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
653   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
654   if (iascii) {
655     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
656     for (i = 0; i < n; i++) {
657       if (size > 1) {
658         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * i));
659       } else {
660         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * i));
661       }
662       for (j = 0; j < 3; j++) {
663 #if defined(PETSC_USE_COMPLEX)
664         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[i * 3 + j]), (double)PetscImaginaryPart(idx[i * 3 + j])));
665 #else
666         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 3 + j]));
667 #endif
668       }
669       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
670     }
671     if (p) {
672       if (size > 1) {
673         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * n));
674       } else {
675         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * n));
676       }
677       for (i = 0; i < p; i++) {
678 #if defined(PETSC_USE_COMPLEX)
679         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[n * 3 + i]), (double)PetscImaginaryPart(idx[n * 3 + i])));
680 #else
681         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[3 * n + i]));
682 #endif
683       }
684       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
685     }
686     PetscCall(PetscViewerFlush(viewer));
687     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
688   } else if (isbinary) {
689     PetscMPIInt *sizes, Ntotal, *displs, NN;
690     PetscScalar *array;
691 
692     PetscCall(PetscMPIIntCast(N, &NN));
693 
694     if (size > 1) {
695       if (rank) {
696         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
697         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, NULL, NULL, NULL, MPIU_SCALAR, 0, comm));
698       } else {
699         PetscCall(PetscMalloc1(size, &sizes));
700         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
701         Ntotal = sizes[0];
702         PetscCall(PetscMalloc1(size, &displs));
703         displs[0] = 0;
704         for (i = 1; i < size; i++) {
705           Ntotal += sizes[i];
706           displs[i] = displs[i - 1] + sizes[i - 1];
707         }
708         PetscCall(PetscMalloc1(Ntotal, &array));
709         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, array, sizes, displs, MPIU_SCALAR, 0, comm));
710         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_SCALAR));
711         PetscCall(PetscFree(sizes));
712         PetscCall(PetscFree(displs));
713         PetscCall(PetscFree(array));
714       }
715     } else {
716       PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_SCALAR));
717     }
718   } else {
719     const char *tname;
720     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
721     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
722   }
723   PetscFunctionReturn(PETSC_SUCCESS);
724 }
725 
726 #if defined(PETSC_HAVE_CUDA)
727   #include <petscdevice_cuda.h>
728 PETSC_EXTERN const char *PetscCUBLASGetErrorName(cublasStatus_t status)
729 {
730   switch (status) {
731   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
732   case CUBLAS_STATUS_SUCCESS:
733     return "CUBLAS_STATUS_SUCCESS";
734   case CUBLAS_STATUS_NOT_INITIALIZED:
735     return "CUBLAS_STATUS_NOT_INITIALIZED";
736   case CUBLAS_STATUS_ALLOC_FAILED:
737     return "CUBLAS_STATUS_ALLOC_FAILED";
738   case CUBLAS_STATUS_INVALID_VALUE:
739     return "CUBLAS_STATUS_INVALID_VALUE";
740   case CUBLAS_STATUS_ARCH_MISMATCH:
741     return "CUBLAS_STATUS_ARCH_MISMATCH";
742   case CUBLAS_STATUS_MAPPING_ERROR:
743     return "CUBLAS_STATUS_MAPPING_ERROR";
744   case CUBLAS_STATUS_EXECUTION_FAILED:
745     return "CUBLAS_STATUS_EXECUTION_FAILED";
746   case CUBLAS_STATUS_INTERNAL_ERROR:
747     return "CUBLAS_STATUS_INTERNAL_ERROR";
748   case CUBLAS_STATUS_NOT_SUPPORTED:
749     return "CUBLAS_STATUS_NOT_SUPPORTED";
750   case CUBLAS_STATUS_LICENSE_ERROR:
751     return "CUBLAS_STATUS_LICENSE_ERROR";
752   #endif
753   default:
754     return "unknown error";
755   }
756 }
757 PETSC_EXTERN const char *PetscCUSolverGetErrorName(cusolverStatus_t status)
758 {
759   switch (status) {
760   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
761   case CUSOLVER_STATUS_SUCCESS:
762     return "CUSOLVER_STATUS_SUCCESS";
763   case CUSOLVER_STATUS_NOT_INITIALIZED:
764     return "CUSOLVER_STATUS_NOT_INITIALIZED";
765   case CUSOLVER_STATUS_INVALID_VALUE:
766     return "CUSOLVER_STATUS_INVALID_VALUE";
767   case CUSOLVER_STATUS_ARCH_MISMATCH:
768     return "CUSOLVER_STATUS_ARCH_MISMATCH";
769   case CUSOLVER_STATUS_INTERNAL_ERROR:
770     return "CUSOLVER_STATUS_INTERNAL_ERROR";
771     #if (CUDART_VERSION >= 9000) /* CUDA 9.0 had these defined on June 2021 */
772   case CUSOLVER_STATUS_ALLOC_FAILED:
773     return "CUSOLVER_STATUS_ALLOC_FAILED";
774   case CUSOLVER_STATUS_MAPPING_ERROR:
775     return "CUSOLVER_STATUS_MAPPING_ERROR";
776   case CUSOLVER_STATUS_EXECUTION_FAILED:
777     return "CUSOLVER_STATUS_EXECUTION_FAILED";
778   case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
779     return "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
780   case CUSOLVER_STATUS_NOT_SUPPORTED:
781     return "CUSOLVER_STATUS_NOT_SUPPORTED ";
782   case CUSOLVER_STATUS_ZERO_PIVOT:
783     return "CUSOLVER_STATUS_ZERO_PIVOT";
784   case CUSOLVER_STATUS_INVALID_LICENSE:
785     return "CUSOLVER_STATUS_INVALID_LICENSE";
786     #endif
787   #endif
788   default:
789     return "unknown error";
790   }
791 }
792 PETSC_EXTERN const char *PetscCUFFTGetErrorName(cufftResult result)
793 {
794   switch (result) {
795   case CUFFT_SUCCESS:
796     return "CUFFT_SUCCESS";
797   case CUFFT_INVALID_PLAN:
798     return "CUFFT_INVALID_PLAN";
799   case CUFFT_ALLOC_FAILED:
800     return "CUFFT_ALLOC_FAILED";
801   case CUFFT_INVALID_TYPE:
802     return "CUFFT_INVALID_TYPE";
803   case CUFFT_INVALID_VALUE:
804     return "CUFFT_INVALID_VALUE";
805   case CUFFT_INTERNAL_ERROR:
806     return "CUFFT_INTERNAL_ERROR";
807   case CUFFT_EXEC_FAILED:
808     return "CUFFT_EXEC_FAILED";
809   case CUFFT_SETUP_FAILED:
810     return "CUFFT_SETUP_FAILED";
811   case CUFFT_INVALID_SIZE:
812     return "CUFFT_INVALID_SIZE";
813   case CUFFT_UNALIGNED_DATA:
814     return "CUFFT_UNALIGNED_DATA";
815   case CUFFT_INCOMPLETE_PARAMETER_LIST:
816     return "CUFFT_INCOMPLETE_PARAMETER_LIST";
817   case CUFFT_INVALID_DEVICE:
818     return "CUFFT_INVALID_DEVICE";
819   case CUFFT_PARSE_ERROR:
820     return "CUFFT_PARSE_ERROR";
821   case CUFFT_NO_WORKSPACE:
822     return "CUFFT_NO_WORKSPACE";
823   case CUFFT_NOT_IMPLEMENTED:
824     return "CUFFT_NOT_IMPLEMENTED";
825   case CUFFT_LICENSE_ERROR:
826     return "CUFFT_LICENSE_ERROR";
827   case CUFFT_NOT_SUPPORTED:
828     return "CUFFT_NOT_SUPPORTED";
829   default:
830     return "unknown error";
831   }
832 }
833 #endif
834 
835 #if defined(PETSC_HAVE_HIP)
836   #include <petscdevice_hip.h>
837 PETSC_EXTERN const char *PetscHIPBLASGetErrorName(hipblasStatus_t status)
838 {
839   switch (status) {
840   case HIPBLAS_STATUS_SUCCESS:
841     return "HIPBLAS_STATUS_SUCCESS";
842   case HIPBLAS_STATUS_NOT_INITIALIZED:
843     return "HIPBLAS_STATUS_NOT_INITIALIZED";
844   case HIPBLAS_STATUS_ALLOC_FAILED:
845     return "HIPBLAS_STATUS_ALLOC_FAILED";
846   case HIPBLAS_STATUS_INVALID_VALUE:
847     return "HIPBLAS_STATUS_INVALID_VALUE";
848   case HIPBLAS_STATUS_ARCH_MISMATCH:
849     return "HIPBLAS_STATUS_ARCH_MISMATCH";
850   case HIPBLAS_STATUS_MAPPING_ERROR:
851     return "HIPBLAS_STATUS_MAPPING_ERROR";
852   case HIPBLAS_STATUS_EXECUTION_FAILED:
853     return "HIPBLAS_STATUS_EXECUTION_FAILED";
854   case HIPBLAS_STATUS_INTERNAL_ERROR:
855     return "HIPBLAS_STATUS_INTERNAL_ERROR";
856   case HIPBLAS_STATUS_NOT_SUPPORTED:
857     return "HIPBLAS_STATUS_NOT_SUPPORTED";
858   default:
859     return "unknown error";
860   }
861 }
862 PETSC_EXTERN const char *PetscHIPSPARSEGetErrorName(hipsparseStatus_t status)
863 {
864   switch (status) {
865   case HIPSPARSE_STATUS_SUCCESS:
866     return "HIPSPARSE_STATUS_SUCCESS";
867   case HIPSPARSE_STATUS_NOT_INITIALIZED:
868     return "HIPSPARSE_STATUS_NOT_INITIALIZED";
869   case HIPSPARSE_STATUS_ALLOC_FAILED:
870     return "HIPSPARSE_STATUS_ALLOC_FAILED";
871   case HIPSPARSE_STATUS_INVALID_VALUE:
872     return "HIPSPARSE_STATUS_INVALID_VALUE";
873   case HIPSPARSE_STATUS_ARCH_MISMATCH:
874     return "HIPSPARSE_STATUS_ARCH_MISMATCH";
875   case HIPSPARSE_STATUS_MAPPING_ERROR:
876     return "HIPSPARSE_STATUS_MAPPING_ERROR";
877   case HIPSPARSE_STATUS_EXECUTION_FAILED:
878     return "HIPSPARSE_STATUS_EXECUTION_FAILED";
879   case HIPSPARSE_STATUS_INTERNAL_ERROR:
880     return "HIPSPARSE_STATUS_INTERNAL_ERROR";
881   case HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
882     return "HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
883   case HIPSPARSE_STATUS_ZERO_PIVOT:
884     return "HIPSPARSE_STATUS_ZERO_PIVOT";
885   case HIPSPARSE_STATUS_NOT_SUPPORTED:
886     return "HIPSPARSE_STATUS_NOT_SUPPORTED";
887   case HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES:
888     return "HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES";
889   default:
890     return "unknown error";
891   }
892 }
893 PETSC_EXTERN const char *PetscHIPSolverGetErrorName(hipsolverStatus_t status)
894 {
895   switch (status) {
896   case HIPSOLVER_STATUS_SUCCESS:
897     return "HIPSOLVER_STATUS_SUCCESS";
898   case HIPSOLVER_STATUS_NOT_INITIALIZED:
899     return "HIPSOLVER_STATUS_NOT_INITIALIZED";
900   case HIPSOLVER_STATUS_ALLOC_FAILED:
901     return "HIPSOLVER_STATUS_ALLOC_FAILED";
902   case HIPSOLVER_STATUS_MAPPING_ERROR:
903     return "HIPSOLVER_STATUS_MAPPING_ERROR";
904   case HIPSOLVER_STATUS_INVALID_VALUE:
905     return "HIPSOLVER_STATUS_INVALID_VALUE";
906   case HIPSOLVER_STATUS_EXECUTION_FAILED:
907     return "HIPSOLVER_STATUS_EXECUTION_FAILED";
908   case HIPSOLVER_STATUS_INTERNAL_ERROR:
909     return "HIPSOLVER_STATUS_INTERNAL_ERROR";
910   case HIPSOLVER_STATUS_NOT_SUPPORTED:
911     return "HIPSOLVER_STATUS_NOT_SUPPORTED ";
912   case HIPSOLVER_STATUS_ARCH_MISMATCH:
913     return "HIPSOLVER_STATUS_ARCH_MISMATCH";
914   case HIPSOLVER_STATUS_HANDLE_IS_NULLPTR:
915     return "HIPSOLVER_STATUS_HANDLE_IS_NULLPTR";
916   case HIPSOLVER_STATUS_INVALID_ENUM:
917     return "HIPSOLVER_STATUS_INVALID_ENUM";
918   case HIPSOLVER_STATUS_UNKNOWN:
919   default:
920     return "HIPSOLVER_STATUS_UNKNOWN";
921   }
922 }
923 #endif
924 
925 /*@
926       PetscMPIErrorString - Given an MPI error code returns the `MPI_Error_string()` appropriately
927            formatted for displaying with the PETSc error handlers.
928 
929  Input Parameter:
930 .  err - the MPI error code
931 
932  Output Parameter:
933 .  string - the MPI error message, should declare its length to be larger than `MPI_MAX_ERROR_STRING`
934 
935    Level: developer
936 
937  Note:
938     Does not return an error code or do error handling because it may be called from inside an error handler
939 
940 @*/
941 void PetscMPIErrorString(PetscMPIInt err, char *string)
942 {
943   char        errorstring[MPI_MAX_ERROR_STRING];
944   PetscMPIInt len, j = 0;
945 
946   MPI_Error_string(err, (char *)errorstring, &len);
947   for (PetscMPIInt i = 0; i < len; i++) {
948     string[j++] = errorstring[i];
949     if (errorstring[i] == '\n') {
950       for (PetscMPIInt k = 0; k < 16; k++) string[j++] = ' ';
951     }
952   }
953   string[j] = 0;
954 }
955