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