1 2 #include <petsc/private/viewerimpl.h> /*I "petscviewer.h" I*/ 3 #include <petscdraw.h> 4 5 PetscClassId PETSC_VIEWER_CLASSID; 6 7 static PetscBool PetscViewerPackageInitialized = PETSC_FALSE; 8 /*@C 9 PetscViewerFinalizePackage - This function destroys any global objects created in the Petsc viewers. It is 10 called from `PetscFinalize()`. 11 12 Level: developer 13 14 .seealso: `PetscFinalize()` 15 @*/ 16 PetscErrorCode PetscViewerFinalizePackage(void) 17 { 18 PetscFunctionBegin; 19 if (Petsc_Viewer_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_keyval)); 20 if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Stdout_keyval)); 21 if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Stderr_keyval)); 22 if (Petsc_Viewer_Binary_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Binary_keyval)); 23 if (Petsc_Viewer_Draw_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Draw_keyval)); 24 #if defined(PETSC_HAVE_HDF5) 25 if (Petsc_Viewer_HDF5_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_HDF5_keyval)); 26 #endif 27 #if defined(PETSC_USE_SOCKETVIEWER) 28 if (Petsc_Viewer_Socket_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Socket_keyval)); 29 #endif 30 PetscCall(PetscFunctionListDestroy(&PetscViewerList)); 31 PetscViewerPackageInitialized = PETSC_FALSE; 32 PetscViewerRegisterAllCalled = PETSC_FALSE; 33 PetscFunctionReturn(0); 34 } 35 36 /*@C 37 PetscViewerInitializePackage - This function initializes everything in the `PetscViewer` package. 38 39 Level: developer 40 41 .seealso: `PetscInitialize()` 42 @*/ 43 PetscErrorCode PetscViewerInitializePackage(void) 44 { 45 char logList[256]; 46 PetscBool opt, pkg; 47 48 PetscFunctionBegin; 49 if (PetscViewerPackageInitialized) PetscFunctionReturn(0); 50 PetscViewerPackageInitialized = PETSC_TRUE; 51 /* Register Classes */ 52 PetscCall(PetscClassIdRegister("Viewer", &PETSC_VIEWER_CLASSID)); 53 /* Register Constructors */ 54 PetscCall(PetscViewerRegisterAll()); 55 /* Process Info */ 56 { 57 PetscClassId classids[1]; 58 59 classids[0] = PETSC_VIEWER_CLASSID; 60 PetscCall(PetscInfoProcessClass("viewer", 1, classids)); 61 } 62 /* Process summary exclusions */ 63 PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt)); 64 if (opt) { 65 PetscCall(PetscStrInList("viewer", logList, ',', &pkg)); 66 if (pkg) PetscCall(PetscLogEventExcludeClass(PETSC_VIEWER_CLASSID)); 67 } 68 #if defined(PETSC_HAVE_MATHEMATICA) 69 PetscCall(PetscViewerMathematicaInitializePackage()); 70 #endif 71 /* Register package finalizer */ 72 PetscCall(PetscRegisterFinalize(PetscViewerFinalizePackage)); 73 PetscFunctionReturn(0); 74 } 75 76 /*@ 77 PetscViewerDestroy - Destroys a `PetscViewer`. 78 79 Collective on viewer 80 81 Input Parameters: 82 . viewer - the `PetscViewer` to be destroyed. 83 84 Level: beginner 85 86 .seealso: `PetscViewer`, `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerCreate()`, `PetscViewerDrawOpen()` 87 @*/ 88 PetscErrorCode PetscViewerDestroy(PetscViewer *viewer) 89 { 90 PetscFunctionBegin; 91 if (!*viewer) PetscFunctionReturn(0); 92 PetscValidHeaderSpecific(*viewer, PETSC_VIEWER_CLASSID, 1); 93 94 PetscCall(PetscViewerFlush(*viewer)); 95 if (--((PetscObject)(*viewer))->refct > 0) { 96 *viewer = NULL; 97 PetscFunctionReturn(0); 98 } 99 100 PetscCall(PetscObjectSAWsViewOff((PetscObject)*viewer)); 101 if ((*viewer)->ops->destroy) PetscCall((*(*viewer)->ops->destroy)(*viewer)); 102 PetscCall(PetscHeaderDestroy(viewer)); 103 PetscFunctionReturn(0); 104 } 105 106 /*@C 107 PetscViewerAndFormatCreate - Creates a `PetscViewerAndFormat` struct. 108 109 Collective on viewer 110 111 Input Parameters: 112 + viewer - the viewer 113 - format - the format 114 115 Output Parameter: 116 . vf - viewer and format object 117 118 Level: developer 119 120 Notes: 121 This increases the reference count of the viewer so you can destroy the viewer object after this call 122 123 This is used as the context variable for many of the `TS`, `SNES`, and `KSP` monitor functions 124 125 .seealso: `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerCreate()`, `PetscViewerDrawOpen()`, `PetscViewerAndFormatDestroy()` 126 @*/ 127 PetscErrorCode PetscViewerAndFormatCreate(PetscViewer viewer, PetscViewerFormat format, PetscViewerAndFormat **vf) 128 { 129 PetscFunctionBegin; 130 PetscCall(PetscObjectReference((PetscObject)viewer)); 131 PetscCall(PetscNew(vf)); 132 (*vf)->viewer = viewer; 133 (*vf)->format = format; 134 (*vf)->lg = NULL; 135 (*vf)->data = NULL; 136 PetscFunctionReturn(0); 137 } 138 139 /*@C 140 PetscViewerAndFormatDestroy - Destroys a `PetscViewerAndFormat` struct. 141 142 Collective on vf 143 144 Input Parameters: 145 . vf - the `PetscViewerAndFormat` to be destroyed. 146 147 Level: developer 148 149 .seealso: `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerCreate()`, `PetscViewerDrawOpen()`, `PetscViewerAndFormatCreate()` 150 @*/ 151 PetscErrorCode PetscViewerAndFormatDestroy(PetscViewerAndFormat **vf) 152 { 153 PetscFunctionBegin; 154 PetscCall(PetscViewerDestroy(&(*vf)->viewer)); 155 PetscCall(PetscDrawLGDestroy(&(*vf)->lg)); 156 PetscCall(PetscFree(*vf)); 157 PetscFunctionReturn(0); 158 } 159 160 /*@C 161 PetscViewerGetType - Returns the type of a `PetscViewer`. 162 163 Not Collective 164 165 Input Parameter: 166 . viewer - the `PetscViewer` 167 168 Output Parameter: 169 . type - PetscViewer type (see below) 170 171 Available Types Include: 172 + `PETSCVIEWERSOCKET` - Socket PetscViewer 173 . `PETSCVIEWERASCII` - ASCII PetscViewer 174 . `PETSCVIEWERBINARY` - binary file PetscViewer 175 . `PETSCVIEWERSTRING` - string PetscViewer 176 - `PETSCVIEWERDRAW` - drawing PetscViewer 177 178 Level: intermediate 179 180 Note: 181 See include/petscviewer.h for a complete list of `PetscViewer`s. 182 183 `PetscViewerType` is actually a string 184 185 .seealso: `PetscViewerType`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType` 186 @*/ 187 PetscErrorCode PetscViewerGetType(PetscViewer viewer, PetscViewerType *type) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 191 PetscValidPointer(type, 2); 192 *type = ((PetscObject)viewer)->type_name; 193 PetscFunctionReturn(0); 194 } 195 196 /*@C 197 PetscViewerSetOptionsPrefix - Sets the prefix used for searching for all 198 `PetscViewer` options in the database. 199 200 Logically Collective on viewer 201 202 Input Parameters: 203 + viewer - the `PetscViewer` context 204 - prefix - the prefix to prepend to all option names 205 206 Note: 207 A hyphen (-) must NOT be given at the beginning of the prefix name. 208 The first character of all runtime options is AUTOMATICALLY the hyphen. 209 210 Level: advanced 211 212 .seealso: `PetscViewer`, `PetscViewerSetFromOptions()` 213 @*/ 214 PetscErrorCode PetscViewerSetOptionsPrefix(PetscViewer viewer, const char prefix[]) 215 { 216 PetscFunctionBegin; 217 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 218 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)viewer, prefix)); 219 PetscFunctionReturn(0); 220 } 221 222 /*@C 223 PetscViewerAppendOptionsPrefix - Appends to the prefix used for searching for all 224 `PetscViewer` options in the database. 225 226 Logically Collective on viewer 227 228 Input Parameters: 229 + viewer - the PetscViewer context 230 - prefix - the prefix to prepend to all option names 231 232 Note: 233 A hyphen (-) must NOT be given at the beginning of the prefix name. 234 The first character of all runtime options is AUTOMATICALLY the hyphen. 235 236 Level: advanced 237 238 .seealso: `PetscViewer`, `PetscViewerGetOptionsPrefix()` 239 @*/ 240 PetscErrorCode PetscViewerAppendOptionsPrefix(PetscViewer viewer, const char prefix[]) 241 { 242 PetscFunctionBegin; 243 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 244 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)viewer, prefix)); 245 PetscFunctionReturn(0); 246 } 247 248 /*@C 249 PetscViewerGetOptionsPrefix - Sets the prefix used for searching for all 250 PetscViewer options in the database. 251 252 Not Collective 253 254 Input Parameter: 255 . viewer - the `PetscViewer` context 256 257 Output Parameter: 258 . prefix - pointer to the prefix string used 259 260 Fortran Note: 261 The user should pass in a string 'prefix' of sufficient length to hold the prefix. 262 263 Level: advanced 264 265 .seealso: `PetscViewer`, `PetscViewerAppendOptionsPrefix()` 266 @*/ 267 PetscErrorCode PetscViewerGetOptionsPrefix(PetscViewer viewer, const char *prefix[]) 268 { 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 271 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)viewer, prefix)); 272 PetscFunctionReturn(0); 273 } 274 275 /*@ 276 PetscViewerSetUp - Sets up the internal viewer data structures for the later use. 277 278 Collective on viewer 279 280 Input Parameters: 281 . viewer - the `PetscViewer` context 282 283 Note: 284 For basic use of the `PetscViewer` classes the user need not explicitly call 285 `PetscViewerSetUp()`, since these actions will happen automatically. 286 287 Level: advanced 288 289 .seealso: `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()` 290 @*/ 291 PetscErrorCode PetscViewerSetUp(PetscViewer viewer) 292 { 293 PetscFunctionBegin; 294 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 295 if (viewer->setupcalled) PetscFunctionReturn(0); 296 PetscTryTypeMethod(viewer, setup); 297 viewer->setupcalled = PETSC_TRUE; 298 PetscFunctionReturn(0); 299 } 300 301 /*@C 302 PetscViewerViewFromOptions - View from the viewer based on the options database values 303 304 Collective on A 305 306 Input Parameters: 307 + A - the `PetscViewer` context 308 . obj - Optional object that provides the prefix for the option names 309 - name - command line option 310 311 Level: intermediate 312 313 .seealso: `PetscViewer`, `PetscViewerView`, `PetscObjectViewFromOptions()`, `PetscViewerCreate()` 314 @*/ 315 PetscErrorCode PetscViewerViewFromOptions(PetscViewer A, PetscObject obj, const char name[]) 316 { 317 PetscFunctionBegin; 318 PetscValidHeaderSpecific(A, PETSC_VIEWER_CLASSID, 1); 319 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 320 PetscFunctionReturn(0); 321 } 322 323 /*@C 324 PetscViewerView - Visualizes a viewer object. 325 326 Collective on v 327 328 Input Parameters: 329 + v - the viewer to be viewed 330 - viewer - visualization context 331 332 Note: 333 The available visualization contexts include 334 .vb 335 PETSC_VIEWER_STDOUT_SELF - standard output (default) 336 PETSC_VIEWER_STDOUT_WORLD - synchronized standard output where only the first rank opens the file. Other processors send their data to the first rank 337 PETSC_VIEWER_DRAW_WORLD - graphical display of nonzero structure 338 .ve 339 340 Level: beginner 341 342 .seealso: `PetscViewer`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, 343 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerLoad()` 344 @*/ 345 PetscErrorCode PetscViewerView(PetscViewer v, PetscViewer viewer) 346 { 347 PetscBool iascii; 348 PetscViewerFormat format; 349 #if defined(PETSC_HAVE_SAWS) 350 PetscBool issaws; 351 #endif 352 353 PetscFunctionBegin; 354 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 355 PetscValidType(v, 1); 356 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)v), &viewer)); 357 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 358 PetscCheckSameComm(v, 1, viewer, 2); 359 360 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 361 #if defined(PETSC_HAVE_SAWS) 362 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 363 #endif 364 if (iascii) { 365 PetscCall(PetscViewerGetFormat(viewer, &format)); 366 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)v, viewer)); 367 if (format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 368 if (v->format) PetscCall(PetscViewerASCIIPrintf(viewer, " Viewer format = %s\n", PetscViewerFormats[v->format])); 369 PetscCall(PetscViewerASCIIPushTab(viewer)); 370 PetscTryTypeMethod(v, view, viewer); 371 PetscCall(PetscViewerASCIIPopTab(viewer)); 372 } 373 #if defined(PETSC_HAVE_SAWS) 374 } else if (issaws) { 375 if (!((PetscObject)v)->amsmem) { 376 PetscCall(PetscObjectViewSAWs((PetscObject)v, viewer)); 377 PetscTryTypeMethod(v, view, viewer); 378 } 379 #endif 380 } 381 PetscFunctionReturn(0); 382 } 383 384 /*@C 385 PetscViewerRead - Reads data from a `PetscViewer` 386 387 Collective 388 389 Input Parameters: 390 + viewer - The viewer 391 . data - Location to write the data 392 . num - Number of items of data to read 393 - datatype - Type of data to read 394 395 Output Parameters: 396 . count - number of items of data actually read, or NULL 397 398 Note: 399 If datatype is `PETSC_STRING` and num is negative, reads until a newline character is found, 400 until a maximum of (-num - 1) chars. 401 402 Level: beginner 403 404 .seealso: `PetscViewer`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, 405 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, 406 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer` 407 @*/ 408 PetscErrorCode PetscViewerRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype) 409 { 410 PetscFunctionBegin; 411 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 412 if (dtype == PETSC_STRING) { 413 PetscInt c, i = 0, cnt; 414 char *s = (char *)data; 415 if (num >= 0) { 416 for (c = 0; c < num; c++) { 417 /* Skip leading whitespaces */ 418 do { 419 PetscCall((*viewer->ops->read)(viewer, &(s[i]), 1, &cnt, PETSC_CHAR)); 420 if (!cnt) break; 421 } while (s[i] == '\n' || s[i] == '\t' || s[i] == ' ' || s[i] == '\0' || s[i] == '\v' || s[i] == '\f' || s[i] == '\r'); 422 i++; 423 /* Read strings one char at a time */ 424 do { 425 PetscCall((*viewer->ops->read)(viewer, &(s[i++]), 1, &cnt, PETSC_CHAR)); 426 if (!cnt) break; 427 } while (s[i - 1] != '\n' && s[i - 1] != '\t' && s[i - 1] != ' ' && s[i - 1] != '\0' && s[i - 1] != '\v' && s[i - 1] != '\f' && s[i - 1] != '\r'); 428 /* Terminate final string */ 429 if (c == num - 1) s[i - 1] = '\0'; 430 } 431 } else { 432 /* Read until a \n is encountered (-num is the max size allowed) */ 433 do { 434 PetscCall((*viewer->ops->read)(viewer, &(s[i++]), 1, &cnt, PETSC_CHAR)); 435 if (i == -num || !cnt) break; 436 } while (s[i - 1] != '\n'); 437 /* Terminate final string */ 438 s[i - 1] = '\0'; 439 c = i; 440 } 441 if (count) *count = c; 442 else PetscCheck(c >= num, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_READ, "Insufficient data, only read %" PetscInt_FMT " < %" PetscInt_FMT " strings", c, num); 443 } else PetscUseTypeMethod(viewer, read, data, num, count, dtype); 444 PetscFunctionReturn(0); 445 } 446 447 /*@ 448 PetscViewerReadable - Return a flag whether the viewer can be read from 449 450 Not Collective 451 452 Input Parameters: 453 . viewer - the `PetscViewer` context 454 455 Output Parameters: 456 . flg - `PETSC_TRUE` if the viewer is readable, `PETSC_FALSE` otherwise 457 458 Note: 459 `PETSC_TRUE` means that viewer's `PetscViewerType` supports reading (this holds e.g. for `PETSCVIEWERBINARY`) 460 and viewer is in a mode allowing reading, i.e. `PetscViewerFileGetMode()` 461 returns one of `FILE_MODE_READ`, `FILE_MODE_UPDATE`, `FILE_MODE_APPEND_UPDATE`. 462 463 Level: intermediate 464 465 .seealso: `PetscViewer`, `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()` 466 @*/ 467 PetscErrorCode PetscViewerReadable(PetscViewer viewer, PetscBool *flg) 468 { 469 PetscFileMode mode; 470 PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL; 471 472 PetscFunctionBegin; 473 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 474 PetscValidBoolPointer(flg, 2); 475 PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f)); 476 *flg = PETSC_FALSE; 477 if (!f) PetscFunctionReturn(0); 478 PetscCall((*f)(viewer, &mode)); 479 switch (mode) { 480 case FILE_MODE_READ: 481 case FILE_MODE_UPDATE: 482 case FILE_MODE_APPEND_UPDATE: 483 *flg = PETSC_TRUE; 484 default: 485 break; 486 } 487 PetscFunctionReturn(0); 488 } 489 490 /*@ 491 PetscViewerWritable - Return a flag whether the viewer can be written to 492 493 Not Collective 494 495 Input Parameters: 496 . viewer - the `PetscViewer` context 497 498 Output Parameters: 499 . flg - `PETSC_TRUE` if the viewer is writable, `PETSC_FALSE` otherwise 500 501 Note: 502 `PETSC_TRUE` means viewer is in a mode allowing writing, i.e. `PetscViewerFileGetMode()` 503 returns one of `FILE_MODE_WRITE`, `FILE_MODE_APPEND`, `FILE_MODE_UPDATE`, `FILE_MODE_APPEND_UPDATE`. 504 505 Level: intermediate 506 507 .seealso: `PetscViewer`, `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()` 508 @*/ 509 PetscErrorCode PetscViewerWritable(PetscViewer viewer, PetscBool *flg) 510 { 511 PetscFileMode mode; 512 PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL; 513 514 PetscFunctionBegin; 515 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 516 PetscValidBoolPointer(flg, 2); 517 PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f)); 518 *flg = PETSC_TRUE; 519 if (!f) PetscFunctionReturn(0); 520 PetscCall((*f)(viewer, &mode)); 521 if (mode == FILE_MODE_READ) *flg = PETSC_FALSE; 522 PetscFunctionReturn(0); 523 } 524 525 /*@ 526 PetscViewerCheckReadable - Check whether the viewer can be read from, generates an error if not 527 528 Collective 529 530 Input Parameters: 531 . viewer - the `PetscViewer` context 532 533 Level: intermediate 534 535 .seealso: `PetscViewer`, `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()` 536 @*/ 537 PetscErrorCode PetscViewerCheckReadable(PetscViewer viewer) 538 { 539 PetscBool flg; 540 541 PetscFunctionBegin; 542 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 543 PetscCall(PetscViewerReadable(viewer, &flg)); 544 PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Viewer doesn't support reading, or is not in reading mode (FILE_MODE_READ, FILE_MODE_UPDATE, FILE_MODE_APPEND_UPDATE)"); 545 PetscFunctionReturn(0); 546 } 547 548 /*@ 549 PetscViewerCheckWritable - Check whether the viewer can be written to, generates an error if not 550 551 Collective 552 553 Input Parameters: 554 . viewer - the `PetscViewer` context 555 556 Level: intermediate 557 558 .seealso: `PetscViewer`, `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()` 559 @*/ 560 PetscErrorCode PetscViewerCheckWritable(PetscViewer viewer) 561 { 562 PetscBool flg; 563 564 PetscFunctionBegin; 565 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 566 PetscCall(PetscViewerWritable(viewer, &flg)); 567 PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Viewer doesn't support writing, or is in FILE_MODE_READ mode"); 568 PetscFunctionReturn(0); 569 } 570