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