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:   void *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, void *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,lldb or gdb> - 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, void *ctx), void *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, void *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"};

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

    254:   Not Collective, No Fortran Support

    256:   Input Parameter:
    257: . errnum - the error code

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

    264:   Level: developer

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

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

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

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

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

    323:   throw std::runtime_error(str);
    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:   PetscIntView - Prints an array of integers; useful for debugging.

    430:   Collective

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

    437:   Level: intermediate

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

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

    445: .seealso: `PetscViewer`, `PetscRealView()`
    446: @*/
    447: PetscErrorCode PetscIntView(PetscInt N, const PetscInt idx[], PetscViewer viewer)
    448: {
    449:   PetscMPIInt rank, size;
    450:   PetscInt    j, i, n = N / 20, p = N % 20;
    451:   PetscBool   iascii, isbinary;
    452:   MPI_Comm    comm;

    454:   PetscFunctionBegin;
    455:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
    457:   if (N) PetscAssertPointer(idx, 2);
    458:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
    459:   PetscCallMPI(MPI_Comm_size(comm, &size));
    460:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

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

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

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

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

    527:   Collective

    529:   Input Parameters:
    530: + N      - number of `PetscReal` in array
    531: . idx    - array of `PetscReal`
    532: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

    534:   Level: intermediate

    536:   Note:
    537:   This may be called from within the debugger, passing 0 as the viewer

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

    542: .seealso: `PetscViewer`, `PetscIntView()`
    543: @*/
    544: PetscErrorCode PetscRealView(PetscInt N, const PetscReal idx[], PetscViewer viewer)
    545: {
    546:   PetscMPIInt rank, size;
    547:   PetscInt    j, i, n = N / 5, p = N % 5;
    548:   PetscBool   iascii, isbinary;
    549:   MPI_Comm    comm;

    551:   PetscFunctionBegin;
    552:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
    554:   PetscAssertPointer(idx, 2);
    555:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
    556:   PetscCallMPI(MPI_Comm_size(comm, &size));
    557:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

    559:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
    560:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
    561:   if (iascii) {
    562:     PetscInt tab;

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

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

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

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

    632:   Collective

    634:   Input Parameters:
    635: + N      - number of scalars in array
    636: . idx    - array of scalars
    637: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

    639:   Level: intermediate

    641:   Note:
    642:   This may be called from within the debugger, passing 0 as the viewer

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

    647: .seealso: `PetscViewer`, `PetscIntView()`, `PetscRealView()`
    648: @*/
    649: PetscErrorCode PetscScalarView(PetscInt N, const PetscScalar idx[], PetscViewer viewer)
    650: {
    651:   PetscMPIInt rank, size;
    652:   PetscInt    j, i, n = N / 3, p = N % 3;
    653:   PetscBool   iascii, isbinary;
    654:   MPI_Comm    comm;

    656:   PetscFunctionBegin;
    657:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
    659:   if (N) PetscAssertPointer(idx, 2);
    660:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
    661:   PetscCallMPI(MPI_Comm_size(comm, &size));
    662:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

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

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

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

    738: #if defined(PETSC_HAVE_CUDA)
    739: #include <petscdevice_cuda.h>
    740: PETSC_EXTERN const char *PetscCUBLASGetErrorName(cublasStatus_t status)
    741: {
    742:   switch (status) {
    743:   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
    744:   case CUBLAS_STATUS_SUCCESS:
    745:     return "CUBLAS_STATUS_SUCCESS";
    746:   case CUBLAS_STATUS_NOT_INITIALIZED:
    747:     return "CUBLAS_STATUS_NOT_INITIALIZED";
    748:   case CUBLAS_STATUS_ALLOC_FAILED:
    749:     return "CUBLAS_STATUS_ALLOC_FAILED";
    750:   case CUBLAS_STATUS_INVALID_VALUE:
    751:     return "CUBLAS_STATUS_INVALID_VALUE";
    752:   case CUBLAS_STATUS_ARCH_MISMATCH:
    753:     return "CUBLAS_STATUS_ARCH_MISMATCH";
    754:   case CUBLAS_STATUS_MAPPING_ERROR:
    755:     return "CUBLAS_STATUS_MAPPING_ERROR";
    756:   case CUBLAS_STATUS_EXECUTION_FAILED:
    757:     return "CUBLAS_STATUS_EXECUTION_FAILED";
    758:   case CUBLAS_STATUS_INTERNAL_ERROR:
    759:     return "CUBLAS_STATUS_INTERNAL_ERROR";
    760:   case CUBLAS_STATUS_NOT_SUPPORTED:
    761:     return "CUBLAS_STATUS_NOT_SUPPORTED";
    762:   case CUBLAS_STATUS_LICENSE_ERROR:
    763:     return "CUBLAS_STATUS_LICENSE_ERROR";
    764:   #endif
    765:   default:
    766:     return "unknown error";
    767:   }
    768: }
    769: PETSC_EXTERN const char *PetscCUSolverGetErrorName(cusolverStatus_t status)
    770: {
    771:   switch (status) {
    772:   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
    773:   case CUSOLVER_STATUS_SUCCESS:
    774:     return "CUSOLVER_STATUS_SUCCESS";
    775:   case CUSOLVER_STATUS_NOT_INITIALIZED:
    776:     return "CUSOLVER_STATUS_NOT_INITIALIZED";
    777:   case CUSOLVER_STATUS_INVALID_VALUE:
    778:     return "CUSOLVER_STATUS_INVALID_VALUE";
    779:   case CUSOLVER_STATUS_ARCH_MISMATCH:
    780:     return "CUSOLVER_STATUS_ARCH_MISMATCH";
    781:   case CUSOLVER_STATUS_INTERNAL_ERROR:
    782:     return "CUSOLVER_STATUS_INTERNAL_ERROR";
    783:     #if (CUDART_VERSION >= 9000) /* CUDA 9.0 had these defined on June 2021 */
    784:   case CUSOLVER_STATUS_ALLOC_FAILED:
    785:     return "CUSOLVER_STATUS_ALLOC_FAILED";
    786:   case CUSOLVER_STATUS_MAPPING_ERROR:
    787:     return "CUSOLVER_STATUS_MAPPING_ERROR";
    788:   case CUSOLVER_STATUS_EXECUTION_FAILED:
    789:     return "CUSOLVER_STATUS_EXECUTION_FAILED";
    790:   case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
    791:     return "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
    792:   case CUSOLVER_STATUS_NOT_SUPPORTED:
    793:     return "CUSOLVER_STATUS_NOT_SUPPORTED ";
    794:   case CUSOLVER_STATUS_ZERO_PIVOT:
    795:     return "CUSOLVER_STATUS_ZERO_PIVOT";
    796:   case CUSOLVER_STATUS_INVALID_LICENSE:
    797:     return "CUSOLVER_STATUS_INVALID_LICENSE";
    798:     #endif
    799:   #endif
    800:   default:
    801:     return "unknown error";
    802:   }
    803: }
    804: PETSC_EXTERN const char *PetscCUFFTGetErrorName(cufftResult result)
    805: {
    806:   switch (result) {
    807:   case CUFFT_SUCCESS:
    808:     return "CUFFT_SUCCESS";
    809:   case CUFFT_INVALID_PLAN:
    810:     return "CUFFT_INVALID_PLAN";
    811:   case CUFFT_ALLOC_FAILED:
    812:     return "CUFFT_ALLOC_FAILED";
    813:   case CUFFT_INVALID_TYPE:
    814:     return "CUFFT_INVALID_TYPE";
    815:   case CUFFT_INVALID_VALUE:
    816:     return "CUFFT_INVALID_VALUE";
    817:   case CUFFT_INTERNAL_ERROR:
    818:     return "CUFFT_INTERNAL_ERROR";
    819:   case CUFFT_EXEC_FAILED:
    820:     return "CUFFT_EXEC_FAILED";
    821:   case CUFFT_SETUP_FAILED:
    822:     return "CUFFT_SETUP_FAILED";
    823:   case CUFFT_INVALID_SIZE:
    824:     return "CUFFT_INVALID_SIZE";
    825:   case CUFFT_UNALIGNED_DATA:
    826:     return "CUFFT_UNALIGNED_DATA";
    827:   case CUFFT_INCOMPLETE_PARAMETER_LIST:
    828:     return "CUFFT_INCOMPLETE_PARAMETER_LIST";
    829:   case CUFFT_INVALID_DEVICE:
    830:     return "CUFFT_INVALID_DEVICE";
    831:   case CUFFT_PARSE_ERROR:
    832:     return "CUFFT_PARSE_ERROR";
    833:   case CUFFT_NO_WORKSPACE:
    834:     return "CUFFT_NO_WORKSPACE";
    835:   case CUFFT_NOT_IMPLEMENTED:
    836:     return "CUFFT_NOT_IMPLEMENTED";
    837:   case CUFFT_LICENSE_ERROR:
    838:     return "CUFFT_LICENSE_ERROR";
    839:   case CUFFT_NOT_SUPPORTED:
    840:     return "CUFFT_NOT_SUPPORTED";
    841:   default:
    842:     return "unknown error";
    843:   }
    844: }
    845: #endif

    847: #if defined(PETSC_HAVE_HIP)
    848: #include <petscdevice_hip.h>
    849: PETSC_EXTERN const char *PetscHIPBLASGetErrorName(hipblasStatus_t status)
    850: {
    851:   switch (status) {
    852:   case HIPBLAS_STATUS_SUCCESS:
    853:     return "HIPBLAS_STATUS_SUCCESS";
    854:   case HIPBLAS_STATUS_NOT_INITIALIZED:
    855:     return "HIPBLAS_STATUS_NOT_INITIALIZED";
    856:   case HIPBLAS_STATUS_ALLOC_FAILED:
    857:     return "HIPBLAS_STATUS_ALLOC_FAILED";
    858:   case HIPBLAS_STATUS_INVALID_VALUE:
    859:     return "HIPBLAS_STATUS_INVALID_VALUE";
    860:   case HIPBLAS_STATUS_ARCH_MISMATCH:
    861:     return "HIPBLAS_STATUS_ARCH_MISMATCH";
    862:   case HIPBLAS_STATUS_MAPPING_ERROR:
    863:     return "HIPBLAS_STATUS_MAPPING_ERROR";
    864:   case HIPBLAS_STATUS_EXECUTION_FAILED:
    865:     return "HIPBLAS_STATUS_EXECUTION_FAILED";
    866:   case HIPBLAS_STATUS_INTERNAL_ERROR:
    867:     return "HIPBLAS_STATUS_INTERNAL_ERROR";
    868:   case HIPBLAS_STATUS_NOT_SUPPORTED:
    869:     return "HIPBLAS_STATUS_NOT_SUPPORTED";
    870:   default:
    871:     return "unknown error";
    872:   }
    873: }
    874: PETSC_EXTERN const char *PetscHIPSPARSEGetErrorName(hipsparseStatus_t status)
    875: {
    876:   switch (status) {
    877:   case HIPSPARSE_STATUS_SUCCESS:
    878:     return "HIPSPARSE_STATUS_SUCCESS";
    879:   case HIPSPARSE_STATUS_NOT_INITIALIZED:
    880:     return "HIPSPARSE_STATUS_NOT_INITIALIZED";
    881:   case HIPSPARSE_STATUS_ALLOC_FAILED:
    882:     return "HIPSPARSE_STATUS_ALLOC_FAILED";
    883:   case HIPSPARSE_STATUS_INVALID_VALUE:
    884:     return "HIPSPARSE_STATUS_INVALID_VALUE";
    885:   case HIPSPARSE_STATUS_ARCH_MISMATCH:
    886:     return "HIPSPARSE_STATUS_ARCH_MISMATCH";
    887:   case HIPSPARSE_STATUS_MAPPING_ERROR:
    888:     return "HIPSPARSE_STATUS_MAPPING_ERROR";
    889:   case HIPSPARSE_STATUS_EXECUTION_FAILED:
    890:     return "HIPSPARSE_STATUS_EXECUTION_FAILED";
    891:   case HIPSPARSE_STATUS_INTERNAL_ERROR:
    892:     return "HIPSPARSE_STATUS_INTERNAL_ERROR";
    893:   case HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
    894:     return "HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
    895:   case HIPSPARSE_STATUS_ZERO_PIVOT:
    896:     return "HIPSPARSE_STATUS_ZERO_PIVOT";
    897:   case HIPSPARSE_STATUS_NOT_SUPPORTED:
    898:     return "HIPSPARSE_STATUS_NOT_SUPPORTED";
    899:   case HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES:
    900:     return "HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES";
    901:   default:
    902:     return "unknown error";
    903:   }
    904: }
    905: PETSC_EXTERN const char *PetscHIPSolverGetErrorName(hipsolverStatus_t status)
    906: {
    907:   switch (status) {
    908:   case HIPSOLVER_STATUS_SUCCESS:
    909:     return "HIPSOLVER_STATUS_SUCCESS";
    910:   case HIPSOLVER_STATUS_NOT_INITIALIZED:
    911:     return "HIPSOLVER_STATUS_NOT_INITIALIZED";
    912:   case HIPSOLVER_STATUS_ALLOC_FAILED:
    913:     return "HIPSOLVER_STATUS_ALLOC_FAILED";
    914:   case HIPSOLVER_STATUS_MAPPING_ERROR:
    915:     return "HIPSOLVER_STATUS_MAPPING_ERROR";
    916:   case HIPSOLVER_STATUS_INVALID_VALUE:
    917:     return "HIPSOLVER_STATUS_INVALID_VALUE";
    918:   case HIPSOLVER_STATUS_EXECUTION_FAILED:
    919:     return "HIPSOLVER_STATUS_EXECUTION_FAILED";
    920:   case HIPSOLVER_STATUS_INTERNAL_ERROR:
    921:     return "HIPSOLVER_STATUS_INTERNAL_ERROR";
    922:   case HIPSOLVER_STATUS_NOT_SUPPORTED:
    923:     return "HIPSOLVER_STATUS_NOT_SUPPORTED ";
    924:   case HIPSOLVER_STATUS_ARCH_MISMATCH:
    925:     return "HIPSOLVER_STATUS_ARCH_MISMATCH";
    926:   case HIPSOLVER_STATUS_HANDLE_IS_NULLPTR:
    927:     return "HIPSOLVER_STATUS_HANDLE_IS_NULLPTR";
    928:   case HIPSOLVER_STATUS_INVALID_ENUM:
    929:     return "HIPSOLVER_STATUS_INVALID_ENUM";
    930:   case HIPSOLVER_STATUS_UNKNOWN:
    931:   default:
    932:     return "HIPSOLVER_STATUS_UNKNOWN";
    933:   }
    934: }
    935: #endif

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

    941:   Not Collective, No Fortran Support

    943:   Input Parameters:
    944: + err  - the MPI error code
    945: - slen - length of `string`, should be at least as large as `MPI_MAX_ERROR_STRING`

    947:   Output Parameter:
    948: . string - the MPI error message

    950:   Level: developer

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

    955: .seealso: `PetscErrorCode` `PetscErrorMessage()`
    956: @*/
    957: void PetscMPIErrorString(PetscMPIInt err, size_t slen, char *string)
    958: {
    959:   char        errorstring[MPI_MAX_ERROR_STRING];
    960:   PetscMPIInt len;
    961:   size_t      j = 0;

    963:   MPI_Error_string(err, (char *)errorstring, &len);
    964:   for (PetscMPIInt i = 0; i < len && j < slen - 2; i++) {
    965:     string[j++] = errorstring[i];
    966:     if (errorstring[i] == '\n') {
    967:       for (PetscMPIInt k = 0; k < 16 && j < slen - 2; k++) string[j++] = ' ';
    968:     }
    969:   }
    970:   string[j] = 0;
    971: }