xref: /petsc/src/sys/classes/viewer/interface/viewreg.c (revision e91eccc2778f456fc991f5a9b142a3a67738bfd5)
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|format]] %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,PETSCVIEWERGLVIS,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           case 8:
312             if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) CHKERRQ(PETSC_ERR_PLIB);
313             break;
314           default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported viewer %s",loc0_vtype);
315           }
316           ierr = PetscObjectReference((PetscObject)*viewer);CHKERRQ(ierr);
317         } else {
318           if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
319             ierr = PetscViewerASCIIGetStdout(comm,viewer);CHKERRQ(ierr);
320             ierr = PetscObjectReference((PetscObject)*viewer);CHKERRQ(ierr);
321           } else {
322             PetscFileMode fmode;
323             ierr = PetscViewerCreate(comm,viewer);CHKERRQ(ierr);
324             ierr = PetscViewerSetType(*viewer,*loc0_vtype ? loc0_vtype : "ascii");CHKERRQ(ierr);
325             fmode = FILE_MODE_WRITE;
326             if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
327               ierr = PetscEnumFind(PetscFileModes,loc3_fmode,(PetscEnum*)&fmode,&flag);CHKERRQ(ierr);
328               if (!flag) SETERRQ1(comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown file mode: %s",loc3_fmode);
329             }
330             if (loc2_fmt) {
331               PetscBool tk,im;
332               ierr = PetscStrcmp(loc1_fname,"tikz",&tk);CHKERRQ(ierr);
333               ierr = PetscStrcmp(loc1_fname,"image",&im);CHKERRQ(ierr);
334               if (tk || im) {
335                 ierr = PetscViewerDrawSetInfo(*viewer,NULL,loc2_fmt,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
336                 *loc2_fmt = 0;
337               }
338             }
339             ierr = PetscViewerFileSetMode(*viewer,flag?fmode:FILE_MODE_WRITE);CHKERRQ(ierr);
340             ierr = PetscViewerFileSetName(*viewer,loc1_fname);CHKERRQ(ierr);
341             if (*loc1_fname) {
342               ierr = PetscViewerDrawSetDrawType(*viewer,loc1_fname);CHKERRQ(ierr);
343             }
344           }
345         }
346       }
347       if (viewer) {
348         ierr = PetscViewerSetUp(*viewer);CHKERRQ(ierr);
349       }
350       if (loc2_fmt && *loc2_fmt) {
351         ierr = PetscEnumFind(PetscViewerFormats,loc2_fmt,(PetscEnum*)format,&flag);CHKERRQ(ierr);
352         if (!flag) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer format %s",loc2_fmt);
353       }
354       ierr = PetscFree(loc0_vtype);CHKERRQ(ierr);
355     }
356   }
357   PetscFunctionReturn(0);
358 }
359 
360 /*@
361    PetscViewerCreate - Creates a viewing context
362 
363    Collective on MPI_Comm
364 
365    Input Parameter:
366 .  comm - MPI communicator
367 
368    Output Parameter:
369 .  inviewer - location to put the PetscViewer context
370 
371    Level: advanced
372 
373    Concepts: graphics^creating PetscViewer
374    Concepts: file input/output^creating PetscViewer
375    Concepts: sockets^creating PetscViewer
376 
377 .seealso: PetscViewerDestroy(), PetscViewerSetType(), PetscViewerType
378 
379 @*/
380 PetscErrorCode  PetscViewerCreate(MPI_Comm comm,PetscViewer *inviewer)
381 {
382   PetscViewer    viewer;
383   PetscErrorCode ierr;
384 
385   PetscFunctionBegin;
386   *inviewer = 0;
387   ierr = PetscViewerInitializePackage();CHKERRQ(ierr);
388   ierr         = PetscHeaderCreate(viewer,PETSC_VIEWER_CLASSID,"PetscViewer","PetscViewer","Viewer",comm,PetscViewerDestroy,NULL);CHKERRQ(ierr);
389   *inviewer    = viewer;
390   viewer->data = 0;
391   PetscFunctionReturn(0);
392 }
393 
394 /*@C
395    PetscViewerSetType - Builds PetscViewer for a particular implementation.
396 
397    Collective on PetscViewer
398 
399    Input Parameter:
400 +  viewer      - the PetscViewer context
401 -  type        - for example, PETSCVIEWERASCII
402 
403    Options Database Command:
404 .  -draw_type  <type> - Sets the type; use -help for a list
405     of available methods (for instance, ascii)
406 
407    Level: advanced
408 
409    Notes:
410    See "include/petscviewer.h" for available methods (for instance,
411    PETSCVIEWERSOCKET)
412 
413 .seealso: PetscViewerCreate(), PetscViewerGetType(), PetscViewerType, PetscViewerPushFormat()
414 @*/
415 PetscErrorCode  PetscViewerSetType(PetscViewer viewer,PetscViewerType type)
416 {
417   PetscErrorCode ierr,(*r)(PetscViewer);
418   PetscBool      match;
419 
420   PetscFunctionBegin;
421   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
422   PetscValidCharPointer(type,2);
423   ierr = PetscObjectTypeCompare((PetscObject)viewer,type,&match);CHKERRQ(ierr);
424   if (match) PetscFunctionReturn(0);
425 
426   /* cleanup any old type that may be there */
427   if (viewer->data) {
428     ierr         = (*viewer->ops->destroy)(viewer);CHKERRQ(ierr);
429 
430     viewer->ops->destroy = NULL;
431     viewer->data         = 0;
432   }
433   ierr = PetscMemzero(viewer->ops,sizeof(struct _PetscViewerOps));CHKERRQ(ierr);
434 
435   ierr =  PetscFunctionListFind(PetscViewerList,type,&r);CHKERRQ(ierr);
436   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown PetscViewer type given: %s",type);
437 
438   ierr = PetscObjectChangeTypeName((PetscObject)viewer,type);CHKERRQ(ierr);
439   ierr = (*r)(viewer);CHKERRQ(ierr);
440   PetscFunctionReturn(0);
441 }
442 
443 /*@C
444    PetscViewerRegister - Adds a viewer
445 
446    Not Collective
447 
448    Input Parameters:
449 +  name_solver - name of a new user-defined viewer
450 -  routine_create - routine to create method context
451 
452    Level: developer
453    Notes:
454    PetscViewerRegister() may be called multiple times to add several user-defined viewers.
455 
456    Sample usage:
457 .vb
458    PetscViewerRegister("my_viewer_type",MyViewerCreate);
459 .ve
460 
461    Then, your solver can be chosen with the procedural interface via
462 $     PetscViewerSetType(viewer,"my_viewer_type")
463    or at runtime via the option
464 $     -viewer_type my_viewer_type
465 
466   Concepts: registering^Viewers
467 
468 .seealso: PetscViewerRegisterAll(), PetscViewerRegisterDestroy()
469  @*/
470 PetscErrorCode  PetscViewerRegister(const char *sname,PetscErrorCode (*function)(PetscViewer))
471 {
472   PetscErrorCode ierr;
473 
474   PetscFunctionBegin;
475   ierr = PetscFunctionListAdd(&PetscViewerList,sname,function);CHKERRQ(ierr);
476   PetscFunctionReturn(0);
477 }
478 
479 /*@C
480    PetscViewerSetFromOptions - Sets the graphics type from the options database.
481       Defaults to a PETSc X windows graphics.
482 
483    Collective on PetscViewer
484 
485    Input Parameter:
486 .     PetscViewer - the graphics context
487 
488    Level: intermediate
489 
490    Notes:
491     Must be called after PetscViewerCreate() before the PetscViewer is used.
492 
493   Concepts: PetscViewer^setting options
494 
495 .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerType
496 
497 @*/
498 PetscErrorCode  PetscViewerSetFromOptions(PetscViewer viewer)
499 {
500   PetscErrorCode    ierr;
501   char              vtype[256];
502   PetscBool         flg;
503 
504   PetscFunctionBegin;
505   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
506 
507   if (!PetscViewerList) {
508     ierr = PetscViewerRegisterAll();CHKERRQ(ierr);
509   }
510   ierr = PetscObjectOptionsBegin((PetscObject)viewer);CHKERRQ(ierr);
511   ierr = PetscOptionsFList("-viewer_type","Type of PetscViewer","None",PetscViewerList,(char*)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII),vtype,256,&flg);CHKERRQ(ierr);
512   if (flg) {
513     ierr = PetscViewerSetType(viewer,vtype);CHKERRQ(ierr);
514   }
515   /* type has not been set? */
516   if (!((PetscObject)viewer)->type_name) {
517     ierr = PetscViewerSetType(viewer,PETSCVIEWERASCII);CHKERRQ(ierr);
518   }
519   if (viewer->ops->setfromoptions) {
520     ierr = (*viewer->ops->setfromoptions)(PetscOptionsObject,viewer);CHKERRQ(ierr);
521   }
522 
523   /* process any options handlers added with PetscObjectAddOptionsHandler() */
524   ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)viewer);CHKERRQ(ierr);
525   ierr = PetscViewerViewFromOptions(viewer,NULL,"-viewer_view");CHKERRQ(ierr);
526   ierr = PetscOptionsEnd();CHKERRQ(ierr);
527   PetscFunctionReturn(0);
528 }
529 
530 PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer,PetscInt *mcnt,PetscInt *cnt)
531 {
532   PetscErrorCode ierr;
533   PetscFunctionBegin;
534   ierr = PetscViewerBinaryGetFlowControl(viewer,mcnt);CHKERRQ(ierr);
535   ierr = PetscViewerBinaryGetFlowControl(viewer,cnt);CHKERRQ(ierr);
536   PetscFunctionReturn(0);
537 }
538 
539 PetscErrorCode PetscViewerFlowControlStepMaster(PetscViewer viewer,PetscInt i,PetscInt *mcnt,PetscInt cnt)
540 {
541   PetscErrorCode ierr;
542   MPI_Comm       comm;
543 
544   PetscFunctionBegin;
545   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
546   if (i >= *mcnt) {
547     *mcnt += cnt;
548     ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
549   }
550   PetscFunctionReturn(0);
551 }
552 
553 PetscErrorCode PetscViewerFlowControlEndMaster(PetscViewer viewer,PetscInt *mcnt)
554 {
555   PetscErrorCode ierr;
556   MPI_Comm       comm;
557   PetscFunctionBegin;
558   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
559   *mcnt = 0;
560   ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
561   PetscFunctionReturn(0);
562 }
563 
564 PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer,PetscMPIInt rank,PetscInt *mcnt)
565 {
566   PetscErrorCode ierr;
567   MPI_Comm       comm;
568   PetscFunctionBegin;
569   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
570   while (PETSC_TRUE) {
571     if (rank < *mcnt) break;
572     ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
573   }
574   PetscFunctionReturn(0);
575 }
576 
577 PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer,PetscInt *mcnt)
578 {
579   PetscErrorCode ierr;
580   MPI_Comm       comm;
581   PetscFunctionBegin;
582   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
583   while (PETSC_TRUE) {
584     ierr = MPI_Bcast(mcnt,1,MPIU_INT,0,comm);CHKERRQ(ierr);
585     if (!*mcnt) break;
586   }
587   PetscFunctionReturn(0);
588 }
589