Actual source code: view.c

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

  3: PetscClassId PETSC_VIEWER_CLASSID;

  5: static PetscBool PetscViewerPackageInitialized = PETSC_FALSE;

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

 11:   Level: developer

 13: .seealso: [](sec_viewers), `PetscViewer`, `PetscFinalize()`, `PetscViewerInitializePackage()`
 14: @*/
 15: PetscErrorCode PetscViewerFinalizePackage(void)
 16: {
 17:   PetscFunctionBegin;
 18:   if (Petsc_Viewer_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_keyval));
 19:   if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Stdout_keyval));
 20:   if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Stderr_keyval));
 21:   if (Petsc_Viewer_Binary_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Binary_keyval));
 22:   if (Petsc_Viewer_Draw_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Draw_keyval));
 23: #if PetscDefined(HAVE_HDF5)
 24:   if (Petsc_Viewer_HDF5_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_HDF5_keyval));
 25: #endif
 26: #if PetscDefined(USE_SOCKETVIEWER)
 27:   if (Petsc_Viewer_Socket_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Socket_keyval));
 28: #endif
 29:   PetscCall(PetscFunctionListDestroy(&PetscViewerList));
 30:   PetscViewerPackageInitialized = PETSC_FALSE;
 31:   PetscViewerRegisterAllCalled  = PETSC_FALSE;
 32:   PetscFunctionReturn(PETSC_SUCCESS);
 33: }

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

 38:   Level: developer

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

 47:   PetscFunctionBegin;
 48:   if (PetscViewerPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
 49:   PetscViewerPackageInitialized = PETSC_TRUE;
 50:   /* Register Classes */
 51:   PetscCall(PetscClassIdRegister("Viewer", &PETSC_VIEWER_CLASSID));
 52:   /* Register Constructors */
 53:   PetscCall(PetscViewerRegisterAll());
 54:   /* Process Info */
 55:   {
 56:     PetscClassId classids[1];

 58:     classids[0] = PETSC_VIEWER_CLASSID;
 59:     PetscCall(PetscInfoProcessClass("viewer", 1, classids));
 60:   }
 61:   /* Process summary exclusions */
 62:   PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt));
 63:   if (opt) {
 64:     PetscCall(PetscStrInList("viewer", logList, ',', &pkg));
 65:     if (pkg) PetscCall(PetscLogEventExcludeClass(PETSC_VIEWER_CLASSID));
 66:   }
 67: #if PetscDefined(HAVE_MATHEMATICA)
 68:   PetscCall(PetscViewerMathematicaInitializePackage());
 69: #endif
 70:   /* Register package finalizer */
 71:   PetscCall(PetscRegisterFinalize(PetscViewerFinalizePackage));
 72:   PetscFunctionReturn(PETSC_SUCCESS);
 73: }

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

 78:   Collective

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

 83:   Level: beginner

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

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

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

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

108:   Collective

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

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

117:   Level: developer

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

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

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

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

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

143: /*@
144:   PetscViewerAndFormatDestroy - Destroys a `PetscViewerAndFormat` struct created with `PetscViewerAndFormatCreate()`

146:   Collective

148:   Input Parameter:
149: . vf - the `PetscViewerAndFormat` to be destroyed.

151:   Level: developer

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

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

169:   Not Collective

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

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

177:   Level: intermediate

179:   Note:
180:   `type` should not be retained for later use as it will be an invalid pointer if the `PetscViewerType` of `viewer` is changed.

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

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

197:   Logically Collective

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

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

207:   Level: advanced

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

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

223:   Logically Collective

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

229:   Level: advanced

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

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

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

249:   Not Collective

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

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

257:   Level: advanced

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

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

272:   Collective

274:   Input Parameter:
275: . viewer - the `PetscViewer` context

277:   Level: advanced

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

283: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`
284: @*/
285: PetscErrorCode PetscViewerSetUp(PetscViewer viewer)
286: {
287:   PetscFunctionBegin;
289:   if (viewer->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
290:   PetscTryTypeMethod(viewer, setup);
291:   viewer->setupcalled = PETSC_TRUE;
292:   PetscFunctionReturn(PETSC_SUCCESS);
293: }

295: /*@
296:   PetscViewerViewFromOptions - View from the viewer based on options in the options database

298:   Collective

300:   Input Parameters:
301: + A    - the `PetscViewer` context
302: . obj  - optional object that provides the prefix for the option names, pass `NULL` to use the options prefix of `A`
303: - name - command line option

305:   Options Database Key:
306: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`

308:   Level: intermediate

310:   Note:
311:   This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
312:   rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.

314: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerView()`, `PetscObjectViewFromOptions()`, `PetscViewerCreate()`, `PetscOptionsCreateViewer()`
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         isascii;
341:   PetscViewerFormat format;
342: #if PetscDefined(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, &isascii));
354: #if PetscDefined(HAVE_SAWS)
355:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
356: #endif
357:   if (isascii) {
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 PetscDefined(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: /*@
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: }