xref: /petsc/src/sys/classes/viewer/interface/view.c (revision 7de69702b957b5de648b60762d01f4e5276d32ac)
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 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()`, `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.
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)->lg     = NULL;
141   (*vf)->data   = NULL;
142   PetscFunctionReturn(PETSC_SUCCESS);
143 }
144 
145 /*@C
146    PetscViewerAndFormatDestroy - Destroys a `PetscViewerAndFormat` struct created with `PetscViewerAndFormatCreate()`
147 
148    Collective
149 
150    Input Parameter:
151 .  vf - the `PetscViewerAndFormat` to be destroyed.
152 
153    Level: developer
154 
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 }
166 
167 /*@C
168    PetscViewerGetType - Returns the type of a `PetscViewer`.
169 
170    Not Collective
171 
172    Input Parameter:
173 .   viewer - the `PetscViewer`
174 
175    Output Parameter:
176 .  type - `PetscViewerType`
177 
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`
184 
185    Level: intermediate
186 
187    Note:
188    `PetscViewerType` is actually a string
189 
190 .seealso: [](sec_viewers), `PetscViewerType`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
191 @*/
192 PetscErrorCode PetscViewerGetType(PetscViewer viewer, PetscViewerType *type)
193 {
194   PetscFunctionBegin;
195   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
196   PetscValidPointer(type, 2);
197   *type = ((PetscObject)viewer)->type_name;
198   PetscFunctionReturn(PETSC_SUCCESS);
199 }
200 
201 /*@C
202    PetscViewerSetOptionsPrefix - Sets the prefix used for searching for
203    `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.
204 
205    Logically Collective
206 
207    Input Parameters:
208 +  viewer - the `PetscViewer` context
209 -  prefix - the prefix to prepend to all option names
210 
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.
214 
215    Level: advanced
216 
217 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerSetFromOptions()`, `PetscViewerAppendOptionsPrefix()`
218 @*/
219 PetscErrorCode PetscViewerSetOptionsPrefix(PetscViewer viewer, const char prefix[])
220 {
221   PetscFunctionBegin;
222   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
223   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)viewer, prefix));
224   PetscFunctionReturn(PETSC_SUCCESS);
225 }
226 
227 /*@C
228    PetscViewerAppendOptionsPrefix - Appends to the prefix used for searching for
229    `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.
230 
231    Logically Collective
232 
233    Input Parameters:
234 +  viewer - the `PetscViewer` context
235 -  prefix - the prefix to prepend to all option names
236 
237    Level: advanced
238 
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.
242 
243 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerGetOptionsPrefix()`, `PetscViewerSetOptionsPrefix()`
244 @*/
245 PetscErrorCode PetscViewerAppendOptionsPrefix(PetscViewer viewer, const char prefix[])
246 {
247   PetscFunctionBegin;
248   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
249   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)viewer, prefix));
250   PetscFunctionReturn(PETSC_SUCCESS);
251 }
252 
253 /*@C
254    PetscViewerGetOptionsPrefix - Gets the prefix used for searching for
255    `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.
256 
257    Not Collective
258 
259    Input Parameter:
260 .  viewer - the `PetscViewer` context
261 
262    Output Parameter:
263 .  prefix - pointer to the prefix string used
264 
265    Level: advanced
266 
267    Fortran Note:
268    The user should pass in a string 'prefix' of sufficient length to hold the prefix.
269 
270 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerAppendOptionsPrefix()`, `PetscViewerSetOptionsPrefix()`
271 @*/
272 PetscErrorCode PetscViewerGetOptionsPrefix(PetscViewer viewer, const char *prefix[])
273 {
274   PetscFunctionBegin;
275   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
276   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)viewer, prefix));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281    PetscViewerSetUp - Sets up the internal viewer data structures for the later use.
282 
283    Collective
284 
285    Input Parameter:
286 .  viewer - the `PetscViewer` context
287 
288    Level: advanced
289 
290    Note:
291    For basic use of the `PetscViewer` classes the user need not explicitly call
292    `PetscViewerSetUp()`, since these actions will happen automatically.
293 
294 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`
295 @*/
296 PetscErrorCode PetscViewerSetUp(PetscViewer viewer)
297 {
298   PetscFunctionBegin;
299   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
300   if (viewer->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
301   PetscTryTypeMethod(viewer, setup);
302   viewer->setupcalled = PETSC_TRUE;
303   PetscFunctionReturn(PETSC_SUCCESS);
304 }
305 
306 /*@C
307    PetscViewerViewFromOptions - View from the viewer based on options in the options database
308 
309    Collective
310 
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
315 
316    Level: intermediate
317 
318    Note:
319    See `PetscObjectViewFromOptions()` for details on the viewers and formats support via this interface
320 
321 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerView`, `PetscObjectViewFromOptions()`, `PetscViewerCreate()`
322 @*/
323 PetscErrorCode PetscViewerViewFromOptions(PetscViewer A, PetscObject obj, const char name[])
324 {
325   PetscFunctionBegin;
326   PetscValidHeaderSpecific(A, PETSC_VIEWER_CLASSID, 1);
327   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
328   PetscFunctionReturn(PETSC_SUCCESS);
329 }
330 
331 /*@C
332    PetscViewerView - Visualizes a viewer object.
333 
334    Collective
335 
336    Input Parameters:
337 +  v - the viewer to be viewed
338 -  viewer - visualization context
339 
340    Level: beginner
341 
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
352 
353   PetscFunctionBegin;
354   PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1);
355   PetscValidType(v, 1);
356   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)v), &viewer));
357   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
358   PetscCheckSameComm(v, 1, viewer, 2);
359 
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 }
383 
384 /*@C
385    PetscViewerRead - Reads data from a `PetscViewer`
386 
387    Collective
388 
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
394 
395    Output Parameter:
396 .  count - number of items of data actually read, or `NULL`
397 
398    Level: beginner
399 
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.
403 
404    Only certain viewers, such as `PETSCVIEWERBINARY` can be read from, see `PetscViewerReadable()`
405 
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;
413   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
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 }
448 
449 /*@
450    PetscViewerReadable - Return a flag whether the viewer can be read from with `PetscViewerRead()`
451 
452    Not Collective
453 
454    Input Parameter:
455 .  viewer - the `PetscViewer` context
456 
457    Output Parameter:
458 .  flg - `PETSC_TRUE` if the viewer is readable, `PETSC_FALSE` otherwise
459 
460    Level: intermediate
461 
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`.
466 
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;
473 
474   PetscFunctionBegin;
475   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
476   PetscValidBoolPointer(flg, 2);
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 }
491 
492 /*@
493    PetscViewerWritable - Return a flag whether the viewer can be written to with `PetscViewerWrite()`
494 
495    Not Collective
496 
497    Input Parameter:
498 .  viewer - the `PetscViewer` context
499 
500    Output Parameter:
501 .  flg - `PETSC_TRUE` if the viewer is writable, `PETSC_FALSE` otherwise
502 
503    Level: intermediate
504 
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`.
508 
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;
515 
516   PetscFunctionBegin;
517   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
518   PetscValidBoolPointer(flg, 2);
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 }
526 
527 /*@
528    PetscViewerCheckReadable - Check whether the viewer can be read from, generates an error if not
529 
530    Collective
531 
532    Input Parameter:
533 .  viewer - the `PetscViewer` context
534 
535    Level: intermediate
536 
537 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
538 @*/
539 PetscErrorCode PetscViewerCheckReadable(PetscViewer viewer)
540 {
541   PetscBool flg;
542 
543   PetscFunctionBegin;
544   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
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 }
549 
550 /*@
551    PetscViewerCheckWritable - Check whether the viewer can be written to, generates an error if not
552 
553    Collective
554 
555    Input Parameter:
556 .  viewer - the `PetscViewer` context
557 
558    Level: intermediate
559 
560 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
561 @*/
562 PetscErrorCode PetscViewerCheckWritable(PetscViewer viewer)
563 {
564   PetscBool flg;
565 
566   PetscFunctionBegin;
567   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
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 }
572