Actual source code: err.c

  1: /*
  2:       Code that allows one to set the error handlers
  3:       Portions of this code are under:
  4:       Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
  5: */
  6: #include <petsc/private/petscimpl.h>
  7: #include <petscviewer.h>

  9: typedef struct _EH *EH;
 10: struct _EH {
 11:   PetscErrorCode (*handler)(MPI_Comm, int, const char *, const char *, PetscErrorCode, PetscErrorType, const char *, void *);
 12:   PetscCtx ctx;
 13:   EH       previous;
 14: };

 16: /* This is here to allow the traceback error handler (or potentially other error handlers)
 17:    to certify that PETSCABORT is being called on all MPI processes, and that it should be possible to call
 18:    MPI_Finalize() and exit().  This should only be used when `PetscCIEnabledPortabeErrorOutput == PETSC_TRUE`
 19:    to allow testing of error messages.  Do not rely on this for clean exit in production. */
 20: PetscBool petscabortmpifinalize = PETSC_FALSE;

 22: static EH eh = NULL;

 24: /*@C
 25:   PetscEmacsClientErrorHandler - Error handler that uses the emacsclient program to
 26:   load the file where the error occurred. Then calls the "previous" error handler.

 28:   Not Collective, No Fortran Support

 30:   Input Parameters:
 31: + comm - communicator over which error occurred
 32: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
 33: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
 34: . fun  - the function name of the calling routine
 35: . mess - an error text string, usually just printed to the screen
 36: . n    - the generic error number
 37: . p    - `PETSC_ERROR_INITIAL` indicates this is the first time the error handler is being called while `PETSC_ERROR_REPEAT` indicates it was previously called
 38: - ctx  - error handler context

 40:   Options Database Key:
 41: . -on_error_emacs machinename - will contact machinename to open the Emacs client there

 43:   Level: developer

 45:   Note:
 46:   You must put (server-start) in your .emacs file for the emacsclient software to work

 48:   Developer Note:
 49:   Since this is an error handler it cannot call `PetscCall()`; thus we just return if an error is detected.
 50:   But some of the functions it calls do perform error checking that may not be appropriate in a error handler call.

 52: .seealso: `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`,
 53:           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscReturnErrorHandler()`,
 54:           `PetscErrorType`, `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`, `PetscErrorCode`
 55:  @*/
 56: PetscErrorCode PetscEmacsClientErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, PetscCtx ctx)
 57: {
 58:   PetscErrorCode ierr;
 59:   char           command[PETSC_MAX_PATH_LEN];
 60:   const char    *pdir;
 61:   FILE          *fp;

 63:   ierr = PetscGetPetscDir(&pdir);
 64:   if (ierr) return ierr;
 65:   ierr = PetscSNPrintf(command, PETSC_STATIC_ARRAY_LENGTH(command), "cd %s; emacsclient --no-wait +%d %s\n", pdir, line, file);
 66:   if (ierr) return ierr;
 67: #if defined(PETSC_HAVE_POPEN)
 68:   ierr = PetscPOpen(MPI_COMM_WORLD, (char *)ctx, command, "r", &fp);
 69:   if (ierr) return ierr;
 70:   ierr = PetscPClose(MPI_COMM_WORLD, fp);
 71:   if (ierr) return ierr;
 72: #else
 73:   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
 74: #endif
 75:   ierr = PetscPopErrorHandler();
 76:   if (ierr) return ierr; /* remove this handler from the stack of handlers */
 77:   if (!eh) {
 78:     ierr = PetscTraceBackErrorHandler(comm, line, fun, file, n, p, mess, NULL);
 79:     if (ierr) return ierr;
 80:   } else {
 81:     ierr = (*eh->handler)(comm, line, fun, file, n, p, mess, eh->ctx);
 82:     if (ierr) return ierr;
 83:   }
 84:   return PETSC_SUCCESS;
 85: }

 87: /*@C
 88:   PetscPushErrorHandler - Sets a routine to be called on detection of errors.

 90:   Not Collective, No Fortran Support

 92:   Input Parameters:
 93: + handler - error handler routine
 94: - ctx     - optional handler context that contains information needed by the handler (for
 95:             example file pointers for error messages etc.)

 97:   Calling sequence of `handler`:
 98: + comm - communicator over which error occurred
 99: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
100: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
101: . fun  - the function name of the calling routine
102: . n    - the generic error number (see list defined in include/petscerror.h)
103: . p    - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
104: . mess - an error text string, usually just printed to the screen
105: - ctx  - the error handler context

107:   Options Database Keys:
108: + -on_error_attach_debugger [noxterm,][(gdb|lldb)] - starts up the debugger if an error occurs
109: - -on_error_abort                                  - aborts the program if an error occurs

111:   Level: intermediate

113:   Note:
114:   The currently available PETSc error handlers include `PetscTraceBackErrorHandler()`,
115:   `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, and `PetscReturnErrorHandler()`.

117:   Fortran Note:
118:   You can only push a single error handler from Fortran before popping it.

120: .seealso: `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscPushSignalHandler()`,
121:           `PetscErrorType`, `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`, `PetscErrorCode`
122: @*/
123: PetscErrorCode PetscPushErrorHandler(PetscErrorCode (*handler)(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, PetscCtx ctx), PetscCtx ctx)
124: {
125:   EH neweh;

127:   PetscFunctionBegin;
128:   PetscCall(PetscNew(&neweh));
129:   if (eh) neweh->previous = eh;
130:   else neweh->previous = NULL;
131:   neweh->handler = handler;
132:   neweh->ctx     = ctx;
133:   eh             = neweh;
134:   PetscFunctionReturn(PETSC_SUCCESS);
135: }

137: /*@
138:   PetscPopErrorHandler - Removes the latest error handler that was
139:   pushed with `PetscPushErrorHandler()`.

141:   Not Collective

143:   Level: intermediate

145: .seealso: `PetscPushErrorHandler()`
146: @*/
147: PetscErrorCode PetscPopErrorHandler(void)
148: {
149:   EH tmp;

151:   PetscFunctionBegin;
152:   if (!eh) PetscFunctionReturn(PETSC_SUCCESS);
153:   tmp = eh;
154:   eh  = eh->previous;
155:   PetscCall(PetscFree(tmp));
156:   PetscFunctionReturn(PETSC_SUCCESS);
157: }

159: /*@C
160:   PetscReturnErrorHandler - Error handler that causes a return without printing an error message.

162:   Not Collective, No Fortran Support

164:   Input Parameters:
165: + comm - communicator over which error occurred
166: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
167: . fun  - the function name
168: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
169: . mess - an error text string, usually just printed to the screen
170: . n    - the generic error number
171: . p    - `PETSC_ERROR_INITIAL` indicates this is the first time the error handler is being called while `PETSC_ERROR_REPEAT` indicates it was previously called
172: - ctx  - error handler context

174:   Level: developer

176:   Notes:
177:   Users do not directly employ this routine

179:   Use `PetscPushErrorHandler()` to set the desired error handler.  The
180:   currently available PETSc error handlers include `PetscTraceBackErrorHandler()`,
181:   `PetscAttachDebuggerErrorHandler()`, and `PetscAbortErrorHandler()`.

183: .seealso: `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscError()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscTraceBackErrorHandler()`,
184:           `PetscAttachDebuggerErrorHandler()`, `PetscEmacsClientErrorHandler()`,
185:           `PetscErrorType`, `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`, `PetscErrorCode`
186:  @*/
187: PetscErrorCode PetscReturnErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, PetscCtx ctx)
188: {
189:   (void)comm;
190:   (void)line;
191:   (void)fun;
192:   (void)file;
193:   (void)p;
194:   (void)mess;
195:   (void)ctx;
196:   return n;
197: }

199: static char PetscErrorBaseMessage[1024];
200: /*
201:        The numerical values for these are defined in include/petscerror.h; any changes
202:    there must also be made here
203: */
204: static const char *PetscErrorStrings[] = {
205:   /*55 */ "Out of memory",
206:   "No support for this operation for this object type",
207:   "No support for this operation on this system",
208:   /*58 */ "Operation done in wrong order",
209:   /*59 */ "Signal received",
210:   /*60 */ "Nonconforming object sizes",
211:   "Argument aliasing not permitted",
212:   "Invalid argument",
213:   /*63 */ "Argument out of range",
214:   "Corrupt argument: https://petsc.org/release/faq/#valgrind",
215:   "Unable to open file",
216:   "Read from file failed",
217:   "Write to file failed",
218:   "Invalid pointer",
219:   /*69 */ "Arguments must have same type",
220:   /*70 */ "Attempt to use a pointer that does not point to a valid accessible location",
221:   /*71 */ "Zero pivot in LU factorization: https://petsc.org/release/faq/#zeropivot",
222:   /*72 */ "Floating point exception",
223:   /*73 */ "Object is in wrong state",
224:   "Corrupted PETSc object",
225:   "Arguments are incompatible",
226:   "Error in external library",
227:   /*77 */ "PETSc has generated inconsistent data",
228:   "Memory corruption: https://petsc.org/release/faq/#valgrind",
229:   "Unexpected data in file",
230:   /*80 */ "Arguments must have same communicators",
231:   /*81 */ "Zero pivot in Cholesky factorization: https://petsc.org/release/faq/#zeropivot",
232:   "",
233:   "",
234:   "Overflow in integer operation: https://petsc.org/release/faq/#64-bit-indices",
235:   /*85 */ "Null argument, when expecting valid pointer",
236:   /*86 */ "Unknown type. Check for miss-spelling or missing package: https://petsc.org/release/install/install/#external-packages",
237:   /*87 */ "MPI library at runtime is not compatible with MPI used at compile time",
238:   /*88 */ "Error in system call",
239:   /*89 */ "Object Type not set: https://petsc.org/release/faq/#object-type-not-set",
240:   /*90 */ "",
241:   /*   */ "",
242:   /*92 */ "See https://petsc.org/release/overview/linear_solve_table/ for possible LU and Cholesky solvers",
243:   /*93 */ "You cannot overwrite this option since that will conflict with other previously set options",
244:   /*94 */ "Example/application run with number of MPI ranks it does not support",
245:   /*95 */ "Missing or incorrect user input",
246:   /*96 */ "GPU resources unavailable",
247:   /*97 */ "GPU error",
248:   /*98 */ "General MPI error",
249:   /*99 */ "PetscError() incorrectly returned an error code of 0",
250:   /*   */ "",
251:   /*101*/ "Unhandled Python Exception",
252:   NULL};

254: /*@C
255:   PetscErrorMessage - Returns the text string associated with a PETSc error code.

257:   Not Collective, No Fortran Support

259:   Input Parameter:
260: . errnum - the error code

262:   Output Parameters:
263: + text     - the error message (`NULL` if not desired)
264: - specific - the specific error message that was set with `SETERRQ()` or
265:              `PetscError()`. (`NULL` if not desired)

267:   Level: developer

269: .seealso: `PetscErrorCode`, `PetscPushErrorHandler()`, `PetscAttachDebuggerErrorHandler()`,
270:           `PetscError()`, `SETERRQ()`, `PetscCall()`, `PetscAbortErrorHandler()`,
271:           `PetscTraceBackErrorHandler()`
272: @*/
273: PetscErrorCode PetscErrorMessage(PetscErrorCode errnum, const char *text[], const char *specific[])
274: {
275:   PetscFunctionBegin;
276:   if (text) {
277:     if (errnum > PETSC_ERR_MIN_VALUE && errnum < PETSC_ERR_MAX_VALUE) {
278:       size_t len;

280:       *text = PetscErrorStrings[errnum - PETSC_ERR_MIN_VALUE - 1];
281:       PetscCall(PetscStrlen(*text, &len));
282:       if (!len) *text = NULL;
283:     } else if (errnum == PETSC_ERR_BOOLEAN_MACRO_FAILURE) {
284:       /* this "error code" arises from failures in boolean macros, where the || operator is
285:          used to short-circuit the macro call in case of error. This has the side effect of
286:          "returning" either 0 (PETSC_SUCCESS) or 1 (PETSC_ERR_UNKNONWN):

288:          #define PETSC_FOO(x) ((PetscErrorCode)(PetscBar(x) || PetscBaz(x)))

290:          If PetscBar() fails (returns nonzero) PetscBaz() is not executed but the result of
291:          this expression is boolean false, hence PETSC_ERR_UNNOWN
292:        */
293:       *text = "Error occurred in boolean short-circuit in macro";
294:     } else {
295:       *text = NULL;
296:     }
297:   }
298:   if (specific) *specific = PetscErrorBaseMessage;
299:   PetscFunctionReturn(PETSC_SUCCESS);
300: }

302: #if defined(PETSC_CLANGUAGE_CXX)
303:   /* C++ exceptions are formally not allowed to propagate through extern "C" code. In practice, far too much software
304:  * would be broken if implementations did not handle it in some common cases. However, keep in mind
305:  *
306:  *   Rule 62. Don't allow exceptions to propagate across module boundaries
307:  *
308:  * in "C++ Coding Standards" by Sutter and Alexandrescu. (This accounts for part of the ongoing C++ binary interface
309:  * instability.) Having PETSc raise errors as C++ exceptions was probably misguided and should eventually be removed.
310:  *
311:  * Here is the problem: You have a C++ function call a PETSc function, and you would like to maintain the error message
312:  * and stack information from the PETSc error. You could make everyone write exactly this code in their C++, but that
313:  * seems crazy to me.
314:  */
315:   #include <sstream>
316:   #include <stdexcept>
317: static void PetscCxxErrorThrow()
318: {
319:   if (eh && eh->ctx) {
320:     std::ostringstream *msg;
321:     msg = (std::ostringstream *)eh->ctx;
322:     throw std::runtime_error(msg->str());
323:   } else throw std::runtime_error("Error detected in C PETSc");
324: }
325: #endif

327: /*@C
328:   PetscError - Routine that is called when an error has been detected, usually called through the macro `SETERRQ`(`PETSC_COMM_SELF`,)` or by `PetscCall()`.

330:   Collective

332:   Input Parameters:
333: + comm - communicator over which error occurred.  ALL MPI processes of this communicator MUST call this routine
334: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
335: . func - the function name in which the error was detected
336: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
337: . n    - the generic error number
338: . p    - `PETSC_ERROR_INITIAL` indicates the error was initially detected, `PETSC_ERROR_REPEAT` indicates this is a traceback from a previously detected error
339: - mess - formatted message string - aka printf

341:   Options Database Keys:
342: + -error_output_stdout - output the error messages to `stdout` instead of the default `stderr`
343: - -error_output_none   - do not output the error messages

345:   Level: intermediate

347:   Notes:
348:   PETSc error handling is done with error return codes. A non-zero return indicates an error
349:   was detected. The return-value of this routine is what is ultimately returned by
350:   `SETERRQ()`.

352:   Numerical errors (potential divide by zero, for example) are not managed by the
353:   error return codes; they are managed via, for example, `KSPGetConvergedReason()` that
354:   indicates if the solve was successful or not. The option `-ksp_error_if_not_converged`, for
355:   example, turns numerical failures into hard errors managed via `PetscError()`.

357:   PETSc provides a rich supply of error handlers, see the list below, and users can also
358:   provide their own error handlers.

360:   If the user sets their own error handler (via `PetscPushErrorHandler()`) they may return any
361:   arbitrary value from it, but are encouraged to return nonzero values. If the return value is
362:   zero, `SETERRQ()` will ignore the value and return `PETSC_ERR_RETURN` (a nonzero value)
363:   instead.

365:   Most users need not directly use this routine and the error handlers, but can instead use
366:   the simplified interface `PetscCall()` or `SETERRQ()`.

368:   Fortran Note:
369:   This routine is used differently from Fortran
370: .vb
371:   PetscError(MPI_Comm comm, PetscErrorCode n, PetscErrorType p, char *message)
372: .ve

374:   Developer Note:
375:   Since this is called after an error condition it should not be calling any error handlers (currently it ignores any error codes)
376:   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
377:   but this annoying.

379: .seealso: `PetscErrorCode`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`,
380:           `PetscReturnErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscEmacsClientErrorHandler()`,
381:           `SETERRQ()`, `PetscCall()`, `CHKMEMQ`, `PetscErrorMessage()`, `PETSCABORT()`, `PetscErrorType`, `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`
382: @*/
383: PetscErrorCode PetscError(MPI_Comm comm, int line, const char *func, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, ...)
384: {
385:   va_list        Argp;
386:   size_t         fullLength;
387:   char           buf[2048], *lbuf = NULL;
388:   PetscBool      ismain;
389:   PetscErrorCode ierr;

391:   if (!PetscErrorHandlingInitialized) return n;
392:   if (comm == MPI_COMM_NULL) comm = PETSC_COMM_SELF;

394:   /* Compose the message evaluating the print format */
395:   if (mess) {
396:     va_start(Argp, mess);
397:     (void)PetscVSNPrintf(buf, 2048, mess, &fullLength, Argp);
398:     va_end(Argp);
399:     lbuf = buf;
400:     if (p == PETSC_ERROR_INITIAL) (void)PetscStrncpy(PetscErrorBaseMessage, lbuf, sizeof(PetscErrorBaseMessage));
401:   }

403:   if (p == PETSC_ERROR_INITIAL && n != PETSC_ERR_MEMC) (void)PetscMallocValidate(__LINE__, PETSC_FUNCTION_NAME, __FILE__);

405:   if (!eh) ierr = PetscTraceBackErrorHandler(comm, line, func, file, n, p, lbuf, NULL);
406:   else ierr = (*eh->handler)(comm, line, func, file, n, p, lbuf, eh->ctx);
407:   PetscStackClearTop;

409:   /*
410:       If this is called from the main() routine we abort the program.
411:       We cannot just return because them some MPI processes may continue to attempt to run
412:       while this process simply exits.
413:   */
414:   if (func) {
415:     (void)PetscStrncmp(func, "main", 4, &ismain);
416:     if (ismain) {
417:       if (petscwaitonerrorflg) (void)PetscSleep(1000);
418:       PETSCABORT(comm, ierr);
419:     }
420:   }
421: #if defined(PETSC_CLANGUAGE_CXX)
422:   if (p == PETSC_ERROR_IN_CXX) PetscCxxErrorThrow();
423: #endif
424:   return ierr;
425: }

427: /*@
428:   PetscIntViewNumColumns - Prints an array of integers; useful for debugging.

430:   Collective

432:   Input Parameters:
433: + N      - number of integers in array
434: . Ncol   - number of integers to print per row
435: . idx    - array of integers
436: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

438:   Level: intermediate

440:   Note:
441:   This may be called from within the debugger, passing 0 as the viewer

443:   This API may be removed in the future.

445:   Developer Note:
446:   `idx` cannot be const because may be passed to binary viewer where temporary byte swapping may be done

448: .seealso: `PetscViewer`, `PetscIntView()`, `PetscRealView()`
449: @*/
450: PetscErrorCode PetscIntViewNumColumns(PetscInt N, PetscInt Ncol, const PetscInt idx[], PetscViewer viewer)
451: {
452:   PetscMPIInt rank, size;
453:   PetscInt    j, i, n = N / Ncol, p = N % Ncol;
454:   PetscBool   isascii, isbinary;
455:   MPI_Comm    comm;

457:   PetscFunctionBegin;
458:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
459:   if (N) PetscAssertPointer(idx, 3);
461:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
462:   PetscCallMPI(MPI_Comm_size(comm, &size));
463:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

465:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
466:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
467:   if (isascii) {
468:     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
469:     for (i = 0; i < n; i++) {
470:       if (size > 1) {
471:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, Ncol * i));
472:       } else {
473:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", Ncol * i));
474:       }
475:       for (j = 0; j < Ncol; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[i * Ncol + j]));
476:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
477:     }
478:     if (p) {
479:       if (size > 1) {
480:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, Ncol * n));
481:       } else {
482:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", Ncol * n));
483:       }
484:       for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[Ncol * n + i]));
485:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
486:     }
487:     PetscCall(PetscViewerFlush(viewer));
488:     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
489:   } else if (isbinary) {
490:     PetscMPIInt *sizes, Ntotal, *displs, NN;
491:     PetscInt    *array;

493:     PetscCall(PetscMPIIntCast(N, &NN));

495:     if (size > 1) {
496:       if (rank) {
497:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
498:         PetscCallMPI(MPI_Gatherv(idx, NN, MPIU_INT, NULL, NULL, NULL, MPIU_INT, 0, comm));
499:       } else {
500:         PetscCall(PetscMalloc1(size, &sizes));
501:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
502:         Ntotal = sizes[0];
503:         PetscCall(PetscMalloc1(size, &displs));
504:         displs[0] = 0;
505:         for (i = 1; i < size; i++) {
506:           Ntotal += sizes[i];
507:           displs[i] = displs[i - 1] + sizes[i - 1];
508:         }
509:         PetscCall(PetscMalloc1(Ntotal, &array));
510:         PetscCallMPI(MPI_Gatherv(idx, NN, MPIU_INT, array, sizes, displs, MPIU_INT, 0, comm));
511:         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_INT));
512:         PetscCall(PetscFree(sizes));
513:         PetscCall(PetscFree(displs));
514:         PetscCall(PetscFree(array));
515:       }
516:     } else {
517:       PetscCall(PetscViewerBinaryWrite(viewer, idx, N, PETSC_INT));
518:     }
519:   } else {
520:     const char *tname;
521:     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
522:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
523:   }
524:   PetscFunctionReturn(PETSC_SUCCESS);
525: }

527: /*@
528:   PetscRealViewNumColumns - Prints an array of doubles; useful for debugging.

530:   Collective

532:   Input Parameters:
533: + N      - number of `PetscReal` in array
534: . Ncol   - number of `PetscReal` to print per row
535: . idx    - array of `PetscReal`
536: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

538:   Level: intermediate

540:   Note:
541:   This may be called from within the debugger, passing 0 as the viewer

543:   This API may be removed in the future.

545:   Developer Note:
546:   `idx` cannot be const because may be passed to binary viewer where temporary byte swapping may be done

548: .seealso: `PetscViewer`, `PetscRealView()`, `PetscIntView()`
549: @*/
550: PetscErrorCode PetscRealViewNumColumns(PetscInt N, PetscInt Ncol, const PetscReal idx[], PetscViewer viewer)
551: {
552:   PetscMPIInt rank, size;
553:   PetscInt    j, i, n = N / Ncol, p = N % Ncol;
554:   PetscBool   isascii, isbinary;
555:   MPI_Comm    comm;

557:   PetscFunctionBegin;
558:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
559:   if (N) PetscAssertPointer(idx, 3);
561:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
562:   PetscCallMPI(MPI_Comm_size(comm, &size));
563:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

565:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
566:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
567:   if (isascii) {
568:     PetscInt tab;

570:     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
571:     PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
572:     for (i = 0; i < n; i++) {
573:       PetscCall(PetscViewerASCIISetTab(viewer, tab));
574:       if (size > 1) {
575:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, Ncol * i));
576:       } else {
577:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", Ncol * i));
578:       }
579:       PetscCall(PetscViewerASCIISetTab(viewer, 0));
580:       for (j = 0; j < Ncol; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * Ncol + j]));
581:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
582:     }
583:     if (p) {
584:       PetscCall(PetscViewerASCIISetTab(viewer, tab));
585:       if (size > 1) {
586:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, Ncol * n));
587:       } else {
588:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", Ncol * n));
589:       }
590:       PetscCall(PetscViewerASCIISetTab(viewer, 0));
591:       for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[Ncol * n + i]));
592:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
593:     }
594:     PetscCall(PetscViewerFlush(viewer));
595:     PetscCall(PetscViewerASCIISetTab(viewer, tab));
596:     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
597:   } else if (isbinary) {
598:     PetscMPIInt *sizes, *displs, Ntotal, NN;
599:     PetscReal   *array;

601:     PetscCall(PetscMPIIntCast(N, &NN));

603:     if (size > 1) {
604:       if (rank) {
605:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
606:         PetscCallMPI(MPI_Gatherv(idx, NN, MPIU_REAL, NULL, NULL, NULL, MPIU_REAL, 0, comm));
607:       } else {
608:         PetscCall(PetscMalloc1(size, &sizes));
609:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
610:         Ntotal = sizes[0];
611:         PetscCall(PetscMalloc1(size, &displs));
612:         displs[0] = 0;
613:         for (i = 1; i < size; i++) {
614:           Ntotal += sizes[i];
615:           displs[i] = displs[i - 1] + sizes[i - 1];
616:         }
617:         PetscCall(PetscMalloc1(Ntotal, &array));
618:         PetscCallMPI(MPI_Gatherv(idx, NN, MPIU_REAL, array, sizes, displs, MPIU_REAL, 0, comm));
619:         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_REAL));
620:         PetscCall(PetscFree(sizes));
621:         PetscCall(PetscFree(displs));
622:         PetscCall(PetscFree(array));
623:       }
624:     } else {
625:       PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_REAL));
626:     }
627:   } else {
628:     const char *tname;
629:     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
630:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
631:   }
632:   PetscFunctionReturn(PETSC_SUCCESS);
633: }

635: /*@
636:   PetscScalarViewNumColumns - Prints an array of doubles; useful for debugging.

638:   Collective

640:   Input Parameters:
641: + N      - number of `PetscScalar` in array
642: . Ncol   - number of `PetscScalar` to print per row
643: . idx    - array of `PetscScalar`
644: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

646:   Level: intermediate

648:   Note:
649:   This may be called from within the debugger, passing 0 as the viewer

651:   This API may be removed in the future.

653:   Developer Note:
654:   `idx` cannot be const because may be passed to binary viewer where temporary byte swapping may be done

656: .seealso: `PetscViewer`, `PetscRealView()`, `PetscScalarView()`, `PetscIntView()`
657: @*/
658: PetscErrorCode PetscScalarViewNumColumns(PetscInt N, PetscInt Ncol, const PetscScalar idx[], PetscViewer viewer)
659: {
660:   PetscMPIInt rank, size;
661:   PetscInt    j, i, n = N / Ncol, p = N % Ncol;
662:   PetscBool   isascii, isbinary;
663:   MPI_Comm    comm;

665:   PetscFunctionBegin;
666:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
667:   if (N) PetscAssertPointer(idx, 3);
669:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
670:   PetscCallMPI(MPI_Comm_size(comm, &size));
671:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

673:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
674:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
675:   if (isascii) {
676:     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
677:     for (i = 0; i < n; i++) {
678:       if (size > 1) {
679:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, Ncol * i));
680:       } else {
681:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", Ncol * i));
682:       }
683:       for (j = 0; j < Ncol; j++) {
684: #if defined(PETSC_USE_COMPLEX)
685:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[i * Ncol + j]), (double)PetscImaginaryPart(idx[i * Ncol + j])));
686: #else
687:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * Ncol + j]));
688: #endif
689:       }
690:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
691:     }
692:     if (p) {
693:       if (size > 1) {
694:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, Ncol * n));
695:       } else {
696:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", Ncol * n));
697:       }
698:       for (i = 0; i < p; i++) {
699: #if defined(PETSC_USE_COMPLEX)
700:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[n * Ncol + i]), (double)PetscImaginaryPart(idx[n * Ncol + i])));
701: #else
702:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[Ncol * n + i]));
703: #endif
704:       }
705:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
706:     }
707:     PetscCall(PetscViewerFlush(viewer));
708:     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
709:   } else if (isbinary) {
710:     PetscMPIInt *sizes, Ntotal, *displs, NN;
711:     PetscScalar *array;

713:     PetscCall(PetscMPIIntCast(N, &NN));

715:     if (size > 1) {
716:       if (rank) {
717:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
718:         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, NULL, NULL, NULL, MPIU_SCALAR, 0, comm));
719:       } else {
720:         PetscCall(PetscMalloc1(size, &sizes));
721:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
722:         Ntotal = sizes[0];
723:         PetscCall(PetscMalloc1(size, &displs));
724:         displs[0] = 0;
725:         for (i = 1; i < size; i++) {
726:           Ntotal += sizes[i];
727:           displs[i] = displs[i - 1] + sizes[i - 1];
728:         }
729:         PetscCall(PetscMalloc1(Ntotal, &array));
730:         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, array, sizes, displs, MPIU_SCALAR, 0, comm));
731:         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_SCALAR));
732:         PetscCall(PetscFree(sizes));
733:         PetscCall(PetscFree(displs));
734:         PetscCall(PetscFree(array));
735:       }
736:     } else {
737:       PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_SCALAR));
738:     }
739:   } else {
740:     const char *tname;
741:     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
742:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
743:   }
744:   PetscFunctionReturn(PETSC_SUCCESS);
745: }

747: /*@
748:   PetscIntView - Prints an array of integers; useful for debugging.

750:   Collective

752:   Input Parameters:
753: + N      - number of integers in array
754: . idx    - array of integers
755: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

757:   Level: intermediate

759:   Note:
760:   This may be called from within the debugger, passing 0 as the viewer

762:   This API may be removed in the future.

764:   Same as `PetscIntViewNumColumns()` with 20 values per row

766:   Developer Note:
767:   `idx` cannot be const because may be passed to binary viewer where temporary byte swapping may be done

769: .seealso: `PetscViewer`, `PetscIntViewNumColumns()`, `PetscRealView()`
770: @*/
771: PetscErrorCode PetscIntView(PetscInt N, const PetscInt idx[], PetscViewer viewer)
772: {
773:   PetscFunctionBegin;
774:   PetscCall(PetscIntViewNumColumns(N, 20, idx, viewer));
775:   PetscFunctionReturn(PETSC_SUCCESS);
776: }

778: /*@
779:   PetscRealView - Prints an array of doubles; useful for debugging.

781:   Collective

783:   Input Parameters:
784: + N      - number of `PetscReal` in array
785: . idx    - array of `PetscReal`
786: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

788:   Level: intermediate

790:   Note:
791:   This may be called from within the debugger, passing 0 as the viewer

793:   This API may be removed in the future.

795:   Same as `PetscRealViewNumColumns()` with 5 values per row

797:   Developer Note:
798:   `idx` cannot be const because may be passed to binary viewer where temporary byte swapping may be done

800: .seealso: `PetscViewer`, `PetscIntView()`
801: @*/
802: PetscErrorCode PetscRealView(PetscInt N, const PetscReal idx[], PetscViewer viewer)
803: {
804:   PetscFunctionBegin;
805:   PetscCall(PetscRealViewNumColumns(N, 5, idx, viewer));
806:   PetscFunctionReturn(PETSC_SUCCESS);
807: }

809: /*@
810:   PetscScalarView - Prints an array of `PetscScalar`; useful for debugging.

812:   Collective

814:   Input Parameters:
815: + N      - number of scalars in array
816: . idx    - array of scalars
817: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

819:   Level: intermediate

821:   Note:
822:   This may be called from within the debugger, passing 0 as the viewer

824:   This API may be removed in the future.

826:   Same as `PetscScalarViewNumColumns()` with 3 values per row

828:   Developer Note:
829:   `idx` cannot be const because may be passed to binary viewer where byte swapping may be done

831: .seealso: `PetscViewer`, `PetscIntView()`, `PetscRealView()`
832: @*/
833: PetscErrorCode PetscScalarView(PetscInt N, const PetscScalar idx[], PetscViewer viewer)
834: {
835:   PetscFunctionBegin;
836:   PetscCall(PetscScalarViewNumColumns(N, 3, idx, viewer));
837:   PetscFunctionReturn(PETSC_SUCCESS);
838: }

840: #if defined(PETSC_HAVE_CUDA)
841: #include <petscdevice_cuda.h>
842: PETSC_EXTERN const char *PetscCUBLASGetErrorName(cublasStatus_t status)
843: {
844:   switch (status) {
845:   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
846:   case CUBLAS_STATUS_SUCCESS:
847:     return "CUBLAS_STATUS_SUCCESS";
848:   case CUBLAS_STATUS_NOT_INITIALIZED:
849:     return "CUBLAS_STATUS_NOT_INITIALIZED";
850:   case CUBLAS_STATUS_ALLOC_FAILED:
851:     return "CUBLAS_STATUS_ALLOC_FAILED";
852:   case CUBLAS_STATUS_INVALID_VALUE:
853:     return "CUBLAS_STATUS_INVALID_VALUE";
854:   case CUBLAS_STATUS_ARCH_MISMATCH:
855:     return "CUBLAS_STATUS_ARCH_MISMATCH";
856:   case CUBLAS_STATUS_MAPPING_ERROR:
857:     return "CUBLAS_STATUS_MAPPING_ERROR";
858:   case CUBLAS_STATUS_EXECUTION_FAILED:
859:     return "CUBLAS_STATUS_EXECUTION_FAILED";
860:   case CUBLAS_STATUS_INTERNAL_ERROR:
861:     return "CUBLAS_STATUS_INTERNAL_ERROR";
862:   case CUBLAS_STATUS_NOT_SUPPORTED:
863:     return "CUBLAS_STATUS_NOT_SUPPORTED";
864:   case CUBLAS_STATUS_LICENSE_ERROR:
865:     return "CUBLAS_STATUS_LICENSE_ERROR";
866:   #endif
867:   default:
868:     return "unknown error";
869:   }
870: }
871: PETSC_EXTERN const char *PetscCUSolverGetErrorName(cusolverStatus_t status)
872: {
873:   switch (status) {
874:   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
875:   case CUSOLVER_STATUS_SUCCESS:
876:     return "CUSOLVER_STATUS_SUCCESS";
877:   case CUSOLVER_STATUS_NOT_INITIALIZED:
878:     return "CUSOLVER_STATUS_NOT_INITIALIZED";
879:   case CUSOLVER_STATUS_INVALID_VALUE:
880:     return "CUSOLVER_STATUS_INVALID_VALUE";
881:   case CUSOLVER_STATUS_ARCH_MISMATCH:
882:     return "CUSOLVER_STATUS_ARCH_MISMATCH";
883:   case CUSOLVER_STATUS_INTERNAL_ERROR:
884:     return "CUSOLVER_STATUS_INTERNAL_ERROR";
885:     #if (CUDART_VERSION >= 9000) /* CUDA 9.0 had these defined on June 2021 */
886:   case CUSOLVER_STATUS_ALLOC_FAILED:
887:     return "CUSOLVER_STATUS_ALLOC_FAILED";
888:   case CUSOLVER_STATUS_MAPPING_ERROR:
889:     return "CUSOLVER_STATUS_MAPPING_ERROR";
890:   case CUSOLVER_STATUS_EXECUTION_FAILED:
891:     return "CUSOLVER_STATUS_EXECUTION_FAILED";
892:   case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
893:     return "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
894:   case CUSOLVER_STATUS_NOT_SUPPORTED:
895:     return "CUSOLVER_STATUS_NOT_SUPPORTED ";
896:   case CUSOLVER_STATUS_ZERO_PIVOT:
897:     return "CUSOLVER_STATUS_ZERO_PIVOT";
898:   case CUSOLVER_STATUS_INVALID_LICENSE:
899:     return "CUSOLVER_STATUS_INVALID_LICENSE";
900:     #endif
901:   #endif
902:   default:
903:     return "unknown error";
904:   }
905: }
906: PETSC_EXTERN const char *PetscCUFFTGetErrorName(cufftResult result)
907: {
908:   switch (result) {
909:   case CUFFT_SUCCESS:
910:     return "CUFFT_SUCCESS";
911:   case CUFFT_INVALID_PLAN:
912:     return "CUFFT_INVALID_PLAN";
913:   case CUFFT_ALLOC_FAILED:
914:     return "CUFFT_ALLOC_FAILED";
915:   case CUFFT_INVALID_TYPE:
916:     return "CUFFT_INVALID_TYPE";
917:   case CUFFT_INVALID_VALUE:
918:     return "CUFFT_INVALID_VALUE";
919:   case CUFFT_INTERNAL_ERROR:
920:     return "CUFFT_INTERNAL_ERROR";
921:   case CUFFT_EXEC_FAILED:
922:     return "CUFFT_EXEC_FAILED";
923:   case CUFFT_SETUP_FAILED:
924:     return "CUFFT_SETUP_FAILED";
925:   case CUFFT_INVALID_SIZE:
926:     return "CUFFT_INVALID_SIZE";
927:   case CUFFT_UNALIGNED_DATA:
928:     return "CUFFT_UNALIGNED_DATA";
929:   case CUFFT_INVALID_DEVICE:
930:     return "CUFFT_INVALID_DEVICE";
931:   case CUFFT_NO_WORKSPACE:
932:     return "CUFFT_NO_WORKSPACE";
933:   case CUFFT_NOT_IMPLEMENTED:
934:     return "CUFFT_NOT_IMPLEMENTED";
935:   case CUFFT_NOT_SUPPORTED:
936:     return "CUFFT_NOT_SUPPORTED";
937:   #if PETSC_PKG_CUDA_VERSION_LT(13, 0, 0)
938:   case CUFFT_INCOMPLETE_PARAMETER_LIST:
939:     return "CUFFT_INCOMPLETE_PARAMETER_LIST";
940:   case CUFFT_PARSE_ERROR:
941:     return "CUFFT_PARSE_ERROR";
942:   case CUFFT_LICENSE_ERROR:
943:     return "CUFFT_LICENSE_ERROR";
944:   #endif
945:   default:
946:     return "unknown error";
947:   }
948: }
949: #endif

951: #if defined(PETSC_HAVE_HIP)
952: #include <petscdevice_hip.h>
953: PETSC_EXTERN const char *PetscHIPBLASGetErrorName(hipblasStatus_t status)
954: {
955:   switch (status) {
956:   case HIPBLAS_STATUS_SUCCESS:
957:     return "HIPBLAS_STATUS_SUCCESS";
958:   case HIPBLAS_STATUS_NOT_INITIALIZED:
959:     return "HIPBLAS_STATUS_NOT_INITIALIZED";
960:   case HIPBLAS_STATUS_ALLOC_FAILED:
961:     return "HIPBLAS_STATUS_ALLOC_FAILED";
962:   case HIPBLAS_STATUS_INVALID_VALUE:
963:     return "HIPBLAS_STATUS_INVALID_VALUE";
964:   case HIPBLAS_STATUS_ARCH_MISMATCH:
965:     return "HIPBLAS_STATUS_ARCH_MISMATCH";
966:   case HIPBLAS_STATUS_MAPPING_ERROR:
967:     return "HIPBLAS_STATUS_MAPPING_ERROR";
968:   case HIPBLAS_STATUS_EXECUTION_FAILED:
969:     return "HIPBLAS_STATUS_EXECUTION_FAILED";
970:   case HIPBLAS_STATUS_INTERNAL_ERROR:
971:     return "HIPBLAS_STATUS_INTERNAL_ERROR";
972:   case HIPBLAS_STATUS_NOT_SUPPORTED:
973:     return "HIPBLAS_STATUS_NOT_SUPPORTED";
974:   default:
975:     return "unknown error";
976:   }
977: }
978: PETSC_EXTERN const char *PetscHIPSPARSEGetErrorName(hipsparseStatus_t status)
979: {
980:   switch (status) {
981:   case HIPSPARSE_STATUS_SUCCESS:
982:     return "HIPSPARSE_STATUS_SUCCESS";
983:   case HIPSPARSE_STATUS_NOT_INITIALIZED:
984:     return "HIPSPARSE_STATUS_NOT_INITIALIZED";
985:   case HIPSPARSE_STATUS_ALLOC_FAILED:
986:     return "HIPSPARSE_STATUS_ALLOC_FAILED";
987:   case HIPSPARSE_STATUS_INVALID_VALUE:
988:     return "HIPSPARSE_STATUS_INVALID_VALUE";
989:   case HIPSPARSE_STATUS_ARCH_MISMATCH:
990:     return "HIPSPARSE_STATUS_ARCH_MISMATCH";
991:   case HIPSPARSE_STATUS_MAPPING_ERROR:
992:     return "HIPSPARSE_STATUS_MAPPING_ERROR";
993:   case HIPSPARSE_STATUS_EXECUTION_FAILED:
994:     return "HIPSPARSE_STATUS_EXECUTION_FAILED";
995:   case HIPSPARSE_STATUS_INTERNAL_ERROR:
996:     return "HIPSPARSE_STATUS_INTERNAL_ERROR";
997:   case HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
998:     return "HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
999:   case HIPSPARSE_STATUS_ZERO_PIVOT:
1000:     return "HIPSPARSE_STATUS_ZERO_PIVOT";
1001:   case HIPSPARSE_STATUS_NOT_SUPPORTED:
1002:     return "HIPSPARSE_STATUS_NOT_SUPPORTED";
1003:   case HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES:
1004:     return "HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES";
1005:   default:
1006:     return "unknown error";
1007:   }
1008: }
1009: PETSC_EXTERN const char *PetscHIPSolverGetErrorName(hipsolverStatus_t status)
1010: {
1011:   switch (status) {
1012:   case HIPSOLVER_STATUS_SUCCESS:
1013:     return "HIPSOLVER_STATUS_SUCCESS";
1014:   case HIPSOLVER_STATUS_NOT_INITIALIZED:
1015:     return "HIPSOLVER_STATUS_NOT_INITIALIZED";
1016:   case HIPSOLVER_STATUS_ALLOC_FAILED:
1017:     return "HIPSOLVER_STATUS_ALLOC_FAILED";
1018:   case HIPSOLVER_STATUS_MAPPING_ERROR:
1019:     return "HIPSOLVER_STATUS_MAPPING_ERROR";
1020:   case HIPSOLVER_STATUS_INVALID_VALUE:
1021:     return "HIPSOLVER_STATUS_INVALID_VALUE";
1022:   case HIPSOLVER_STATUS_EXECUTION_FAILED:
1023:     return "HIPSOLVER_STATUS_EXECUTION_FAILED";
1024:   case HIPSOLVER_STATUS_INTERNAL_ERROR:
1025:     return "HIPSOLVER_STATUS_INTERNAL_ERROR";
1026:   case HIPSOLVER_STATUS_NOT_SUPPORTED:
1027:     return "HIPSOLVER_STATUS_NOT_SUPPORTED ";
1028:   case HIPSOLVER_STATUS_ARCH_MISMATCH:
1029:     return "HIPSOLVER_STATUS_ARCH_MISMATCH";
1030:   case HIPSOLVER_STATUS_HANDLE_IS_NULLPTR:
1031:     return "HIPSOLVER_STATUS_HANDLE_IS_NULLPTR";
1032:   case HIPSOLVER_STATUS_INVALID_ENUM:
1033:     return "HIPSOLVER_STATUS_INVALID_ENUM";
1034:   case HIPSOLVER_STATUS_UNKNOWN:
1035:   default:
1036:     return "HIPSOLVER_STATUS_UNKNOWN";
1037:   }
1038: }
1039: #endif

1041: /*@C
1042:   PetscMPIErrorString - Given an MPI error code returns the `MPI_Error_string()` appropriately
1043:   formatted for displaying with the PETSc error handlers.

1045:   Not Collective, No Fortran Support

1047:   Input Parameters:
1048: + err  - the MPI error code
1049: - slen - length of `string`, should be at least as large as `MPI_MAX_ERROR_STRING`

1051:   Output Parameter:
1052: . string - the MPI error message

1054:   Level: developer

1056:   Note:
1057:   Does not return an error code or do error handling because it may be called from inside an error handler

1059: .seealso: `PetscErrorCode` `PetscErrorMessage()`
1060: @*/
1061: void PetscMPIErrorString(PetscMPIInt err, size_t slen, char *string)
1062: {
1063:   char        errorstring[MPI_MAX_ERROR_STRING];
1064:   PetscMPIInt len;
1065:   size_t      j = 0;

1067:   MPI_Error_string(err, (char *)errorstring, &len);
1068:   for (PetscMPIInt i = 0; i < len && j < slen - 2; i++) {
1069:     string[j++] = errorstring[i];
1070:     if (errorstring[i] == '\n') {
1071:       for (PetscMPIInt k = 0; k < 16 && j < slen - 2; k++) string[j++] = ' ';
1072:     }
1073:   }
1074:   string[j] = 0;
1075: }