xref: /petsc/src/sys/classes/viewer/interface/viewreg.c (revision e08b1d6d0faae6eca507e20c9d3498f81719d047)
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   PetscCall(PetscSegBufferDestroy(&(*hp)->strings));
23   PetscCall(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   PetscCall(PetscNew(hp));
41   (*hp)->printed = kh_init(HTPrinted);
42   PetscCall(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   PetscCall(PetscStrlen(pre,&l1));
73   PetscCall(PetscStrlen(name,&l2));
74   if (l1+l2 == 0) {
75     *found = PETSC_FALSE;
76     PetscFunctionReturn(0);
77   }
78 #if !defined(PETSC_HAVE_THREADSAFETY)
79   PetscCall(PetscSegBufferGet(hp->strings,l1+l2+1,&both));
80   PetscCall(PetscStrcpy(both,pre));
81   PetscCall(PetscStrcat(both,name));
82   kh_put(HTPrinted,hp->printed,both,&newitem);
83   if (!newitem) {
84     PetscCall(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   PetscCheck(inoviewers < PETSCVIEWERGETVIEWEROFFPUSHESMAX,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()`, `PetscOptionsHeadBegin()`,
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   PetscCall(PetscOptionsGetViewerOff(&flag));
225   if (flag) PetscFunctionReturn(0);
226 
227   PetscCall(PetscOptionsHasHelp(NULL,&hashelp));
228   if (hashelp) {
229     PetscBool found;
230 
231     if (!PetscOptionsHelpPrintedSingleton) {
232       PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
233     }
234     PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton,pre,name,&found));
235     if (!found && viewer) {
236       PetscCall((*PetscHelpPrintf)(comm,"----------------------------------------\nViewer (-%s%s) options:\n",pre ? pre : "",name+1));
237       PetscCall((*PetscHelpPrintf)(comm,"  -%s%s ascii[:[filename][:[format][:append]]]: %s (%s)\n",pre ? pre : "",name+1,"Prints object to stdout or ASCII file","PetscOptionsGetViewer"));
238       PetscCall((*PetscHelpPrintf)(comm,"  -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n",pre ? pre : "",name+1,"Saves object to a binary file","PetscOptionsGetViewer"));
239       PetscCall((*PetscHelpPrintf)(comm,"  -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n",pre ? pre : "",name+1,"Draws object","PetscOptionsGetViewer"));
240       PetscCall((*PetscHelpPrintf)(comm,"  -%s%s socket[:port]: %s (%s)\n",pre ? pre : "",name+1,"Pushes object to a Unix socket","PetscOptionsGetViewer"));
241       PetscCall((*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   PetscCall(PetscOptionsFindPair(options,pre,name,&value,&flag));
247   if (flag) {
248     if (set) *set = PETSC_TRUE;
249     if (!value) {
250       if (viewer) {
251         PetscCall(PetscViewerASCIIGetStdout(comm,viewer));
252         PetscCall(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       PetscCall(PetscStrallocpy(value,&loc0_vtype));
260       PetscCall(PetscStrchr(loc0_vtype,':',&loc1_fname));
261       if (loc1_fname) {
262         *loc1_fname++ = 0;
263         PetscCall(PetscStrchr(loc1_fname,':',&loc2_fmt));
264       }
265       if (loc2_fmt) {
266         *loc2_fmt++ = 0;
267         PetscCall(PetscStrchr(loc2_fmt,':',&loc3_fmode));
268       }
269       if (loc3_fmode) *loc3_fmode++ = 0;
270       PetscCall(PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii",viewers,&cnt));
271       PetscCheck(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             PetscCall(PetscViewerASCIIGetStdout(comm,viewer));
277             break;
278           case 1:
279             if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PetscCall(PETSC_ERR_PLIB);
280             break;
281           case 2:
282             if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PetscCall(PETSC_ERR_PLIB);
283             break;
284 #if defined(PETSC_USE_SOCKET_VIEWER)
285           case 3:
286             if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PetscCall(PETSC_ERR_PLIB);
287             break;
288 #endif
289 #if defined(PETSC_HAVE_MATLAB_ENGINE)
290           case 4:
291             if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PetscCall(PETSC_ERR_PLIB);
292             break;
293 #endif
294 #if defined(PETSC_HAVE_SAWS)
295           case 5:
296             if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PetscCall(PETSC_ERR_PLIB);
297             break;
298 #endif
299 #if defined(PETSC_HAVE_HDF5)
300           case 7:
301             if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PetscCall(PETSC_ERR_PLIB);
302             break;
303 #endif
304           case 8:
305             if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PetscCall(PETSC_ERR_PLIB);
306             break;
307 #if defined(PETSC_HAVE_EXODUSII)
308           case 9:
309             if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PetscCall(PETSC_ERR_PLIB);
310             break;
311 #endif
312           default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported viewer %s",loc0_vtype);
313           }
314           PetscCall(PetscObjectReference((PetscObject)*viewer));
315         } else {
316           if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
317             PetscCall(PetscViewerASCIIGetStdout(comm,viewer));
318             PetscCall(PetscObjectReference((PetscObject)*viewer));
319           } else {
320             PetscFileMode fmode;
321             PetscCall(PetscViewerCreate(comm,viewer));
322             PetscCall(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               PetscCall(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               PetscCall(PetscStrcmp(loc1_fname,"tikz",&tk));
331               PetscCall(PetscStrcmp(loc1_fname,"image",&im));
332               if (tk || im) {
333                 PetscCall(PetscViewerDrawSetInfo(*viewer,NULL,loc2_fmt,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE));
334                 *loc2_fmt = 0;
335               }
336             }
337             PetscCall(PetscViewerFileSetMode(*viewer,flag?fmode:FILE_MODE_WRITE));
338             PetscCall(PetscViewerFileSetName(*viewer,loc1_fname));
339             if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer,loc1_fname));
340             PetscCall(PetscViewerSetFromOptions(*viewer));
341           }
342         }
343       }
344       if (viewer) PetscCall(PetscViewerSetUp(*viewer));
345       if (loc2_fmt && *loc2_fmt) {
346         PetscViewerFormat tfmt;
347 
348         PetscCall(PetscEnumFind(PetscViewerFormats,loc2_fmt,(PetscEnum*)&tfmt,&flag));
349         if (format) *format = tfmt;
350         PetscCheck(flag,PETSC_COMM_SELF,PETSC_ERR_SUP,"Unknown viewer format %s",loc2_fmt);
351       } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */
352         PetscCall(PetscViewerGetFormat(*viewer,format));
353       }
354       PetscCall(PetscFree(loc0_vtype));
355     }
356   }
357   PetscFunctionReturn(0);
358 }
359 
360 /*@
361    PetscViewerCreate - Creates a viewing context
362 
363    Collective
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 .seealso: `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType`
374 
375 @*/
376 PetscErrorCode  PetscViewerCreate(MPI_Comm comm,PetscViewer *inviewer)
377 {
378   PetscViewer    viewer;
379 
380   PetscFunctionBegin;
381   *inviewer = NULL;
382   PetscCall(PetscViewerInitializePackage());
383   PetscCall(PetscHeaderCreate(viewer,PETSC_VIEWER_CLASSID,"PetscViewer","PetscViewer","Viewer",comm,PetscViewerDestroy,PetscViewerView));
384   *inviewer    = viewer;
385   viewer->data = NULL;
386   PetscFunctionReturn(0);
387 }
388 
389 /*@C
390    PetscViewerSetType - Builds PetscViewer for a particular implementation.
391 
392    Collective on PetscViewer
393 
394    Input Parameters:
395 +  viewer      - the PetscViewer context
396 -  type        - for example, PETSCVIEWERASCII
397 
398    Options Database Command:
399 .  -viewer_type  <type> - Sets the type; use -help for a list
400     of available methods (for instance, ascii)
401 
402    Level: advanced
403 
404    Notes:
405    See "include/petscviewer.h" for available methods (for instance,
406    PETSCVIEWERSOCKET)
407 
408 .seealso: `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
409 @*/
410 PetscErrorCode  PetscViewerSetType(PetscViewer viewer,PetscViewerType type)
411 {
412   PetscBool      match;
413   PetscErrorCode (*r)(PetscViewer);
414 
415   PetscFunctionBegin;
416   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
417   PetscValidCharPointer(type,2);
418   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,type,&match));
419   if (match) PetscFunctionReturn(0);
420 
421   /* cleanup any old type that may be there */
422   PetscTryTypeMethod(viewer,destroy);
423   viewer->ops->destroy = NULL;
424   viewer->data         = NULL;
425 
426   PetscCall(PetscMemzero(viewer->ops,sizeof(struct _PetscViewerOps)));
427 
428   PetscCall(PetscFunctionListFind(PetscViewerList,type,&r));
429   PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown PetscViewer type given: %s",type);
430 
431   PetscCall(PetscObjectChangeTypeName((PetscObject)viewer,type));
432   PetscCall((*r)(viewer));
433   PetscFunctionReturn(0);
434 }
435 
436 /*@C
437    PetscViewerRegister - Adds a viewer
438 
439    Not Collective
440 
441    Input Parameters:
442 +  name_solver - name of a new user-defined viewer
443 -  routine_create - routine to create method context
444 
445    Level: developer
446    Notes:
447    PetscViewerRegister() may be called multiple times to add several user-defined viewers.
448 
449    Sample usage:
450 .vb
451    PetscViewerRegister("my_viewer_type",MyViewerCreate);
452 .ve
453 
454    Then, your solver can be chosen with the procedural interface via
455 $     PetscViewerSetType(viewer,"my_viewer_type")
456    or at runtime via the option
457 $     -viewer_type my_viewer_type
458 
459 .seealso: `PetscViewerRegisterAll()`
460  @*/
461 PetscErrorCode  PetscViewerRegister(const char *sname,PetscErrorCode (*function)(PetscViewer))
462 {
463   PetscFunctionBegin;
464   PetscCall(PetscViewerInitializePackage());
465   PetscCall(PetscFunctionListAdd(&PetscViewerList,sname,function));
466   PetscFunctionReturn(0);
467 }
468 
469 /*@C
470    PetscViewerSetFromOptions - Sets the graphics type from the options database.
471       Defaults to a PETSc X windows graphics.
472 
473    Collective on PetscViewer
474 
475    Input Parameter:
476 .     PetscViewer - the graphics context
477 
478    Level: intermediate
479 
480    Notes:
481     Must be called after PetscViewerCreate() before the PetscViewer is used.
482 
483 .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
484 
485 @*/
486 PetscErrorCode  PetscViewerSetFromOptions(PetscViewer viewer)
487 {
488   char              vtype[256];
489   PetscBool         flg;
490 
491   PetscFunctionBegin;
492   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
493 
494   if (!PetscViewerList) {
495     PetscCall(PetscViewerRegisterAll());
496   }
497   PetscObjectOptionsBegin((PetscObject)viewer);
498   PetscCall(PetscOptionsFList("-viewer_type","Type of PetscViewer","None",PetscViewerList,(char*)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII),vtype,256,&flg));
499   if (flg) PetscCall(PetscViewerSetType(viewer,vtype));
500   /* type has not been set? */
501   if (!((PetscObject)viewer)->type_name) {
502     PetscCall(PetscViewerSetType(viewer,PETSCVIEWERASCII));
503   }
504   PetscTryTypeMethod(viewer,setfromoptions,PetscOptionsObject);
505 
506   /* process any options handlers added with PetscObjectAddOptionsHandler() */
507   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer,PetscOptionsObject));
508   PetscCall(PetscViewerViewFromOptions(viewer,NULL,"-viewer_view"));
509   PetscOptionsEnd();
510   PetscFunctionReturn(0);
511 }
512 
513 PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer,PetscInt *mcnt,PetscInt *cnt)
514 {
515   PetscFunctionBegin;
516   PetscCall(PetscViewerBinaryGetFlowControl(viewer,mcnt));
517   PetscCall(PetscViewerBinaryGetFlowControl(viewer,cnt));
518   PetscFunctionReturn(0);
519 }
520 
521 PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer,PetscInt i,PetscInt *mcnt,PetscInt cnt)
522 {
523   MPI_Comm       comm;
524 
525   PetscFunctionBegin;
526   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
527   if (i >= *mcnt) {
528     *mcnt += cnt;
529     PetscCallMPI(MPI_Bcast(mcnt,1,MPIU_INT,0,comm));
530   }
531   PetscFunctionReturn(0);
532 }
533 
534 PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer,PetscInt *mcnt)
535 {
536   MPI_Comm       comm;
537   PetscFunctionBegin;
538   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
539   *mcnt = 0;
540   PetscCallMPI(MPI_Bcast(mcnt,1,MPIU_INT,0,comm));
541   PetscFunctionReturn(0);
542 }
543 
544 PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer,PetscMPIInt rank,PetscInt *mcnt)
545 {
546   MPI_Comm       comm;
547   PetscFunctionBegin;
548   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
549   while (PETSC_TRUE) {
550     if (rank < *mcnt) break;
551     PetscCallMPI(MPI_Bcast(mcnt,1,MPIU_INT,0,comm));
552   }
553   PetscFunctionReturn(0);
554 }
555 
556 PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer,PetscInt *mcnt)
557 {
558   MPI_Comm       comm;
559   PetscFunctionBegin;
560   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
561   while (PETSC_TRUE) {
562     PetscCallMPI(MPI_Bcast(mcnt,1,MPIU_INT,0,comm));
563     if (!*mcnt) break;
564   }
565   PetscFunctionReturn(0);
566 }
567