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>

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

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

 21: static EH eh = NULL;

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

 27:   Not Collective, No Fortran Support

 29:   Input Parameters:
 30: + comm - communicator over which error occurred
 31: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
 32: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
 33: . fun  - the function name of the calling routine
 34: . mess - an error text string, usually just printed to the screen
 35: . n    - the generic error number
 36: . 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
 37: - ctx  - error handler context

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

 42:   Level: developer

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

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

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

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

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

 89:   Not Collective, No Fortran Support

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

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

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

110:   Level: intermediate

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

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

119: .seealso: `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscPushSignalHandler()`,
120:           `PetscErrorType`, `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`, `PetscErrorCode`
121: @*/
122: 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)
123: {
124:   EH neweh;

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

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

140:   Not Collective

142:   Level: intermediate

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

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

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

161:   Not Collective, No Fortran Support

163:   Input Parameters:
164: + comm - communicator over which error occurred
165: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
166: . fun  - the function name
167: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
168: . mess - an error text string, usually just printed to the screen
169: . n    - the generic error number
170: . 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
171: - ctx  - error handler context

173:   Level: developer

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

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

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

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

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

255:   Not Collective, No Fortran Support

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

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

265:   Level: developer

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

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

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

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

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

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

328:   Collective

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

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

343:   Level: intermediate

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

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

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

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

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

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

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

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

389:   if (!PetscErrorHandlingInitialized) return n;
390:   if (comm == MPI_COMM_NULL) comm = PETSC_COMM_SELF;

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

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

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

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

425: #if PetscDefined(HAVE_CUDA)
426: #include <petscdevice_cuda.h>
427: PETSC_EXTERN const char *PetscCUBLASGetErrorName(cublasStatus_t status)
428: {
429:   switch (status) {
430:   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
431:   case CUBLAS_STATUS_SUCCESS:
432:     return "CUBLAS_STATUS_SUCCESS";
433:   case CUBLAS_STATUS_NOT_INITIALIZED:
434:     return "CUBLAS_STATUS_NOT_INITIALIZED";
435:   case CUBLAS_STATUS_ALLOC_FAILED:
436:     return "CUBLAS_STATUS_ALLOC_FAILED";
437:   case CUBLAS_STATUS_INVALID_VALUE:
438:     return "CUBLAS_STATUS_INVALID_VALUE";
439:   case CUBLAS_STATUS_ARCH_MISMATCH:
440:     return "CUBLAS_STATUS_ARCH_MISMATCH";
441:   case CUBLAS_STATUS_MAPPING_ERROR:
442:     return "CUBLAS_STATUS_MAPPING_ERROR";
443:   case CUBLAS_STATUS_EXECUTION_FAILED:
444:     return "CUBLAS_STATUS_EXECUTION_FAILED";
445:   case CUBLAS_STATUS_INTERNAL_ERROR:
446:     return "CUBLAS_STATUS_INTERNAL_ERROR";
447:   case CUBLAS_STATUS_NOT_SUPPORTED:
448:     return "CUBLAS_STATUS_NOT_SUPPORTED";
449:   case CUBLAS_STATUS_LICENSE_ERROR:
450:     return "CUBLAS_STATUS_LICENSE_ERROR";
451:   #endif
452:   default:
453:     return "unknown error";
454:   }
455: }
456: PETSC_EXTERN const char *PetscCUSolverGetErrorName(cusolverStatus_t status)
457: {
458:   switch (status) {
459:   #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
460:   case CUSOLVER_STATUS_SUCCESS:
461:     return "CUSOLVER_STATUS_SUCCESS";
462:   case CUSOLVER_STATUS_NOT_INITIALIZED:
463:     return "CUSOLVER_STATUS_NOT_INITIALIZED";
464:   case CUSOLVER_STATUS_INVALID_VALUE:
465:     return "CUSOLVER_STATUS_INVALID_VALUE";
466:   case CUSOLVER_STATUS_ARCH_MISMATCH:
467:     return "CUSOLVER_STATUS_ARCH_MISMATCH";
468:   case CUSOLVER_STATUS_INTERNAL_ERROR:
469:     return "CUSOLVER_STATUS_INTERNAL_ERROR";
470:     #if (CUDART_VERSION >= 9000) /* CUDA 9.0 had these defined on June 2021 */
471:   case CUSOLVER_STATUS_ALLOC_FAILED:
472:     return "CUSOLVER_STATUS_ALLOC_FAILED";
473:   case CUSOLVER_STATUS_MAPPING_ERROR:
474:     return "CUSOLVER_STATUS_MAPPING_ERROR";
475:   case CUSOLVER_STATUS_EXECUTION_FAILED:
476:     return "CUSOLVER_STATUS_EXECUTION_FAILED";
477:   case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
478:     return "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
479:   case CUSOLVER_STATUS_NOT_SUPPORTED:
480:     return "CUSOLVER_STATUS_NOT_SUPPORTED ";
481:   case CUSOLVER_STATUS_ZERO_PIVOT:
482:     return "CUSOLVER_STATUS_ZERO_PIVOT";
483:   case CUSOLVER_STATUS_INVALID_LICENSE:
484:     return "CUSOLVER_STATUS_INVALID_LICENSE";
485:     #endif
486:   #endif
487:   default:
488:     return "unknown error";
489:   }
490: }
491: PETSC_EXTERN const char *PetscCUFFTGetErrorName(cufftResult result)
492: {
493:   switch (result) {
494:   case CUFFT_SUCCESS:
495:     return "CUFFT_SUCCESS";
496:   case CUFFT_INVALID_PLAN:
497:     return "CUFFT_INVALID_PLAN";
498:   case CUFFT_ALLOC_FAILED:
499:     return "CUFFT_ALLOC_FAILED";
500:   case CUFFT_INVALID_TYPE:
501:     return "CUFFT_INVALID_TYPE";
502:   case CUFFT_INVALID_VALUE:
503:     return "CUFFT_INVALID_VALUE";
504:   case CUFFT_INTERNAL_ERROR:
505:     return "CUFFT_INTERNAL_ERROR";
506:   case CUFFT_EXEC_FAILED:
507:     return "CUFFT_EXEC_FAILED";
508:   case CUFFT_SETUP_FAILED:
509:     return "CUFFT_SETUP_FAILED";
510:   case CUFFT_INVALID_SIZE:
511:     return "CUFFT_INVALID_SIZE";
512:   case CUFFT_UNALIGNED_DATA:
513:     return "CUFFT_UNALIGNED_DATA";
514:   case CUFFT_INVALID_DEVICE:
515:     return "CUFFT_INVALID_DEVICE";
516:   case CUFFT_NO_WORKSPACE:
517:     return "CUFFT_NO_WORKSPACE";
518:   case CUFFT_NOT_IMPLEMENTED:
519:     return "CUFFT_NOT_IMPLEMENTED";
520:   case CUFFT_NOT_SUPPORTED:
521:     return "CUFFT_NOT_SUPPORTED";
522:   #if PETSC_PKG_CUDA_VERSION_LT(13, 0, 0)
523:   case CUFFT_INCOMPLETE_PARAMETER_LIST:
524:     return "CUFFT_INCOMPLETE_PARAMETER_LIST";
525:   case CUFFT_PARSE_ERROR:
526:     return "CUFFT_PARSE_ERROR";
527:   case CUFFT_LICENSE_ERROR:
528:     return "CUFFT_LICENSE_ERROR";
529:   #endif
530:   default:
531:     return "unknown error";
532:   }
533: }
534: #endif

536: #if PetscDefined(HAVE_HIP)
537: #include <petscdevice_hip.h>
538: PETSC_EXTERN const char *PetscHIPBLASGetErrorName(hipblasStatus_t status)
539: {
540:   switch (status) {
541:   case HIPBLAS_STATUS_SUCCESS:
542:     return "HIPBLAS_STATUS_SUCCESS";
543:   case HIPBLAS_STATUS_NOT_INITIALIZED:
544:     return "HIPBLAS_STATUS_NOT_INITIALIZED";
545:   case HIPBLAS_STATUS_ALLOC_FAILED:
546:     return "HIPBLAS_STATUS_ALLOC_FAILED";
547:   case HIPBLAS_STATUS_INVALID_VALUE:
548:     return "HIPBLAS_STATUS_INVALID_VALUE";
549:   case HIPBLAS_STATUS_ARCH_MISMATCH:
550:     return "HIPBLAS_STATUS_ARCH_MISMATCH";
551:   case HIPBLAS_STATUS_MAPPING_ERROR:
552:     return "HIPBLAS_STATUS_MAPPING_ERROR";
553:   case HIPBLAS_STATUS_EXECUTION_FAILED:
554:     return "HIPBLAS_STATUS_EXECUTION_FAILED";
555:   case HIPBLAS_STATUS_INTERNAL_ERROR:
556:     return "HIPBLAS_STATUS_INTERNAL_ERROR";
557:   case HIPBLAS_STATUS_NOT_SUPPORTED:
558:     return "HIPBLAS_STATUS_NOT_SUPPORTED";
559:   default:
560:     return "unknown error";
561:   }
562: }
563: PETSC_EXTERN const char *PetscHIPSPARSEGetErrorName(hipsparseStatus_t status)
564: {
565:   switch (status) {
566:   case HIPSPARSE_STATUS_SUCCESS:
567:     return "HIPSPARSE_STATUS_SUCCESS";
568:   case HIPSPARSE_STATUS_NOT_INITIALIZED:
569:     return "HIPSPARSE_STATUS_NOT_INITIALIZED";
570:   case HIPSPARSE_STATUS_ALLOC_FAILED:
571:     return "HIPSPARSE_STATUS_ALLOC_FAILED";
572:   case HIPSPARSE_STATUS_INVALID_VALUE:
573:     return "HIPSPARSE_STATUS_INVALID_VALUE";
574:   case HIPSPARSE_STATUS_ARCH_MISMATCH:
575:     return "HIPSPARSE_STATUS_ARCH_MISMATCH";
576:   case HIPSPARSE_STATUS_MAPPING_ERROR:
577:     return "HIPSPARSE_STATUS_MAPPING_ERROR";
578:   case HIPSPARSE_STATUS_EXECUTION_FAILED:
579:     return "HIPSPARSE_STATUS_EXECUTION_FAILED";
580:   case HIPSPARSE_STATUS_INTERNAL_ERROR:
581:     return "HIPSPARSE_STATUS_INTERNAL_ERROR";
582:   case HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
583:     return "HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
584:   case HIPSPARSE_STATUS_ZERO_PIVOT:
585:     return "HIPSPARSE_STATUS_ZERO_PIVOT";
586:   case HIPSPARSE_STATUS_NOT_SUPPORTED:
587:     return "HIPSPARSE_STATUS_NOT_SUPPORTED";
588:   case HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES:
589:     return "HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES";
590:   default:
591:     return "unknown error";
592:   }
593: }
594: PETSC_EXTERN const char *PetscHIPSolverGetErrorName(hipsolverStatus_t status)
595: {
596:   switch (status) {
597:   case HIPSOLVER_STATUS_SUCCESS:
598:     return "HIPSOLVER_STATUS_SUCCESS";
599:   case HIPSOLVER_STATUS_NOT_INITIALIZED:
600:     return "HIPSOLVER_STATUS_NOT_INITIALIZED";
601:   case HIPSOLVER_STATUS_ALLOC_FAILED:
602:     return "HIPSOLVER_STATUS_ALLOC_FAILED";
603:   case HIPSOLVER_STATUS_MAPPING_ERROR:
604:     return "HIPSOLVER_STATUS_MAPPING_ERROR";
605:   case HIPSOLVER_STATUS_INVALID_VALUE:
606:     return "HIPSOLVER_STATUS_INVALID_VALUE";
607:   case HIPSOLVER_STATUS_EXECUTION_FAILED:
608:     return "HIPSOLVER_STATUS_EXECUTION_FAILED";
609:   case HIPSOLVER_STATUS_INTERNAL_ERROR:
610:     return "HIPSOLVER_STATUS_INTERNAL_ERROR";
611:   case HIPSOLVER_STATUS_NOT_SUPPORTED:
612:     return "HIPSOLVER_STATUS_NOT_SUPPORTED ";
613:   case HIPSOLVER_STATUS_ARCH_MISMATCH:
614:     return "HIPSOLVER_STATUS_ARCH_MISMATCH";
615:   case HIPSOLVER_STATUS_HANDLE_IS_NULLPTR:
616:     return "HIPSOLVER_STATUS_HANDLE_IS_NULLPTR";
617:   case HIPSOLVER_STATUS_INVALID_ENUM:
618:     return "HIPSOLVER_STATUS_INVALID_ENUM";
619:   case HIPSOLVER_STATUS_UNKNOWN:
620:   default:
621:     return "HIPSOLVER_STATUS_UNKNOWN";
622:   }
623: }
624: #endif

626: /*@
627:   PetscMPIErrorString - Given an MPI error code returns the `MPI_Error_string()` appropriately
628:   formatted for displaying with the PETSc error handlers.

630:   Not Collective, No Fortran Support

632:   Input Parameters:
633: + err  - the MPI error code
634: - slen - length of `string`, should be at least as large as `MPI_MAX_ERROR_STRING`

636:   Output Parameter:
637: . string - the MPI error message

639:   Level: developer

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

644: .seealso: `PetscErrorCode` `PetscErrorMessage()`
645: @*/
646: void PetscMPIErrorString(PetscMPIInt err, size_t slen, char *string)
647: {
648:   char        errorstring[MPI_MAX_ERROR_STRING];
649:   PetscMPIInt len;
650:   size_t      j = 0;

652:   MPI_Error_string(err, (char *)errorstring, &len);
653:   for (PetscMPIInt i = 0; i < len && j < slen - 2; i++) {
654:     string[j++] = errorstring[i];
655:     if (errorstring[i] == '\n') {
656:       for (PetscMPIInt k = 0; k < 16 && j < slen - 2; k++) string[j++] = ' ';
657:     }
658:   }
659:   string[j] = 0;
660: }