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