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 popping 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 abort the program.
395: We cannot just return because them some MPI processes may continue to attempt to run
396: while this process simply exits.
397: */
398: if (func) {
399: PetscErrorCode cmp_ierr = PetscStrncmp(func, "main", 4, &ismain);
400: if (ismain) {
401: if (petscwaitonerrorflg) cmp_ierr = PetscSleep(1000);
402: (void)cmp_ierr;
403: PETSCABORT(comm, ierr);
404: }
405: }
406: #if defined(PETSC_CLANGUAGE_CXX)
407: if (p == PETSC_ERROR_IN_CXX) PetscCxxErrorThrow();
408: #endif
409: return ierr;
410: }
412: /* -------------------------------------------------------------------------*/
414: /*@C
415: PetscIntView - Prints an array of integers; useful for debugging.
417: Collective
419: Input Parameters:
420: + N - number of integers in array
421: . idx - array of integers
422: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
424: Level: intermediate
426: Note:
427: This may be called from within the debugger
429: Developer Note:
430: idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done
432: .seealso: `PetscViewer`, `PetscRealView()`
433: @*/
434: PetscErrorCode PetscIntView(PetscInt N, const PetscInt idx[], PetscViewer viewer)
435: {
436: PetscMPIInt rank, size;
437: PetscInt j, i, n = N / 20, p = N % 20;
438: PetscBool iascii, isbinary;
439: MPI_Comm comm;
441: PetscFunctionBegin;
442: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
445: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
446: PetscCallMPI(MPI_Comm_size(comm, &size));
447: PetscCallMPI(MPI_Comm_rank(comm, &rank));
449: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
450: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
451: if (iascii) {
452: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
453: for (i = 0; i < n; i++) {
454: if (size > 1) {
455: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * i));
456: } else {
457: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * i));
458: }
459: for (j = 0; j < 20; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[i * 20 + j]));
460: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
461: }
462: if (p) {
463: if (size > 1) {
464: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * n));
465: } else {
466: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * n));
467: }
468: for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[20 * n + i]));
469: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
470: }
471: PetscCall(PetscViewerFlush(viewer));
472: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
473: } else if (isbinary) {
474: PetscMPIInt *sizes, Ntotal, *displs, NN;
475: PetscInt *array;
477: PetscCall(PetscMPIIntCast(N, &NN));
479: if (size > 1) {
480: if (rank) {
481: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
482: PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, NULL, NULL, NULL, MPIU_INT, 0, comm));
483: } else {
484: PetscCall(PetscMalloc1(size, &sizes));
485: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
486: Ntotal = sizes[0];
487: PetscCall(PetscMalloc1(size, &displs));
488: displs[0] = 0;
489: for (i = 1; i < size; i++) {
490: Ntotal += sizes[i];
491: displs[i] = displs[i - 1] + sizes[i - 1];
492: }
493: PetscCall(PetscMalloc1(Ntotal, &array));
494: PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, array, sizes, displs, MPIU_INT, 0, comm));
495: PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_INT));
496: PetscCall(PetscFree(sizes));
497: PetscCall(PetscFree(displs));
498: PetscCall(PetscFree(array));
499: }
500: } else {
501: PetscCall(PetscViewerBinaryWrite(viewer, idx, N, PETSC_INT));
502: }
503: } else {
504: const char *tname;
505: PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
506: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
507: }
508: PetscFunctionReturn(PETSC_SUCCESS);
509: }
511: /*@C
512: PetscRealView - Prints an array of doubles; useful for debugging.
514: Collective
516: Input Parameters:
517: + N - number of `PetscReal` in array
518: . idx - array of `PetscReal`
519: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
521: Level: intermediate
523: Note:
524: This may be called from within the debugger
526: Developer Note:
527: idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done
529: .seealso: `PetscViewer`, `PetscIntView()`
530: @*/
531: PetscErrorCode PetscRealView(PetscInt N, const PetscReal idx[], PetscViewer viewer)
532: {
533: PetscMPIInt rank, size;
534: PetscInt j, i, n = N / 5, p = N % 5;
535: PetscBool iascii, isbinary;
536: MPI_Comm comm;
538: PetscFunctionBegin;
539: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
542: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
543: PetscCallMPI(MPI_Comm_size(comm, &size));
544: PetscCallMPI(MPI_Comm_rank(comm, &rank));
546: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
547: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
548: if (iascii) {
549: PetscInt tab;
551: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
552: PetscCall(PetscViewerASCIIGetTab(viewer, &tab));
553: for (i = 0; i < n; i++) {
554: PetscCall(PetscViewerASCIISetTab(viewer, tab));
555: if (size > 1) {
556: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * i));
557: } else {
558: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * i));
559: }
560: PetscCall(PetscViewerASCIISetTab(viewer, 0));
561: for (j = 0; j < 5; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 5 + j]));
562: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
563: }
564: if (p) {
565: PetscCall(PetscViewerASCIISetTab(viewer, tab));
566: if (size > 1) {
567: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * n));
568: } else {
569: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * n));
570: }
571: PetscCall(PetscViewerASCIISetTab(viewer, 0));
572: for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[5 * n + i]));
573: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
574: }
575: PetscCall(PetscViewerFlush(viewer));
576: PetscCall(PetscViewerASCIISetTab(viewer, tab));
577: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
578: } else if (isbinary) {
579: PetscMPIInt *sizes, *displs, Ntotal, NN;
580: PetscReal *array;
582: PetscCall(PetscMPIIntCast(N, &NN));
584: if (size > 1) {
585: if (rank) {
586: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
587: PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, NULL, NULL, NULL, MPIU_REAL, 0, comm));
588: } else {
589: PetscCall(PetscMalloc1(size, &sizes));
590: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
591: Ntotal = sizes[0];
592: PetscCall(PetscMalloc1(size, &displs));
593: displs[0] = 0;
594: for (i = 1; i < size; i++) {
595: Ntotal += sizes[i];
596: displs[i] = displs[i - 1] + sizes[i - 1];
597: }
598: PetscCall(PetscMalloc1(Ntotal, &array));
599: PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, array, sizes, displs, MPIU_REAL, 0, comm));
600: PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_REAL));
601: PetscCall(PetscFree(sizes));
602: PetscCall(PetscFree(displs));
603: PetscCall(PetscFree(array));
604: }
605: } else {
606: PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_REAL));
607: }
608: } else {
609: const char *tname;
610: PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
611: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
612: }
613: PetscFunctionReturn(PETSC_SUCCESS);
614: }
616: /*@C
617: PetscScalarView - Prints an array of `PetscScalar`; useful for debugging.
619: Collective
621: Input Parameters:
622: + N - number of scalars in array
623: . idx - array of scalars
624: - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0
626: Level: intermediate
628: Note:
629: This may be called from within the debugger
631: Developer Note:
632: idx cannot be const because may be passed to binary viewer where byte swapping may be done
634: .seealso: `PetscViewer`, `PetscIntView()`, `PetscRealView()`
635: @*/
636: PetscErrorCode PetscScalarView(PetscInt N, const PetscScalar idx[], PetscViewer viewer)
637: {
638: PetscMPIInt rank, size;
639: PetscInt j, i, n = N / 3, p = N % 3;
640: PetscBool iascii, isbinary;
641: MPI_Comm comm;
643: PetscFunctionBegin;
644: if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
647: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
648: PetscCallMPI(MPI_Comm_size(comm, &size));
649: PetscCallMPI(MPI_Comm_rank(comm, &rank));
651: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
652: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
653: if (iascii) {
654: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
655: for (i = 0; i < n; i++) {
656: if (size > 1) {
657: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * i));
658: } else {
659: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * i));
660: }
661: for (j = 0; j < 3; j++) {
662: #if defined(PETSC_USE_COMPLEX)
663: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[i * 3 + j]), (double)PetscImaginaryPart(idx[i * 3 + j])));
664: #else
665: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 3 + j]));
666: #endif
667: }
668: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
669: }
670: if (p) {
671: if (size > 1) {
672: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * n));
673: } else {
674: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * n));
675: }
676: for (i = 0; i < p; i++) {
677: #if defined(PETSC_USE_COMPLEX)
678: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[n * 3 + i]), (double)PetscImaginaryPart(idx[n * 3 + i])));
679: #else
680: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[3 * n + i]));
681: #endif
682: }
683: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
684: }
685: PetscCall(PetscViewerFlush(viewer));
686: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
687: } else if (isbinary) {
688: PetscMPIInt *sizes, Ntotal, *displs, NN;
689: PetscScalar *array;
691: PetscCall(PetscMPIIntCast(N, &NN));
693: if (size > 1) {
694: if (rank) {
695: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm));
696: PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, NULL, NULL, NULL, MPIU_SCALAR, 0, comm));
697: } else {
698: PetscCall(PetscMalloc1(size, &sizes));
699: PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm));
700: Ntotal = sizes[0];
701: PetscCall(PetscMalloc1(size, &displs));
702: displs[0] = 0;
703: for (i = 1; i < size; i++) {
704: Ntotal += sizes[i];
705: displs[i] = displs[i - 1] + sizes[i - 1];
706: }
707: PetscCall(PetscMalloc1(Ntotal, &array));
708: PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, array, sizes, displs, MPIU_SCALAR, 0, comm));
709: PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_SCALAR));
710: PetscCall(PetscFree(sizes));
711: PetscCall(PetscFree(displs));
712: PetscCall(PetscFree(array));
713: }
714: } else {
715: PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_SCALAR));
716: }
717: } else {
718: const char *tname;
719: PetscCall(PetscObjectGetName((PetscObject)viewer, &tname));
720: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname);
721: }
722: PetscFunctionReturn(PETSC_SUCCESS);
723: }
725: #if defined(PETSC_HAVE_CUDA)
726: #include <petscdevice_cuda.h>
727: PETSC_EXTERN const char *PetscCUBLASGetErrorName(cublasStatus_t status)
728: {
729: switch (status) {
730: #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
731: case CUBLAS_STATUS_SUCCESS:
732: return "CUBLAS_STATUS_SUCCESS";
733: case CUBLAS_STATUS_NOT_INITIALIZED:
734: return "CUBLAS_STATUS_NOT_INITIALIZED";
735: case CUBLAS_STATUS_ALLOC_FAILED:
736: return "CUBLAS_STATUS_ALLOC_FAILED";
737: case CUBLAS_STATUS_INVALID_VALUE:
738: return "CUBLAS_STATUS_INVALID_VALUE";
739: case CUBLAS_STATUS_ARCH_MISMATCH:
740: return "CUBLAS_STATUS_ARCH_MISMATCH";
741: case CUBLAS_STATUS_MAPPING_ERROR:
742: return "CUBLAS_STATUS_MAPPING_ERROR";
743: case CUBLAS_STATUS_EXECUTION_FAILED:
744: return "CUBLAS_STATUS_EXECUTION_FAILED";
745: case CUBLAS_STATUS_INTERNAL_ERROR:
746: return "CUBLAS_STATUS_INTERNAL_ERROR";
747: case CUBLAS_STATUS_NOT_SUPPORTED:
748: return "CUBLAS_STATUS_NOT_SUPPORTED";
749: case CUBLAS_STATUS_LICENSE_ERROR:
750: return "CUBLAS_STATUS_LICENSE_ERROR";
751: #endif
752: default:
753: return "unknown error";
754: }
755: }
756: PETSC_EXTERN const char *PetscCUSolverGetErrorName(cusolverStatus_t status)
757: {
758: switch (status) {
759: #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */
760: case CUSOLVER_STATUS_SUCCESS:
761: return "CUSOLVER_STATUS_SUCCESS";
762: case CUSOLVER_STATUS_NOT_INITIALIZED:
763: return "CUSOLVER_STATUS_NOT_INITIALIZED";
764: case CUSOLVER_STATUS_INVALID_VALUE:
765: return "CUSOLVER_STATUS_INVALID_VALUE";
766: case CUSOLVER_STATUS_ARCH_MISMATCH:
767: return "CUSOLVER_STATUS_ARCH_MISMATCH";
768: case CUSOLVER_STATUS_INTERNAL_ERROR:
769: return "CUSOLVER_STATUS_INTERNAL_ERROR";
770: #if (CUDART_VERSION >= 9000) /* CUDA 9.0 had these defined on June 2021 */
771: case CUSOLVER_STATUS_ALLOC_FAILED:
772: return "CUSOLVER_STATUS_ALLOC_FAILED";
773: case CUSOLVER_STATUS_MAPPING_ERROR:
774: return "CUSOLVER_STATUS_MAPPING_ERROR";
775: case CUSOLVER_STATUS_EXECUTION_FAILED:
776: return "CUSOLVER_STATUS_EXECUTION_FAILED";
777: case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
778: return "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
779: case CUSOLVER_STATUS_NOT_SUPPORTED:
780: return "CUSOLVER_STATUS_NOT_SUPPORTED ";
781: case CUSOLVER_STATUS_ZERO_PIVOT:
782: return "CUSOLVER_STATUS_ZERO_PIVOT";
783: case CUSOLVER_STATUS_INVALID_LICENSE:
784: return "CUSOLVER_STATUS_INVALID_LICENSE";
785: #endif
786: #endif
787: default:
788: return "unknown error";
789: }
790: }
791: PETSC_EXTERN const char *PetscCUFFTGetErrorName(cufftResult result)
792: {
793: switch (result) {
794: case CUFFT_SUCCESS:
795: return "CUFFT_SUCCESS";
796: case CUFFT_INVALID_PLAN:
797: return "CUFFT_INVALID_PLAN";
798: case CUFFT_ALLOC_FAILED:
799: return "CUFFT_ALLOC_FAILED";
800: case CUFFT_INVALID_TYPE:
801: return "CUFFT_INVALID_TYPE";
802: case CUFFT_INVALID_VALUE:
803: return "CUFFT_INVALID_VALUE";
804: case CUFFT_INTERNAL_ERROR:
805: return "CUFFT_INTERNAL_ERROR";
806: case CUFFT_EXEC_FAILED:
807: return "CUFFT_EXEC_FAILED";
808: case CUFFT_SETUP_FAILED:
809: return "CUFFT_SETUP_FAILED";
810: case CUFFT_INVALID_SIZE:
811: return "CUFFT_INVALID_SIZE";
812: case CUFFT_UNALIGNED_DATA:
813: return "CUFFT_UNALIGNED_DATA";
814: case CUFFT_INCOMPLETE_PARAMETER_LIST:
815: return "CUFFT_INCOMPLETE_PARAMETER_LIST";
816: case CUFFT_INVALID_DEVICE:
817: return "CUFFT_INVALID_DEVICE";
818: case CUFFT_PARSE_ERROR:
819: return "CUFFT_PARSE_ERROR";
820: case CUFFT_NO_WORKSPACE:
821: return "CUFFT_NO_WORKSPACE";
822: case CUFFT_NOT_IMPLEMENTED:
823: return "CUFFT_NOT_IMPLEMENTED";
824: case CUFFT_LICENSE_ERROR:
825: return "CUFFT_LICENSE_ERROR";
826: case CUFFT_NOT_SUPPORTED:
827: return "CUFFT_NOT_SUPPORTED";
828: default:
829: return "unknown error";
830: }
831: }
832: #endif
834: #if defined(PETSC_HAVE_HIP)
835: #include <petscdevice_hip.h>
836: PETSC_EXTERN const char *PetscHIPBLASGetErrorName(hipblasStatus_t status)
837: {
838: switch (status) {
839: case HIPBLAS_STATUS_SUCCESS:
840: return "HIPBLAS_STATUS_SUCCESS";
841: case HIPBLAS_STATUS_NOT_INITIALIZED:
842: return "HIPBLAS_STATUS_NOT_INITIALIZED";
843: case HIPBLAS_STATUS_ALLOC_FAILED:
844: return "HIPBLAS_STATUS_ALLOC_FAILED";
845: case HIPBLAS_STATUS_INVALID_VALUE:
846: return "HIPBLAS_STATUS_INVALID_VALUE";
847: case HIPBLAS_STATUS_ARCH_MISMATCH:
848: return "HIPBLAS_STATUS_ARCH_MISMATCH";
849: case HIPBLAS_STATUS_MAPPING_ERROR:
850: return "HIPBLAS_STATUS_MAPPING_ERROR";
851: case HIPBLAS_STATUS_EXECUTION_FAILED:
852: return "HIPBLAS_STATUS_EXECUTION_FAILED";
853: case HIPBLAS_STATUS_INTERNAL_ERROR:
854: return "HIPBLAS_STATUS_INTERNAL_ERROR";
855: case HIPBLAS_STATUS_NOT_SUPPORTED:
856: return "HIPBLAS_STATUS_NOT_SUPPORTED";
857: default:
858: return "unknown error";
859: }
860: }
861: PETSC_EXTERN const char *PetscHIPSPARSEGetErrorName(hipsparseStatus_t status)
862: {
863: switch (status) {
864: case HIPSPARSE_STATUS_SUCCESS:
865: return "HIPSPARSE_STATUS_SUCCESS";
866: case HIPSPARSE_STATUS_NOT_INITIALIZED:
867: return "HIPSPARSE_STATUS_NOT_INITIALIZED";
868: case HIPSPARSE_STATUS_ALLOC_FAILED:
869: return "HIPSPARSE_STATUS_ALLOC_FAILED";
870: case HIPSPARSE_STATUS_INVALID_VALUE:
871: return "HIPSPARSE_STATUS_INVALID_VALUE";
872: case HIPSPARSE_STATUS_ARCH_MISMATCH:
873: return "HIPSPARSE_STATUS_ARCH_MISMATCH";
874: case HIPSPARSE_STATUS_MAPPING_ERROR:
875: return "HIPSPARSE_STATUS_MAPPING_ERROR";
876: case HIPSPARSE_STATUS_EXECUTION_FAILED:
877: return "HIPSPARSE_STATUS_EXECUTION_FAILED";
878: case HIPSPARSE_STATUS_INTERNAL_ERROR:
879: return "HIPSPARSE_STATUS_INTERNAL_ERROR";
880: case HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED:
881: return "HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED";
882: case HIPSPARSE_STATUS_ZERO_PIVOT:
883: return "HIPSPARSE_STATUS_ZERO_PIVOT";
884: case HIPSPARSE_STATUS_NOT_SUPPORTED:
885: return "HIPSPARSE_STATUS_NOT_SUPPORTED";
886: case HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES:
887: return "HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES";
888: default:
889: return "unknown error";
890: }
891: }
892: PETSC_EXTERN const char *PetscHIPSolverGetErrorName(hipsolverStatus_t status)
893: {
894: switch (status) {
895: case HIPSOLVER_STATUS_SUCCESS:
896: return "HIPSOLVER_STATUS_SUCCESS";
897: case HIPSOLVER_STATUS_NOT_INITIALIZED:
898: return "HIPSOLVER_STATUS_NOT_INITIALIZED";
899: case HIPSOLVER_STATUS_ALLOC_FAILED:
900: return "HIPSOLVER_STATUS_ALLOC_FAILED";
901: case HIPSOLVER_STATUS_MAPPING_ERROR:
902: return "HIPSOLVER_STATUS_MAPPING_ERROR";
903: case HIPSOLVER_STATUS_INVALID_VALUE:
904: return "HIPSOLVER_STATUS_INVALID_VALUE";
905: case HIPSOLVER_STATUS_EXECUTION_FAILED:
906: return "HIPSOLVER_STATUS_EXECUTION_FAILED";
907: case HIPSOLVER_STATUS_INTERNAL_ERROR:
908: return "HIPSOLVER_STATUS_INTERNAL_ERROR";
909: case HIPSOLVER_STATUS_NOT_SUPPORTED:
910: return "HIPSOLVER_STATUS_NOT_SUPPORTED ";
911: case HIPSOLVER_STATUS_ARCH_MISMATCH:
912: return "HIPSOLVER_STATUS_ARCH_MISMATCH";
913: case HIPSOLVER_STATUS_HANDLE_IS_NULLPTR:
914: return "HIPSOLVER_STATUS_HANDLE_IS_NULLPTR";
915: case HIPSOLVER_STATUS_INVALID_ENUM:
916: return "HIPSOLVER_STATUS_INVALID_ENUM";
917: case HIPSOLVER_STATUS_UNKNOWN:
918: default:
919: return "HIPSOLVER_STATUS_UNKNOWN";
920: }
921: }
922: #endif
924: /*@
925: PetscMPIErrorString - Given an MPI error code returns the `MPI_Error_string()` appropriately
926: formatted for displaying with the PETSc error handlers.
928: Input Parameter:
929: . err - the MPI error code
931: Output Parameter:
932: . string - the MPI error message, should declare its length to be larger than `MPI_MAX_ERROR_STRING`
934: Level: developer
936: Note:
937: Does not return an error code or do error handling because it may be called from inside an error handler
939: @*/
940: void PetscMPIErrorString(PetscMPIInt err, char *string)
941: {
942: char errorstring[MPI_MAX_ERROR_STRING];
943: PetscMPIInt len, j = 0;
945: MPI_Error_string(err, (char *)errorstring, &len);
946: for (PetscMPIInt i = 0; i < len; i++) {
947: string[j++] = errorstring[i];
948: if (errorstring[i] == '\n') {
949: for (PetscMPIInt k = 0; k < 16; k++) string[j++] = ' ';
950: }
951: }
952: string[j] = 0;
953: }