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