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:   /* these options are printed outside any PetscOptionsBegin()/PetscOptionsEnd() block; they are documented
340:      in the manual section a PetscViewer belongs to, and the default options database is used here so that
341:      this agrees with the rest of the help output */
342:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Viewer", &hashelp));
343:   if (hashelp) {
344:     PetscBool found;

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

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

374:       PetscCall(PetscStrallocpy(value, &loc0_viewer_string));
375:       PetscCall(PetscStrlen(loc0_viewer_string, &viewer_string_length));
376:       this_viewer_string = loc0_viewer_string;

378:       do {
379:         PetscViewer       *this_viewer;
380:         PetscViewerFormat *this_viewer_format;
381:         char              *next_viewer_string = NULL;
382:         char              *comma_separator    = NULL;
383:         PetscInt           n                  = *n_max_p;

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

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

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

410:   Collective

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

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

423:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

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

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

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

492:   Collective

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

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

508:   Level: intermediate

510:   Notes:
511:   See `PetscOptionsCreateViewer()` for how the viewer specifications are interpreted.

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

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

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

528:   Collective

530:   Input Parameter:
531: . comm - MPI communicator

533:   Output Parameter:
534: . inviewer - location to put the `PetscViewer` context

536:   Level: advanced

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

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

553: /*@
554:   PetscViewerSetType - Builds `PetscViewer` for a particular implementation.

556:   Collective

558:   Input Parameters:
559: + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()`
560: - type   - for example, `PETSCVIEWERASCII`

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

565:   Level: advanced

567:   Note:
568:   See `PetscViewerType` for possible values

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

577:   PetscFunctionBegin;
579:   PetscAssertPointer(type, 2);
580:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match));
581:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

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

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

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

593:   PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type));
594:   PetscCall((*r)(viewer));
595:   PetscFunctionReturn(PETSC_SUCCESS);
596: }

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

601:   Not Collective, No Fortran Support

603:   Input Parameters:
604: + sname    - name of a new user-defined viewer
605: - function - routine to create method context

607:   Level: developer

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

612:   Example Usage:
613: .vb
614:    PetscViewerRegister("my_viewer_type", MyViewerCreate);
615: .ve

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

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

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

639:   Collective

641:   Input Parameter:
642: . viewer - the viewer context

644:   Level: intermediate

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

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

656:   PetscFunctionBegin;

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

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

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

677:   Collective

679:   Input Parameter:
680: . viewer - the binary viewer

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

686:   Level: developer

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

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

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

707:   Collective

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

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

717:   Level: developer

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

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

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

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

742:   Collective

744:   Input Parameter:
745: . viewer - the binary viewer

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

750:   Level: developer

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

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

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

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

772:   Collective

774:   Input Parameters:
775: + viewer - the binary viewer
776: - rank   - the calling MPI process rank

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

781:   Level: developer

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

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

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

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

806:   Collective

808:   Input Parameter:
809: . viewer - the binary viewer

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

814:   Level: developer

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

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

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