Actual source code: err.c
1: /*
2: Code that allows one to set the error handlers
3: Portions of this code are under:
4: Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5: */
6: #include <petsc/private/petscimpl.h>
7: #include <petscviewer.h>
9: typedef struct _EH *EH;
10: struct _EH {
11: PetscErrorCode (*handler)(MPI_Comm, int, const char *, const char *, PetscErrorCode, PetscErrorType, const char *, void *);
12: void *ctx;
13: EH previous;
14: };
16: /* This is here to allow the traceback error handler (or potentially other error handlers)
17: to certify that PETSCABORT is being called on all MPI processes, and that it should be possible to call
18: MPI_Finalize() and exit(). This should only be used when `PetscCIEnabledPortabeErrorOutput == PETSC_TRUE`
19: to allow testing of error messages. Do not rely on this for clean exit in production. */
20: PetscBool petscabortmpifinalize = PETSC_FALSE;
22: static EH eh = NULL;
24: /*@C
25: PetscEmacsClientErrorHandler - Error handler that uses the emacsclient program to
26: load the file where the error occurred. Then calls the "previous" error handler.
28: Not Collective
30: Input Parameters:
31: + comm - communicator over which error occurred
32: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
33: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
34: . fun - the function name of the calling routine
35: . mess - an error text string, usually just printed to the screen
36: . n - the generic error number
37: . p - `PETSC_ERROR_INITIAL` indicates this is the first time the error handler is being called while `PETSC_ERROR_REPEAT` indicates it was previously called
38: - ctx - error handler context
40: Options Database Key:
41: . -on_error_emacs <machinename> - will contact machinename to open the Emacs client there
43: Level: developer
45: Note:
46: You must put (server-start) in your .emacs file for the emacsclient software to work
48: Developer Note:
49: Since this is an error handler it cannot call `PetscCall()`; thus we just return if an error is detected.
50: But some of the functions it calls do perform error checking that may not be appropriate in a error handler call.
52: .seealso: `PetscError()`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`,
53: `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscReturnErrorHandler()`,
54: `PetscErrorType`, `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`, `PetscErrorCode`
55: @*/
56: PetscErrorCode PetscEmacsClientErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx)
57: {
58: PetscErrorCode ierr;
59: char command[PETSC_MAX_PATH_LEN];
60: const char *pdir;
61: FILE *fp;
63: ierr = PetscGetPetscDir(&pdir);
64: if (ierr) return ierr;
65: ierr = PetscSNPrintf(command, PETSC_STATIC_ARRAY_LENGTH(command), "cd %s; emacsclient --no-wait +%d %s\n", pdir, line, file);
66: if (ierr) return ierr;
67: #if defined(PETSC_HAVE_POPEN)
68: ierr = PetscPOpen(MPI_COMM_WORLD, (char *)ctx, command, "r", &fp);
69: if (ierr) return ierr;
70: ierr = PetscPClose(MPI_COMM_WORLD, fp);
71: if (ierr) return ierr;
72: #else
73: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
74: #endif
75: ierr = PetscPopErrorHandler();
76: if (ierr) return ierr; /* remove this handler from the stack of handlers */
77: if (!eh) {
78: ierr = PetscTraceBackErrorHandler(comm, line, fun, file, n, p, mess, NULL);
79: if (ierr) return ierr;
80: } else {
81: ierr = (*eh->handler)(comm, line, fun, file, n, p, mess, eh->ctx);
82: if (ierr) return ierr;
83: }
84: return PETSC_SUCCESS;
85: }
87: /*@C
88: PetscPushErrorHandler - Sets a routine to be called on detection of errors.
90: Not Collective
92: Input Parameters:
93: + handler - error handler routine
94: - ctx - optional handler context that contains information needed by the handler (for
95: example file pointers for error messages etc.)
97: Calling sequence of `handler`:
98: + comm - communicator over which error occurred
99: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
100: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
101: . fun - the function name of the calling routine
102: . n - the generic error number (see list defined in include/petscerror.h)
103: . p - `PETSC_ERROR_INITIAL` if error just detected, otherwise `PETSC_ERROR_REPEAT`
104: . mess - an error text string, usually just printed to the screen
105: - ctx - the error handler context
107: Options Database Keys:
108: + -on_error_attach_debugger <noxterm,lldb or gdb> - starts up the debugger if an error occurs
109: - -on_error_abort - aborts the program if an error occurs
111: Level: intermediate
113: Note:
114: The currently available PETSc error handlers include `PetscTraceBackErrorHandler()`,
115: `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, and `PetscReturnErrorHandler()`.
117: Fortran Note:
118: You can only push a single error handler from Fortran before popping it.
120: .seealso: `PetscPopErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscPushSignalHandler()`,
121: `PetscErrorType`, `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`, `PetscErrorCode`
122: @*/
123: PetscErrorCode PetscPushErrorHandler(PetscErrorCode (*handler)(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx), void *ctx)
124: {
125: EH neweh;
127: PetscFunctionBegin;
128: PetscCall(PetscNew(&neweh));
129: if (eh) neweh->previous = eh;
130: else neweh->previous = NULL;
131: neweh->handler = handler;
132: neweh->ctx = ctx;
133: eh = neweh;
134: PetscFunctionReturn(PETSC_SUCCESS);
135: }
137: /*@
138: PetscPopErrorHandler - Removes the latest error handler that was
139: pushed with `PetscPushErrorHandler()`.
141: Not Collective
143: Level: intermediate
145: .seealso: `PetscPushErrorHandler()`
146: @*/
147: PetscErrorCode PetscPopErrorHandler(void)
148: {
149: EH tmp;
151: PetscFunctionBegin;
152: if (!eh) PetscFunctionReturn(PETSC_SUCCESS);
153: tmp = eh;
154: eh = eh->previous;
155: PetscCall(PetscFree(tmp));
156: PetscFunctionReturn(PETSC_SUCCESS);
157: }
159: /*@C
160: PetscReturnErrorHandler - Error handler that causes a return without printing an error message.
162: Not Collective
164: Input Parameters:
165: + comm - communicator over which error occurred
166: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
167: . fun - the function name
168: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
169: . mess - an error text string, usually just printed to the screen
170: . n - the generic error number
171: . p - `PETSC_ERROR_INITIAL` indicates this is the first time the error handler is being called while `PETSC_ERROR_REPEAT` indicates it was previously called
172: - ctx - error handler context
174: Level: developer
176: Notes:
177: Users do not directly employ this routine
179: Use `PetscPushErrorHandler()` to set the desired error handler. The
180: currently available PETSc error handlers include `PetscTraceBackErrorHandler()`,
181: `PetscAttachDebuggerErrorHandler()`, and `PetscAbortErrorHandler()`.
183: .seealso: `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscError()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, `PetscTraceBackErrorHandler()`,
184: `PetscAttachDebuggerErrorHandler()`, `PetscEmacsClientErrorHandler()`,
185: `PetscErrorType`, `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`, `PetscErrorCode`
186: @*/
187: PetscErrorCode PetscReturnErrorHandler(MPI_Comm comm, int line, const char *fun, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, void *ctx)
188: {
189: (void)comm;
190: (void)line;
191: (void)fun;
192: (void)file;
193: (void)p;
194: (void)mess;
195: (void)ctx;
196: return n;
197: }
199: static char PetscErrorBaseMessage[1024];
200: /*
201: The numerical values for these are defined in include/petscerror.h; any changes
202: there must also be made here
203: */
204: static const char *PetscErrorStrings[] = {
205: /*55 */ "Out of memory",
206: "No support for this operation for this object type",
207: "No support for this operation on this system",
208: /*58 */ "Operation done in wrong order",
209: /*59 */ "Signal received",
210: /*60 */ "Nonconforming object sizes",
211: "Argument aliasing not permitted",
212: "Invalid argument",
213: /*63 */ "Argument out of range",
214: "Corrupt argument: https://petsc.org/release/faq/#valgrind",
215: "Unable to open file",
216: "Read from file failed",
217: "Write to file failed",
218: "Invalid pointer",
219: /*69 */ "Arguments must have same type",
220: /*70 */ "Attempt to use a pointer that does not point to a valid accessible location",
221: /*71 */ "Zero pivot in LU factorization: https://petsc.org/release/faq/#zeropivot",
222: /*72 */ "Floating point exception",
223: /*73 */ "Object is in wrong state",
224: "Corrupted Petsc object",
225: "Arguments are incompatible",
226: "Error in external library",
227: /*77 */ "Petsc has generated inconsistent data",
228: "Memory corruption: https://petsc.org/release/faq/#valgrind",
229: "Unexpected data in file",
230: /*80 */ "Arguments must have same communicators",
231: /*81 */ "Zero pivot in Cholesky factorization: https://petsc.org/release/faq/#zeropivot",
232: "",
233: "",
234: "Overflow in integer operation: https://petsc.org/release/faq/#64-bit-indices",
235: /*85 */ "Null argument, when expecting valid pointer",
236: /*86 */ "Unknown type. Check for miss-spelling or missing package: https://petsc.org/release/install/install/#external-packages",
237: /*87 */ "MPI library at runtime is not compatible with MPI used at compile time",
238: /*88 */ "Error in system call",
239: /*89 */ "Object Type not set: https://petsc.org/release/faq/#object-type-not-set",
240: /*90 */ "",
241: /* */ "",
242: /*92 */ "See https://petsc.org/release/overview/linear_solve_table/ for possible LU and Cholesky solvers",
243: /*93 */ "You cannot overwrite this option since that will conflict with other previously set options",
244: /*94 */ "Example/application run with number of MPI ranks it does not support",
245: /*95 */ "Missing or incorrect user input",
246: /*96 */ "GPU resources unavailable",
247: /*97 */ "GPU error",
248: /*98 */ "General MPI error",
249: /*99 */ "PetscError() incorrectly returned an error code of 0"};
251: /*@C
252: PetscErrorMessage - Returns the text string associated with a PETSc error code.
254: Not Collective
256: Input Parameter:
257: . errnum - the error code
259: Output Parameters:
260: + text - the error message (`NULL` if not desired)
261: - specific - the specific error message that was set with `SETERRQ()` or
262: `PetscError()`. (`NULL` if not desired)
264: Level: developer
266: .seealso: `PetscErrorCode`, `PetscPushErrorHandler()`, `PetscAttachDebuggerErrorHandler()`,
267: `PetscError()`, `SETERRQ()`, `PetscCall()` `PetscAbortErrorHandler()`,
268: `PetscTraceBackErrorHandler()`
269: @*/
270: PetscErrorCode PetscErrorMessage(PetscErrorCode errnum, const char *text[], char **specific)
271: {
272: PetscFunctionBegin;
273: if (text) {
274: if (errnum > PETSC_ERR_MIN_VALUE && errnum < PETSC_ERR_MAX_VALUE) {
275: size_t len;
277: *text = PetscErrorStrings[errnum - PETSC_ERR_MIN_VALUE - 1];
278: PetscCall(PetscStrlen(*text, &len));
279: if (!len) *text = NULL;
280: } else if (errnum == PETSC_ERR_BOOLEAN_MACRO_FAILURE) {
281: /* this "error code" arises from failures in boolean macros, where the || operator is
282: used to short-circuit the macro call in case of error. This has the side effect of
283: "returning" either 0 (PETSC_SUCCESS) or 1 (PETSC_ERR_UNKNONWN):
285: #define PETSC_FOO(x) ((PetscErrorCode)(PetscBar(x) || PetscBaz(x)))
287: If PetscBar() fails (returns nonzero) PetscBaz() is not executed but the result of
288: this expression is boolean false, hence PETSC_ERR_UNNOWN
289: */
290: *text = "Error occurred in boolean shortcuit in macro";
291: } else {
292: *text = NULL;
293: }
294: }
295: if (specific) *specific = PetscErrorBaseMessage;
296: PetscFunctionReturn(PETSC_SUCCESS);
297: }
299: #if defined(PETSC_CLANGUAGE_CXX)
300: /* C++ exceptions are formally not allowed to propagate through extern "C" code. In practice, far too much software
301: * would be broken if implementations did not handle it it some common cases. However, keep in mind
302: *
303: * Rule 62. Don't allow exceptions to propagate across module boundaries
304: *
305: * in "C++ Coding Standards" by Sutter and Alexandrescu. (This accounts for part of the ongoing C++ binary interface
306: * instability.) Having PETSc raise errors as C++ exceptions was probably misguided and should eventually be removed.
307: *
308: * Here is the problem: You have a C++ function call a PETSc function, and you would like to maintain the error message
309: * and stack information from the PETSc error. You could make everyone write exactly this code in their C++, but that
310: * seems crazy to me.
311: */
312: #include <sstream>
313: #include <stdexcept>
314: static void PetscCxxErrorThrow()
315: {
316: const char *str;
317: if (eh && eh->ctx) {
318: std::ostringstream *msg;
319: msg = (std::ostringstream *)eh->ctx;
320: str = msg->str().c_str();
321: } else str = "Error detected in C PETSc";
323: throw std::runtime_error(str);
324: }
325: #endif
327: /*@C
328: PetscError - Routine that is called when an error has been detected, usually called through the macro `SETERRQ`(`PETSC_COMM_SELF`,)` or by `PetscCall()`.
330: Collective
332: Input Parameters:
333: + comm - communicator over which error occurred. ALL MPI processes of this communicator MUST call this routine
334: . line - the line number of the error (usually indicated by `__LINE__` in the calling routine)
335: . func - the function name in which the error was detected
336: . file - the file in which the error was detected (usually indicated by `__FILE__` in the calling routine)
337: . n - the generic error number
338: . p - `PETSC_ERROR_INITIAL` indicates the error was initially detected, `PETSC_ERROR_REPEAT` indicates this is a traceback from a previously detected error
339: - mess - formatted message string - aka printf
341: Options Database Keys:
342: + -error_output_stdout - output the error messages to `stdout` instead of the default `stderr`
343: - -error_output_none - do not output the error messages
345: Level: intermediate
347: Notes:
348: PETSc error handling is done with error return codes. A non-zero return indicates an error
349: was detected. The return-value of this routine is what is ultimately returned by
350: `SETERRQ()`.
352: Numerical errors (potential divide by zero, for example) are not managed by the
353: error return codes; they are managed via, for example, `KSPGetConvergedReason()` that
354: indicates if the solve was successful or not. The option `-ksp_error_if_not_converged`, for
355: example, turns numerical failures into hard errors managed via `PetscError()`.
357: PETSc provides a rich supply of error handlers, see the list below, and users can also
358: provide their own error handlers.
360: If the user sets their own error handler (via `PetscPushErrorHandler()`) they may return any
361: arbitrary value from it, but are encouraged to return nonzero values. If the return value is
362: zero, `SETERRQ()` will ignore the value and return `PETSC_ERR_RETURN` (a nonzero value)
363: instead.
365: Most users need not directly use this routine and the error handlers, but can instead use
366: the simplified interface `PetscCall()` or `SETERRQ()`.
368: Fortran Note:
369: This routine is used differently from Fortran
370: .vb
371: PetscError(MPI_Comm comm, PetscErrorCode n, PetscErrorType p, char *message)
372: .ve
374: Developer Note:
375: Since this is called after an error condition it should not be calling any error handlers (currently it ignores any error codes)
376: BUT this routine does call regular PETSc functions that may call error handlers, this is problematic and could be fixed by never calling other PETSc routines
377: but this annoying.
379: .seealso: `PetscErrorCode`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`,
380: `PetscReturnErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscEmacsClientErrorHandler()`,
381: `SETERRQ()`, `PetscCall()`, `CHKMEMQ`, `PetscErrorMessage()`, `PETSCABORT()`, `PetscErrorType`, `PETSC_ERROR_INITIAL`, `PETSC_ERROR_REPEAT`
382: @*/
383: PetscErrorCode PetscError(MPI_Comm comm, int line, const char *func, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, ...)
384: {
385: va_list Argp;
386: size_t fullLength;
387: char buf[2048], *lbuf = NULL;
388: PetscBool ismain;
389: PetscErrorCode ierr;
391: if (!PetscErrorHandlingInitialized) return n;
392: if (comm == MPI_COMM_NULL) comm = PETSC_COMM_SELF;
394: /* Compose the message evaluating the print format */
395: if (mess) {
396: va_start(Argp, mess);
397: ierr = PetscVSNPrintf(buf, 2048, mess, &fullLength, Argp);
398: va_end(Argp);
399: lbuf = buf;
400: if (p == PETSC_ERROR_INITIAL) ierr = PetscStrncpy(PetscErrorBaseMessage, lbuf, sizeof(PetscErrorBaseMessage));
401: }
403: if (p == PETSC_ERROR_INITIAL && n != PETSC_ERR_MEMC) ierr = PetscMallocValidate(__LINE__, PETSC_FUNCTION_NAME, __FILE__);
405: if (!eh) ierr = PetscTraceBackErrorHandler(comm, line, func, file, n, p, lbuf, NULL);
406: else ierr = (*eh->handler)(comm, line, func, file, n, p, lbuf, eh->ctx);
407: PetscStackClearTop;
409: /*
410: If this is called from the main() routine we abort the program.
411: We cannot just return because them some MPI processes may continue to attempt to run
412: while this process simply exits.
413: */
414: if (func) {
415: PetscErrorCode cmp_ierr = PetscStrncmp(func, "main", 4, &ismain);
416: if (ismain) {
417: if (petscwaitonerrorflg) cmp_ierr = PetscSleep(1000);
418: (void)cmp_ierr;
419: PETSCABORT(comm, ierr);
420: }
421: }
422: #if defined(PETSC_CLANGUAGE_CXX)
423: if (p == PETSC_ERROR_IN_CXX) PetscCxxErrorThrow();
424: #endif
425: return ierr;
426: }
428: /*@C
429: PetscIntView - Prints an array of integers; useful for debugging.
431: Collective
433: Input Parameters:
434: + N - number of integers in array
435: . idx - array of integers
436: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
438: Level: intermediate
440: Note:
441: This may be called from within the debugger
443: Developer Note:
444: `idx` cannot be const because may be passed to binary viewer where temporary byte swapping may be done
446: .seealso: `PetscViewer`, `PetscRealView()`
447: @*/
448: PetscErrorCode PetscIntView(PetscInt N, const PetscInt idx[], PetscViewer viewer)
449: {
450: PetscMPIInt rank, size;
451: PetscInt j, i, n = N / 20, p = N % 20;
452: PetscBool iascii, isbinary;
453: MPI_Comm comm;
455: PetscFunctionBegin;
456: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
458: if (N) PetscAssertPointer(idx, 2);
459: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
460: PetscCallMPI(MPI_Comm_size(comm, &size));
461: PetscCallMPI(MPI_Comm_rank(comm, &rank));
463: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
464: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
465: if (iascii) {
466: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
467: for (i = 0; i < n; i++) {
468: if (size > 1) {
469: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * i));
470: } else {
471: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * i));
472: }
473: for (j = 0; j < 20; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[i * 20 + j]));
474: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
475: }
476: if (p) {
477: if (size > 1) {
478: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * n));
479: } else {
480: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * n));
481: }
482: for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[20 * n + i]));
483: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
484: }
485: PetscCall(PetscViewerFlush(viewer));
486: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
487: } else if (isbinary) {
488: PetscMPIInt *sizes, Ntotal, *displs, NN;
489: PetscInt *array;
491: PetscCall(PetscMPIIntCast(N, &NN));
493: if (size > 1) {
494: if (rank) {
495: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
496: PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, NULL, NULL, NULL, MPIU_INT, 0, comm));
497: } else {
498: PetscCall(PetscMalloc1(size, &sizes));
499: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
500: Ntotal = sizes[0];
501: PetscCall(PetscMalloc1(size, &displs));
502: displs[0] = 0;
503: for (i = 1; i < size; i++) {
504: Ntotal += sizes[i];
505: displs[i] = displs[i - 1] + sizes[i - 1];
506: }
507: PetscCall(PetscMalloc1(Ntotal, &array));
508: PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, array, sizes, displs, MPIU_INT, 0, comm));
509: PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_INT));
510: PetscCall(PetscFree(sizes));
511: PetscCall(PetscFree(displs));
512: PetscCall(PetscFree(array));
513: }
514: } else {
515: PetscCall(PetscViewerBinaryWrite(viewer, idx, N, PETSC_INT));
516: }
517: } else {
518: const char *tname;
519: PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
520: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
521: }
522: PetscFunctionReturn(PETSC_SUCCESS);
523: }
525: /*@C
526: PetscRealView - Prints an array of doubles; useful for debugging.
528: Collective
530: Input Parameters:
531: + N - number of `PetscReal` in array
532: . idx - array of `PetscReal`
533: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
535: Level: intermediate
537: Note:
538: This may be called from within the debugger
540: Developer Note:
541: `idx` cannot be const because may be passed to binary viewer where temporary byte swapping may be done
543: .seealso: `PetscViewer`, `PetscIntView()`
544: @*/
545: PetscErrorCode PetscRealView(PetscInt N, const PetscReal idx[], PetscViewer viewer)
546: {
547: PetscMPIInt rank, size;
548: PetscInt j, i, n = N / 5, p = N % 5;
549: PetscBool iascii, isbinary;
550: MPI_Comm comm;
552: PetscFunctionBegin;
553: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
555: PetscAssertPointer(idx, 2);
556: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
557: PetscCallMPI(MPI_Comm_size(comm, &size));
558: PetscCallMPI(MPI_Comm_rank(comm, &rank));
560: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
561: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
562: if (iascii) {
563: PetscInt tab;
565: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
566: PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
567: for (i = 0; i < n; i++) {
568: PetscCall(PetscViewerASCIISetTab(viewer, tab));
569: if (size > 1) {
570: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * i));
571: } else {
572: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * i));
573: }
574: PetscCall(PetscViewerASCIISetTab(viewer, 0));
575: for (j = 0; j < 5; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 5 + j]));
576: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
577: }
578: if (p) {
579: PetscCall(PetscViewerASCIISetTab(viewer, tab));
580: if (size > 1) {
581: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * n));
582: } else {
583: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * n));
584: }
585: PetscCall(PetscViewerASCIISetTab(viewer, 0));
586: for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[5 * n + i]));
587: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
588: }
589: PetscCall(PetscViewerFlush(viewer));
590: PetscCall(PetscViewerASCIISetTab(viewer, tab));
591: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
592: } else if (isbinary) {
593: PetscMPIInt *sizes, *displs, Ntotal, NN;
594: PetscReal *array;
596: PetscCall(PetscMPIIntCast(N, &NN));
598: if (size > 1) {
599: if (rank) {
600: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
601: PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, NULL, NULL, NULL, MPIU_REAL, 0, comm));
602: } else {
603: PetscCall(PetscMalloc1(size, &sizes));
604: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
605: Ntotal = sizes[0];
606: PetscCall(PetscMalloc1(size, &displs));
607: displs[0] = 0;
608: for (i = 1; i < size; i++) {
609: Ntotal += sizes[i];
610: displs[i] = displs[i - 1] + sizes[i - 1];
611: }
612: PetscCall(PetscMalloc1(Ntotal, &array));
613: PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, array, sizes, displs, MPIU_REAL, 0, comm));
614: PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_REAL));
615: PetscCall(PetscFree(sizes));
616: PetscCall(PetscFree(displs));
617: PetscCall(PetscFree(array));
618: }
619: } else {
620: PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_REAL));
621: }
622: } else {
623: const char *tname;
624: PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
625: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
626: }
627: PetscFunctionReturn(PETSC_SUCCESS);
628: }
630: /*@C
631: PetscScalarView - Prints an array of `PetscScalar`; useful for debugging.
633: Collective
635: Input Parameters:
636: + N - number of scalars in array
637: . idx - array of scalars
638: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
640: Level: intermediate
642: Note:
643: This may be called from within the debugger
645: Developer Note:
646: `idx` cannot be const because may be passed to binary viewer where byte swapping may be done
648: .seealso: `PetscViewer`, `PetscIntView()`, `PetscRealView()`
649: @*/
650: PetscErrorCode PetscScalarView(PetscInt N, const PetscScalar idx[], PetscViewer viewer)
651: {
652: PetscMPIInt rank, size;
653: PetscInt j, i, n = N / 3, p = N % 3;
654: PetscBool iascii, isbinary;
655: MPI_Comm comm;
657: PetscFunctionBegin;
658: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
660: if (N) PetscAssertPointer(idx, 2);
661: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
662: PetscCallMPI(MPI_Comm_size(comm, &size));
663: PetscCallMPI(MPI_Comm_rank(comm, &rank));
665: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
666: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
667: if (iascii) {
668: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
669: for (i = 0; i < n; i++) {
670: if (size > 1) {
671: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * i));
672: } else {
673: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * i));
674: }
675: for (j = 0; j < 3; j++) {
676: #if defined(PETSC_USE_COMPLEX)
677: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[i * 3 + j]), (double)PetscImaginaryPart(idx[i * 3 + j])));
678: #else
679: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 3 + j]));
680: #endif
681: }
682: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
683: }
684: if (p) {
685: if (size > 1) {
686: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * n));
687: } else {
688: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * n));
689: }
690: for (i = 0; i < p; i++) {
691: #if defined(PETSC_USE_COMPLEX)
692: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[n * 3 + i]), (double)PetscImaginaryPart(idx[n * 3 + i])));
693: #else
694: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[3 * n + i]));
695: #endif
696: }
697: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
698: }
699: PetscCall(PetscViewerFlush(viewer));
700: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
701: } else if (isbinary) {
702: PetscMPIInt *sizes, Ntotal, *displs, NN;
703: PetscScalar *array;
705: PetscCall(PetscMPIIntCast(N, &NN));
707: if (size > 1) {
708: if (rank) {
709: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
710: PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, NULL, NULL, NULL, MPIU_SCALAR, 0, comm));
711: } else {
712: PetscCall(PetscMalloc1(size, &sizes));
713: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
714: Ntotal = sizes[0];
715: PetscCall(PetscMalloc1(size, &displs));
716: displs[0] = 0;
717: for (i = 1; i < size; i++) {
718: Ntotal += sizes[i];
719: displs[i] = displs[i - 1] + sizes[i - 1];
720: }
721: PetscCall(PetscMalloc1(Ntotal, &array));
722: PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, array, sizes, displs, MPIU_SCALAR, 0, comm));
723: PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_SCALAR));
724: PetscCall(PetscFree(sizes));
725: PetscCall(PetscFree(displs));
726: PetscCall(PetscFree(array));
727: }
728: } else {
729: PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_SCALAR));
730: }
731: } else {
732: const char *tname;
733: PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
734: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
735: }
736: PetscFunctionReturn(PETSC_SUCCESS);
737: }
739: #if defined(PETSC_HAVE_CUDA)
740: #include <petscdevice_cuda.h>
741: PETSC_EXTERN const char *PetscCUBLASGetErrorName(cublasStatus_t status)
742: {
743: switch (status) {
744: #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
745: case CUBLAS_STATUS_SUCCESS:
746: return "CUBLAS_STATUS_SUCCESS";
747: case CUBLAS_STATUS_NOT_INITIALIZED:
748: return "CUBLAS_STATUS_NOT_INITIALIZED";
749: case CUBLAS_STATUS_ALLOC_FAILED:
750: return "CUBLAS_STATUS_ALLOC_FAILED";
751: case CUBLAS_STATUS_INVALID_VALUE:
752: return "CUBLAS_STATUS_INVALID_VALUE";
753: case CUBLAS_STATUS_ARCH_MISMATCH:
754: return "CUBLAS_STATUS_ARCH_MISMATCH";
755: case CUBLAS_STATUS_MAPPING_ERROR:
756: return "CUBLAS_STATUS_MAPPING_ERROR";
757: case CUBLAS_STATUS_EXECUTION_FAILED:
758: return "CUBLAS_STATUS_EXECUTION_FAILED";
759: case CUBLAS_STATUS_INTERNAL_ERROR:
760: return "CUBLAS_STATUS_INTERNAL_ERROR";
761: case CUBLAS_STATUS_NOT_SUPPORTED:
762: return "CUBLAS_STATUS_NOT_SUPPORTED";
763: case CUBLAS_STATUS_LICENSE_ERROR:
764: return "CUBLAS_STATUS_LICENSE_ERROR";
765: #endif
766: default:
767: return "unknown error";
768: }
769: }
770: PETSC_EXTERN const char *PetscCUSolverGetErrorName(cusolverStatus_t status)
771: {
772: switch (status) {
773: #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
774: case CUSOLVER_STATUS_SUCCESS:
775: return "CUSOLVER_STATUS_SUCCESS";
776: case CUSOLVER_STATUS_NOT_INITIALIZED:
777: return "CUSOLVER_STATUS_NOT_INITIALIZED";
778: case CUSOLVER_STATUS_INVALID_VALUE:
779: return "CUSOLVER_STATUS_INVALID_VALUE";
780: case CUSOLVER_STATUS_ARCH_MISMATCH:
781: return "CUSOLVER_STATUS_ARCH_MISMATCH";
782: case CUSOLVER_STATUS_INTERNAL_ERROR:
783: return "CUSOLVER_STATUS_INTERNAL_ERROR";
784: #if (CUDART_VERSION >= 9000) /* CUDA 9.0 had these defined on June 2021 */
785: case CUSOLVER_STATUS_ALLOC_FAILED:
786: return "CUSOLVER_STATUS_ALLOC_FAILED";
787: case CUSOLVER_STATUS_MAPPING_ERROR:
788: return "CUSOLVER_STATUS_MAPPING_ERROR";
789: case CUSOLVER_STATUS_EXECUTION_FAILED:
790: return "CUSOLVER_STATUS_EXECUTION_FAILED";
791: case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
792: return "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
793: case CUSOLVER_STATUS_NOT_SUPPORTED:
794: return "CUSOLVER_STATUS_NOT_SUPPORTED ";
795: case CUSOLVER_STATUS_ZERO_PIVOT:
796: return "CUSOLVER_STATUS_ZERO_PIVOT";
797: case CUSOLVER_STATUS_INVALID_LICENSE:
798: return "CUSOLVER_STATUS_INVALID_LICENSE";
799: #endif
800: #endif
801: default:
802: return "unknown error";
803: }
804: }
805: PETSC_EXTERN const char *PetscCUFFTGetErrorName(cufftResult result)
806: {
807: switch (result) {
808: case CUFFT_SUCCESS:
809: return "CUFFT_SUCCESS";
810: case CUFFT_INVALID_PLAN:
811: return "CUFFT_INVALID_PLAN";
812: case CUFFT_ALLOC_FAILED:
813: return "CUFFT_ALLOC_FAILED";
814: case CUFFT_INVALID_TYPE:
815: return "CUFFT_INVALID_TYPE";
816: case CUFFT_INVALID_VALUE:
817: return "CUFFT_INVALID_VALUE";
818: case CUFFT_INTERNAL_ERROR:
819: return "CUFFT_INTERNAL_ERROR";
820: case CUFFT_EXEC_FAILED:
821: return "CUFFT_EXEC_FAILED";
822: case CUFFT_SETUP_FAILED:
823: return "CUFFT_SETUP_FAILED";
824: case CUFFT_INVALID_SIZE:
825: return "CUFFT_INVALID_SIZE";
826: case CUFFT_UNALIGNED_DATA:
827: return "CUFFT_UNALIGNED_DATA";
828: case CUFFT_INCOMPLETE_PARAMETER_LIST:
829: return "CUFFT_INCOMPLETE_PARAMETER_LIST";
830: case CUFFT_INVALID_DEVICE:
831: return "CUFFT_INVALID_DEVICE";
832: case CUFFT_PARSE_ERROR:
833: return "CUFFT_PARSE_ERROR";
834: case CUFFT_NO_WORKSPACE:
835: return "CUFFT_NO_WORKSPACE";
836: case CUFFT_NOT_IMPLEMENTED:
837: return "CUFFT_NOT_IMPLEMENTED";
838: case CUFFT_LICENSE_ERROR:
839: return "CUFFT_LICENSE_ERROR";
840: case CUFFT_NOT_SUPPORTED:
841: return "CUFFT_NOT_SUPPORTED";
842: default:
843: return "unknown error";
844: }
845: }
846: #endif
848: #if defined(PETSC_HAVE_HIP)
849: #include <petscdevice_hip.h>
850: PETSC_EXTERN const char *PetscHIPBLASGetErrorName(hipblasStatus_t status)
851: {
852: switch (status) {
853: case HIPBLAS_STATUS_SUCCESS:
854: return "HIPBLAS_STATUS_SUCCESS";
855: case HIPBLAS_STATUS_NOT_INITIALIZED:
856: return "HIPBLAS_STATUS_NOT_INITIALIZED";
857: case HIPBLAS_STATUS_ALLOC_FAILED:
858: return "HIPBLAS_STATUS_ALLOC_FAILED";
859: case HIPBLAS_STATUS_INVALID_VALUE:
860: return "HIPBLAS_STATUS_INVALID_VALUE";
861: case HIPBLAS_STATUS_ARCH_MISMATCH:
862: return "HIPBLAS_STATUS_ARCH_MISMATCH";
863: case HIPBLAS_STATUS_MAPPING_ERROR:
864: return "HIPBLAS_STATUS_MAPPING_ERROR";
865: case HIPBLAS_STATUS_EXECUTION_FAILED:
866: return "HIPBLAS_STATUS_EXECUTION_FAILED";
867: case HIPBLAS_STATUS_INTERNAL_ERROR:
868: return "HIPBLAS_STATUS_INTERNAL_ERROR";
869: case HIPBLAS_STATUS_NOT_SUPPORTED:
870: return "HIPBLAS_STATUS_NOT_SUPPORTED";
871: default:
872: return "unknown error";
873: }
874: }
875: PETSC_EXTERN const char *PetscHIPSPARSEGetErrorName(hipsparseStatus_t status)
876: {
877: switch (status) {
878: case HIPSPARSE_STATUS_SUCCESS:
879: return "HIPSPARSE_STATUS_SUCCESS";
880: case HIPSPARSE_STATUS_NOT_INITIALIZED:
881: return "HIPSPARSE_STATUS_NOT_INITIALIZED";
882: case HIPSPARSE_STATUS_ALLOC_FAILED:
883: return "HIPSPARSE_STATUS_ALLOC_FAILED";
884: case HIPSPARSE_STATUS_INVALID_VALUE:
885: return "HIPSPARSE_STATUS_INVALID_VALUE";
886: case HIPSPARSE_STATUS_ARCH_MISMATCH:
887: return "HIPSPARSE_STATUS_ARCH_MISMATCH";
888: case HIPSPARSE_STATUS_MAPPING_ERROR:
889: return "HIPSPARSE_STATUS_MAPPING_ERROR";
890: case HIPSPARSE_STATUS_EXECUTION_FAILED:
891: return "HIPSPARSE_STATUS_EXECUTION_FAILED";
892: case HIPSPARSE_STATUS_INTERNAL_ERROR:
893: return "HIPSPARSE_STATUS_INTERNAL_ERROR";
894: case HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
895: return "HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
896: case HIPSPARSE_STATUS_ZERO_PIVOT:
897: return "HIPSPARSE_STATUS_ZERO_PIVOT";
898: case HIPSPARSE_STATUS_NOT_SUPPORTED:
899: return "HIPSPARSE_STATUS_NOT_SUPPORTED";
900: case HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES:
901: return "HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES";
902: default:
903: return "unknown error";
904: }
905: }
906: PETSC_EXTERN const char *PetscHIPSolverGetErrorName(hipsolverStatus_t status)
907: {
908: switch (status) {
909: case HIPSOLVER_STATUS_SUCCESS:
910: return "HIPSOLVER_STATUS_SUCCESS";
911: case HIPSOLVER_STATUS_NOT_INITIALIZED:
912: return "HIPSOLVER_STATUS_NOT_INITIALIZED";
913: case HIPSOLVER_STATUS_ALLOC_FAILED:
914: return "HIPSOLVER_STATUS_ALLOC_FAILED";
915: case HIPSOLVER_STATUS_MAPPING_ERROR:
916: return "HIPSOLVER_STATUS_MAPPING_ERROR";
917: case HIPSOLVER_STATUS_INVALID_VALUE:
918: return "HIPSOLVER_STATUS_INVALID_VALUE";
919: case HIPSOLVER_STATUS_EXECUTION_FAILED:
920: return "HIPSOLVER_STATUS_EXECUTION_FAILED";
921: case HIPSOLVER_STATUS_INTERNAL_ERROR:
922: return "HIPSOLVER_STATUS_INTERNAL_ERROR";
923: case HIPSOLVER_STATUS_NOT_SUPPORTED:
924: return "HIPSOLVER_STATUS_NOT_SUPPORTED ";
925: case HIPSOLVER_STATUS_ARCH_MISMATCH:
926: return "HIPSOLVER_STATUS_ARCH_MISMATCH";
927: case HIPSOLVER_STATUS_HANDLE_IS_NULLPTR:
928: return "HIPSOLVER_STATUS_HANDLE_IS_NULLPTR";
929: case HIPSOLVER_STATUS_INVALID_ENUM:
930: return "HIPSOLVER_STATUS_INVALID_ENUM";
931: case HIPSOLVER_STATUS_UNKNOWN:
932: default:
933: return "HIPSOLVER_STATUS_UNKNOWN";
934: }
935: }
936: #endif
938: /*@C
939: PetscMPIErrorString - Given an MPI error code returns the `MPI_Error_string()` appropriately
940: formatted for displaying with the PETSc error handlers.
942: Input Parameter:
943: . err - the MPI error code
945: Output Parameter:
946: . string - the MPI error message, should declare its length to be larger than `MPI_MAX_ERROR_STRING`
948: Level: developer
950: Note:
951: Does not return an error code or do error handling because it may be called from inside an error handler
953: .seealso: `PetscErrorCode` `PetscErrorMessage()`
954: @*/
955: void PetscMPIErrorString(PetscMPIInt err, char *string)
956: {
957: char errorstring[MPI_MAX_ERROR_STRING];
958: PetscMPIInt len, j = 0;
960: MPI_Error_string(err, (char *)errorstring, &len);
961: for (PetscMPIInt i = 0; i < len; i++) {
962: string[j++] = errorstring[i];
963: if (errorstring[i] == '\n') {
964: for (PetscMPIInt k = 0; k < 16; k++) string[j++] = ' ';
965: }
966: }
967: string[j] = 0;
968: }