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