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