Actual source code: view.c

      1: #include <petsc/private/viewerimpl.h>
      2: #include <petscdraw.h>

      4: PetscClassId PETSC_VIEWER_CLASSID;

      6: static PetscBool PetscViewerPackageInitialized = PETSC_FALSE;

      8: /*@C
      9:   PetscViewerFinalizePackage - This function destroys any global objects created in PETSc viewers. It is
     10:   called from `PetscFinalize()`.

     12:   Level: developer

     14: .seealso: [](sec_viewers), `PetscViewer`, `PetscFinalize()`, `PetscViewerInitializePackage()`
     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(PETSC_SUCCESS);
     34: }

     36: /*@C
     37:   PetscViewerInitializePackage - This function initializes everything in the `PetscViewer` package.

     39:   Level: developer

     41: .seealso: [](sec_viewers), `PetscViewer`, `PetscInitialize()`, `PetscViewerFinalizePackage()`
     42: @*/
     43: PetscErrorCode PetscViewerInitializePackage(void)
     44: {
     45:   char      logList[256];
     46:   PetscBool opt, pkg;

     48:   PetscFunctionBegin;
     49:   if (PetscViewerPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
     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];

     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(PETSC_SUCCESS);
     74: }

     76: /*@
     77:   PetscViewerDestroy - Destroys a `PetscViewer`.

     79:   Collective

     81:   Input Parameter:
     82: . viewer - the `PetscViewer` to be destroyed.

     84:   Level: beginner

     86: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`
     87: @*/
     88: PetscErrorCode PetscViewerDestroy(PetscViewer *viewer)
     89: {
     90:   PetscFunctionBegin;
     91:   if (!*viewer) PetscFunctionReturn(PETSC_SUCCESS);

     94:   PetscCall(PetscViewerFlush(*viewer));
     95:   if (--((PetscObject)*viewer)->refct > 0) {
     96:     *viewer = NULL;
     97:     PetscFunctionReturn(PETSC_SUCCESS);
     98:   }

    100:   PetscCall(PetscObjectSAWsViewOff((PetscObject)*viewer));
    101:   PetscTryTypeMethod(*viewer, destroy);
    102:   PetscCall(PetscHeaderDestroy(viewer));
    103:   PetscFunctionReturn(PETSC_SUCCESS);
    104: }

    106: /*@C
    107:   PetscViewerAndFormatCreate - Creates a `PetscViewerAndFormat` struct.

    109:   Collective

    111:   Input Parameters:
    112: + viewer - the viewer
    113: - format - the format

    115:   Output Parameter:
    116: . vf - viewer and format object

    118:   Level: developer

    120:   Notes:
    121:   This increases the reference count of the viewer.

    123:   Use `PetscViewerAndFormatDestroy()` to free the struct

    125:   This is used as the context variable for many of the `TS`, `SNES`, and `KSP` monitor functions

    127:   This construct exists because it allows one to keep track of the use of a `PetscViewerFormat` without requiring the
    128:   format in the viewer to be permanently changed.

    130: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerAndFormat`, `PetscViewerFormat`, `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerCreate()`,
    131:           `PetscViewerDrawOpen()`, `PetscViewerAndFormatDestroy()`
    132: @*/
    133: PetscErrorCode PetscViewerAndFormatCreate(PetscViewer viewer, PetscViewerFormat format, PetscViewerAndFormat **vf)
    134: {
    135:   PetscFunctionBegin;
    136:   PetscCall(PetscObjectReference((PetscObject)viewer));
    137:   PetscCall(PetscNew(vf));
    138:   (*vf)->viewer = viewer;
    139:   (*vf)->format = format;
    140:   (*vf)->lg     = NULL;
    141:   (*vf)->data   = NULL;
    142:   PetscFunctionReturn(PETSC_SUCCESS);
    143: }

    145: /*@C
    146:   PetscViewerAndFormatDestroy - Destroys a `PetscViewerAndFormat` struct created with `PetscViewerAndFormatCreate()`

    148:   Collective

    150:   Input Parameter:
    151: . vf - the `PetscViewerAndFormat` to be destroyed.

    153:   Level: developer

    155: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerAndFormat`, `PetscViewerFormat`, `PetscViewerAndFormatCreate()`, `PetscViewerSocketOpen()`,
    156:           `PetscViewerASCIIOpen()`, `PetscViewerCreate()`, `PetscViewerDrawOpen()`
    157: @*/
    158: PetscErrorCode PetscViewerAndFormatDestroy(PetscViewerAndFormat **vf)
    159: {
    160:   PetscFunctionBegin;
    161:   PetscCall(PetscViewerDestroy(&(*vf)->viewer));
    162:   PetscCall(PetscDrawLGDestroy(&(*vf)->lg));
    163:   PetscCall(PetscFree(*vf));
    164:   PetscFunctionReturn(PETSC_SUCCESS);
    165: }

    167: /*@
    168:   PetscViewerGetType - Returns the type of a `PetscViewer`.

    170:   Not Collective

    172:   Input Parameter:
    173: . viewer - the `PetscViewer`

    175:   Output Parameter:
    176: . type - `PetscViewerType`

    178:   Level: intermediate

    180:   Note:
    181:   `PetscViewerType` is actually a string

    183: .seealso: [](sec_viewers), `PetscViewerType`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`
    184: @*/
    185: PetscErrorCode PetscViewerGetType(PetscViewer viewer, PetscViewerType *type)
    186: {
    187:   PetscFunctionBegin;
    189:   PetscAssertPointer(type, 2);
    190:   *type = ((PetscObject)viewer)->type_name;
    191:   PetscFunctionReturn(PETSC_SUCCESS);
    192: }

    194: /*@
    195:   PetscViewerSetOptionsPrefix - Sets the prefix used for searching for
    196:   `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.

    198:   Logically Collective

    200:   Input Parameters:
    201: + viewer - the `PetscViewer` context
    202: - prefix - the prefix to prepend to all option names

    204:   Note:
    205:   A hyphen (-) must NOT be given at the beginning of the prefix name.
    206:   The first character of all runtime options is AUTOMATICALLY the hyphen.

    208:   Level: advanced

    210: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerSetFromOptions()`, `PetscViewerAppendOptionsPrefix()`
    211: @*/
    212: PetscErrorCode PetscViewerSetOptionsPrefix(PetscViewer viewer, const char prefix[])
    213: {
    214:   PetscFunctionBegin;
    216:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)viewer, prefix));
    217:   PetscFunctionReturn(PETSC_SUCCESS);
    218: }

    220: /*@
    221:   PetscViewerAppendOptionsPrefix - Appends to the prefix used for searching for
    222:   `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.

    224:   Logically Collective

    226:   Input Parameters:
    227: + viewer - the `PetscViewer` context
    228: - prefix - the prefix to prepend to all option names

    230:   Level: advanced

    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.

    236: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerGetOptionsPrefix()`, `PetscViewerSetOptionsPrefix()`
    237: @*/
    238: PetscErrorCode PetscViewerAppendOptionsPrefix(PetscViewer viewer, const char prefix[])
    239: {
    240:   PetscFunctionBegin;
    242:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)viewer, prefix));
    243:   PetscFunctionReturn(PETSC_SUCCESS);
    244: }

    246: /*@
    247:   PetscViewerGetOptionsPrefix - Gets the prefix used for searching for
    248:   `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.

    250:   Not Collective

    252:   Input Parameter:
    253: . viewer - the `PetscViewer` context

    255:   Output Parameter:
    256: . prefix - pointer to the prefix string used

    258:   Level: advanced

    260:   Fortran Notes:
    261:   The user should pass in a string 'prefix' of sufficient length to hold the prefix.

    263: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerAppendOptionsPrefix()`, `PetscViewerSetOptionsPrefix()`
    264: @*/
    265: PetscErrorCode PetscViewerGetOptionsPrefix(PetscViewer viewer, const char *prefix[])
    266: {
    267:   PetscFunctionBegin;
    269:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)viewer, prefix));
    270:   PetscFunctionReturn(PETSC_SUCCESS);
    271: }

    273: /*@
    274:   PetscViewerSetUp - Sets up the internal viewer data structures for the later use.

    276:   Collective

    278:   Input Parameter:
    279: . viewer - the `PetscViewer` context

    281:   Level: advanced

    283:   Note:
    284:   For basic use of the `PetscViewer` classes the user need not explicitly call
    285:   `PetscViewerSetUp()`, since these actions will happen automatically.

    287: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`
    288: @*/
    289: PetscErrorCode PetscViewerSetUp(PetscViewer viewer)
    290: {
    291:   PetscFunctionBegin;
    293:   if (viewer->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
    294:   PetscTryTypeMethod(viewer, setup);
    295:   viewer->setupcalled = PETSC_TRUE;
    296:   PetscFunctionReturn(PETSC_SUCCESS);
    297: }

    299: /*@
    300:   PetscViewerViewFromOptions - View from the viewer based on options in the options database

    302:   Collective

    304:   Input Parameters:
    305: + A    - the `PetscViewer` context
    306: . obj  - Optional object that provides the prefix for the option names
    307: - name - command line option

    309:   Level: intermediate

    311:   Note:
    312:   See `PetscObjectViewFromOptions()` for details on the viewers and formats support via this interface

    314: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerView`, `PetscObjectViewFromOptions()`, `PetscViewerCreate()`
    315: @*/
    316: PetscErrorCode PetscViewerViewFromOptions(PetscViewer A, PetscObject obj, const char name[])
    317: {
    318:   PetscFunctionBegin;
    320:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
    321:   PetscFunctionReturn(PETSC_SUCCESS);
    322: }

    324: /*@
    325:   PetscViewerView - Visualizes a viewer object.

    327:   Collective

    329:   Input Parameters:
    330: + v      - the viewer to be viewed
    331: - viewer - visualization context

    333:   Level: beginner

    335: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`,
    336:           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerLoad()`
    337: @*/
    338: PetscErrorCode PetscViewerView(PetscViewer v, PetscViewer viewer)
    339: {
    340:   PetscBool         iascii;
    341:   PetscViewerFormat format;
    342: #if defined(PETSC_HAVE_SAWS)
    343:   PetscBool issaws;
    344: #endif

    346:   PetscFunctionBegin;
    349:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)v), &viewer));
    351:   PetscCheckSameComm(v, 1, viewer, 2);

    353:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
    354: #if defined(PETSC_HAVE_SAWS)
    355:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
    356: #endif
    357:   if (iascii) {
    358:     PetscCall(PetscViewerGetFormat(viewer, &format));
    359:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)v, viewer));
    360:     if (format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
    361:       if (v->format) PetscCall(PetscViewerASCIIPrintf(viewer, "  Viewer format = %s\n", PetscViewerFormats[v->format]));
    362:       PetscCall(PetscViewerASCIIPushTab(viewer));
    363:       PetscTryTypeMethod(v, view, viewer);
    364:       PetscCall(PetscViewerASCIIPopTab(viewer));
    365:     }
    366: #if defined(PETSC_HAVE_SAWS)
    367:   } else if (issaws) {
    368:     if (!((PetscObject)v)->amsmem) {
    369:       PetscCall(PetscObjectViewSAWs((PetscObject)v, viewer));
    370:       PetscTryTypeMethod(v, view, viewer);
    371:     }
    372: #endif
    373:   }
    374:   PetscFunctionReturn(PETSC_SUCCESS);
    375: }

    377: /*@C
    378:   PetscViewerRead - Reads data from a `PetscViewer`

    380:   Collective

    382:   Input Parameters:
    383: + viewer - The viewer
    384: . data   - Location to write the data, treated as an array of the type defined by `datatype`
    385: . num    - Number of items of data to read
    386: - dtype  - Type of data to read

    388:   Output Parameter:
    389: . count - number of items of data actually read, or `NULL`

    391:   Level: beginner

    393:   Notes:
    394:   If datatype is `PETSC_STRING` and `num` is negative, reads until a newline character is found,
    395:   until a maximum of (-num - 1) chars.

    397:   Only certain viewers, such as `PETSCVIEWERBINARY` can be read from, see `PetscViewerReadable()`

    399: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
    400:           `PetscViewerReadable()`, `PetscViewerBinaryGetDescriptor()`,
    401:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`
    402: @*/
    403: PetscErrorCode PetscViewerRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
    404: {
    405:   PetscFunctionBegin;
    407:   if (dtype == PETSC_STRING) {
    408:     PetscInt c, i = 0, cnt;
    409:     char    *s = (char *)data;
    410:     if (num >= 0) {
    411:       for (c = 0; c < num; c++) {
    412:         /* Skip leading whitespaces */
    413:         do {
    414:           PetscUseTypeMethod(viewer, read, &s[i], 1, &cnt, PETSC_CHAR);
    415:           if (!cnt) break;
    416:         } while (s[i] == '\n' || s[i] == '\t' || s[i] == ' ' || s[i] == '\0' || s[i] == '\v' || s[i] == '\f' || s[i] == '\r');
    417:         i++;
    418:         /* Read strings one char at a time */
    419:         do {
    420:           PetscUseTypeMethod(viewer, read, &s[i++], 1, &cnt, PETSC_CHAR);
    421:           if (!cnt) break;
    422:         } 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');
    423:         /* Terminate final string */
    424:         if (c == num - 1) s[i - 1] = '\0';
    425:       }
    426:     } else {
    427:       /* Read until a \n is encountered (-num is the max size allowed) */
    428:       do {
    429:         PetscUseTypeMethod(viewer, read, &s[i++], 1, &cnt, PETSC_CHAR);
    430:         if (i == -num || !cnt) break;
    431:       } while (s[i - 1] != '\n');
    432:       /* Terminate final string */
    433:       s[i - 1] = '\0';
    434:       c        = i;
    435:     }
    436:     if (count) *count = c;
    437:     else PetscCheck(c >= num, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_READ, "Insufficient data, only read %" PetscInt_FMT " < %" PetscInt_FMT " strings", c, num);
    438:   } else PetscUseTypeMethod(viewer, read, data, num, count, dtype);
    439:   PetscFunctionReturn(PETSC_SUCCESS);
    440: }

    442: /*@
    443:   PetscViewerReadable - Return a flag whether the viewer can be read from with `PetscViewerRead()`

    445:   Not Collective

    447:   Input Parameter:
    448: . viewer - the `PetscViewer` context

    450:   Output Parameter:
    451: . flg - `PETSC_TRUE` if the viewer is readable, `PETSC_FALSE` otherwise

    453:   Level: intermediate

    455:   Note:
    456:   `PETSC_TRUE` means that viewer's `PetscViewerType` supports reading, that is `PetscViewerRead()`, (this holds e.g. for `PETSCVIEWERBINARY`)
    457:   and the viewer is in a mode allowing reading, i.e. `PetscViewerFileGetMode()`
    458:   returns one of `FILE_MODE_READ`, `FILE_MODE_UPDATE`, `FILE_MODE_APPEND_UPDATE`.

    460: .seealso: [](sec_viewers), `PetscViewerRead()`, `PetscViewer`, `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
    461: @*/
    462: PetscErrorCode PetscViewerReadable(PetscViewer viewer, PetscBool *flg)
    463: {
    464:   PetscFileMode mode;
    465:   PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL;

    467:   PetscFunctionBegin;
    469:   PetscAssertPointer(flg, 2);
    470:   PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f));
    471:   *flg = PETSC_FALSE;
    472:   if (!f) PetscFunctionReturn(PETSC_SUCCESS);
    473:   PetscCall((*f)(viewer, &mode));
    474:   switch (mode) {
    475:   case FILE_MODE_READ:
    476:   case FILE_MODE_UPDATE:
    477:   case FILE_MODE_APPEND_UPDATE:
    478:     *flg = PETSC_TRUE;
    479:   default:
    480:     break;
    481:   }
    482:   PetscFunctionReturn(PETSC_SUCCESS);
    483: }

    485: /*@
    486:   PetscViewerWritable - Return a flag whether the viewer can be written to with `PetscViewerWrite()`

    488:   Not Collective

    490:   Input Parameter:
    491: . viewer - the `PetscViewer` context

    493:   Output Parameter:
    494: . flg - `PETSC_TRUE` if the viewer is writable, `PETSC_FALSE` otherwise

    496:   Level: intermediate

    498:   Note:
    499:   `PETSC_TRUE` means viewer is in a mode allowing writing, i.e. `PetscViewerFileGetMode()`
    500:   returns one of `FILE_MODE_WRITE`, `FILE_MODE_APPEND`, `FILE_MODE_UPDATE`, `FILE_MODE_APPEND_UPDATE`.

    502: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
    503: @*/
    504: PetscErrorCode PetscViewerWritable(PetscViewer viewer, PetscBool *flg)
    505: {
    506:   PetscFileMode mode;
    507:   PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL;

    509:   PetscFunctionBegin;
    511:   PetscAssertPointer(flg, 2);
    512:   PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f));
    513:   *flg = PETSC_TRUE;
    514:   if (!f) PetscFunctionReturn(PETSC_SUCCESS);
    515:   PetscCall((*f)(viewer, &mode));
    516:   if (mode == FILE_MODE_READ) *flg = PETSC_FALSE;
    517:   PetscFunctionReturn(PETSC_SUCCESS);
    518: }

    520: /*@
    521:   PetscViewerCheckReadable - Check whether the viewer can be read from, generates an error if not

    523:   Collective

    525:   Input Parameter:
    526: . viewer - the `PetscViewer` context

    528:   Level: intermediate

    530: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
    531: @*/
    532: PetscErrorCode PetscViewerCheckReadable(PetscViewer viewer)
    533: {
    534:   PetscBool flg;

    536:   PetscFunctionBegin;
    538:   PetscCall(PetscViewerReadable(viewer, &flg));
    539:   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)");
    540:   PetscFunctionReturn(PETSC_SUCCESS);
    541: }

    543: /*@
    544:   PetscViewerCheckWritable - Check whether the viewer can be written to, generates an error if not

    546:   Collective

    548:   Input Parameter:
    549: . viewer - the `PetscViewer` context

    551:   Level: intermediate

    553: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
    554: @*/
    555: PetscErrorCode PetscViewerCheckWritable(PetscViewer viewer)
    556: {
    557:   PetscBool flg;

    559:   PetscFunctionBegin;
    561:   PetscCall(PetscViewerWritable(viewer, &flg));
    562:   PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Viewer doesn't support writing, or is in FILE_MODE_READ mode");
    563:   PetscFunctionReturn(PETSC_SUCCESS);
    564: }