1 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> /*I "petscsys.h" I*/ 8 #include <petscviewer.h> 9 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 }; 16 17 static EH eh = NULL; 18 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. 22 23 Not Collective 24 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 33 34 Options Database Key: 35 . -on_error_emacs <machinename> - will contact machinename to open the Emacs client there 36 37 Level: developer 38 39 Note: 40 You must put (server-start) in your .emacs file for the emacsclient software to work 41 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. 45 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; 55 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 } 79 80 /*@C 81 PetscPushErrorHandler - Sets a routine to be called on detection of errors. 82 83 Not Collective 84 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.) 89 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 99 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 103 104 Level: intermediate 105 106 Note: 107 The currently available PETSc error handlers include `PetscTraceBackErrorHandler()`, 108 `PetscAttachDebuggerErrorHandler()`, `PetscAbortErrorHandler()`, and `PetscMPIAbortErrorHandler()`, `PetscReturnErrorHandler()`. 109 110 Fortran Note: 111 You can only push one error handler from Fortran before popping it. 112 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; 118 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 } 128 129 /*@ 130 PetscPopErrorHandler - Removes the latest error handler that was 131 pushed with `PetscPushErrorHandler()`. 132 133 Not Collective 134 135 Level: intermediate 136 137 .seealso: `PetscPushErrorHandler()` 138 @*/ 139 PetscErrorCode PetscPopErrorHandler(void) 140 { 141 EH tmp; 142 143 PetscFunctionBegin; 144 if (!eh) PetscFunctionReturn(PETSC_SUCCESS); 145 tmp = eh; 146 eh = eh->previous; 147 PetscCall(PetscFree(tmp)); 148 PetscFunctionReturn(PETSC_SUCCESS); 149 } 150 151 /*@C 152 PetscReturnErrorHandler - Error handler that causes a return without printing an error message. 153 154 Not Collective 155 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 164 165 Level: developer 166 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) 172 173 `PetscIgnoreErrorHandler()` does the same thing as this function, but is deprecated, you should use this function. 174 175 Use `PetscPushErrorHandler()` to set the desired error handler. 176 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 } 184 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"}; 236 237 /*@C 238 PetscErrorMessage - Returns the text string associated with a PETSc error code. 239 240 Not Collective 241 242 Input Parameter: 243 . errnum - the error code 244 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) 249 250 Level: developer 251 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; 262 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): 270 271 #define PETSC_FOO(x) ((PetscErrorCode)(PetscBar(x) || PetscBaz(x))) 272 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 } 284 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"; 308 309 throw std::runtime_error(str); 310 } 311 #endif 312 313 /*@C 314 PetscError - Routine that is called when an error has been detected, usually called through the macro SETERRQ(PETSC_COMM_SELF,). 315 316 Collective 317 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 326 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 330 331 Level: intermediate 332 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()`. 337 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()`. 342 343 PETSc provides a rich supply of error handlers, see the list below, and users can also 344 provide their own error handlers. 345 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. 350 351 Most users need not directly use this routine and the error handlers, but can instead use 352 the simplified interface `PetscCall()` or `SETERRQ()`. 353 354 Fortran Note: 355 This routine is used differently from Fortran 356 $ PetscError(MPI_Comm comm, PetscErrorCode n, PetscErrorType p, char *message) 357 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. 362 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; 374 375 if (!PetscErrorHandlingInitialized) return n; 376 if (comm == MPI_COMM_NULL) comm = PETSC_COMM_SELF; 377 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 } 386 387 if (p == PETSC_ERROR_INITIAL && n != PETSC_ERR_MEMC) ierr = PetscMallocValidate(__LINE__, PETSC_FUNCTION_NAME, __FILE__); 388 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; 392 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 } 411 412 /* -------------------------------------------------------------------------*/ 413 414 /*@C 415 PetscIntView - Prints an array of integers; useful for debugging. 416 417 Collective 418 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 423 424 Level: intermediate 425 426 Note: 427 This may be called from within the debugger 428 429 Developer Note: 430 idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done 431 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; 440 441 PetscFunctionBegin; 442 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 443 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3); 444 if (N) PetscValidIntPointer(idx, 2); 445 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 446 PetscCallMPI(MPI_Comm_size(comm, &size)); 447 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 448 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; 476 477 PetscCall(PetscMPIIntCast(N, &NN)); 478 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 } 510 511 /*@C 512 PetscRealView - Prints an array of doubles; useful for debugging. 513 514 Collective 515 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 520 521 Level: intermediate 522 523 Note: 524 This may be called from within the debugger 525 526 Developer Note: 527 idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done 528 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; 537 538 PetscFunctionBegin; 539 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 540 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3); 541 PetscValidRealPointer(idx, 2); 542 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 543 PetscCallMPI(MPI_Comm_size(comm, &size)); 544 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 545 546 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 547 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 548 if (iascii) { 549 PetscInt tab; 550 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; 581 582 PetscCall(PetscMPIIntCast(N, &NN)); 583 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 } 615 616 /*@C 617 PetscScalarView - Prints an array of `PetscScalar`; useful for debugging. 618 619 Collective 620 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 625 626 Level: intermediate 627 628 Note: 629 This may be called from within the debugger 630 631 Developer Note: 632 idx cannot be const because may be passed to binary viewer where byte swapping may be done 633 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; 642 643 PetscFunctionBegin; 644 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 645 PetscValidHeader(viewer, 3); 646 if (N) PetscValidScalarPointer(idx, 2); 647 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 648 PetscCallMPI(MPI_Comm_size(comm, &size)); 649 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 650 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; 690 691 PetscCall(PetscMPIIntCast(N, &NN)); 692 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 } 724 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 833 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 923 924 /*@ 925 PetscMPIErrorString - Given an MPI error code returns the `MPI_Error_string()` appropriately 926 formatted for displaying with the PETSc error handlers. 927 928 Input Parameter: 929 . err - the MPI error code 930 931 Output Parameter: 932 . string - the MPI error message, should declare its length to be larger than `MPI_MAX_ERROR_STRING` 933 934 Level: developer 935 936 Note: 937 Does not return an error code or do error handling because it may be called from inside an error handler 938 939 @*/ 940 void PetscMPIErrorString(PetscMPIInt err, char *string) 941 { 942 char errorstring[MPI_MAX_ERROR_STRING]; 943 PetscMPIInt len, j = 0; 944 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 } 954