Actual source code: view.c


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

  5: PetscClassId PETSC_VIEWER_CLASSID;

  7: 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()`, `PetscViewerCreate()`, `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:   if ((*viewer)->ops->destroy) PetscCall((*(*viewer)->ops->destroy)(*viewer));
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()`, `PetscViewerAndFormatDestroy()`
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: /*@C
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:    Available Types Include:
179: +  `PETSCVIEWERSOCKET` - Socket `PetscViewer`
180: .  `PETSCVIEWERASCII` - ASCII `PetscViewer`
181: .  `PETSCVIEWERBINARY` - binary file `PetscViewer`
182: .  `PETSCVIEWERSTRING` - string `PetscViewer`
183: -  `PETSCVIEWERDRAW` - drawing `PetscViewer`

185:    Level: intermediate

187:    Note:
188:    `PetscViewerType` is actually a string

190: .seealso: [](sec_viewers), `PetscViewerType`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
191: @*/
192: PetscErrorCode PetscViewerGetType(PetscViewer viewer, PetscViewerType *type)
193: {
194:   PetscFunctionBegin;
197:   *type = ((PetscObject)viewer)->type_name;
198:   PetscFunctionReturn(PETSC_SUCCESS);
199: }

201: /*@C
202:    PetscViewerSetOptionsPrefix - Sets the prefix used for searching for
203:    `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.

205:    Logically Collective

207:    Input Parameters:
208: +  viewer - the `PetscViewer` context
209: -  prefix - the prefix to prepend to all option names

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

215:    Level: advanced

217: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerSetFromOptions()`, `PetscViewerAppendOptionsPrefix()`
218: @*/
219: PetscErrorCode PetscViewerSetOptionsPrefix(PetscViewer viewer, const char prefix[])
220: {
221:   PetscFunctionBegin;
223:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)viewer, prefix));
224:   PetscFunctionReturn(PETSC_SUCCESS);
225: }

227: /*@C
228:    PetscViewerAppendOptionsPrefix - Appends to the prefix used for searching for
229:    `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.

231:    Logically Collective

233:    Input Parameters:
234: +  viewer - the `PetscViewer` context
235: -  prefix - the prefix to prepend to all option names

237:    Level: advanced

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

243: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerGetOptionsPrefix()`, `PetscViewerSetOptionsPrefix()`
244: @*/
245: PetscErrorCode PetscViewerAppendOptionsPrefix(PetscViewer viewer, const char prefix[])
246: {
247:   PetscFunctionBegin;
249:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)viewer, prefix));
250:   PetscFunctionReturn(PETSC_SUCCESS);
251: }

253: /*@C
254:    PetscViewerGetOptionsPrefix - Gets the prefix used for searching for
255:    `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.

257:    Not Collective

259:    Input Parameter:
260: .  viewer - the `PetscViewer` context

262:    Output Parameter:
263: .  prefix - pointer to the prefix string used

265:    Level: advanced

267:    Fortran Note:
268:    The user should pass in a string 'prefix' of sufficient length to hold the prefix.

270: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerAppendOptionsPrefix()`, `PetscViewerSetOptionsPrefix()`
271: @*/
272: PetscErrorCode PetscViewerGetOptionsPrefix(PetscViewer viewer, const char *prefix[])
273: {
274:   PetscFunctionBegin;
276:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)viewer, prefix));
277:   PetscFunctionReturn(PETSC_SUCCESS);
278: }

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

283:    Collective

285:    Input Parameter:
286: .  viewer - the `PetscViewer` context

288:    Level: advanced

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

294: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`
295: @*/
296: PetscErrorCode PetscViewerSetUp(PetscViewer viewer)
297: {
298:   PetscFunctionBegin;
300:   if (viewer->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
301:   PetscTryTypeMethod(viewer, setup);
302:   viewer->setupcalled = PETSC_TRUE;
303:   PetscFunctionReturn(PETSC_SUCCESS);
304: }

306: /*@C
307:    PetscViewerViewFromOptions - View from the viewer based on options in the options database

309:    Collective

311:    Input Parameters:
312: +  A - the `PetscViewer` context
313: .  obj - Optional object that provides the prefix for the option names
314: -  name - command line option

316:    Level: intermediate

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

321: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerView`, `PetscObjectViewFromOptions()`, `PetscViewerCreate()`
322: @*/
323: PetscErrorCode PetscViewerViewFromOptions(PetscViewer A, PetscObject obj, const char name[])
324: {
325:   PetscFunctionBegin;
327:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
328:   PetscFunctionReturn(PETSC_SUCCESS);
329: }

331: /*@C
332:    PetscViewerView - Visualizes a viewer object.

334:    Collective

336:    Input Parameters:
337: +  v - the viewer to be viewed
338: -  viewer - visualization context

340:    Level: beginner

342: .seealso: [](sec_viewers), `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

353:   PetscFunctionBegin;
356:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)v), &viewer));
358:   PetscCheckSameComm(v, 1, viewer, 2);

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

384: /*@C
385:    PetscViewerRead - Reads data from a `PetscViewer`

387:    Collective

389:    Input Parameters:
390: +  viewer   - The viewer
391: .  data     - Location to write the data, treated as an array of the type defined by `datatype`
392: .  num      - Number of items of data to read
393: -  datatype - Type of data to read

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

398:    Level: beginner

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

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

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

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

452:    Not Collective

454:    Input Parameter:
455: .  viewer - the `PetscViewer` context

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

460:    Level: intermediate

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

467: .seealso: [](sec_viewers), `PetscViewerRead()`, `PetscViewer`, `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
468: @*/
469: PetscErrorCode PetscViewerReadable(PetscViewer viewer, PetscBool *flg)
470: {
471:   PetscFileMode mode;
472:   PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL;

474:   PetscFunctionBegin;
477:   PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f));
478:   *flg = PETSC_FALSE;
479:   if (!f) PetscFunctionReturn(PETSC_SUCCESS);
480:   PetscCall((*f)(viewer, &mode));
481:   switch (mode) {
482:   case FILE_MODE_READ:
483:   case FILE_MODE_UPDATE:
484:   case FILE_MODE_APPEND_UPDATE:
485:     *flg = PETSC_TRUE;
486:   default:
487:     break;
488:   }
489:   PetscFunctionReturn(PETSC_SUCCESS);
490: }

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

495:    Not Collective

497:    Input Parameter:
498: .  viewer - the `PetscViewer` context

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

503:    Level: intermediate

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

509: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
510: @*/
511: PetscErrorCode PetscViewerWritable(PetscViewer viewer, PetscBool *flg)
512: {
513:   PetscFileMode mode;
514:   PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL;

516:   PetscFunctionBegin;
519:   PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f));
520:   *flg = PETSC_TRUE;
521:   if (!f) PetscFunctionReturn(PETSC_SUCCESS);
522:   PetscCall((*f)(viewer, &mode));
523:   if (mode == FILE_MODE_READ) *flg = PETSC_FALSE;
524:   PetscFunctionReturn(PETSC_SUCCESS);
525: }

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

530:    Collective

532:    Input Parameter:
533: .  viewer - the `PetscViewer` context

535:    Level: intermediate

537: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
538: @*/
539: PetscErrorCode PetscViewerCheckReadable(PetscViewer viewer)
540: {
541:   PetscBool flg;

543:   PetscFunctionBegin;
545:   PetscCall(PetscViewerReadable(viewer, &flg));
546:   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)");
547:   PetscFunctionReturn(PETSC_SUCCESS);
548: }

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

553:    Collective

555:    Input Parameter:
556: .  viewer - the `PetscViewer` context

558:    Level: intermediate

560: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
561: @*/
562: PetscErrorCode PetscViewerCheckWritable(PetscViewer viewer)
563: {
564:   PetscBool flg;

566:   PetscFunctionBegin;
568:   PetscCall(PetscViewerWritable(viewer, &flg));
569:   PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Viewer doesn't support writing, or is in FILE_MODE_READ mode");
570:   PetscFunctionReturn(PETSC_SUCCESS);
571: }