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