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: }