xref: /petsc/src/sys/classes/viewer/interface/viewreg.c (revision da8c939b118068a1ceac5e4b3ba271c87cfc5bc7)
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   Output Parameter:
32 . hp - the created object
33 
34   Not Collective
35 
36   Level: developer
37 
38 .seealso: `PetscOptionsHelpPrintedCheck()`, `PetscOptionsHelpPrintChecked()`
39 @*/
40 PetscErrorCode PetscOptionsHelpPrintedCreate(PetscOptionsHelpPrinted *hp)
41 {
42   PetscFunctionBegin;
43   PetscCall(PetscNew(hp));
44   (*hp)->printed = kh_init(HTPrinted);
45   PetscCall(PetscSegBufferCreate(sizeof(char), 10000, &(*hp)->strings));
46   PetscFunctionReturn(PETSC_SUCCESS);
47 }
48 
49 /*@C
50   PetscOptionsHelpPrintedCheck - Checks if a particular pre, name pair has previous been entered (meaning the help message was printed)
51 
52   Not Collective
53 
54   Input Parameters:
55 + hp   - the object used to manage tracking what help messages have been printed
56 . pre  - the prefix part of the string, many be `NULL`
57 - name - the string to look for (cannot be `NULL`)
58 
59   Output Parameter:
60 . found - `PETSC_TRUE` if the string was already set
61 
62   Level: intermediate
63 
64 .seealso: `PetscOptionsHelpPrintedCreate()`
65 @*/
66 PetscErrorCode PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrinted hp, const char *pre, const char *name, PetscBool *found)
67 {
68   size_t l1, l2;
69 #if !defined(PETSC_HAVE_THREADSAFETY)
70   char *both;
71   int   newitem;
72 #endif
73 
74   PetscFunctionBegin;
75   PetscCall(PetscStrlen(pre, &l1));
76   PetscCall(PetscStrlen(name, &l2));
77   if (l1 + l2 == 0) {
78     *found = PETSC_FALSE;
79     PetscFunctionReturn(PETSC_SUCCESS);
80   }
81 #if !defined(PETSC_HAVE_THREADSAFETY)
82   size_t lboth = l1 + l2 + 1;
83   PetscCall(PetscSegBufferGet(hp->strings, lboth, &both));
84   PetscCall(PetscStrncpy(both, pre, lboth));
85   PetscCall(PetscStrncpy(both + l1, name, l2 + 1));
86   kh_put(HTPrinted, hp->printed, both, &newitem);
87   if (!newitem) PetscCall(PetscSegBufferUnuse(hp->strings, lboth));
88   *found = newitem ? PETSC_FALSE : PETSC_TRUE;
89 #else
90   *found = PETSC_FALSE;
91 #endif
92   PetscFunctionReturn(PETSC_SUCCESS);
93 }
94 
95 static PetscBool noviewer = PETSC_FALSE;
96 static PetscBool noviewers[PETSCVIEWERGETVIEWEROFFPUSHESMAX];
97 static PetscInt  inoviewers = 0;
98 
99 /*@
100   PetscOptionsPushGetViewerOff - sets if a `PetscOptionsGetViewer()` returns a viewer.
101 
102   Logically Collective
103 
104   Input Parameter:
105 . flg - `PETSC_TRUE` to turn off viewer creation, `PETSC_FALSE` to turn it on.
106 
107   Level: developer
108 
109   Note:
110   Calling `XXXViewFromOptions` in an inner loop can be expensive.  This can appear, for example, when using
111   many small subsolves.  Call this function to control viewer creation in `PetscOptionsGetViewer()`, thus removing the expensive `XXXViewFromOptions` calls.
112 
113   Developer Notes:
114   Instead of using this approach, the calls to `PetscOptionsGetViewer()` can be moved into `XXXSetFromOptions()`
115 
116 .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsPopGetViewerOff()`
117 @*/
118 PetscErrorCode PetscOptionsPushGetViewerOff(PetscBool flg)
119 {
120   PetscFunctionBegin;
121   PetscCheck(inoviewers < PETSCVIEWERGETVIEWEROFFPUSHESMAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPushGetViewerOff(), perhaps you forgot PetscOptionsPopGetViewerOff()?");
122 
123   noviewers[inoviewers++] = noviewer;
124   noviewer                = flg;
125   PetscFunctionReturn(PETSC_SUCCESS);
126 }
127 
128 /*@
129   PetscOptionsPopGetViewerOff - reset whether `PetscOptionsGetViewer()` returns a viewer.
130 
131   Logically Collective
132 
133   Level: developer
134 
135   Note:
136   See `PetscOptionsPushGetViewerOff()`
137 
138 .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()`
139 @*/
140 PetscErrorCode PetscOptionsPopGetViewerOff(void)
141 {
142   PetscFunctionBegin;
143   PetscCheck(inoviewers, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPopGetViewerOff(), perhaps you forgot PetscOptionsPushGetViewerOff()?");
144   noviewer = noviewers[--inoviewers];
145   PetscFunctionReturn(PETSC_SUCCESS);
146 }
147 
148 /*@
149   PetscOptionsGetViewerOff - does `PetscOptionsGetViewer()` return a viewer?
150 
151   Logically Collective
152 
153   Output Parameter:
154 . flg - whether viewers are returned.
155 
156   Level: developer
157 
158   Note:
159   See `PetscOptionsPushGetViewerOff()`
160 
161 .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`
162 @*/
163 PetscErrorCode PetscOptionsGetViewerOff(PetscBool *flg)
164 {
165   PetscFunctionBegin;
166   PetscAssertPointer(flg, 1);
167   *flg = noviewer;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 static PetscErrorCode PetscOptionsGetViewers_Single(MPI_Comm comm, const char value[], PetscViewer *viewer, PetscViewerFormat *format)
172 {
173   char       *loc0_vtype = NULL, *loc1_fname = NULL, *loc2_fmt = NULL, *loc3_fmode = NULL;
174   PetscInt    cnt;
175   size_t      viewer_string_length;
176   const char *viewers[] = {PETSCVIEWERASCII, PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSOCKET, PETSCVIEWERMATLAB, PETSCVIEWERSAWS, PETSCVIEWERVTK, PETSCVIEWERHDF5, PETSCVIEWERGLVIS, PETSCVIEWEREXODUSII, NULL};
177 
178   PetscFunctionBegin;
179   PetscCall(PetscStrlen(value, &viewer_string_length));
180   if (!viewer_string_length) {
181     if (format) *format = PETSC_VIEWER_DEFAULT;
182     if (viewer) {
183       PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
184       PetscCall(PetscObjectReference((PetscObject)*viewer));
185     }
186     PetscFunctionReturn(PETSC_SUCCESS);
187   }
188 
189   PetscCall(PetscStrallocpy(value, &loc0_vtype));
190   PetscCall(PetscStrchr(loc0_vtype, ':', &loc1_fname));
191   if (loc1_fname) {
192     *loc1_fname++ = 0;
193     PetscCall(PetscStrchr(loc1_fname, ':', &loc2_fmt));
194   }
195   if (loc2_fmt) {
196     *loc2_fmt++ = 0;
197     PetscCall(PetscStrchr(loc2_fmt, ':', &loc3_fmode));
198   }
199   if (loc3_fmode) *loc3_fmode++ = 0;
200   PetscCall(PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii", viewers, &cnt));
201   PetscCheck(cnt <= (PetscInt)sizeof(viewers) - 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Unknown viewer type: %s", loc0_vtype);
202   if (viewer) {
203     if (!loc1_fname) {
204       switch (cnt) {
205       case 0:
206         PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
207         break;
208       case 1:
209         if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PetscCall(PETSC_ERR_PLIB);
210         break;
211       case 2:
212         if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PetscCall(PETSC_ERR_PLIB);
213         break;
214 #if defined(PETSC_USE_SOCKET_VIEWER)
215       case 3:
216         if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PetscCall(PETSC_ERR_PLIB);
217         break;
218 #endif
219 #if defined(PETSC_HAVE_MATLAB)
220       case 4:
221         if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PetscCall(PETSC_ERR_PLIB);
222         break;
223 #endif
224 #if defined(PETSC_HAVE_SAWS)
225       case 5:
226         if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PetscCall(PETSC_ERR_PLIB);
227         break;
228 #endif
229 #if defined(PETSC_HAVE_HDF5)
230       case 7:
231         if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PetscCall(PETSC_ERR_PLIB);
232         break;
233 #endif
234       case 8:
235         if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PetscCall(PETSC_ERR_PLIB);
236         break;
237 #if defined(PETSC_HAVE_EXODUSII)
238       case 9:
239         if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PetscCall(PETSC_ERR_PLIB);
240         break;
241 #endif
242       default:
243         SETERRQ(comm, PETSC_ERR_SUP, "Unsupported viewer %s", loc0_vtype);
244       }
245       PetscCall(PetscObjectReference((PetscObject)*viewer));
246     } else {
247       if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
248         PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
249         PetscCall(PetscObjectReference((PetscObject)*viewer));
250       } else {
251         PetscFileMode fmode;
252         PetscBool     flag = PETSC_FALSE;
253 
254         PetscCall(PetscViewerCreate(comm, viewer));
255         PetscCall(PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii"));
256         fmode = FILE_MODE_WRITE;
257         if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
258           PetscCall(PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag));
259           PetscCheck(flag, comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown file mode: %s", loc3_fmode);
260         }
261         if (loc2_fmt) {
262           PetscBool tk, im;
263           PetscCall(PetscStrcmp(loc1_fname, "tikz", &tk));
264           PetscCall(PetscStrcmp(loc1_fname, "image", &im));
265           if (tk || im) {
266             PetscCall(PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE));
267             *loc2_fmt = 0;
268           }
269         }
270         PetscCall(PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE));
271         PetscCall(PetscViewerFileSetName(*viewer, loc1_fname));
272         if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer, loc1_fname));
273         PetscCall(PetscViewerSetFromOptions(*viewer));
274       }
275     }
276   }
277   if (viewer) PetscCall(PetscViewerSetUp(*viewer));
278   if (loc2_fmt && *loc2_fmt) {
279     PetscViewerFormat tfmt;
280     PetscBool         flag;
281 
282     PetscCall(PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag));
283     if (format) *format = tfmt;
284     PetscCheck(flag, comm, PETSC_ERR_SUP, "Unknown viewer format %s", loc2_fmt);
285   } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */
286     PetscCall(PetscViewerGetFormat(*viewer, format));
287   }
288   PetscCall(PetscFree(loc0_vtype));
289 
290   PetscFunctionReturn(PETSC_SUCCESS);
291 }
292 
293 static PetscErrorCode PetscOptionsGetViewers_Internal(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscInt *n_max_p, PetscViewer viewer[], PetscViewerFormat format[], PetscBool *set, const char func_name[], PetscBool allow_multiple)
294 {
295   const char *value;
296   PetscBool   flag, hashelp;
297   PetscInt    n_max;
298 
299   PetscFunctionBegin;
300   PetscAssertPointer(name, 4);
301   PetscAssertPointer(n_max_p, 5);
302   n_max = *n_max_p;
303   PetscCheck(n_max >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid size %" PetscInt_FMT " of passed arrays", *n_max_p);
304   *n_max_p = 0;
305 
306   if (set) *set = PETSC_FALSE;
307   PetscCall(PetscOptionsGetViewerOff(&flag));
308   if (flag) PetscFunctionReturn(PETSC_SUCCESS);
309 
310   PetscCall(PetscOptionsHasHelp(NULL, &hashelp));
311   if (hashelp) {
312     PetscBool found;
313 
314     if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
315     PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found));
316     if (!found && viewer) {
317       PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1));
318       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s ascii[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Prints object to stdout or ASCII file", func_name));
319       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", func_name));
320       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", func_name));
321       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", func_name));
322       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", func_name));
323       if (allow_multiple) PetscCall((*PetscHelpPrintf)(comm, "  -%s%s v1[,v2,...]: %s (%s)\n", pre ? pre : "", name + 1, "Multiple viewers", func_name));
324     }
325   }
326 
327   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
328   if (flag) {
329     if (set) *set = PETSC_TRUE;
330     if (!value) {
331       PetscCheck(n_max > 0, comm, PETSC_ERR_ARG_SIZ, "More viewers (1) than max available (0)");
332       if (format) *format = PETSC_VIEWER_DEFAULT;
333       if (viewer) {
334         PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
335         PetscCall(PetscObjectReference((PetscObject)*viewer));
336       }
337       *n_max_p = 1;
338     } else {
339       char  *loc0_viewer_string = NULL, *this_viewer_string = NULL;
340       size_t viewer_string_length;
341 
342       PetscCall(PetscStrallocpy(value, &loc0_viewer_string));
343       PetscCall(PetscStrlen(loc0_viewer_string, &viewer_string_length));
344       this_viewer_string = loc0_viewer_string;
345 
346       do {
347         PetscViewer       *this_viewer;
348         PetscViewerFormat *this_viewer_format;
349         char              *next_viewer_string = NULL;
350         char              *comma_separator    = NULL;
351         PetscInt           n                  = *n_max_p;
352 
353         PetscCheck(n < n_max, comm, PETSC_ERR_PLIB, "More viewers than max available (%d)", (int)n_max);
354 
355         PetscCall(PetscStrchr(this_viewer_string, ',', &comma_separator));
356         if (comma_separator) {
357           PetscCheck(allow_multiple, comm, PETSC_ERR_ARG_OUTOFRANGE, "Trying to pass multiple viewers to %s: only one allowed.  Use PetscOptionsGetViewers() instead", func_name);
358           *comma_separator   = 0;
359           next_viewer_string = comma_separator + 1;
360         }
361         this_viewer = viewer ? &viewer[n] : NULL;
362         if (this_viewer) *this_viewer = NULL;
363         this_viewer_format = format ? &format[n] : NULL;
364         if (this_viewer_format) *this_viewer_format = PETSC_VIEWER_DEFAULT;
365         PetscCall(PetscOptionsGetViewers_Single(comm, this_viewer_string, this_viewer, this_viewer_format));
366         this_viewer_string = next_viewer_string;
367         (*n_max_p)++;
368       } while (this_viewer_string);
369       PetscCall(PetscFree(loc0_viewer_string));
370     }
371   }
372   PetscFunctionReturn(PETSC_SUCCESS);
373 }
374 
375 /*@C
376   PetscOptionsGetViewer - Gets a viewer appropriate for the type indicated by the user
377 
378   Collective
379 
380   Input Parameters:
381 + comm    - the communicator to own the viewer
382 . options - options database, use `NULL` for default global database
383 . pre     - the string to prepend to the name or `NULL`
384 - name    - the option one is seeking
385 
386   Output Parameters:
387 + viewer - the viewer, pass `NULL` if not needed
388 . format - the `PetscViewerFormat` requested by the user, pass `NULL` if not needed
389 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
390 
391   Level: intermediate
392 
393   Notes:
394   If no value is provided ascii:stdout is used
395 +       ascii[:[filename][:[format][:append]]]  -  defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
396   for example ascii::ascii_info prints just the information about the object not all details
397   unless :append is given filename opens in write mode, overwriting what was already there
398 .       binary[:[filename][:[format][:append]]] -  defaults to the file binaryoutput
399 .       draw[:drawtype[:filename]]              -  for example, draw:tikz, draw:tikz:figure.tex  or draw:x
400 .       socket[:port]                           -  defaults to the standard output port
401 -       saws[:communicatorname]                 -   publishes object to the Scientific Application Webserver (SAWs)
402 
403   Use `PetscViewerDestroy()` after using the viewer, otherwise a memory leak will occur
404 
405   You can control whether calls to this function create a viewer (or return early with *set of `PETSC_FALSE`) with
406   `PetscOptionsPushGetViewerOff()`.  This is useful if calling many small subsolves, in which case XXXViewFromOptions can take
407   an appreciable fraction of the runtime.
408 
409   If PETSc is configured with `--with-viewfromoptions=0` this function always returns with *set of `PETSC_FALSE`
410 
411 .seealso: [](sec_viewers), `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
412           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
413           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
414           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
415           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
416           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
417           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`,
418           `PetscOptionsGetViewerOff()`
419 @*/
420 PetscErrorCode PetscOptionsGetViewer(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
421 {
422   PetscInt  n_max = 1;
423   PetscBool set_internal;
424 
425   PetscFunctionBegin;
426   if (viewer) *viewer = NULL;
427   if (format) *format = PETSC_VIEWER_DEFAULT;
428   PetscCall(PetscOptionsGetViewers_Internal(comm, options, pre, name, &n_max, viewer, format, &set_internal, PETSC_FUNCTION_NAME, PETSC_FALSE));
429   if (set_internal) PetscAssert(n_max == 1, comm, PETSC_ERR_PLIB, "Unexpected: %d != 1 viewers set", (int)n_max);
430   if (set) *set = set_internal;
431   PetscFunctionReturn(PETSC_SUCCESS);
432 }
433 
434 /*@C
435   PetscOptionsGetViewers - Get multiple viewers from a comma-separated list in the options database
436 
437   Collective
438 
439   Input Parameters:
440 + comm    - the communicator to own the viewer
441 . options - options database, use `NULL` for default global database
442 . pre     - the string to prepend to the name or `NULL`
443 . name    - the option one is seeking
444 - n_max   - on input: the maximum number of viewers; on output: the number of viewers in the comma-separated list
445 
446   Output Parameters:
447 + viewers - an array to hold at least `n_max` `PetscViewer`s, or `NULL` if not needed; on output: if not `NULL`, the
448              first `n_max` entries are initialized `PetscViewer`s
449 . formats - an array to hold at least `n_max` `PetscViewerFormat`s, or `NULL` if not needed; on output: if not
450              `NULL`, the first `n_max` entries are valid `PetscViewewFormat`s
451 - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`
452 
453   Level: intermediate
454 
455   Note:
456   See `PetscOptionsGetViewer()` for how the format strings for the viewers are interpreted.  Use `PetscViewerDestroy()` on each viewer, otherwise a memory leak will occur.
457 
458   If PETSc is configured with `--with-viewfromoptions=0` this function always returns with `n_max` of 0 and `set` of `PETSC_FALSE`
459 
460 .seealso: [](sec_viewers), `PetscOptionsGetViewer()`
461 @*/
462 PetscErrorCode PetscOptionsGetViewers(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscInt *n_max, PetscViewer viewers[], PetscViewerFormat formats[], PetscBool *set)
463 {
464   PetscFunctionBegin;
465   PetscCall(PetscOptionsGetViewers_Internal(comm, options, pre, name, n_max, viewers, formats, set, PETSC_FUNCTION_NAME, PETSC_TRUE));
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470   PetscViewerCreate - Creates a viewing context. A `PetscViewer` represents a file, a graphical window, a Unix socket or a variety of other ways
471   of viewing a PETSc object
472 
473   Collective
474 
475   Input Parameter:
476 . comm - MPI communicator
477 
478   Output Parameter:
479 . inviewer - location to put the `PetscViewer` context
480 
481   Level: advanced
482 
483 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType`
484 @*/
485 PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer)
486 {
487   PetscViewer viewer;
488 
489   PetscFunctionBegin;
490   *inviewer = NULL;
491   PetscCall(PetscViewerInitializePackage());
492   PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView));
493   *inviewer    = viewer;
494   viewer->data = NULL;
495   PetscFunctionReturn(PETSC_SUCCESS);
496 }
497 
498 /*@C
499   PetscViewerSetType - Builds `PetscViewer` for a particular implementation.
500 
501   Collective
502 
503   Input Parameters:
504 + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()`
505 - type   - for example, `PETSCVIEWERASCII`
506 
507   Options Database Key:
508 . -viewer_type  <type> - Sets the type; use -help for a list of available methods (for instance, ascii)
509 
510   Level: advanced
511 
512   Note:
513   See `PetscViewerType` for possible values
514 
515 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
516 @*/
517 PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type)
518 {
519   PetscBool match;
520   PetscErrorCode (*r)(PetscViewer);
521 
522   PetscFunctionBegin;
523   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
524   PetscAssertPointer(type, 2);
525   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match));
526   if (match) PetscFunctionReturn(PETSC_SUCCESS);
527 
528   /* cleanup any old type that may be there */
529   PetscTryTypeMethod(viewer, destroy);
530   viewer->ops->destroy = NULL;
531   viewer->data         = NULL;
532 
533   PetscCall(PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps)));
534 
535   PetscCall(PetscFunctionListFind(PetscViewerList, type, &r));
536   PetscCheck(r, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscViewer type given: %s", type);
537 
538   PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type));
539   PetscCall((*r)(viewer));
540   PetscFunctionReturn(PETSC_SUCCESS);
541 }
542 
543 /*@C
544   PetscViewerRegister - Adds a viewer to those available for use with `PetscViewerSetType()`
545 
546   Not Collective
547 
548   Input Parameters:
549 + sname    - name of a new user-defined viewer
550 - function - routine to create method context
551 
552   Level: developer
553 
554   Note:
555   `PetscViewerRegister()` may be called multiple times to add several user-defined viewers.
556 
557   Example Usage:
558 .vb
559    PetscViewerRegister("my_viewer_type", MyViewerCreate);
560 .ve
561 
562   Then, your solver can be chosen with the procedural interface via
563 $     PetscViewerSetType(viewer, "my_viewer_type")
564   or at runtime via the option
565 $     -viewer_type my_viewer_type
566 
567 .seealso: [](sec_viewers), `PetscViewerRegisterAll()`
568  @*/
569 PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
570 {
571   PetscFunctionBegin;
572   PetscCall(PetscViewerInitializePackage());
573   PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function));
574   PetscFunctionReturn(PETSC_SUCCESS);
575 }
576 
577 /*@C
578   PetscViewerSetFromOptions - Sets various options for a viewer based on values in the options database.
579 
580   Collective
581 
582   Input Parameter:
583 . viewer - the viewer context
584 
585   Level: intermediate
586 
587   Note:
588   Must be called after `PetscViewerCreate()` but before the `PetscViewer` is used.
589 
590 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
591 @*/
592 PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
593 {
594   char      vtype[256];
595   PetscBool flg;
596 
597   PetscFunctionBegin;
598   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
599 
600   if (!PetscViewerList) PetscCall(PetscViewerRegisterAll());
601   PetscObjectOptionsBegin((PetscObject)viewer);
602   PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, 256, &flg));
603   if (flg) PetscCall(PetscViewerSetType(viewer, vtype));
604   /* type has not been set? */
605   if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
606   PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject);
607 
608   /* process any options handlers added with PetscObjectAddOptionsHandler() */
609   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject));
610   PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view"));
611   PetscOptionsEnd();
612   PetscFunctionReturn(PETSC_SUCCESS);
613 }
614 
615 PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
616 {
617   PetscFunctionBegin;
618   PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt));
619   PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt));
620   PetscFunctionReturn(PETSC_SUCCESS);
621 }
622 
623 PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
624 {
625   MPI_Comm comm;
626 
627   PetscFunctionBegin;
628   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
629   if (i >= *mcnt) {
630     *mcnt += cnt;
631     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
632   }
633   PetscFunctionReturn(PETSC_SUCCESS);
634 }
635 
636 PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
637 {
638   MPI_Comm comm;
639   PetscFunctionBegin;
640   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
641   *mcnt = 0;
642   PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
643   PetscFunctionReturn(PETSC_SUCCESS);
644 }
645 
646 PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
647 {
648   MPI_Comm comm;
649   PetscFunctionBegin;
650   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
651   while (PETSC_TRUE) {
652     if (rank < *mcnt) break;
653     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
654   }
655   PetscFunctionReturn(PETSC_SUCCESS);
656 }
657 
658 PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
659 {
660   MPI_Comm comm;
661   PetscFunctionBegin;
662   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
663   while (PETSC_TRUE) {
664     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
665     if (!*mcnt) break;
666   }
667   PetscFunctionReturn(PETSC_SUCCESS);
668 }
669