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