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 poping 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 call MPI_Abort() instead of 395 return to allow the parallel program to be properly shutdown. 396 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 } 412 413 /* -------------------------------------------------------------------------*/ 414 415 /*@C 416 PetscIntView - Prints an array of integers; useful for debugging. 417 418 Collective 419 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 424 425 Level: intermediate 426 427 Note: 428 This may be called from within the debugger 429 430 Developer Note: 431 idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done 432 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; 441 442 PetscFunctionBegin; 443 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 444 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3); 445 if (N) PetscValidIntPointer(idx, 2); 446 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 447 PetscCallMPI(MPI_Comm_size(comm, &size)); 448 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 449 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; 477 478 PetscCall(PetscMPIIntCast(N, &NN)); 479 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 } 511 512 /*@C 513 PetscRealView - Prints an array of doubles; useful for debugging. 514 515 Collective 516 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 521 522 Level: intermediate 523 524 Note: 525 This may be called from within the debugger 526 527 Developer Note: 528 idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done 529 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; 538 539 PetscFunctionBegin; 540 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 541 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3); 542 PetscValidRealPointer(idx, 2); 543 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 544 PetscCallMPI(MPI_Comm_size(comm, &size)); 545 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 546 547 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 548 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 549 if (iascii) { 550 PetscInt tab; 551 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; 582 583 PetscCall(PetscMPIIntCast(N, &NN)); 584 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 } 616 617 /*@C 618 PetscScalarView - Prints an array of `PetscScalar`; useful for debugging. 619 620 Collective 621 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 626 627 Level: intermediate 628 629 Note: 630 This may be called from within the debugger 631 632 Developer Note: 633 idx cannot be const because may be passed to binary viewer where byte swapping may be done 634 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; 643 644 PetscFunctionBegin; 645 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 646 PetscValidHeader(viewer, 3); 647 if (N) PetscValidScalarPointer(idx, 2); 648 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 649 PetscCallMPI(MPI_Comm_size(comm, &size)); 650 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 651 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; 691 692 PetscCall(PetscMPIIntCast(N, &NN)); 693 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 } 725 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 834 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 924 925 /*@ 926 PetscMPIErrorString - Given an MPI error code returns the `MPI_Error_string()` appropriately 927 formatted for displaying with the PETSc error handlers. 928 929 Input Parameter: 930 . err - the MPI error code 931 932 Output Parameter: 933 . string - the MPI error message, should declare its length to be larger than `MPI_MAX_ERROR_STRING` 934 935 Level: developer 936 937 Note: 938 Does not return an error code or do error handling because it may be called from inside an error handler 939 940 @*/ 941 void PetscMPIErrorString(PetscMPIInt err, char *string) 942 { 943 char errorstring[MPI_MAX_ERROR_STRING]; 944 PetscMPIInt len, j = 0; 945 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 } 955