Actual source code: err.c


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

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

 17: static EH eh = NULL;

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

 23:    Not Collective

 25:    Input Parameters:
 26: +  comm - communicator over which error occurred
 27: .  line - the line number of the error (indicated by __LINE__)
 28: .  file - the file in which the error was detected (indicated by __FILE__)
 29: .  mess - an error text string, usually just printed to the screen
 30: .  n - the generic error number
 31: .  p - specific error number
 32: -  ctx - error handler context

 34:    Options Database Key:
 35: .   -on_error_emacs <machinename> - will contact machinename to open the Emacs client there

 37:    Level: developer

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

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

 46: .seealso: `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`,
 47:           `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscReturnErrorHandler()`
 48:  @*/
 49: PetscErrorCode PetscEmacsClientErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx)
 50: {
 51:   PetscErrorCode ierr;
 52:   char           command[PETSC_MAX_PATH_LEN];
 53:   const char    *pdir;
 54:   FILE          *fp;

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

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

 83:    Not Collective

 85:    Input Parameters:
 86: +  handler - error handler routine
 87: -  ctx - optional handler context that contains information needed by the handler (for
 88:          example file pointers for error messages etc.)

 90:    Calling sequence of `handler`:
 91: $  PetscErrorCode handler(MPI_Comm comm, int line, char *func, char *file, PetscErrorCode n, int p, char *mess, void *ctx);
 92: +  comm - communicator over which error occurred
 93: .  line - the line number of the error (indicated by __LINE__)
 94: .  file - the file in which the error was detected (indicated by __FILE__)
 95: .  n - the generic error number (see list defined in include/petscerror.h)
 96: .  p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
 97: .  mess - an error text string, usually just printed to the screen
 98: -  ctx - the error handler context

100:    Options Database Keys:
101: +   -on_error_attach_debugger <noxterm,gdb or dbx> - starts up the debugger if an error occurs
102: -   -on_error_abort - aborts the program if an error occurs

104:    Level: intermediate

106:    Note:
107:    The currently available PETSc error handlers include `PetscTraceBackErrorHandler()`,
108:    `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, and `PetscMPIAbortErrorHandler()`, `PetscReturnErrorHandler()`.

110:    Fortran Note:
111:     You can only push one error handler from Fortran before poping it.

113: .seealso: `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscPushSignalHandler()`
114: @*/
115: PetscErrorCode PetscPushErrorHandler(PetscErrorCode (*handler)(MPI_Comm comm, int, const char *, const char *, PetscErrorCode, PetscErrorType, const char *, void *), void *ctx)
116: {
117:   EH neweh;

119:   PetscFunctionBegin;
120:   PetscCall(PetscNew(&neweh));
121:   if (eh) neweh->previous = eh;
122:   else neweh->previous = NULL;
123:   neweh->handler = handler;
124:   neweh->ctx     = ctx;
125:   eh             = neweh;
126:   PetscFunctionReturn(PETSC_SUCCESS);
127: }

129: /*@
130:    PetscPopErrorHandler - Removes the latest error handler that was
131:    pushed with `PetscPushErrorHandler()`.

133:    Not Collective

135:    Level: intermediate

137: .seealso: `PetscPushErrorHandler()`
138: @*/
139: PetscErrorCode PetscPopErrorHandler(void)
140: {
141:   EH tmp;

143:   PetscFunctionBegin;
144:   if (!eh) PetscFunctionReturn(PETSC_SUCCESS);
145:   tmp = eh;
146:   eh  = eh->previous;
147:   PetscCall(PetscFree(tmp));
148:   PetscFunctionReturn(PETSC_SUCCESS);
149: }

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

154:    Not Collective

156:    Input Parameters:
157: +  comm - communicator over which error occurred
158: .  line - the line number of the error (indicated by __LINE__)
159: .  file - the file in which the error was detected (indicated by __FILE__)
160: .  mess - an error text string, usually just printed to the screen
161: .  n - the generic error number
162: .  p - specific error number
163: -  ctx - error handler context

165:    Level: developer

167:    Notes:
168:    Most users need not directly employ this routine and the other error
169:    handlers, but can instead use the simplified interface `SETERRQ()`, which has
170:    the calling sequence
171: $     SETERRQ(comm,number,mess)

173:    `PetscIgnoreErrorHandler()` does the same thing as this function, but is deprecated, you should use this function.

175:    Use `PetscPushErrorHandler()` to set the desired error handler.

177: .seealso: `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscError()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscTraceBackErrorHandler()`,
178:           `PetscAttachDebuggerErrorHandler()`, `PetscEmacsClientErrorHandler()`
179:  @*/
180: PetscErrorCode PetscReturnErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx)
181: {
182:   return n;
183: }

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

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

240:   Not Collective

242:   Input Parameter:
243: . errnum - the error code

245:   Output Parameters:
246: + text - the error message (`NULL` if not desired)
247: - specific - the specific error message that was set with `SETERRQ()` or
248:              `PetscError()`. (`NULL` if not desired)

250:   Level: developer

252: .seealso: `PetscErrorCode`, `PetscPushErrorHandler()`, `PetscAttachDebuggerErrorHandler()`,
253: `PetscError()`, `SETERRQ()`, `PetscCall()` `PetscAbortErrorHandler()`,
254: `PetscTraceBackErrorHandler()`
255: @*/
256: PetscErrorCode PetscErrorMessage(PetscErrorCode errnum, const char *text[], char **specific)
257: {
258:   PetscFunctionBegin;
259:   if (text) {
260:     if (errnum > PETSC_ERR_MIN_VALUE && errnum < PETSC_ERR_MAX_VALUE) {
261:       size_t len;

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

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

273:          If PetscBar() fails (returns nonzero) PetscBaz() is not executed but the result of
274:          this expression is boolean false, hence PETSC_ERR_UNNOWN
275:        */
276:       *text = "Error occurred in boolean shortcuit in macro";
277:     } else {
278:       *text = NULL;
279:     }
280:   }
281:   if (specific) *specific = PetscErrorBaseMessage;
282:   PetscFunctionReturn(PETSC_SUCCESS);
283: }

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

309:   throw std::runtime_error(str);
310: }
311: #endif

313: /*@C
314:    PetscError - Routine that is called when an error has been detected, usually called through the macro SETERRQ(PETSC_COMM_SELF,).

316:   Collective

318:    Input Parameters:
319: +  comm - communicator over which error occurred.  ALL ranks of this communicator MUST call this routine
320: .  line - the line number of the error (indicated by __LINE__)
321: .  func - the function name in which the error was detected
322: .  file - the file in which the error was detected (indicated by __FILE__)
323: .  n - the generic error number
324: .  p - `PETSC_ERROR_INITIAL` indicates the error was initially detected, `PETSC_ERROR_REPEAT` indicates this is a traceback from a previously detected error
325: -  mess - formatted message string - aka printf

327:   Options Database Keys:
328: +  -error_output_stdout - output the error messages to stdout instead of the default stderr
329: -  -error_output_none - do not output the error messages

331:   Level: intermediate

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

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

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

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

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

354:    Fortran Note:
355:    This routine is used differently from Fortran
356: $    PetscError(MPI_Comm comm,PetscErrorCode n,PetscErrorType p,char *message)

358:    Developer Note:
359:    Since this is called after an error condition it should not be calling any error handlers (currently it ignores any error codes)
360:    BUT this routine does call regular PETSc functions that may call error handlers, this is problematic and could be fixed by never calling other PETSc routines
361:    but this annoying.

363: .seealso: `PetscErrorCode`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`,
364:           `PetscReturnErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscEmacsClientErrorHandler()`,
365:           `SETERRQ()`, `PetscCall()`, `CHKMEMQ`, `SETERRQ()`, `SETERRQ()`, `PetscErrorMessage()`, `PETSCABORT()`
366: @*/
367: PetscErrorCode PetscError(MPI_Comm comm, int line, const char *func, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, ...)
368: {
369:   va_list        Argp;
370:   size_t         fullLength;
371:   char           buf[2048], *lbuf = NULL;
372:   PetscBool      ismain;
373:   PetscErrorCode ierr;

375:   if (!PetscErrorHandlingInitialized) return n;
376:   if (comm == MPI_COMM_NULL) comm = PETSC_COMM_SELF;

378:   /* Compose the message evaluating the print format */
379:   if (mess) {
380:     va_start(Argp, mess);
381:     ierr = PetscVSNPrintf(buf, 2048, mess, &fullLength, Argp);
382:     va_end(Argp);
383:     lbuf = buf;
384:     if (p == PETSC_ERROR_INITIAL) ierr = PetscStrncpy(PetscErrorBaseMessage, lbuf, sizeof(PetscErrorBaseMessage));
385:   }

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

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

393:   /*
394:       If this is called from the main() routine we call MPI_Abort() instead of
395:     return to allow the parallel program to be properly shutdown.

397:     Does not call PETSCABORT() since that would provide the wrong source file and line number information
398:   */
399:   if (func) {
400:     PetscErrorCode cmp_ierr = PetscStrncmp(func, "main", 4, &ismain);
401:     if (ismain) {
402:       if (petscwaitonerrorflg) cmp_ierr = PetscSleep(1000);
403:       (void)cmp_ierr;
404:       PETSCABORT(comm, ierr);
405:     }
406:   }
407: #if defined(PETSC_CLANGUAGE_CXX)
408:   if (p == PETSC_ERROR_IN_CXX) PetscCxxErrorThrow();
409: #endif
410:   return ierr;
411: }

413: /* -------------------------------------------------------------------------*/

415: /*@C
416:     PetscIntView - Prints an array of integers; useful for debugging.

418:     Collective

420:     Input Parameters:
421: +   N - number of integers in array
422: .   idx - array of integers
423: -   viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

425:   Level: intermediate

427:     Note:
428:     This may be called from within the debugger

430:     Developer Note:
431:     idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done

433: .seealso: `PetscViewer`, `PetscRealView()`
434: @*/
435: PetscErrorCode PetscIntView(PetscInt N, const PetscInt idx[], PetscViewer viewer)
436: {
437:   PetscMPIInt rank, size;
438:   PetscInt    j, i, n = N / 20, p = N % 20;
439:   PetscBool   iascii, isbinary;
440:   MPI_Comm    comm;

442:   PetscFunctionBegin;
443:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
446:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
447:   PetscCallMPI(MPI_Comm_size(comm, &size));
448:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

450:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
451:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
452:   if (iascii) {
453:     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
454:     for (i = 0; i < n; i++) {
455:       if (size > 1) {
456:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * i));
457:       } else {
458:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * i));
459:       }
460:       for (j = 0; j < 20; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[i * 20 + j]));
461:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
462:     }
463:     if (p) {
464:       if (size > 1) {
465:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * n));
466:       } else {
467:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * n));
468:       }
469:       for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[20 * n + i]));
470:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
471:     }
472:     PetscCall(PetscViewerFlush(viewer));
473:     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
474:   } else if (isbinary) {
475:     PetscMPIInt *sizes, Ntotal, *displs, NN;
476:     PetscInt    *array;

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

480:     if (size > 1) {
481:       if (rank) {
482:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
483:         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, NULL, NULL, NULL, MPIU_INT, 0, comm));
484:       } else {
485:         PetscCall(PetscMalloc1(size, &sizes));
486:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
487:         Ntotal = sizes[0];
488:         PetscCall(PetscMalloc1(size, &displs));
489:         displs[0] = 0;
490:         for (i = 1; i < size; i++) {
491:           Ntotal += sizes[i];
492:           displs[i] = displs[i - 1] + sizes[i - 1];
493:         }
494:         PetscCall(PetscMalloc1(Ntotal, &array));
495:         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, array, sizes, displs, MPIU_INT, 0, comm));
496:         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_INT));
497:         PetscCall(PetscFree(sizes));
498:         PetscCall(PetscFree(displs));
499:         PetscCall(PetscFree(array));
500:       }
501:     } else {
502:       PetscCall(PetscViewerBinaryWrite(viewer, idx, N, PETSC_INT));
503:     }
504:   } else {
505:     const char *tname;
506:     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
507:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
508:   }
509:   PetscFunctionReturn(PETSC_SUCCESS);
510: }

512: /*@C
513:     PetscRealView - Prints an array of doubles; useful for debugging.

515:     Collective

517:     Input Parameters:
518: +   N - number of `PetscReal` in array
519: .   idx - array of `PetscReal`
520: -   viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

522:   Level: intermediate

524:     Note:
525:     This may be called from within the debugger

527:     Developer Note:
528:     idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done

530: .seealso: `PetscViewer`, `PetscIntView()`
531: @*/
532: PetscErrorCode PetscRealView(PetscInt N, const PetscReal idx[], PetscViewer viewer)
533: {
534:   PetscMPIInt rank, size;
535:   PetscInt    j, i, n = N / 5, p = N % 5;
536:   PetscBool   iascii, isbinary;
537:   MPI_Comm    comm;

539:   PetscFunctionBegin;
540:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
543:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
544:   PetscCallMPI(MPI_Comm_size(comm, &size));
545:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

547:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
548:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
549:   if (iascii) {
550:     PetscInt tab;

552:     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
553:     PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
554:     for (i = 0; i < n; i++) {
555:       PetscCall(PetscViewerASCIISetTab(viewer, tab));
556:       if (size > 1) {
557:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * i));
558:       } else {
559:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * i));
560:       }
561:       PetscCall(PetscViewerASCIISetTab(viewer, 0));
562:       for (j = 0; j < 5; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 5 + j]));
563:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
564:     }
565:     if (p) {
566:       PetscCall(PetscViewerASCIISetTab(viewer, tab));
567:       if (size > 1) {
568:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * n));
569:       } else {
570:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * n));
571:       }
572:       PetscCall(PetscViewerASCIISetTab(viewer, 0));
573:       for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[5 * n + i]));
574:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
575:     }
576:     PetscCall(PetscViewerFlush(viewer));
577:     PetscCall(PetscViewerASCIISetTab(viewer, tab));
578:     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
579:   } else if (isbinary) {
580:     PetscMPIInt *sizes, *displs, Ntotal, NN;
581:     PetscReal   *array;

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

585:     if (size > 1) {
586:       if (rank) {
587:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
588:         PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, NULL, NULL, NULL, MPIU_REAL, 0, comm));
589:       } else {
590:         PetscCall(PetscMalloc1(size, &sizes));
591:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
592:         Ntotal = sizes[0];
593:         PetscCall(PetscMalloc1(size, &displs));
594:         displs[0] = 0;
595:         for (i = 1; i < size; i++) {
596:           Ntotal += sizes[i];
597:           displs[i] = displs[i - 1] + sizes[i - 1];
598:         }
599:         PetscCall(PetscMalloc1(Ntotal, &array));
600:         PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, array, sizes, displs, MPIU_REAL, 0, comm));
601:         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_REAL));
602:         PetscCall(PetscFree(sizes));
603:         PetscCall(PetscFree(displs));
604:         PetscCall(PetscFree(array));
605:       }
606:     } else {
607:       PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_REAL));
608:     }
609:   } else {
610:     const char *tname;
611:     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
612:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
613:   }
614:   PetscFunctionReturn(PETSC_SUCCESS);
615: }

617: /*@C
618:     PetscScalarView - Prints an array of `PetscScalar`; useful for debugging.

620:     Collective

622:     Input Parameters:
623: +   N - number of scalars in array
624: .   idx - array of scalars
625: -   viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0

627:   Level: intermediate

629:     Note:
630:     This may be called from within the debugger

632:     Developer Note:
633:     idx cannot be const because may be passed to binary viewer where byte swapping may be done

635: .seealso: `PetscViewer`, `PetscIntView()`, `PetscRealView()`
636: @*/
637: PetscErrorCode PetscScalarView(PetscInt N, const PetscScalar idx[], PetscViewer viewer)
638: {
639:   PetscMPIInt rank, size;
640:   PetscInt    j, i, n = N / 3, p = N % 3;
641:   PetscBool   iascii, isbinary;
642:   MPI_Comm    comm;

644:   PetscFunctionBegin;
645:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
648:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
649:   PetscCallMPI(MPI_Comm_size(comm, &size));
650:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

652:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
653:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
654:   if (iascii) {
655:     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
656:     for (i = 0; i < n; i++) {
657:       if (size > 1) {
658:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * i));
659:       } else {
660:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * i));
661:       }
662:       for (j = 0; j < 3; j++) {
663: #if defined(PETSC_USE_COMPLEX)
664:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[i * 3 + j]), (double)PetscImaginaryPart(idx[i * 3 + j])));
665: #else
666:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 3 + j]));
667: #endif
668:       }
669:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
670:     }
671:     if (p) {
672:       if (size > 1) {
673:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * n));
674:       } else {
675:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * n));
676:       }
677:       for (i = 0; i < p; i++) {
678: #if defined(PETSC_USE_COMPLEX)
679:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[n * 3 + i]), (double)PetscImaginaryPart(idx[n * 3 + i])));
680: #else
681:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[3 * n + i]));
682: #endif
683:       }
684:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
685:     }
686:     PetscCall(PetscViewerFlush(viewer));
687:     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
688:   } else if (isbinary) {
689:     PetscMPIInt *sizes, Ntotal, *displs, NN;
690:     PetscScalar *array;

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

694:     if (size > 1) {
695:       if (rank) {
696:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
697:         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, NULL, NULL, NULL, MPIU_SCALAR, 0, comm));
698:       } else {
699:         PetscCall(PetscMalloc1(size, &sizes));
700:         PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
701:         Ntotal = sizes[0];
702:         PetscCall(PetscMalloc1(size, &displs));
703:         displs[0] = 0;
704:         for (i = 1; i < size; i++) {
705:           Ntotal += sizes[i];
706:           displs[i] = displs[i - 1] + sizes[i - 1];
707:         }
708:         PetscCall(PetscMalloc1(Ntotal, &array));
709:         PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, array, sizes, displs, MPIU_SCALAR, 0, comm));
710:         PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_SCALAR));
711:         PetscCall(PetscFree(sizes));
712:         PetscCall(PetscFree(displs));
713:         PetscCall(PetscFree(array));
714:       }
715:     } else {
716:       PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_SCALAR));
717:     }
718:   } else {
719:     const char *tname;
720:     PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
721:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
722:   }
723:   PetscFunctionReturn(PETSC_SUCCESS);
724: }

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

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

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

929:  Input Parameter:
930: .  err - the MPI error code

932:  Output Parameter:
933: .  string - the MPI error message, should declare its length to be larger than `MPI_MAX_ERROR_STRING`

935:    Level: developer

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

940: @*/
941: void PetscMPIErrorString(PetscMPIInt err, char *string)
942: {
943:   char        errorstring[MPI_MAX_ERROR_STRING];
944:   PetscMPIInt len, j = 0;

946:   MPI_Error_string(err, (char *)errorstring, &len);
947:   for (PetscMPIInt i = 0; i < len; i++) {
948:     string[j++] = errorstring[i];
949:     if (errorstring[i] == '\n') {
950:       for (PetscMPIInt k = 0; k < 16; k++) string[j++] = ' ';
951:     }
952:   }
953:   string[j] = 0;
954: }