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 0; 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(0); 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(0); 146 tmp = eh; 147 eh = eh->previous; 148 PetscCall(PetscFree(tmp)); 149 PetscFunctionReturn(0); 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 `PetscError()`. (NULL if not desired) 249 250 Level: developer 251 252 .seealso: `PetscPushErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscError()`, `SETERRQ()`, `PetscCall()` 253 `PetscAbortErrorHandler()`, `PetscTraceBackErrorHandler()` 254 @*/ 255 PetscErrorCode PetscErrorMessage(int errnum, const char *text[], char **specific) 256 { 257 size_t len; 258 259 PetscFunctionBegin; 260 if (text && errnum > PETSC_ERR_MIN_VALUE && errnum < PETSC_ERR_MAX_VALUE) { 261 *text = PetscErrorStrings[errnum - PETSC_ERR_MIN_VALUE - 1]; 262 PetscCall(PetscStrlen(*text, &len)); 263 if (!len) *text = NULL; 264 } else if (text) *text = NULL; 265 266 if (specific) *specific = PetscErrorBaseMessage; 267 PetscFunctionReturn(0); 268 } 269 270 #if defined(PETSC_CLANGUAGE_CXX) 271 /* C++ exceptions are formally not allowed to propagate through extern "C" code. In practice, far too much software 272 * would be broken if implementations did not handle it it some common cases. However, keep in mind 273 * 274 * Rule 62. Don't allow exceptions to propagate across module boundaries 275 * 276 * in "C++ Coding Standards" by Sutter and Alexandrescu. (This accounts for part of the ongoing C++ binary interface 277 * instability.) Having PETSc raise errors as C++ exceptions was probably misguided and should eventually be removed. 278 * 279 * Here is the problem: You have a C++ function call a PETSc function, and you would like to maintain the error message 280 * and stack information from the PETSc error. You could make everyone write exactly this code in their C++, but that 281 * seems crazy to me. 282 */ 283 #include <sstream> 284 #include <stdexcept> 285 static void PetscCxxErrorThrow() 286 { 287 const char *str; 288 if (eh && eh->ctx) { 289 std::ostringstream *msg; 290 msg = (std::ostringstream *)eh->ctx; 291 str = msg->str().c_str(); 292 } else str = "Error detected in C PETSc"; 293 294 throw std::runtime_error(str); 295 } 296 #endif 297 298 /*@C 299 PetscError - Routine that is called when an error has been detected, usually called through the macro SETERRQ(PETSC_COMM_SELF,). 300 301 Collective 302 303 Input Parameters: 304 + comm - communicator over which error occurred. ALL ranks of this communicator MUST call this routine 305 . line - the line number of the error (indicated by __LINE__) 306 . func - the function name in which the error was detected 307 . file - the file in which the error was detected (indicated by __FILE__) 308 . n - the generic error number 309 . p - `PETSC_ERROR_INITIAL` indicates the error was initially detected, `PETSC_ERROR_REPEAT` indicates this is a traceback from a previously detected error 310 - mess - formatted message string - aka printf 311 312 Options Database Keys: 313 + -error_output_stdout - output the error messages to stdout instead of the default stderr 314 - -error_output_none - do not output the error messages 315 316 Level: intermediate 317 318 Notes: 319 PETSc error handling is done with error return codes. A non-zero return indicates an error 320 was detected. The return-value of this routine is what is ultimately returned by 321 `SETERRQ()`. 322 323 Note that numerical errors (potential divide by zero, for example) are not managed by the 324 error return codes; they are managed via, for example, `KSPGetConvergedReason()` that 325 indicates if the solve was successful or not. The option `-ksp_error_if_not_converged`, for 326 example, turns numerical failures into hard errors managed via `PetscError()`. 327 328 PETSc provides a rich supply of error handlers, see the list below, and users can also 329 provide their own error handlers. 330 331 If the user sets their own error handler (via `PetscPushErrorHandler()`) they may return any 332 arbitrary value from it, but are encouraged to return nonzero values. If the return value is 333 zero, `SETERRQ()` will ignore the value and return `PETSC_ERR_RETURN` (a nonzero value) 334 instead. 335 336 Most users need not directly use this routine and the error handlers, but can instead use 337 the simplified interface `PetscCall()` or `SETERRQ()`. 338 339 Fortran Note: 340 This routine is used differently from Fortran 341 $ PetscError(MPI_Comm comm,PetscErrorCode n,PetscErrorType p,char *message) 342 343 Developer Note: 344 Since this is called after an error condition it should not be calling any error handlers (currently it ignores any error codes) 345 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 346 but this annoying. 347 348 .seealso: `PetscErrorCode`, `PetscPushErrorHandler()`, `PetscPopErrorHandler()`, `PetscTraceBackErrorHandler()`, `PetscAbortErrorHandler()`, `PetscMPIAbortErrorHandler()`, 349 `PetscReturnErrorHandler()`, `PetscAttachDebuggerErrorHandler()`, `PetscEmacsClientErrorHandler()`, 350 `SETERRQ()`, `PetscCall()`, `CHKMEMQ`, `SETERRQ()`, `SETERRQ()`, `PetscErrorMessage()`, `PETSCABORT()` 351 @*/ 352 PetscErrorCode PetscError(MPI_Comm comm, int line, const char *func, const char *file, PetscErrorCode n, PetscErrorType p, const char *mess, ...) 353 { 354 va_list Argp; 355 size_t fullLength; 356 char buf[2048], *lbuf = NULL; 357 PetscBool ismain; 358 PetscErrorCode ierr; 359 360 if (!PetscErrorHandlingInitialized) return n; 361 if (comm == MPI_COMM_NULL) comm = PETSC_COMM_SELF; 362 363 /* Compose the message evaluating the print format */ 364 if (mess) { 365 va_start(Argp, mess); 366 PetscVSNPrintf(buf, 2048, mess, &fullLength, Argp); 367 va_end(Argp); 368 lbuf = buf; 369 if (p == PETSC_ERROR_INITIAL) PetscStrncpy(PetscErrorBaseMessage, lbuf, 1023); 370 } 371 372 if (p == PETSC_ERROR_INITIAL && n != PETSC_ERR_MEMC) PetscMallocValidate(__LINE__, PETSC_FUNCTION_NAME, __FILE__); 373 374 if (!eh) ierr = PetscTraceBackErrorHandler(comm, line, func, file, n, p, lbuf, NULL); 375 else ierr = (*eh->handler)(comm, line, func, file, n, p, lbuf, eh->ctx); 376 PetscStackClearTop; 377 378 /* 379 If this is called from the main() routine we call MPI_Abort() instead of 380 return to allow the parallel program to be properly shutdown. 381 382 Does not call PETSCABORT() since that would provide the wrong source file and line number information 383 */ 384 if (func) { 385 PetscStrncmp(func, "main", 4, &ismain); 386 if (ismain) { 387 if (petscwaitonerrorflg) PetscSleep(1000); 388 PETSCABORT(comm, ierr); 389 } 390 } 391 #if defined(PETSC_CLANGUAGE_CXX) 392 if (p == PETSC_ERROR_IN_CXX) PetscCxxErrorThrow(); 393 #endif 394 return ierr; 395 } 396 397 /* -------------------------------------------------------------------------*/ 398 399 /*@C 400 PetscIntView - Prints an array of integers; useful for debugging. 401 402 Collective 403 404 Input Parameters: 405 + N - number of integers in array 406 . idx - array of integers 407 - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0 408 409 Level: intermediate 410 411 Note: 412 This may be called from within the debugger 413 414 Developer Note: 415 idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done 416 417 .seealso: `PetscViewer`, `PetscRealView()` 418 @*/ 419 PetscErrorCode PetscIntView(PetscInt N, const PetscInt idx[], PetscViewer viewer) 420 { 421 PetscMPIInt rank, size; 422 PetscInt j, i, n = N / 20, p = N % 20; 423 PetscBool iascii, isbinary; 424 MPI_Comm comm; 425 426 PetscFunctionBegin; 427 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 428 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3); 429 if (N) PetscValidIntPointer(idx, 2); 430 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 431 PetscCallMPI(MPI_Comm_size(comm, &size)); 432 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 433 434 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 435 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 436 if (iascii) { 437 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 438 for (i = 0; i < n; i++) { 439 if (size > 1) { 440 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * i)); 441 } else { 442 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * i)); 443 } 444 for (j = 0; j < 20; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[i * 20 + j])); 445 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 446 } 447 if (p) { 448 if (size > 1) { 449 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %" PetscInt_FMT ":", rank, 20 * n)); 450 } else { 451 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%" PetscInt_FMT ":", 20 * n)); 452 } 453 for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, idx[20 * n + i])); 454 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 455 } 456 PetscCall(PetscViewerFlush(viewer)); 457 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 458 } else if (isbinary) { 459 PetscMPIInt *sizes, Ntotal, *displs, NN; 460 PetscInt *array; 461 462 PetscCall(PetscMPIIntCast(N, &NN)); 463 464 if (size > 1) { 465 if (rank) { 466 PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm)); 467 PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, NULL, NULL, NULL, MPIU_INT, 0, comm)); 468 } else { 469 PetscCall(PetscMalloc1(size, &sizes)); 470 PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm)); 471 Ntotal = sizes[0]; 472 PetscCall(PetscMalloc1(size, &displs)); 473 displs[0] = 0; 474 for (i = 1; i < size; i++) { 475 Ntotal += sizes[i]; 476 displs[i] = displs[i - 1] + sizes[i - 1]; 477 } 478 PetscCall(PetscMalloc1(Ntotal, &array)); 479 PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_INT, array, sizes, displs, MPIU_INT, 0, comm)); 480 PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_INT)); 481 PetscCall(PetscFree(sizes)); 482 PetscCall(PetscFree(displs)); 483 PetscCall(PetscFree(array)); 484 } 485 } else { 486 PetscCall(PetscViewerBinaryWrite(viewer, idx, N, PETSC_INT)); 487 } 488 } else { 489 const char *tname; 490 PetscCall(PetscObjectGetName((PetscObject)viewer, &tname)); 491 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname); 492 } 493 PetscFunctionReturn(0); 494 } 495 496 /*@C 497 PetscRealView - Prints an array of doubles; useful for debugging. 498 499 Collective 500 501 Input Parameters: 502 + N - number of `PetscReal` in array 503 . idx - array of `PetscReal` 504 - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0 505 506 Level: intermediate 507 508 Note: 509 This may be called from within the debugger 510 511 Developer Note: 512 idx cannot be const because may be passed to binary viewer where temporary byte swapping may be done 513 514 .seealso: `PetscViewer`, `PetscIntView()` 515 @*/ 516 PetscErrorCode PetscRealView(PetscInt N, const PetscReal idx[], PetscViewer viewer) 517 { 518 PetscMPIInt rank, size; 519 PetscInt j, i, n = N / 5, p = N % 5; 520 PetscBool iascii, isbinary; 521 MPI_Comm comm; 522 523 PetscFunctionBegin; 524 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 525 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 3); 526 PetscValidRealPointer(idx, 2); 527 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 528 PetscCallMPI(MPI_Comm_size(comm, &size)); 529 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 530 531 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 532 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 533 if (iascii) { 534 PetscInt tab; 535 536 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 537 PetscCall(PetscViewerASCIIGetTab(viewer, &tab)); 538 for (i = 0; i < n; i++) { 539 PetscCall(PetscViewerASCIISetTab(viewer, tab)); 540 if (size > 1) { 541 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * i)); 542 } else { 543 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * i)); 544 } 545 PetscCall(PetscViewerASCIISetTab(viewer, 0)); 546 for (j = 0; j < 5; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 5 + j])); 547 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 548 } 549 if (p) { 550 PetscCall(PetscViewerASCIISetTab(viewer, tab)); 551 if (size > 1) { 552 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 5 * n)); 553 } else { 554 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 5 * n)); 555 } 556 PetscCall(PetscViewerASCIISetTab(viewer, 0)); 557 for (i = 0; i < p; i++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[5 * n + i])); 558 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 559 } 560 PetscCall(PetscViewerFlush(viewer)); 561 PetscCall(PetscViewerASCIISetTab(viewer, tab)); 562 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 563 } else if (isbinary) { 564 PetscMPIInt *sizes, *displs, Ntotal, NN; 565 PetscReal *array; 566 567 PetscCall(PetscMPIIntCast(N, &NN)); 568 569 if (size > 1) { 570 if (rank) { 571 PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm)); 572 PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, NULL, NULL, NULL, MPIU_REAL, 0, comm)); 573 } else { 574 PetscCall(PetscMalloc1(size, &sizes)); 575 PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm)); 576 Ntotal = sizes[0]; 577 PetscCall(PetscMalloc1(size, &displs)); 578 displs[0] = 0; 579 for (i = 1; i < size; i++) { 580 Ntotal += sizes[i]; 581 displs[i] = displs[i - 1] + sizes[i - 1]; 582 } 583 PetscCall(PetscMalloc1(Ntotal, &array)); 584 PetscCallMPI(MPI_Gatherv((PetscReal *)idx, NN, MPIU_REAL, array, sizes, displs, MPIU_REAL, 0, comm)); 585 PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_REAL)); 586 PetscCall(PetscFree(sizes)); 587 PetscCall(PetscFree(displs)); 588 PetscCall(PetscFree(array)); 589 } 590 } else { 591 PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_REAL)); 592 } 593 } else { 594 const char *tname; 595 PetscCall(PetscObjectGetName((PetscObject)viewer, &tname)); 596 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname); 597 } 598 PetscFunctionReturn(0); 599 } 600 601 /*@C 602 PetscScalarView - Prints an array of `PetscScalar`; useful for debugging. 603 604 Collective 605 606 Input Parameters: 607 + N - number of scalars in array 608 . idx - array of scalars 609 - viewer - location to print array, `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF` or 0 610 611 Level: intermediate 612 613 Note: 614 This may be called from within the debugger 615 616 Developer Note: 617 idx cannot be const because may be passed to binary viewer where byte swapping may be done 618 619 .seealso: `PetscViewer`, `PetscIntView()`, `PetscRealView()` 620 @*/ 621 PetscErrorCode PetscScalarView(PetscInt N, const PetscScalar idx[], PetscViewer viewer) 622 { 623 PetscMPIInt rank, size; 624 PetscInt j, i, n = N / 3, p = N % 3; 625 PetscBool iascii, isbinary; 626 MPI_Comm comm; 627 628 PetscFunctionBegin; 629 if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF; 630 PetscValidHeader(viewer, 3); 631 if (N) PetscValidScalarPointer(idx, 2); 632 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 633 PetscCallMPI(MPI_Comm_size(comm, &size)); 634 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 635 636 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 637 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary)); 638 if (iascii) { 639 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 640 for (i = 0; i < n; i++) { 641 if (size > 1) { 642 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * i)); 643 } else { 644 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * i)); 645 } 646 for (j = 0; j < 3; j++) { 647 #if defined(PETSC_USE_COMPLEX) 648 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[i * 3 + j]), (double)PetscImaginaryPart(idx[i * 3 + j]))); 649 #else 650 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[i * 3 + j])); 651 #endif 652 } 653 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 654 } 655 if (p) { 656 if (size > 1) { 657 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %2" PetscInt_FMT ":", rank, 3 * n)); 658 } else { 659 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%2" PetscInt_FMT ":", 3 * n)); 660 } 661 for (i = 0; i < p; i++) { 662 #if defined(PETSC_USE_COMPLEX) 663 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " (%12.4e,%12.4e)", (double)PetscRealPart(idx[n * 3 + i]), (double)PetscImaginaryPart(idx[n * 3 + i]))); 664 #else 665 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %12.4e", (double)idx[3 * n + i])); 666 #endif 667 } 668 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n")); 669 } 670 PetscCall(PetscViewerFlush(viewer)); 671 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 672 } else if (isbinary) { 673 PetscMPIInt *sizes, Ntotal, *displs, NN; 674 PetscScalar *array; 675 676 PetscCall(PetscMPIIntCast(N, &NN)); 677 678 if (size > 1) { 679 if (rank) { 680 PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm)); 681 PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, NULL, NULL, NULL, MPIU_SCALAR, 0, comm)); 682 } else { 683 PetscCall(PetscMalloc1(size, &sizes)); 684 PetscCallMPI(MPI_Gather(&NN, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm)); 685 Ntotal = sizes[0]; 686 PetscCall(PetscMalloc1(size, &displs)); 687 displs[0] = 0; 688 for (i = 1; i < size; i++) { 689 Ntotal += sizes[i]; 690 displs[i] = displs[i - 1] + sizes[i - 1]; 691 } 692 PetscCall(PetscMalloc1(Ntotal, &array)); 693 PetscCallMPI(MPI_Gatherv((void *)idx, NN, MPIU_SCALAR, array, sizes, displs, MPIU_SCALAR, 0, comm)); 694 PetscCall(PetscViewerBinaryWrite(viewer, array, Ntotal, PETSC_SCALAR)); 695 PetscCall(PetscFree(sizes)); 696 PetscCall(PetscFree(displs)); 697 PetscCall(PetscFree(array)); 698 } 699 } else { 700 PetscCall(PetscViewerBinaryWrite(viewer, (void *)idx, N, PETSC_SCALAR)); 701 } 702 } else { 703 const char *tname; 704 PetscCall(PetscObjectGetName((PetscObject)viewer, &tname)); 705 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle that PetscViewer of type %s", tname); 706 } 707 PetscFunctionReturn(0); 708 } 709 710 #if defined(PETSC_HAVE_CUDA) 711 #include <petscdevice_cuda.h> 712 PETSC_EXTERN const char *PetscCUBLASGetErrorName(cublasStatus_t status) 713 { 714 switch (status) { 715 #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */ 716 case CUBLAS_STATUS_SUCCESS: 717 return "CUBLAS_STATUS_SUCCESS"; 718 case CUBLAS_STATUS_NOT_INITIALIZED: 719 return "CUBLAS_STATUS_NOT_INITIALIZED"; 720 case CUBLAS_STATUS_ALLOC_FAILED: 721 return "CUBLAS_STATUS_ALLOC_FAILED"; 722 case CUBLAS_STATUS_INVALID_VALUE: 723 return "CUBLAS_STATUS_INVALID_VALUE"; 724 case CUBLAS_STATUS_ARCH_MISMATCH: 725 return "CUBLAS_STATUS_ARCH_MISMATCH"; 726 case CUBLAS_STATUS_MAPPING_ERROR: 727 return "CUBLAS_STATUS_MAPPING_ERROR"; 728 case CUBLAS_STATUS_EXECUTION_FAILED: 729 return "CUBLAS_STATUS_EXECUTION_FAILED"; 730 case CUBLAS_STATUS_INTERNAL_ERROR: 731 return "CUBLAS_STATUS_INTERNAL_ERROR"; 732 case CUBLAS_STATUS_NOT_SUPPORTED: 733 return "CUBLAS_STATUS_NOT_SUPPORTED"; 734 case CUBLAS_STATUS_LICENSE_ERROR: 735 return "CUBLAS_STATUS_LICENSE_ERROR"; 736 #endif 737 default: 738 return "unknown error"; 739 } 740 } 741 PETSC_EXTERN const char *PetscCUSolverGetErrorName(cusolverStatus_t status) 742 { 743 switch (status) { 744 #if (CUDART_VERSION >= 8000) /* At least CUDA 8.0 of Sep. 2016 had these */ 745 case CUSOLVER_STATUS_SUCCESS: 746 return "CUSOLVER_STATUS_SUCCESS"; 747 case CUSOLVER_STATUS_NOT_INITIALIZED: 748 return "CUSOLVER_STATUS_NOT_INITIALIZED"; 749 case CUSOLVER_STATUS_INVALID_VALUE: 750 return "CUSOLVER_STATUS_INVALID_VALUE"; 751 case CUSOLVER_STATUS_ARCH_MISMATCH: 752 return "CUSOLVER_STATUS_ARCH_MISMATCH"; 753 case CUSOLVER_STATUS_INTERNAL_ERROR: 754 return "CUSOLVER_STATUS_INTERNAL_ERROR"; 755 #if (CUDART_VERSION >= 9000) /* CUDA 9.0 had these defined on June 2021 */ 756 case CUSOLVER_STATUS_ALLOC_FAILED: 757 return "CUSOLVER_STATUS_ALLOC_FAILED"; 758 case CUSOLVER_STATUS_MAPPING_ERROR: 759 return "CUSOLVER_STATUS_MAPPING_ERROR"; 760 case CUSOLVER_STATUS_EXECUTION_FAILED: 761 return "CUSOLVER_STATUS_EXECUTION_FAILED"; 762 case CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED: 763 return "CUSOLVER_STATUS_MATRIX_TYPE_NOT_SUPPORTED"; 764 case CUSOLVER_STATUS_NOT_SUPPORTED: 765 return "CUSOLVER_STATUS_NOT_SUPPORTED "; 766 case CUSOLVER_STATUS_ZERO_PIVOT: 767 return "CUSOLVER_STATUS_ZERO_PIVOT"; 768 case CUSOLVER_STATUS_INVALID_LICENSE: 769 return "CUSOLVER_STATUS_INVALID_LICENSE"; 770 #endif 771 #endif 772 default: 773 return "unknown error"; 774 } 775 } 776 PETSC_EXTERN const char *PetscCUFFTGetErrorName(cufftResult result) 777 { 778 switch (result) { 779 case CUFFT_SUCCESS: 780 return "CUFFT_SUCCESS"; 781 case CUFFT_INVALID_PLAN: 782 return "CUFFT_INVALID_PLAN"; 783 case CUFFT_ALLOC_FAILED: 784 return "CUFFT_ALLOC_FAILED"; 785 case CUFFT_INVALID_TYPE: 786 return "CUFFT_INVALID_TYPE"; 787 case CUFFT_INVALID_VALUE: 788 return "CUFFT_INVALID_VALUE"; 789 case CUFFT_INTERNAL_ERROR: 790 return "CUFFT_INTERNAL_ERROR"; 791 case CUFFT_EXEC_FAILED: 792 return "CUFFT_EXEC_FAILED"; 793 case CUFFT_SETUP_FAILED: 794 return "CUFFT_SETUP_FAILED"; 795 case CUFFT_INVALID_SIZE: 796 return "CUFFT_INVALID_SIZE"; 797 case CUFFT_UNALIGNED_DATA: 798 return "CUFFT_UNALIGNED_DATA"; 799 case CUFFT_INCOMPLETE_PARAMETER_LIST: 800 return "CUFFT_INCOMPLETE_PARAMETER_LIST"; 801 case CUFFT_INVALID_DEVICE: 802 return "CUFFT_INVALID_DEVICE"; 803 case CUFFT_PARSE_ERROR: 804 return "CUFFT_PARSE_ERROR"; 805 case CUFFT_NO_WORKSPACE: 806 return "CUFFT_NO_WORKSPACE"; 807 case CUFFT_NOT_IMPLEMENTED: 808 return "CUFFT_NOT_IMPLEMENTED"; 809 case CUFFT_LICENSE_ERROR: 810 return "CUFFT_LICENSE_ERROR"; 811 case CUFFT_NOT_SUPPORTED: 812 return "CUFFT_NOT_SUPPORTED"; 813 default: 814 return "unknown error"; 815 } 816 } 817 #endif 818 819 #if defined(PETSC_HAVE_HIP) 820 #include <petscdevice_hip.h> 821 PETSC_EXTERN const char *PetscHIPBLASGetErrorName(hipblasStatus_t status) 822 { 823 switch (status) { 824 case HIPBLAS_STATUS_SUCCESS: 825 return "HIPBLAS_STATUS_SUCCESS"; 826 case HIPBLAS_STATUS_NOT_INITIALIZED: 827 return "HIPBLAS_STATUS_NOT_INITIALIZED"; 828 case HIPBLAS_STATUS_ALLOC_FAILED: 829 return "HIPBLAS_STATUS_ALLOC_FAILED"; 830 case HIPBLAS_STATUS_INVALID_VALUE: 831 return "HIPBLAS_STATUS_INVALID_VALUE"; 832 case HIPBLAS_STATUS_ARCH_MISMATCH: 833 return "HIPBLAS_STATUS_ARCH_MISMATCH"; 834 case HIPBLAS_STATUS_MAPPING_ERROR: 835 return "HIPBLAS_STATUS_MAPPING_ERROR"; 836 case HIPBLAS_STATUS_EXECUTION_FAILED: 837 return "HIPBLAS_STATUS_EXECUTION_FAILED"; 838 case HIPBLAS_STATUS_INTERNAL_ERROR: 839 return "HIPBLAS_STATUS_INTERNAL_ERROR"; 840 case HIPBLAS_STATUS_NOT_SUPPORTED: 841 return "HIPBLAS_STATUS_NOT_SUPPORTED"; 842 default: 843 return "unknown error"; 844 } 845 } 846 PETSC_EXTERN const char *PetscHIPSPARSEGetErrorName(hipsparseStatus_t status) 847 { 848 switch (status) { 849 case HIPSPARSE_STATUS_SUCCESS: 850 return "HIPSPARSE_STATUS_SUCCESS"; 851 case HIPSPARSE_STATUS_NOT_INITIALIZED: 852 return "HIPSPARSE_STATUS_NOT_INITIALIZED"; 853 case HIPSPARSE_STATUS_ALLOC_FAILED: 854 return "HIPSPARSE_STATUS_ALLOC_FAILED"; 855 case HIPSPARSE_STATUS_INVALID_VALUE: 856 return "HIPSPARSE_STATUS_INVALID_VALUE"; 857 case HIPSPARSE_STATUS_ARCH_MISMATCH: 858 return "HIPSPARSE_STATUS_ARCH_MISMATCH"; 859 case HIPSPARSE_STATUS_MAPPING_ERROR: 860 return "HIPSPARSE_STATUS_MAPPING_ERROR"; 861 case HIPSPARSE_STATUS_EXECUTION_FAILED: 862 return "HIPSPARSE_STATUS_EXECUTION_FAILED"; 863 case HIPSPARSE_STATUS_INTERNAL_ERROR: 864 return "HIPSPARSE_STATUS_INTERNAL_ERROR"; 865 case HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED: 866 return "HIPSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED"; 867 case HIPSPARSE_STATUS_ZERO_PIVOT: 868 return "HIPSPARSE_STATUS_ZERO_PIVOT"; 869 case HIPSPARSE_STATUS_NOT_SUPPORTED: 870 return "HIPSPARSE_STATUS_NOT_SUPPORTED"; 871 case HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES: 872 return "HIPSPARSE_STATUS_INSUFFICIENT_RESOURCES"; 873 default: 874 return "unknown error"; 875 } 876 } 877 PETSC_EXTERN const char *PetscHIPSolverGetErrorName(hipsolverStatus_t status) 878 { 879 switch (status) { 880 case HIPSOLVER_STATUS_SUCCESS: 881 return "HIPSOLVER_STATUS_SUCCESS"; 882 case HIPSOLVER_STATUS_NOT_INITIALIZED: 883 return "HIPSOLVER_STATUS_NOT_INITIALIZED"; 884 case HIPSOLVER_STATUS_ALLOC_FAILED: 885 return "HIPSOLVER_STATUS_ALLOC_FAILED"; 886 case HIPSOLVER_STATUS_MAPPING_ERROR: 887 return "HIPSOLVER_STATUS_MAPPING_ERROR"; 888 case HIPSOLVER_STATUS_INVALID_VALUE: 889 return "HIPSOLVER_STATUS_INVALID_VALUE"; 890 case HIPSOLVER_STATUS_EXECUTION_FAILED: 891 return "HIPSOLVER_STATUS_EXECUTION_FAILED"; 892 case HIPSOLVER_STATUS_INTERNAL_ERROR: 893 return "HIPSOLVER_STATUS_INTERNAL_ERROR"; 894 case HIPSOLVER_STATUS_NOT_SUPPORTED: 895 return "HIPSOLVER_STATUS_NOT_SUPPORTED "; 896 case HIPSOLVER_STATUS_ARCH_MISMATCH: 897 return "HIPSOLVER_STATUS_ARCH_MISMATCH"; 898 case HIPSOLVER_STATUS_HANDLE_IS_NULLPTR: 899 return "HIPSOLVER_STATUS_HANDLE_IS_NULLPTR"; 900 case HIPSOLVER_STATUS_INVALID_ENUM: 901 return "HIPSOLVER_STATUS_INVALID_ENUM"; 902 case HIPSOLVER_STATUS_UNKNOWN: 903 default: 904 return "HIPSOLVER_STATUS_UNKNOWN"; 905 } 906 } 907 #endif 908 909 /*@ 910 PetscMPIErrorString - Given an MPI error code returns the `MPI_Error_string()` appropriately 911 formatted for displaying with the PETSc error handlers. 912 913 Input Parameter: 914 . err - the MPI error code 915 916 Output Parameter: 917 . string - the MPI error message, should declare its length to be larger than `MPI_MAX_ERROR_STRING` 918 919 Level: developer 920 921 Note: 922 Does not return an error code or do error handling because it may be called from inside an error handler 923 924 @*/ 925 void PetscMPIErrorString(PetscMPIInt err, char *string) 926 { 927 char errorstring[MPI_MAX_ERROR_STRING]; 928 PetscMPIInt len, j = 0; 929 930 MPI_Error_string(err, (char *)errorstring, &len); 931 for (PetscMPIInt i = 0; i < len; i++) { 932 string[j++] = errorstring[i]; 933 if (errorstring[i] == '\n') { 934 for (PetscMPIInt k = 0; k < 16; k++) string[j++] = ' '; 935 } 936 } 937 string[j] = 0; 938 } 939