Actual source code: viewreg.c

  1: #include <petsc/private/viewerimpl.h>
  2: #include <petsc/private/hashtable.h>
  3: #if PetscDefined(HAVE_SAWS)
  4: #include <petscviewersaws.h>
  5: #endif

  7: PetscFunctionList PetscViewerList = NULL;

  9: PetscOptionsHelpPrinted PetscOptionsHelpPrintedSingleton = NULL;
 10: KHASH_SET_INIT_STR(HTPrinted)
 11: struct _n_PetscOptionsHelpPrinted {
 12:   khash_t(HTPrinted) *printed;
 13:   PetscSegBuffer      strings;
 14: };

 16: /*@
 17:   PetscOptionsHelpPrintedDestroy - Destroys the object used to track which help messages have already been printed

 19:   Not Collective

 21:   Input Parameter:
 22: . hp - pointer to the `PetscOptionsHelpPrinted` object to destroy; set to `NULL` on return

 24:   Level: developer

 26: .seealso: `PetscOptionsHelpPrintedCreate()`, `PetscOptionsHelpPrintedCheck()`
 27: @*/
 28: PetscErrorCode PetscOptionsHelpPrintedDestroy(PetscOptionsHelpPrinted *hp)
 29: {
 30:   PetscFunctionBegin;
 31:   if (!*hp) PetscFunctionReturn(PETSC_SUCCESS);
 32:   kh_destroy(HTPrinted, (*hp)->printed);
 33:   PetscCall(PetscSegBufferDestroy(&(*hp)->strings));
 34:   PetscCall(PetscFree(*hp));
 35:   PetscFunctionReturn(PETSC_SUCCESS);
 36: }

 38: /*@
 39:   PetscOptionsHelpPrintedCreate - Creates an object used to manage tracking which help messages have
 40:   been printed so they will not be printed again.

 42:   Output Parameter:
 43: . hp - the created object

 45:   Not Collective

 47:   Level: developer

 49: .seealso: `PetscOptionsHelpPrintedCheck()`, `PetscOptionsHelpPrintChecked()`
 50: @*/
 51: PetscErrorCode PetscOptionsHelpPrintedCreate(PetscOptionsHelpPrinted *hp)
 52: {
 53:   PetscFunctionBegin;
 54:   PetscCall(PetscNew(hp));
 55:   (*hp)->printed = kh_init(HTPrinted);
 56:   PetscCall(PetscSegBufferCreate(sizeof(char), 10000, &(*hp)->strings));
 57:   PetscFunctionReturn(PETSC_SUCCESS);
 58: }

 60: /*@
 61:   PetscOptionsHelpPrintedCheck - Checks if a particular pre, name pair has previous been entered (meaning the help message was printed)

 63:   Not Collective

 65:   Input Parameters:
 66: + hp   - the object used to manage tracking what help messages have been printed
 67: . pre  - the prefix part of the string, many be `NULL`
 68: - name - the string to look for (cannot be `NULL`)

 70:   Output Parameter:
 71: . found - `PETSC_TRUE` if the string was already set

 73:   Level: intermediate

 75: .seealso: `PetscOptionsHelpPrintedCreate()`
 76: @*/
 77: PetscErrorCode PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrinted hp, const char *pre, const char *name, PetscBool *found)
 78: {
 79:   size_t l1, l2;
 80: #if !PetscDefined(HAVE_THREADSAFETY)
 81:   char *both;
 82:   int   newitem;
 83: #endif

 85:   PetscFunctionBegin;
 86:   PetscCall(PetscStrlen(pre, &l1));
 87:   PetscCall(PetscStrlen(name, &l2));
 88:   if (l1 + l2 == 0) {
 89:     *found = PETSC_FALSE;
 90:     PetscFunctionReturn(PETSC_SUCCESS);
 91:   }
 92: #if !PetscDefined(HAVE_THREADSAFETY)
 93:   size_t lboth = l1 + l2 + 1;
 94:   PetscCall(PetscSegBufferGet(hp->strings, lboth, &both));
 95:   PetscCall(PetscStrncpy(both, pre, lboth));
 96:   PetscCall(PetscStrncpy(both + l1, name, l2 + 1));
 97:   kh_put(HTPrinted, hp->printed, both, &newitem);
 98:   if (!newitem) PetscCall(PetscSegBufferUnuse(hp->strings, lboth));
 99:   *found = newitem ? PETSC_FALSE : PETSC_TRUE;
100: #else
101:   *found = PETSC_FALSE;
102: #endif
103:   PetscFunctionReturn(PETSC_SUCCESS);
104: }

106: static PetscBool noviewer = PETSC_FALSE;
107: static PetscBool noviewers[PETSCVIEWERCREATEVIEWEROFFPUSHESMAX];
108: static PetscInt  inoviewers = 0;

110: /*@
111:   PetscOptionsPushCreateViewerOff - sets if `PetscOptionsCreateViewer()`, `PetscOptionsViewer()`, and `PetscOptionsCreateViewers()` return viewers.

113:   Logically Collective

115:   Input Parameter:
116: . flg - `PETSC_TRUE` to turn off viewer creation, `PETSC_FALSE` to turn it on.

118:   Options Database Key:
119: . -viewfromoptions (on|off) - Enable or disable `PetscOptionsCreateViewer()` and `XXXViewFromOptions()` calls, for applications with many small solves turn this off

121:   Level: developer

123:   Note:
124:   Calling `XXXViewFromOptions` in an inner loop can be expensive.  This can appear, for example, when using
125:   many small subsolves.  Call this function to control viewer creation in `PetscOptionsCreateViewer()`, thus removing the expensive `XXXViewFromOptions` calls.

127:   Developer Notes:
128:   Instead of using this approach, the calls to `PetscOptionsCreateViewer()` can be moved into `XXXSetFromOptions()`

130: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPopCreateViewerOff()`
131: @*/
132: PetscErrorCode PetscOptionsPushCreateViewerOff(PetscBool flg)
133: {
134:   PetscFunctionBegin;
135:   PetscCheck(inoviewers < PETSCVIEWERCREATEVIEWEROFFPUSHESMAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPushCreateViewerOff(), perhaps you forgot PetscOptionsPopCreateViewerOff()?");

137:   noviewers[inoviewers++] = noviewer;
138:   noviewer                = flg;
139:   PetscFunctionReturn(PETSC_SUCCESS);
140: }

142: /*@
143:   PetscOptionsPopCreateViewerOff - reset whether `PetscOptionsCreateViewer()` returns a viewer.

145:   Logically Collective

147:   Level: developer

149:   Note:
150:   See `PetscOptionsPushCreateViewerOff()`

152: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPushCreateViewerOff()`
153: @*/
154: PetscErrorCode PetscOptionsPopCreateViewerOff(void)
155: {
156:   PetscFunctionBegin;
157:   PetscCheck(inoviewers, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPopCreateViewerOff(), perhaps you forgot PetscOptionsPushCreateViewerOff()?");
158:   noviewer = noviewers[--inoviewers];
159:   PetscFunctionReturn(PETSC_SUCCESS);
160: }

162: /*@
163:   PetscOptionsGetCreateViewerOff - do `PetscOptionsCreateViewer()`, `PetscOptionsViewer()`, and `PetscOptionsCreateViewers()` return viewers

165:   Logically Collective

167:   Output Parameter:
168: . flg - whether viewers are returned.

170:   Level: developer

172: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`
173: @*/
174: PetscErrorCode PetscOptionsGetCreateViewerOff(PetscBool *flg)
175: {
176:   PetscFunctionBegin;
177:   PetscAssertPointer(flg, 1);
178:   *flg = noviewer;
179:   PetscFunctionReturn(PETSC_SUCCESS);
180: }

182: static PetscErrorCode PetscOptionsCreateViewers_Single(MPI_Comm comm, const char value[], PetscViewer *viewer, PetscViewerFormat *format)
183: {
184:   char    *loc0_vtype = NULL, *loc1_fname = NULL, *loc2_fmt = NULL, *loc3_fmode = NULL;
185:   PetscInt cnt;
186:   size_t   viewer_string_length;
187:   const char *viewers[] = {PETSCVIEWERASCII, PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSOCKET, PETSCVIEWERMATLAB, PETSCVIEWERSAWS, PETSCVIEWERVTK, PETSCVIEWERHDF5, PETSCVIEWERGLVIS, PETSCVIEWEREXODUSII, PETSCVIEWERPYTHON, PETSCVIEWERPYVISTA, NULL}; /* list should be automatically generated from PetscViewersList */

189:   PetscFunctionBegin;
190:   PetscCall(PetscStrlen(value, &viewer_string_length));
191:   if (!viewer_string_length) {
192:     if (format) *format = PETSC_VIEWER_DEFAULT;
193:     if (viewer) {
194:       PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
195:       PetscCall(PetscObjectReference((PetscObject)*viewer));
196:     }
197:     PetscFunctionReturn(PETSC_SUCCESS);
198:   }

200:   PetscCall(PetscStrallocpy(value, &loc0_vtype));
201:   PetscCall(PetscStrchr(loc0_vtype, ':', &loc1_fname));
202:   if (loc1_fname) {
203:     PetscBool is_daos;
204:     *loc1_fname++ = 0;
205:     // When using DAOS, the filename will have the form "daos:/path/to/file.h5", so capture the rest of it.
206:     PetscCall(PetscStrncmp(loc1_fname, "daos:", 5, &is_daos));
207:     PetscCall(PetscStrchr(loc1_fname + (is_daos == PETSC_TRUE ? 5 : 0), ':', &loc2_fmt));
208:   }
209:   if (loc2_fmt) {
210:     *loc2_fmt++ = 0;
211:     PetscCall(PetscStrchr(loc2_fmt, ':', &loc3_fmode));
212:   }
213:   if (loc3_fmode) *loc3_fmode++ = 0;
214:   PetscCall(PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii", viewers, &cnt));
215:   PetscCheck(cnt <= (PetscInt)sizeof(viewers) - 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Unknown viewer type: %s", loc0_vtype);
216:   if (viewer) {
217:     if (!loc1_fname) {
218:       switch (cnt) {
219:       case 0:
220:         PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
221:         PetscCall(PetscObjectReference((PetscObject)*viewer));
222:         break;
223:       case 1:
224:         if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PetscCall(PETSC_ERR_PLIB);
225:         PetscCall(PetscObjectReference((PetscObject)*viewer));
226:         break;
227:       case 2:
228:         if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PetscCall(PETSC_ERR_PLIB);
229:         PetscCall(PetscObjectReference((PetscObject)*viewer));
230:         break;
231: #if PetscDefined(USE_SOCKET_VIEWER)
232:       case 3:
233:         if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PetscCall(PETSC_ERR_PLIB);
234:         PetscCall(PetscObjectReference((PetscObject)*viewer));
235:         break;
236: #endif
237: #if PetscDefined(HAVE_MATLAB)
238:       case 4:
239:         if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PetscCall(PETSC_ERR_PLIB);
240:         PetscCall(PetscObjectReference((PetscObject)*viewer));
241:         break;
242: #endif
243: #if PetscDefined(HAVE_SAWS)
244:       case 5:
245:         if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PetscCall(PETSC_ERR_PLIB);
246:         PetscCall(PetscObjectReference((PetscObject)*viewer));
247:         break;
248: #endif
249: #if PetscDefined(HAVE_HDF5)
250:       case 7:
251:         if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PetscCall(PETSC_ERR_PLIB);
252:         PetscCall(PetscObjectReference((PetscObject)*viewer));
253:         break;
254: #endif
255:       case 8:
256:         if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PetscCall(PETSC_ERR_PLIB);
257:         PetscCall(PetscObjectReference((PetscObject)*viewer));
258:         break;
259: #if PetscDefined(HAVE_EXODUSII)
260:       case 9:
261:         if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PetscCall(PETSC_ERR_PLIB);
262:         PetscCall(PetscObjectReference((PetscObject)*viewer));
263:         break;
264: #endif
265:       case 10:
266:         if (!(*viewer = PETSC_VIEWER_PYTHON_(comm))) PetscCall(PETSC_ERR_PLIB);
267:         PetscCall(PetscObjectReference((PetscObject)*viewer));
268:         break;
269:       case 11:
270:         if (!(*viewer = PETSC_VIEWER_PYVISTA_(comm))) PetscCall(PETSC_ERR_PLIB);
271:         PetscCall(PetscObjectReference((PetscObject)*viewer));
272:         break;
273:       default:
274:         SETERRQ(comm, PETSC_ERR_SUP, "Unsupported viewer %s", loc0_vtype);
275:       }
276:     } else {
277:       if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
278:         PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
279:         PetscCall(PetscObjectReference((PetscObject)*viewer));
280:       } else {
281:         PetscFileMode fmode;
282:         PetscBool     flag = PETSC_FALSE;

284:         PetscCall(PetscViewerCreate(comm, viewer));
285:         PetscCall(PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii"));
286:         fmode = FILE_MODE_WRITE;
287:         if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
288:           PetscCall(PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag));
289:           PetscCheck(flag, comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown file mode: %s", loc3_fmode);
290:         }
291:         if (loc2_fmt) {
292:           PetscBool tk, im;
293:           PetscCall(PetscStrcmp(loc1_fname, "tikz", &tk));
294:           PetscCall(PetscStrcmp(loc1_fname, "image", &im));
295:           if (tk || im) {
296:             PetscCall(PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE));
297:             *loc2_fmt = 0;
298:           }
299:         }
300:         PetscCall(PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE));
301:         PetscCall(PetscViewerFileSetName(*viewer, loc1_fname));
302:         if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer, loc1_fname));
303:         PetscCall(PetscViewerSetFromOptions(*viewer));
304:       }
305:     }
306:   }
307:   if (viewer) PetscCall(PetscViewerSetUp(*viewer));
308:   if (loc2_fmt && *loc2_fmt) {
309:     PetscViewerFormat tfmt;
310:     PetscBool         flag;

312:     PetscCall(PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag));
313:     if (format) *format = tfmt;
314:     PetscCheck(flag, comm, PETSC_ERR_SUP, "Unknown viewer format %s", loc2_fmt);
315:   } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */
316:     PetscCall(PetscViewerGetFormat(*viewer, format));
317:   }
318:   PetscCall(PetscFree(loc0_vtype));
319:   PetscFunctionReturn(PETSC_SUCCESS);
320: }

322: static PetscErrorCode PetscOptionsCreateViewers_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)
323: {
324:   const char *value;
325:   PetscBool   flag, hashelp;
326:   PetscInt    n_max;

328:   PetscFunctionBegin;
329:   PetscAssertPointer(name, 4);
330:   PetscAssertPointer(n_max_p, 5);
331:   n_max = *n_max_p;
332:   PetscCheck(n_max >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid size %" PetscInt_FMT " of passed arrays", *n_max_p);
333:   *n_max_p = 0;

335:   if (set) *set = PETSC_FALSE;
336:   PetscCall(PetscOptionsGetCreateViewerOff(&flag));
337:   if (flag) PetscFunctionReturn(PETSC_SUCCESS);

339:   PetscCall(PetscOptionsHasHelp(NULL, &hashelp));
340:   if (hashelp) {
341:     PetscBool found;

343:     if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
344:     PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found));
345:     if (!found && viewer) {
346:       PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1));
347:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s ascii[:[filename][:[format][:filemode]]]: %s (%s)\n", pre ? pre : "", name + 1, "Prints object to stdout or ASCII file", func_name));
348:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s binary[:[filename][:[format][:filemode]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", func_name));
349:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", func_name));
350:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", func_name));
351:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", func_name));
352:       if (allow_multiple) PetscCall((*PetscHelpPrintf)(comm, "  -%s%s v1[,v2,...]: %s (%s)\n", pre ? pre : "", name + 1, "Multiple viewers", func_name));
353:     }
354:   }

356:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
357:   if (flag) {
358:     if (set) *set = PETSC_TRUE;
359:     if (!value) {
360:       PetscCheck(n_max > 0, comm, PETSC_ERR_ARG_SIZ, "More viewers (1) than max available (0)");
361:       if (format) *format = PETSC_VIEWER_DEFAULT;
362:       if (viewer) {
363:         PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
364:         PetscCall(PetscObjectReference((PetscObject)*viewer));
365:       }
366:       *n_max_p = 1;
367:     } else {
368:       char  *loc0_viewer_string = NULL, *this_viewer_string = NULL;
369:       size_t viewer_string_length;

371:       PetscCall(PetscStrallocpy(value, &loc0_viewer_string));
372:       PetscCall(PetscStrlen(loc0_viewer_string, &viewer_string_length));
373:       this_viewer_string = loc0_viewer_string;

375:       do {
376:         PetscViewer       *this_viewer;
377:         PetscViewerFormat *this_viewer_format;
378:         char              *next_viewer_string = NULL;
379:         char              *comma_separator    = NULL;
380:         PetscInt           n                  = *n_max_p;

382:         PetscCheck(n < n_max, comm, PETSC_ERR_PLIB, "More viewers than max available (%" PetscInt_FMT ")", n_max);

384:         PetscCall(PetscStrchr(this_viewer_string, ',', &comma_separator));
385:         if (comma_separator) {
386:           PetscCheck(allow_multiple, comm, PETSC_ERR_ARG_OUTOFRANGE, "Trying to pass multiple viewers to %s: only one allowed.  Use PetscOptionsCreateViewers() instead", func_name);
387:           *comma_separator   = 0;
388:           next_viewer_string = comma_separator + 1;
389:         }
390:         this_viewer = PetscSafePointerPlusOffset(viewer, n);
391:         if (this_viewer) *this_viewer = NULL;
392:         this_viewer_format = PetscSafePointerPlusOffset(format, n);
393:         if (this_viewer_format) *this_viewer_format = PETSC_VIEWER_DEFAULT;
394:         PetscCall(PetscOptionsCreateViewers_Single(comm, this_viewer_string, this_viewer, this_viewer_format));
395:         this_viewer_string = next_viewer_string;
396:         (*n_max_p)++;
397:       } while (this_viewer_string);
398:       PetscCall(PetscFree(loc0_viewer_string));
399:     }
400:   }
401:   PetscFunctionReturn(PETSC_SUCCESS);
402: }

404: /*@
405:   PetscOptionsCreateViewer - Creates a `PetscViewer` and `PetscViewerFormat` based on a viewer specification in the options database

407:   Collective

409:   Input Parameters:
410: + comm    - the communicator to own the viewer
411: . options - options database, use `NULL` for default global database
412: . prefix  - the string to prepend to the name (may be `NULL`)
413: - name    - the options database name that will be checked for

415:   Output Parameters:
416: + viewer - the viewer, pass `NULL` if not needed
417: . format - the `PetscViewerFormat` requested by the user, pass `NULL` if not needed
418: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

420:   Level: intermediate

422:   Notes:
423:   The Viewer specification has the following form
424: .vb
425:   ascii[:[filename][:[format][:filemode]]]   - filename defaults to stdout
426:   binary[:[filename][:[format][:filemode]]]  - defaults to the filename of binaryoutput
427:   hdf5[:[filename][:[format][:filemode]]]    - HDF5 input and output, PETSCVIEWERHDF5
428:   pyvista[:[filename][:[format][:filemode]]] - display the object with PyVista, PETSCVIEWERPYVISTA
429:   draw[:x]                                   - draw the object to X Windows
430:   draw[:tikz[:filename]]                     - draw the object to a TikZ file
431:   draw[:image[:dirname]]                     - draw the object to an image in memory that gets saved to files in a directory
432:   socket[:port]                              - defaults to the standard socket output port of 5005, see PetscViewerSocketOpen()
433:   saws[:communicatorname]                    - publishes object to the Scientific Application Webserver (SAWs)
434:   vtk:filename.vts                           - VTK output, PETSCVIEWERVTK
435: .ve

437:   See `PetscViewerType` for a list of all available viewer types (the string before the first `:`).

439:   See `PetscViewerFormat` for the possible values of `format`.

441:   See `PetscFileMode` for the possible values of `filemode`.

443:   If no viewer type is indicated before the first `:`, then `ascii` is used.

445:   Unless `filemode` is `append` or `append_update`, files opened in write mode overwrite any previous file.

447:   You can control whether calls to this function return immediately with a value of `set` of `PETSC_FALSE` using `PetscOptionsPushCreateViewerOff()`.
448:   This is useful if calling many small subsolves, in which case `XXXViewFromOptions()` calls can take an appreciable fraction of the runtime.

450:   This routine is thread-safe for accessing predefined `PetscViewer`s like `PETSC_VIEWER_STDOUT_SELF` but not for accessing
451:   files by name.

453:   This routine is used by `KSPMonitorSetFromOptions()`, `SNESMonitorSetFromOptions()`, `TSMonitorSetFromOptions()`, `TaoMonitorSetFromOptions()`, and `DMMonitorSetFromOptions()`,
454:   as well as `PetscObjectViewFromOptions()` and all functions, such as `VecViewFromOptions()` that call it.

456:   Example Usage:
457: .vb
458:   ascii:mesh.tex:ascii_latex - View a `DMPLEX` in LaTeX/TikZ
459:   draw:tikz:figure.tex       - View an object in the file `figure.tex` using TikZ
460: .ve

462: .seealso: [](sec_viewers), `PetscViewerFormat`, `PetscViewerDestroy()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
463:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
464:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
465:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
466:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
467:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
468:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`,
469:           `KSPMonitorSetFromOptions()`, `SNESMonitorSetFromOptions()`, `TSMonitorSetFromOptions()`,
470:           `TaoMonitorSetFromOptions()`, `DMMonitorSetFromOptions()`, `PetscObjectViewFromOptions()`, `VecViewFromOptions()`
471: @*/
472: PetscErrorCode PetscOptionsCreateViewer(MPI_Comm comm, PetscOptions options, const char prefix[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
473: {
474:   PetscInt  n_max = 1;
475:   PetscBool set_internal;

477:   PetscFunctionBegin;
478:   if (viewer) *viewer = NULL;
479:   if (format) *format = PETSC_VIEWER_DEFAULT;
480:   PetscCall(PetscOptionsCreateViewers_Internal(comm, options, prefix, name, &n_max, viewer, format, &set_internal, PETSC_FUNCTION_NAME, PETSC_FALSE));
481:   if (set_internal) PetscAssert(n_max == 1, comm, PETSC_ERR_PLIB, "Unexpected: %" PetscInt_FMT " != 1 viewers set", n_max);
482:   if (set) *set = set_internal;
483:   PetscFunctionReturn(PETSC_SUCCESS);
484: }

486: /*@
487:   PetscOptionsCreateViewers - Create multiple viewers from a comma-separated list of viewer specifications in the options database

489:   Collective

491:   Input Parameters:
492: + comm    - the communicator to own the viewers
493: . options - options database, use `NULL` for default global database
494: . prefix  - the string to prepend to the name (may be `NULL`)
495: . name    - the options database name that will be checked for
496: - n_max   - on input: the maximum number of viewers; on output: the number of viewers found in the comma-separated list

498:   Output Parameters:
499: + viewers - an array to hold at least `n_max` `PetscViewer`s, or `NULL` if not needed; on output: if not `NULL`, the
500:             first `n_max` entries are initialized `PetscViewer`s
501: . formats - an array to hold at least `n_max` `PetscViewerFormat`s, or `NULL` if not needed; on output: if not
502:             `NULL`, the first `n_max` entries are valid `PetscViewewFormat`s
503: - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`

505:   Level: intermediate

507:   Notes:
508:   See `PetscOptionsCreateViewer()` for how the viewer specifications are interpreted.

510:   Use `PetscViewerDestroy()` on each viewer.

512: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`
513: @*/
514: PetscErrorCode PetscOptionsCreateViewers(MPI_Comm comm, PetscOptions options, const char prefix[], const char name[], PetscInt *n_max, PetscViewer viewers[], PetscViewerFormat formats[], PetscBool *set)
515: {
516:   PetscFunctionBegin;
517:   PetscCall(PetscOptionsCreateViewers_Internal(comm, options, prefix, name, n_max, viewers, formats, set, PETSC_FUNCTION_NAME, PETSC_TRUE));
518:   PetscFunctionReturn(PETSC_SUCCESS);
519: }

521: /*@
522:   PetscViewerCreate - Creates a viewing context. A `PetscViewer` represents a file, a graphical window, a Unix socket or a variety of other ways
523:   of viewing a PETSc object

525:   Collective

527:   Input Parameter:
528: . comm - MPI communicator

530:   Output Parameter:
531: . inviewer - location to put the `PetscViewer` context

533:   Level: advanced

535: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType`
536: @*/
537: PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer)
538: {
539:   PetscViewer viewer;

541:   PetscFunctionBegin;
542:   PetscAssertPointer(inviewer, 2);
543:   PetscCall(PetscViewerInitializePackage());
544:   PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView));
545:   *inviewer    = viewer;
546:   viewer->data = NULL;
547:   PetscFunctionReturn(PETSC_SUCCESS);
548: }

550: /*@
551:   PetscViewerSetType - Builds `PetscViewer` for a particular implementation.

553:   Collective

555:   Input Parameters:
556: + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()`
557: - type   - for example, `PETSCVIEWERASCII`

559:   Options Database Key:
560: . -viewer_type  type - Sets the type; use -help for a list of available methods (for instance, ascii)

562:   Level: advanced

564:   Note:
565:   See `PetscViewerType` for possible values

567: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
568: @*/
569: PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type)
570: {
571:   PetscBool match;
572:   PetscErrorCode (*r)(PetscViewer);

574:   PetscFunctionBegin;
576:   PetscAssertPointer(type, 2);
577:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match));
578:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

580:   /* cleanup any old type that may be there */
581:   PetscTryTypeMethod(viewer, destroy);
582:   viewer->ops->destroy = NULL;
583:   viewer->data         = NULL;

585:   PetscCall(PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps)));

587:   PetscCall(PetscFunctionListFind(PetscViewerList, type, &r));
588:   PetscCheck(r, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscViewer type given: %s", type);

590:   PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type));
591:   PetscCall((*r)(viewer));
592:   PetscFunctionReturn(PETSC_SUCCESS);
593: }

595: /*@
596:   PetscViewerRegister - Adds a viewer to those available for use with `PetscViewerSetType()`

598:   Not Collective, No Fortran Support

600:   Input Parameters:
601: + sname    - name of a new user-defined viewer
602: - function - routine to create method context

604:   Level: developer

606:   Note:
607:   `PetscViewerRegister()` may be called multiple times to add several user-defined viewers.

609:   Example Usage:
610: .vb
611:    PetscViewerRegister("my_viewer_type", MyViewerCreate);
612: .ve

614:   Then, your solver can be chosen with the procedural interface via
615: .vb
616:   PetscViewerSetType(viewer, "my_viewer_type")
617: .ve
618:   or at runtime via the option
619: .vb
620:   -viewer_type my_viewer_type
621: .ve

623: .seealso: [](sec_viewers), `PetscViewerRegisterAll()`
624:  @*/
625: PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
626: {
627:   PetscFunctionBegin;
628:   PetscCall(PetscViewerInitializePackage());
629:   PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function));
630:   PetscFunctionReturn(PETSC_SUCCESS);
631: }

633: /*@
634:   PetscViewerSetFromOptions - Sets various options for a viewer based on values in the options database.

636:   Collective

638:   Input Parameter:
639: . viewer - the viewer context

641:   Level: intermediate

643:   Note:
644:   Must be called after `PetscViewerCreate()` but before the `PetscViewer` is used.

646: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
647: @*/
648: PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
649: {
650:   char      vtype[256];
651:   PetscBool flg;

653:   PetscFunctionBegin;

656:   if (!PetscViewerList) PetscCall(PetscViewerRegisterAll());
657:   PetscObjectOptionsBegin((PetscObject)viewer);
658:   PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, sizeof(vtype), &flg));
659:   if (flg) PetscCall(PetscViewerSetType(viewer, vtype));
660:   /* type has not been set? */
661:   if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
662:   PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject);

664:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
665:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject));
666:   PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view"));
667:   PetscOptionsEnd();
668:   PetscFunctionReturn(PETSC_SUCCESS);
669: }

671: /*@
672:   PetscViewerFlowControlStart - Begin a flow-controlled viewer operation on the main MPI process

674:   Collective

676:   Input Parameter:
677: . viewer - the binary viewer

679:   Output Parameters:
680: + mcnt - the current flow-control counter on the main MPI process
681: - cnt  - the flow-control window size (also read from the viewer)

683:   Level: developer

685:   Note:
686:   Used together with `PetscViewerFlowControlStepMain()` and `PetscViewerFlowControlEndMain()` on the main process (rank 0),
687:   and with `PetscViewerFlowControlStepWorker()` and `PetscViewerFlowControlEndWorker()` on the other processes, to serialize
688:   I/O work through a bounded window so that all processes do not simultaneously flood the main process with data.

690: .seealso: `PetscViewer`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`, `PetscViewerFlowControlStepWorker()`,
691:           `PetscViewerFlowControlEndWorker()`, `PetscViewerBinaryGetFlowControl()`
692: @*/
693: PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
694: {
695:   PetscFunctionBegin;
696:   PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt));
697:   PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt));
698:   PetscFunctionReturn(PETSC_SUCCESS);
699: }

701: /*@
702:   PetscViewerFlowControlStepMain - Advance the flow-control window on the main MPI process during a viewer operation

704:   Collective

706:   Input Parameters:
707: + viewer - the binary viewer
708: . i      - the current MPI rank being served
709: - cnt    - the flow-control window size returned by `PetscViewerFlowControlStart()`

711:   Input/Output Parameter:
712: . mcnt - the running flow-control counter; incremented and broadcast when `i` reaches it

714:   Level: developer

716:   Note:
717:   Called on the main MPI process (rank 0) once per worker rank in a loop; when the current rank has caught up to `mcnt`
718:   the window is advanced by `cnt` and broadcast so waiting workers can proceed.

720: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlEndMain()`, `PetscViewerFlowControlStepWorker()`,
721:           `PetscViewerFlowControlEndWorker()`
722: @*/
723: PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
724: {
725:   MPI_Comm comm;

727:   PetscFunctionBegin;
728:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
729:   if (i >= *mcnt) {
730:     *mcnt += cnt;
731:     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
732:   }
733:   PetscFunctionReturn(PETSC_SUCCESS);
734: }

736: /*@
737:   PetscViewerFlowControlEndMain - Finish a flow-controlled viewer operation on the main MPI process by signalling completion to the workers

739:   Collective

741:   Input Parameter:
742: . viewer - the binary viewer

744:   Input/Output Parameter:
745: . mcnt - the flow-control counter; reset to 0 and broadcast to signal completion

747:   Level: developer

749:   Note:
750:   Broadcasting `mcnt = 0` releases any worker MPI processes still waiting inside `PetscViewerFlowControlEndWorker()`.

752: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlStepWorker()`,
753:           `PetscViewerFlowControlEndWorker()`
754: @*/
755: PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
756: {
757:   MPI_Comm comm;

759:   PetscFunctionBegin;
760:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
761:   *mcnt = 0;
762:   PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
763:   PetscFunctionReturn(PETSC_SUCCESS);
764: }

766: /*@
767:   PetscViewerFlowControlStepWorker - Wait on a worker MPI process until the flow-control window includes this rank

769:   Collective

771:   Input Parameters:
772: + viewer - the binary viewer
773: - rank   - the calling MPI process rank

775:   Input/Output Parameter:
776: . mcnt - the flow-control counter; updated with values broadcast from the main MPI process until it exceeds `rank`

778:   Level: developer

780:   Note:
781:   Blocks in a loop of `MPI_Bcast()` until the main MPI process (through `PetscViewerFlowControlStepMain()`) advances the
782:   window past this rank, giving the worker permission to perform its I/O.

784: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`,
785:           `PetscViewerFlowControlEndWorker()`
786: @*/
787: PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
788: {
789:   MPI_Comm comm;

791:   PetscFunctionBegin;
792:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
793:   while (PETSC_TRUE) {
794:     if (rank < *mcnt) break;
795:     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
796:   }
797:   PetscFunctionReturn(PETSC_SUCCESS);
798: }

800: /*@
801:   PetscViewerFlowControlEndWorker - Wait on a worker MPI process for the main MPI process to signal completion of a flow-controlled viewer operation

803:   Collective

805:   Input Parameter:
806: . viewer - the binary viewer

808:   Input/Output Parameter:
809: . mcnt - the flow-control counter; updated with values broadcast from the main MPI process until it becomes 0

811:   Level: developer

813:   Note:
814:   Blocks in a loop of `MPI_Bcast()` until `PetscViewerFlowControlEndMain()` sends a `mcnt = 0` completion signal.

816: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`,
817:           `PetscViewerFlowControlStepWorker()`
818: @*/
819: PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
820: {
821:   MPI_Comm comm;

823:   PetscFunctionBegin;
824:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
825:   while (PETSC_TRUE) {
826:     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
827:     if (!*mcnt) break;
828:   }
829:   PetscFunctionReturn(PETSC_SUCCESS);
830: }