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