xref: /petsc/src/sys/classes/viewer/interface/viewreg.c (revision 53134ebed6238e4143779c3e5c7db66beceae3ba)
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   if (viewer->data) {
423     PetscCall((*viewer->ops->destroy)(viewer));
424 
425     viewer->ops->destroy = NULL;
426     viewer->data         = NULL;
427   }
428   PetscCall(PetscMemzero(viewer->ops,sizeof(struct _PetscViewerOps)));
429 
430   PetscCall(PetscFunctionListFind(PetscViewerList,type,&r));
431   PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown PetscViewer type given: %s",type);
432 
433   PetscCall(PetscObjectChangeTypeName((PetscObject)viewer,type));
434   PetscCall((*r)(viewer));
435   PetscFunctionReturn(0);
436 }
437 
438 /*@C
439    PetscViewerRegister - Adds a viewer
440 
441    Not Collective
442 
443    Input Parameters:
444 +  name_solver - name of a new user-defined viewer
445 -  routine_create - routine to create method context
446 
447    Level: developer
448    Notes:
449    PetscViewerRegister() may be called multiple times to add several user-defined viewers.
450 
451    Sample usage:
452 .vb
453    PetscViewerRegister("my_viewer_type",MyViewerCreate);
454 .ve
455 
456    Then, your solver can be chosen with the procedural interface via
457 $     PetscViewerSetType(viewer,"my_viewer_type")
458    or at runtime via the option
459 $     -viewer_type my_viewer_type
460 
461 .seealso: `PetscViewerRegisterAll()`
462  @*/
463 PetscErrorCode  PetscViewerRegister(const char *sname,PetscErrorCode (*function)(PetscViewer))
464 {
465   PetscFunctionBegin;
466   PetscCall(PetscViewerInitializePackage());
467   PetscCall(PetscFunctionListAdd(&PetscViewerList,sname,function));
468   PetscFunctionReturn(0);
469 }
470 
471 /*@C
472    PetscViewerSetFromOptions - Sets the graphics type from the options database.
473       Defaults to a PETSc X windows graphics.
474 
475    Collective on PetscViewer
476 
477    Input Parameter:
478 .     PetscViewer - the graphics context
479 
480    Level: intermediate
481 
482    Notes:
483     Must be called after PetscViewerCreate() before the PetscViewer is used.
484 
485 .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
486 
487 @*/
488 PetscErrorCode  PetscViewerSetFromOptions(PetscViewer viewer)
489 {
490   char              vtype[256];
491   PetscBool         flg;
492 
493   PetscFunctionBegin;
494   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
495 
496   if (!PetscViewerList) {
497     PetscCall(PetscViewerRegisterAll());
498   }
499   PetscObjectOptionsBegin((PetscObject)viewer);
500   PetscCall(PetscOptionsFList("-viewer_type","Type of PetscViewer","None",PetscViewerList,(char*)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII),vtype,256,&flg));
501   if (flg) PetscCall(PetscViewerSetType(viewer,vtype));
502   /* type has not been set? */
503   if (!((PetscObject)viewer)->type_name) {
504     PetscCall(PetscViewerSetType(viewer,PETSCVIEWERASCII));
505   }
506   if (viewer->ops->setfromoptions) PetscCall((*viewer->ops->setfromoptions)(PetscOptionsObject,viewer));
507 
508   /* process any options handlers added with PetscObjectAddOptionsHandler() */
509   PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)viewer));
510   PetscCall(PetscViewerViewFromOptions(viewer,NULL,"-viewer_view"));
511   PetscOptionsEnd();
512   PetscFunctionReturn(0);
513 }
514 
515 PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer,PetscInt *mcnt,PetscInt *cnt)
516 {
517   PetscFunctionBegin;
518   PetscCall(PetscViewerBinaryGetFlowControl(viewer,mcnt));
519   PetscCall(PetscViewerBinaryGetFlowControl(viewer,cnt));
520   PetscFunctionReturn(0);
521 }
522 
523 PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer,PetscInt i,PetscInt *mcnt,PetscInt cnt)
524 {
525   MPI_Comm       comm;
526 
527   PetscFunctionBegin;
528   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
529   if (i >= *mcnt) {
530     *mcnt += cnt;
531     PetscCallMPI(MPI_Bcast(mcnt,1,MPIU_INT,0,comm));
532   }
533   PetscFunctionReturn(0);
534 }
535 
536 PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer,PetscInt *mcnt)
537 {
538   MPI_Comm       comm;
539   PetscFunctionBegin;
540   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
541   *mcnt = 0;
542   PetscCallMPI(MPI_Bcast(mcnt,1,MPIU_INT,0,comm));
543   PetscFunctionReturn(0);
544 }
545 
546 PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer,PetscMPIInt rank,PetscInt *mcnt)
547 {
548   MPI_Comm       comm;
549   PetscFunctionBegin;
550   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
551   while (PETSC_TRUE) {
552     if (rank < *mcnt) break;
553     PetscCallMPI(MPI_Bcast(mcnt,1,MPIU_INT,0,comm));
554   }
555   PetscFunctionReturn(0);
556 }
557 
558 PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer,PetscInt *mcnt)
559 {
560   MPI_Comm       comm;
561   PetscFunctionBegin;
562   PetscCall(PetscObjectGetComm((PetscObject)viewer,&comm));
563   while (PETSC_TRUE) {
564     PetscCallMPI(MPI_Bcast(mcnt,1,MPIU_INT,0,comm));
565     if (!*mcnt) break;
566   }
567   PetscFunctionReturn(0);
568 }
569