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