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