xref: /petsc/src/sys/classes/viewer/interface/viewreg.c (revision 19532ea364b07ecd049071e360c10aa6fe9ed42f)
1 
2 #include <petsc/private/viewerimpl.h>  /*I "petscviewer.h" I*/
3 #include <petsc/private/hash.h>
4 #if defined(PETSC_HAVE_SAWS)
5 #include <petscviewersaws.h>
6 #endif
7 
8 PetscFunctionList PetscViewerList = 0;
9 
10 
11 PetscOptionsHelpPrinted PetscOptionsHelpPrintedSingleton = NULL;
12 KHASH_SET_INIT_STR(HTPrinted)
13 struct  _n_PetscOptionsHelpPrinted{
14   khash_t(HTPrinted) *printed;
15   PetscSegBuffer     strings;
16 };
17 
18 PetscErrorCode PetscOptionsHelpPrintedDestroy(PetscOptionsHelpPrinted *hp)
19 {
20   PetscErrorCode ierr;
21 
22   PetscFunctionBegin;
23   if (!*hp) PetscFunctionReturn(0);
24   kh_destroy(HTPrinted,(*hp)->printed);
25   ierr = PetscSegBufferDestroy(&(*hp)->strings);CHKERRQ(ierr);
26   ierr = PetscFree(*hp);CHKERRQ(ierr);
27   PetscFunctionReturn(0);
28 }
29 
30 /*@C
31       PetscOptionsHelpPrintedCreate - Creates an object used to manage tracking which help messages have
32          been printed so they will not be printed again.
33 
34      Not collective
35 
36     Level: developer
37 
38 .seealso: PetscOptionsHelpPrintedCheck(), PetscOptionsHelpPrintChecked()
39 @*/
40 PetscErrorCode PetscOptionsHelpPrintedCreate(PetscOptionsHelpPrinted *hp)
41 {
42   PetscErrorCode             ierr;
43 
44   PetscFunctionBegin;
45   ierr = PetscNew(hp);CHKERRQ(ierr);
46   (*hp)->printed = kh_init(HTPrinted);
47   ierr = PetscSegBufferCreate(sizeof(char),10000,&(*hp)->strings);CHKERRQ(ierr);
48   PetscFunctionReturn(0);
49 }
50 
51 /*@C
52       PetscOptionsHelpPrintedCheck - Checks if a particular pre, name pair has previous been entered (meaning the help message was printed)
53 
54      Not collective
55 
56     Input Parameters:
57 +     hp - the object used to manage tracking what help messages have been printed
58 .     pre - the prefix part of the string, many be NULL
59 -     name - the string to look for (cannot be NULL)
60 
61     Output Parameter:
62 .     found - PETSC_TRUE if the string was already set
63 
64     Level: intermediate
65 
66 
67 .seealso: PetscOptionsHelpPrintedCreate()
68 @*/
69 PetscErrorCode PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrinted hp,const char *pre,const char* name,PetscBool *found)
70 {
71   size_t          l1,l2;
72 #if !defined(PETSC_HAVE_THREADSAFETY)
73   char            *both;
74   khint_t         newitem;
75 #endif
76   PetscErrorCode  ierr;
77 
78   PetscFunctionBegin;
79   ierr = PetscStrlen(pre,&l1);CHKERRQ(ierr);
80   ierr = PetscStrlen(name,&l2);CHKERRQ(ierr);
81   if (l1+l2 == 0) {
82     *found = PETSC_FALSE;
83     PetscFunctionReturn(0);
84   }
85 #if !defined(PETSC_HAVE_THREADSAFETY)
86   ierr = PetscSegBufferGet(hp->strings,l1+l2+1,&both);CHKERRQ(ierr);
87   ierr = PetscStrcpy(both,pre);CHKERRQ(ierr);
88   ierr = PetscStrcat(both,name);CHKERRQ(ierr);
89   kh_put(HTPrinted,hp->printed,both,&newitem);
90   if (!newitem) {
91     ierr = PetscSegBufferUnuse(hp->strings,l1+l2+1);CHKERRQ(ierr);
92   }
93   *found = newitem ? PETSC_FALSE : PETSC_TRUE;
94 #else
95   *found = PETSC_FALSE;
96 #endif
97   PetscFunctionReturn(0);
98 }
99 
100 static PetscBool noviewer = PETSC_FALSE;
101 static PetscBool noviewers[PETSCVIEWERGETVIEWEROFFPUSHESMAX];
102 static PetscInt  inoviewers = 0;
103 
104 /*@
105   PetscOptionsPushGetViewerOff - control whether PetscOptionsGetViewer returns a viewer.
106 
107   Logically Collective
108 
109   Input Parameter:
110 . flg - PETSC_TRUE to turn off viewer creation, PETSC_FALSE to turn it on.
111 
112   Level: developer
113 
114   Notes: Calling XXXViewFromOptions in an inner loop can be very expensive.  This can appear, for example, when using
115    many small subsolves.  Call this function to control viewer creation in PetscOptionsGetViewer, thus removing the expensive XXXViewFromOptions calls.
116 
117 .seealso: PetscOptionsGetViewer(), PetscOptionsPopGetViewerOff()
118 @*/
119 PetscErrorCode  PetscOptionsPushGetViewerOff(PetscBool flg)
120 {
121   PetscFunctionBegin;
122   if (inoviewers > PETSCVIEWERGETVIEWEROFFPUSHESMAX - 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many PetscOptionsPushGetViewerOff(), perhaps you forgot PetscOptionsPopGetViewerOff()?");
123 
124   noviewers[inoviewers++] = noviewer;
125   noviewer = flg;
126   PetscFunctionReturn(0);
127 }
128 
129 /*@
130   PetscOptionsPopGetViewerOff - reset whether PetscOptionsGetViewer returns a viewer.
131 
132   Logically Collective
133 
134   Level: developer
135 
136   Notes: Calling XXXViewFromOptions in an inner loop can be very expensive.  This can appear, for example, when using
137    many small subsolves.  Call this function to control viewer creation in PetscOptionsGetViewer, thus removing the expensive XXXViewFromOptions calls.
138 
139 .seealso: PetscOptionsGetViewer(), PetscOptionsPushGetViewerOff()
140 @*/
141 PetscErrorCode  PetscOptionsPopGetViewerOff(void)
142 {
143   PetscFunctionBegin;
144   if (!inoviewers) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many PetscOptionsPopGetViewerOff(), perhaps you forgot PetscOptionsPushGetViewerOff()?");
145   noviewer = noviewers[--inoviewers];
146   PetscFunctionReturn(0);
147 }
148 
149 /*@
150   PetscOptionsGetViewerOff - does PetscOptionsGetViewer return a viewer?
151 
152   Logically Collective
153 
154   Output Parameter:
155 . flg - whether viewers are returned.
156 
157   Level: developer
158 
159   Notes: Calling XXXViewFromOptions in an inner loop can be very expensive.  This can appear, for example, when using
160    many small subsolves.
161 
162 .seealso: PetscOptionsGetViewer(), PetscOptionsPushGetViewerOff(), PetscOptionsPopGetViewerOff()
163 @*/
164 PetscErrorCode  PetscOptionsGetViewerOff(PetscBool *flg)
165 {
166   PetscFunctionBegin;
167   PetscValidPointer(flg,0);
168   *flg = noviewer;
169   PetscFunctionReturn(0);
170 }
171 
172 /*@C
173    PetscOptionsGetViewer - Gets a viewer appropriate for the type indicated by the user
174 
175    Collective on MPI_Comm
176 
177    Input Parameters:
178 +  comm - the communicator to own the viewer
179 .  pre - the string to prepend to the name or NULL
180 -  name - the option one is seeking
181 
182    Output Parameter:
183 +  viewer - the viewer, pass NULL if not needed
184 .  format - the PetscViewerFormat requested by the user, pass NULL if not needed
185 -  set - PETSC_TRUE if found, else PETSC_FALSE
186 
187    Level: intermediate
188 
189    Notes: If no value is provided ascii:stdout is used
190 $       ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
191                                                   for example ascii::ascii_info prints just the information about the object not all details
192                                                   unless :append is given filename opens in write mode, overwriting what was already there
193 $       binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
194 $       draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
195 $       socket[:port]                             defaults to the standard output port
196 $       saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
197 
198    Use PetscViewerDestroy() after using the viewer, otherwise a memory leak will occur
199 
200    You can control whether calls to this function create a viewer (or return early with *set of PETSC_FALSE) with
201    PetscOptionsPushGetViewerOff.  This is useful if calling many small subsolves, in which case XXXViewFromOptions can take
202    an appreciable fraction of the runtime.
203 
204    If PETSc is configured with --with-viewfromoptions=0 this function always returns with *set of PETSC_FALSE
205 
206 .seealso: PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(),
207           PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool()
208           PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(),
209           PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(),
210           PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(),
211           PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(),
212           PetscOptionsFList(), PetscOptionsEList(), PetscOptionsPushGetViewerOff(), PetscOptionsPopGetViewerOff(),
213           PetscOptionsGetViewerOff()
214 @*/
215 PetscErrorCode  PetscOptionsGetViewer(MPI_Comm comm,const char pre[],const char name[],PetscViewer *viewer,PetscViewerFormat *format,PetscBool  *set)
216 {
217   char                           *value;
218   PetscErrorCode                 ierr;
219   PetscBool                      flag,hashelp;
220 
221   PetscFunctionBegin;
222   PetscValidCharPointer(name,3);
223 
224   if (set) *set = PETSC_FALSE;
225 #if defined(PETSC_SKIP_VIEWFROMOPTIONS)
226   PetscFunctionReturn(0);
227 #endif
228   ierr = PetscOptionsGetViewerOff(&flag);CHKERRQ(ierr);
229   if (flag) PetscFunctionReturn(0);
230 
231   ierr = PetscOptionsHasName(NULL,NULL,"-help",&hashelp);CHKERRQ(ierr);
232   if (hashelp) {
233     PetscBool found;
234 
235     if (!PetscOptionsHelpPrintedSingleton) {
236       ierr = PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton);CHKERRQ(ierr);
237     }
238     ierr = PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton,pre,name,&found);CHKERRQ(ierr);
239     if (!found) {
240       if (viewer) {
241         ierr = (*PetscHelpPrintf)(comm,"\n  -%s%s ascii[:[filename][:[format][:append]]]: %s (%s)\n",pre ? pre : "",name+1,"Prints object to stdout or ASCII file","PetscOptionsGetViewer");CHKERRQ(ierr);
242         ierr = (*PetscHelpPrintf)(comm,"    -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n",pre ? pre : "",name+1,"Saves object to a binary file","PetscOptionsGetViewer");CHKERRQ(ierr);
243         ierr = (*PetscHelpPrintf)(comm,"    -%s%s draw[:drawtype[:filename]] %s (%s)\n",pre ? pre : "",name+1,"Draws object","PetscOptionsGetViewer");CHKERRQ(ierr);
244         ierr = (*PetscHelpPrintf)(comm,"    -%s%s socket[:port]: %s (%s)\n",pre ? pre : "",name+1,"Pushes object to a Unix socket","PetscOptionsGetViewer");CHKERRQ(ierr);
245         ierr = (*PetscHelpPrintf)(comm,"    -%s%s saws[:communicatorname]: %s (%s)\n\n",pre ? pre : "",name+1,"Publishes object to SAWs","PetscOptionsGetViewer");CHKERRQ(ierr);
246       } else {
247         ierr = (*PetscHelpPrintf)(comm,"    -%s%s\n",pre ? pre : "",name+1);CHKERRQ(ierr);
248       }
249     }
250   }
251 
252   if (format) *format = PETSC_VIEWER_DEFAULT;
253   ierr = PetscOptionsFindPair_Private(NULL,pre,name,&value,&flag);CHKERRQ(ierr);
254   if (flag) {
255     if (set) *set = PETSC_TRUE;
256     if (!value) {
257       if (viewer) {
258         ierr = PetscViewerASCIIGetStdout(comm,viewer);CHKERRQ(ierr);
259         ierr = PetscObjectReference((PetscObject)*viewer);CHKERRQ(ierr);
260       }
261     } else {
262       char       *loc0_vtype,*loc1_fname,*loc2_fmt = NULL,*loc3_fmode = NULL;
263       PetscInt   cnt;
264       const char *viewers[] = {PETSCVIEWERASCII,PETSCVIEWERBINARY,PETSCVIEWERDRAW,PETSCVIEWERSOCKET,PETSCVIEWERMATLAB,PETSCVIEWERSAWS,PETSCVIEWERVTK,PETSCVIEWERHDF5,0};
265 
266       ierr = PetscStrallocpy(value,&loc0_vtype);CHKERRQ(ierr);
267       ierr = PetscStrchr(loc0_vtype,':',&loc1_fname);CHKERRQ(ierr);
268       if (loc1_fname) {
269         *loc1_fname++ = 0;
270         ierr = PetscStrchr(loc1_fname,':',&loc2_fmt);CHKERRQ(ierr);
271       }
272       if (loc2_fmt) {
273         *loc2_fmt++ = 0;
274         ierr = PetscStrchr(loc2_fmt,':',&loc3_fmode);CHKERRQ(ierr);
275       }
276       if (loc3_fmode) *loc3_fmode++ = 0;
277       ierr = PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii",viewers,&cnt);CHKERRQ(ierr);
278       if (cnt > (PetscInt) sizeof(viewers)-1) SETERRQ1(comm,PETSC_ERR_ARG_OUTOFRANGE,"Unknown viewer type: %s",loc0_vtype);
279       if (viewer) {
280         if (!loc1_fname) {
281           switch (cnt) {
282           case 0:
283             ierr = PetscViewerASCIIGetStdout(comm,viewer);CHKERRQ(ierr);
284             break;
285           case 1:
286             if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) CHKERRQ(PETSC_ERR_PLIB);
287             break;
288           case 2:
289             if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) CHKERRQ(PETSC_ERR_PLIB);
290             break;
291 #if defined(PETSC_USE_SOCKET_VIEWER)
292           case 3:
293             if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) CHKERRQ(PETSC_ERR_PLIB);
294             break;
295 #endif
296 #if defined(PETSC_HAVE_MATLAB_ENGINE)
297           case 4:
298             if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) CHKERRQ(PETSC_ERR_PLIB);
299             break;
300 #endif
301 #if defined(PETSC_HAVE_SAWS)
302           case 5:
303             if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) CHKERRQ(PETSC_ERR_PLIB);
304             break;
305 #endif
306 #if defined(PETSC_HAVE_HDF5)
307           case 7:
308             if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) CHKERRQ(PETSC_ERR_PLIB);
309             break;
310 #endif
311           default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported viewer %s",loc0_vtype);
312           }
313           ierr = PetscObjectReference((PetscObject)*viewer);CHKERRQ(ierr);
314         } else {
315           if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
316             ierr = PetscViewerASCIIGetStdout(comm,viewer);CHKERRQ(ierr);
317             ierr = PetscObjectReference((PetscObject)*viewer);CHKERRQ(ierr);
318           } else {
319             PetscFileMode fmode;
320             ierr = PetscViewerCreate(comm,viewer);CHKERRQ(ierr);
321             ierr = PetscViewerSetType(*viewer,*loc0_vtype ? loc0_vtype : "ascii");CHKERRQ(ierr);
322             fmode = FILE_MODE_WRITE;
323             if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
324               ierr = PetscEnumFind(PetscFileModes,loc3_fmode,(PetscEnum*)&fmode,&flag);CHKERRQ(ierr);
325               if (!flag) SETERRQ1(comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown file mode: %s",loc3_fmode);
326             }
327             if (loc2_fmt) {
328               PetscBool tk;
329               ierr = PetscStrcmp(loc1_fname,"tikz",&tk);CHKERRQ(ierr);
330               if (tk) {
331                 ierr = PetscViewerDrawSetInfo(*viewer,NULL,loc2_fmt,0,0,0,0);CHKERRQ(ierr);
332                 *loc2_fmt = 0;
333               }
334             }
335             ierr = PetscViewerFileSetMode(*viewer,flag?fmode:FILE_MODE_WRITE);CHKERRQ(ierr);
336             ierr = PetscViewerFileSetName(*viewer,loc1_fname);CHKERRQ(ierr);
337             ierr = PetscViewerDrawSetDrawType(*viewer,loc1_fname);CHKERRQ(ierr);
338           }
339         }
340       }
341       if (viewer) {
342         ierr = PetscViewerSetUp(*viewer);CHKERRQ(ierr);
343       }
344       if (loc2_fmt && *loc2_fmt) {
345         ierr = PetscEnumFind(PetscViewerFormats,loc2_fmt,(PetscEnum*)format,&flag);CHKERRQ(ierr);
346         if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer format %s",loc2_fmt);CHKERRQ(ierr);
347       }
348       ierr = PetscFree(loc0_vtype);CHKERRQ(ierr);
349     }
350   }
351   PetscFunctionReturn(0);
352 }
353 
354 /*@
355    PetscViewerCreate - Creates a viewing context
356 
357    Collective on MPI_Comm
358 
359    Input Parameter:
360 .  comm - MPI communicator
361 
362    Output Parameter:
363 .  inviewer - location to put the PetscViewer context
364 
365    Level: advanced
366 
367    Concepts: graphics^creating PetscViewer
368    Concepts: file input/output^creating PetscViewer
369    Concepts: sockets^creating PetscViewer
370 
371 .seealso: PetscViewerDestroy(), PetscViewerSetType(), PetscViewerType
372 
373 @*/
374 PetscErrorCode  PetscViewerCreate(MPI_Comm comm,PetscViewer *inviewer)
375 {
376   PetscViewer    viewer;
377   PetscErrorCode ierr;
378 
379   PetscFunctionBegin;
380   *inviewer = 0;
381   ierr = PetscViewerInitializePackage();CHKERRQ(ierr);
382   ierr         = PetscHeaderCreate(viewer,PETSC_VIEWER_CLASSID,"PetscViewer","PetscViewer","Viewer",comm,PetscViewerDestroy,NULL);CHKERRQ(ierr);
383   *inviewer    = viewer;
384   viewer->data = 0;
385   PetscFunctionReturn(0);
386 }
387 
388 /*@C
389    PetscViewerSetType - Builds PetscViewer for a particular implementation.
390 
391    Collective on PetscViewer
392 
393    Input Parameter:
394 +  viewer      - the PetscViewer context
395 -  type        - for example, PETSCVIEWERASCII
396 
397    Options Database Command:
398 .  -draw_type  <type> - Sets the type; use -help for a list
399     of available methods (for instance, ascii)
400 
401    Level: advanced
402 
403    Notes:
404    See "include/petscviewer.h" for available methods (for instance,
405    PETSCVIEWERSOCKET)
406 
407 .seealso: PetscViewerCreate(), PetscViewerGetType(), PetscViewerType, PetscViewerPushFormat()
408 @*/
409 PetscErrorCode  PetscViewerSetType(PetscViewer viewer,PetscViewerType type)
410 {
411   PetscErrorCode ierr,(*r)(PetscViewer);
412   PetscBool      match;
413 
414   PetscFunctionBegin;
415   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
416   PetscValidCharPointer(type,2);
417   ierr = PetscObjectTypeCompare((PetscObject)viewer,type,&match);CHKERRQ(ierr);
418   if (match) PetscFunctionReturn(0);
419 
420   /* cleanup any old type that may be there */
421   if (viewer->data) {
422     ierr         = (*viewer->ops->destroy)(viewer);CHKERRQ(ierr);
423 
424     viewer->ops->destroy = NULL;
425     viewer->data         = 0;
426   }
427   ierr = PetscMemzero(viewer->ops,sizeof(struct _PetscViewerOps));CHKERRQ(ierr);
428 
429   ierr =  PetscFunctionListFind(PetscViewerList,type,&r);CHKERRQ(ierr);
430   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown PetscViewer type given: %s",type);
431 
432   ierr = PetscObjectChangeTypeName((PetscObject)viewer,type);CHKERRQ(ierr);
433   ierr = (*r)(viewer);CHKERRQ(ierr);
434   PetscFunctionReturn(0);
435 }
436 
437 /*@C
438    PetscViewerRegister - Adds a viewer
439 
440    Not Collective
441 
442    Input Parameters:
443 +  name_solver - name of a new user-defined viewer
444 -  routine_create - routine to create method context
445 
446    Level: developer
447    Notes:
448    PetscViewerRegister() may be called multiple times to add several user-defined viewers.
449 
450    Sample usage:
451 .vb
452    PetscViewerRegister("my_viewer_type",MyViewerCreate);
453 .ve
454 
455    Then, your solver can be chosen with the procedural interface via
456 $     PetscViewerSetType(viewer,"my_viewer_type")
457    or at runtime via the option
458 $     -viewer_type my_viewer_type
459 
460   Concepts: registering^Viewers
461 
462 .seealso: PetscViewerRegisterAll(), PetscViewerRegisterDestroy()
463  @*/
464 PetscErrorCode  PetscViewerRegister(const char *sname,PetscErrorCode (*function)(PetscViewer))
465 {
466   PetscErrorCode ierr;
467 
468   PetscFunctionBegin;
469   ierr = PetscFunctionListAdd(&PetscViewerList,sname,function);CHKERRQ(ierr);
470   PetscFunctionReturn(0);
471 }
472 
473 /*@C
474    PetscViewerSetFromOptions - Sets the graphics type from the options database.
475       Defaults to a PETSc X windows graphics.
476 
477    Collective on PetscViewer
478 
479    Input Parameter:
480 .     PetscViewer - the graphics context
481 
482    Level: intermediate
483 
484    Notes:
485     Must be called after PetscViewerCreate() before the PetscViewer is used.
486 
487   Concepts: PetscViewer^setting options
488 
489 .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerType
490 
491 @*/
492 PetscErrorCode  PetscViewerSetFromOptions(PetscViewer viewer)
493 {
494   PetscErrorCode    ierr;
495   char              vtype[256];
496   PetscBool         flg;
497 
498   PetscFunctionBegin;
499   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
500 
501   if (!PetscViewerList) {
502     ierr = PetscViewerRegisterAll();CHKERRQ(ierr);
503   }
504   ierr = PetscObjectOptionsBegin((PetscObject)viewer);CHKERRQ(ierr);
505   ierr = PetscOptionsFList("-viewer_type","Type of PetscViewer","None",PetscViewerList,(char*)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII),vtype,256,&flg);CHKERRQ(ierr);
506   if (flg) {
507     ierr = PetscViewerSetType(viewer,vtype);CHKERRQ(ierr);
508   }
509   /* type has not been set? */
510   if (!((PetscObject)viewer)->type_name) {
511     ierr = PetscViewerSetType(viewer,PETSCVIEWERASCII);CHKERRQ(ierr);
512   }
513   if (viewer->ops->setfromoptions) {
514     ierr = (*viewer->ops->setfromoptions)(PetscOptionsObject,viewer);CHKERRQ(ierr);
515   }
516 
517   /* process any options handlers added with PetscObjectAddOptionsHandler() */
518   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)viewer);CHKERRQ(ierr);
519   ierr = PetscViewerViewFromOptions(viewer,NULL,"-viewer_view");CHKERRQ(ierr);
520   ierr = PetscOptionsEnd();CHKERRQ(ierr);
521   PetscFunctionReturn(0);
522 }
523 
524 PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer,PetscInt *mcnt,PetscInt *cnt)
525 {
526   PetscErrorCode ierr;
527   PetscFunctionBegin;
528   ierr = PetscViewerBinaryGetFlowControl(viewer,mcnt);CHKERRQ(ierr);
529   ierr = PetscViewerBinaryGetFlowControl(viewer,cnt);CHKERRQ(ierr);
530   PetscFunctionReturn(0);
531 }
532 
533 PetscErrorCode PetscViewerFlowControlStepMaster(PetscViewer viewer,PetscInt i,PetscInt *mcnt,PetscInt cnt)
534 {
535   PetscErrorCode ierr;
536   MPI_Comm       comm;
537 
538   PetscFunctionBegin;
539   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
540   if (i >= *mcnt) {
541     *mcnt += cnt;
542     ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
543   }
544   PetscFunctionReturn(0);
545 }
546 
547 PetscErrorCode PetscViewerFlowControlEndMaster(PetscViewer viewer,PetscInt *mcnt)
548 {
549   PetscErrorCode ierr;
550   MPI_Comm       comm;
551   PetscFunctionBegin;
552   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
553   *mcnt = 0;
554   ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
555   PetscFunctionReturn(0);
556 }
557 
558 PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer,PetscMPIInt rank,PetscInt *mcnt)
559 {
560   PetscErrorCode ierr;
561   MPI_Comm       comm;
562   PetscFunctionBegin;
563   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
564   while (PETSC_TRUE) {
565     if (rank < *mcnt) break;
566     ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
567   }
568   PetscFunctionReturn(0);
569 }
570 
571 PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer,PetscInt *mcnt)
572 {
573   PetscErrorCode ierr;
574   MPI_Comm       comm;
575   PetscFunctionBegin;
576   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
577   while (PETSC_TRUE) {
578     ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
579     if (!*mcnt) break;
580   }
581   PetscFunctionReturn(0);
582 }
583