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: $    int handler(MPI_Comm comm,int line,char *func,char *file,PetscErrorCode n,int p,char *mess,void *ctx);

 93: +  comm - communicator over which error occurred
 94: .  line - the line number of the error (indicated by __LINE__)
 95: .  file - the file in which the error was detected (indicated by __FILE__)
 96: .  n - the generic error number (see list defined in include/petscerror.h)
 97: .  p - PETSC_ERROR_INITIAL if error just detected, otherwise PETSC_ERROR_REPEAT
 98: .  mess - an error text string, usually just printed to the screen
 99: -  ctx - the error handler context

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

105:    Level: intermediate

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

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

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

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

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

134:    Not Collective

136:    Level: intermediate

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

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

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

155:    Not Collective

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

166:    Level: developer

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

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

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

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

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

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

241:   Not Collective

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

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

251:   Level: developer

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

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

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

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

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

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

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

317:   Collective

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

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

332:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

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

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

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

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

414: /* -------------------------------------------------------------------------*/

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

419:     Collective

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

426:   Level: intermediate

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

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

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

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

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

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

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

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

516:     Collective

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

523:   Level: intermediate

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

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

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

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

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

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

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

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

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

621:     Collective

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

628:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

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

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

936:    Level: developer

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

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

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