Actual source code: viewreg.c

  1: #include <petsc/private/viewerimpl.h>
  2: #include <petsc/private/hashtable.h>
  3: #if defined(PETSC_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: PetscErrorCode PetscOptionsHelpPrintedDestroy(PetscOptionsHelpPrinted *hp)
 17: {
 18:   PetscFunctionBegin;
 19:   if (!*hp) PetscFunctionReturn(PETSC_SUCCESS);
 20:   kh_destroy(HTPrinted, (*hp)->printed);
 21:   PetscCall(PetscSegBufferDestroy(&(*hp)->strings));
 22:   PetscCall(PetscFree(*hp));
 23:   PetscFunctionReturn(PETSC_SUCCESS);
 24: }

 26: /*@C
 27:   PetscOptionsHelpPrintedCreate - Creates an object used to manage tracking which help messages have
 28:   been printed so they will not be printed again.

 30:   Output Parameter:
 31: . hp - the created object

 33:   Not Collective

 35:   Level: developer

 37: .seealso: `PetscOptionsHelpPrintedCheck()`, `PetscOptionsHelpPrintChecked()`
 38: @*/
 39: PetscErrorCode PetscOptionsHelpPrintedCreate(PetscOptionsHelpPrinted *hp)
 40: {
 41:   PetscFunctionBegin;
 42:   PetscCall(PetscNew(hp));
 43:   (*hp)->printed = kh_init(HTPrinted);
 44:   PetscCall(PetscSegBufferCreate(sizeof(char), 10000, &(*hp)->strings));
 45:   PetscFunctionReturn(PETSC_SUCCESS);
 46: }

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

 51:   Not Collective

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

 58:   Output Parameter:
 59: . found - `PETSC_TRUE` if the string was already set

 61:   Level: intermediate

 63: .seealso: `PetscOptionsHelpPrintedCreate()`
 64: @*/
 65: PetscErrorCode PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrinted hp, const char *pre, const char *name, PetscBool *found)
 66: {
 67:   size_t l1, l2;
 68: #if !defined(PETSC_HAVE_THREADSAFETY)
 69:   char *both;
 70:   int   newitem;
 71: #endif

 73:   PetscFunctionBegin;
 74:   PetscCall(PetscStrlen(pre, &l1));
 75:   PetscCall(PetscStrlen(name, &l2));
 76:   if (l1 + l2 == 0) {
 77:     *found = PETSC_FALSE;
 78:     PetscFunctionReturn(PETSC_SUCCESS);
 79:   }
 80: #if !defined(PETSC_HAVE_THREADSAFETY)
 81:   size_t lboth = l1 + l2 + 1;
 82:   PetscCall(PetscSegBufferGet(hp->strings, lboth, &both));
 83:   PetscCall(PetscStrncpy(both, pre, lboth));
 84:   PetscCall(PetscStrncpy(both + l1, name, l2 + 1));
 85:   kh_put(HTPrinted, hp->printed, both, &newitem);
 86:   if (!newitem) PetscCall(PetscSegBufferUnuse(hp->strings, lboth));
 87:   *found = newitem ? PETSC_FALSE : PETSC_TRUE;
 88: #else
 89:   *found = PETSC_FALSE;
 90: #endif
 91:   PetscFunctionReturn(PETSC_SUCCESS);
 92: }

 94: static PetscBool noviewer = PETSC_FALSE;
 95: static PetscBool noviewers[PETSCVIEWERGETVIEWEROFFPUSHESMAX];
 96: static PetscInt  inoviewers = 0;

 98: /*@
 99:   PetscOptionsPushGetViewerOff - sets if a `PetscOptionsGetViewer()` returns a viewer.

101:   Logically Collective

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

106:   Level: developer

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

112:   Developer Notes:
113:   Instead of using this approach, the calls to `PetscOptionsGetViewer()` can be moved into `XXXSetFromOptions()`

115: .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsPopGetViewerOff()`
116: @*/
117: PetscErrorCode PetscOptionsPushGetViewerOff(PetscBool flg)
118: {
119:   PetscFunctionBegin;
120:   PetscCheck(inoviewers < PETSCVIEWERGETVIEWEROFFPUSHESMAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPushGetViewerOff(), perhaps you forgot PetscOptionsPopGetViewerOff()?");

122:   noviewers[inoviewers++] = noviewer;
123:   noviewer                = flg;
124:   PetscFunctionReturn(PETSC_SUCCESS);
125: }

127: /*@
128:   PetscOptionsPopGetViewerOff - reset whether `PetscOptionsGetViewer()` returns a viewer.

130:   Logically Collective

132:   Level: developer

134:   Note:
135:   See `PetscOptionsPushGetViewerOff()`

137: .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()`
138: @*/
139: PetscErrorCode PetscOptionsPopGetViewerOff(void)
140: {
141:   PetscFunctionBegin;
142:   PetscCheck(inoviewers, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPopGetViewerOff(), perhaps you forgot PetscOptionsPushGetViewerOff()?");
143:   noviewer = noviewers[--inoviewers];
144:   PetscFunctionReturn(PETSC_SUCCESS);
145: }

147: /*@
148:   PetscOptionsGetViewerOff - does `PetscOptionsGetViewer()` return a viewer?

150:   Logically Collective

152:   Output Parameter:
153: . flg - whether viewers are returned.

155:   Level: developer

157:   Note:
158:   See `PetscOptionsPushGetViewerOff()`

160: .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`
161: @*/
162: PetscErrorCode PetscOptionsGetViewerOff(PetscBool *flg)
163: {
164:   PetscFunctionBegin;
165:   PetscAssertPointer(flg, 1);
166:   *flg = noviewer;
167:   PetscFunctionReturn(PETSC_SUCCESS);
168: }

170: static PetscErrorCode PetscOptionsGetViewers_Single(MPI_Comm comm, const char value[], PetscViewer *viewer, PetscViewerFormat *format)
171: {
172:   char       *loc0_vtype = NULL, *loc1_fname = NULL, *loc2_fmt = NULL, *loc3_fmode = NULL;
173:   PetscInt    cnt;
174:   size_t      viewer_string_length;
175:   const char *viewers[] = {PETSCVIEWERASCII, PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSOCKET, PETSCVIEWERMATLAB, PETSCVIEWERSAWS, PETSCVIEWERVTK, PETSCVIEWERHDF5, PETSCVIEWERGLVIS, PETSCVIEWEREXODUSII, NULL};

177:   PetscFunctionBegin;
178:   PetscCall(PetscStrlen(value, &viewer_string_length));
179:   if (!viewer_string_length) {
180:     if (format) *format = PETSC_VIEWER_DEFAULT;
181:     if (viewer) PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
182:     PetscFunctionReturn(PETSC_SUCCESS);
183:   }

185:   PetscCall(PetscStrallocpy(value, &loc0_vtype));
186:   PetscCall(PetscStrchr(loc0_vtype, ':', &loc1_fname));
187:   if (loc1_fname) {
188:     *loc1_fname++ = 0;
189:     PetscCall(PetscStrchr(loc1_fname, ':', &loc2_fmt));
190:   }
191:   if (loc2_fmt) {
192:     *loc2_fmt++ = 0;
193:     PetscCall(PetscStrchr(loc2_fmt, ':', &loc3_fmode));
194:   }
195:   if (loc3_fmode) *loc3_fmode++ = 0;
196:   PetscCall(PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii", viewers, &cnt));
197:   PetscCheck(cnt <= (PetscInt)sizeof(viewers) - 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Unknown viewer type: %s", loc0_vtype);
198:   if (viewer) {
199:     if (!loc1_fname) {
200:       switch (cnt) {
201:       case 0:
202:         PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
203:         break;
204:       case 1:
205:         if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PetscCall(PETSC_ERR_PLIB);
206:         break;
207:       case 2:
208:         if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PetscCall(PETSC_ERR_PLIB);
209:         break;
210: #if defined(PETSC_USE_SOCKET_VIEWER)
211:       case 3:
212:         if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PetscCall(PETSC_ERR_PLIB);
213:         break;
214: #endif
215: #if defined(PETSC_HAVE_MATLAB)
216:       case 4:
217:         if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PetscCall(PETSC_ERR_PLIB);
218:         break;
219: #endif
220: #if defined(PETSC_HAVE_SAWS)
221:       case 5:
222:         if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PetscCall(PETSC_ERR_PLIB);
223:         break;
224: #endif
225: #if defined(PETSC_HAVE_HDF5)
226:       case 7:
227:         if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PetscCall(PETSC_ERR_PLIB);
228:         break;
229: #endif
230:       case 8:
231:         if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PetscCall(PETSC_ERR_PLIB);
232:         break;
233: #if defined(PETSC_HAVE_EXODUSII)
234:       case 9:
235:         if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PetscCall(PETSC_ERR_PLIB);
236:         break;
237: #endif
238:       default:
239:         SETERRQ(comm, PETSC_ERR_SUP, "Unsupported viewer %s", loc0_vtype);
240:       }
241:     } else {
242:       if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
243:         PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
244:       } else {
245:         PetscFileMode fmode;
246:         PetscBool     flag = PETSC_FALSE;

248:         PetscCall(PetscViewerCreate(comm, viewer));
249:         PetscCall(PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii"));
250:         fmode = FILE_MODE_WRITE;
251:         if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
252:           PetscCall(PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag));
253:           PetscCheck(flag, comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown file mode: %s", loc3_fmode);
254:         }
255:         if (loc2_fmt) {
256:           PetscBool tk, im;
257:           PetscCall(PetscStrcmp(loc1_fname, "tikz", &tk));
258:           PetscCall(PetscStrcmp(loc1_fname, "image", &im));
259:           if (tk || im) {
260:             PetscCall(PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE));
261:             *loc2_fmt = 0;
262:           }
263:         }
264:         PetscCall(PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE));
265:         PetscCall(PetscViewerFileSetName(*viewer, loc1_fname));
266:         if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer, loc1_fname));
267:         PetscCall(PetscViewerSetFromOptions(*viewer));
268:       }
269:     }
270:   }
271:   if (viewer) PetscCall(PetscViewerSetUp(*viewer));
272:   if (loc2_fmt && *loc2_fmt) {
273:     PetscViewerFormat tfmt;
274:     PetscBool         flag;

276:     PetscCall(PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag));
277:     if (format) *format = tfmt;
278:     PetscCheck(flag, comm, PETSC_ERR_SUP, "Unknown viewer format %s", loc2_fmt);
279:   } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */
280:     PetscCall(PetscViewerGetFormat(*viewer, format));
281:   }
282:   PetscCall(PetscFree(loc0_vtype));
283:   PetscFunctionReturn(PETSC_SUCCESS);
284: }

286: 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)
287: {
288:   const char *value;
289:   PetscBool   flag, hashelp;
290:   PetscInt    n_max;

292:   PetscFunctionBegin;
293:   PetscAssertPointer(name, 4);
294:   PetscAssertPointer(n_max_p, 5);
295:   n_max = *n_max_p;
296:   PetscCheck(n_max >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid size %" PetscInt_FMT " of passed arrays", *n_max_p);
297:   *n_max_p = 0;

299:   if (set) *set = PETSC_FALSE;
300:   PetscCall(PetscOptionsGetViewerOff(&flag));
301:   if (flag) PetscFunctionReturn(PETSC_SUCCESS);

303:   PetscCall(PetscOptionsHasHelp(NULL, &hashelp));
304:   if (hashelp) {
305:     PetscBool found;

307:     if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
308:     PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found));
309:     if (!found && viewer) {
310:       PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1));
311:       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));
312:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", func_name));
313:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", func_name));
314:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", func_name));
315:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", func_name));
316:       if (allow_multiple) PetscCall((*PetscHelpPrintf)(comm, "  -%s%s v1[,v2,...]: %s (%s)\n", pre ? pre : "", name + 1, "Multiple viewers", func_name));
317:     }
318:   }

320:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
321:   if (flag) {
322:     if (set) *set = PETSC_TRUE;
323:     if (!value) {
324:       PetscCheck(n_max > 0, comm, PETSC_ERR_ARG_SIZ, "More viewers (1) than max available (0)");
325:       if (format) *format = PETSC_VIEWER_DEFAULT;
326:       if (viewer) PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
327:       *n_max_p = 1;
328:     } else {
329:       char  *loc0_viewer_string = NULL, *this_viewer_string = NULL;
330:       size_t viewer_string_length;

332:       PetscCall(PetscStrallocpy(value, &loc0_viewer_string));
333:       PetscCall(PetscStrlen(loc0_viewer_string, &viewer_string_length));
334:       this_viewer_string = loc0_viewer_string;

336:       do {
337:         PetscViewer       *this_viewer;
338:         PetscViewerFormat *this_viewer_format;
339:         char              *next_viewer_string = NULL;
340:         char              *comma_separator    = NULL;
341:         PetscInt           n                  = *n_max_p;

343:         PetscCheck(n < n_max, comm, PETSC_ERR_PLIB, "More viewers than max available (%d)", (int)n_max);

345:         PetscCall(PetscStrchr(this_viewer_string, ',', &comma_separator));
346:         if (comma_separator) {
347:           PetscCheck(allow_multiple, comm, PETSC_ERR_ARG_OUTOFRANGE, "Trying to pass multiple viewers to %s: only one allowed.  Use PetscOptionsGetViewers() instead", func_name);
348:           *comma_separator   = 0;
349:           next_viewer_string = comma_separator + 1;
350:         }
351:         this_viewer = PetscSafePointerPlusOffset(viewer, n);
352:         if (this_viewer) *this_viewer = NULL;
353:         this_viewer_format = PetscSafePointerPlusOffset(format, n);
354:         if (this_viewer_format) *this_viewer_format = PETSC_VIEWER_DEFAULT;
355:         PetscCall(PetscOptionsGetViewers_Single(comm, this_viewer_string, this_viewer, this_viewer_format));
356:         this_viewer_string = next_viewer_string;
357:         (*n_max_p)++;
358:       } while (this_viewer_string);
359:       PetscCall(PetscFree(loc0_viewer_string));
360:     }
361:   }
362:   PetscFunctionReturn(PETSC_SUCCESS);
363: }

365: /*@C
366:   PetscOptionsGetViewer - Gets a viewer appropriate for the type indicated by the user

368:   Collective

370:   Input Parameters:
371: + comm    - the communicator to own the viewer
372: . options - options database, use `NULL` for default global database
373: . pre     - the string to prepend to the name or `NULL`
374: - name    - the options database name that will be checked for

376:   Output Parameters:
377: + viewer - the viewer, pass `NULL` if not needed
378: . format - the `PetscViewerFormat` requested by the user, pass `NULL` if not needed
379: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

381:   Level: intermediate

383:   Notes:
384:   If no value is provided ascii:stdout is used
385: +       ascii[:[filename][:[format][:append]]]  -  defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
386:   for example ascii::ascii_info prints just the information about the object not all details
387:   unless :append is given filename opens in write mode, overwriting what was already there
388: .       binary[:[filename][:[format][:append]]] -  defaults to the file binaryoutput
389: .       draw[:drawtype[:filename]]              -  for example, draw:tikz, draw:tikz:figure.tex  or draw:x
390: .       socket[:port]                           -  defaults to the standard output port
391: -       saws[:communicatorname]                 -   publishes object to the Scientific Application Webserver (SAWs)

393:   Use `PetscOptionsRestoreViewer()` after using the viewer, do not use `PetscViewerDestroy()`

395:   You can control whether calls to this function create a viewer (or return early with *set of `PETSC_FALSE`) with
396:   `PetscOptionsPushGetViewerOff()`.  This is useful if calling many small subsolves, in which case XXXViewFromOptions can take
397:   an appreciable fraction of the runtime.

399:   If PETSc is configured with `--with-viewfromoptions=0` this function always returns with *set of `PETSC_FALSE`

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

404: .seealso: [](sec_viewers), `PetscOptionsRestoreViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
405:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
406:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
407:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
408:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
409:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
410:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`,
411:           `PetscOptionsGetViewerOff()`
412: @*/
413: PetscErrorCode PetscOptionsGetViewer(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
414: {
415:   PetscInt  n_max = 1;
416:   PetscBool set_internal;

418:   PetscFunctionBegin;
419:   if (viewer) *viewer = NULL;
420:   if (format) *format = PETSC_VIEWER_DEFAULT;
421:   PetscCall(PetscOptionsGetViewers_Internal(comm, options, pre, name, &n_max, viewer, format, &set_internal, PETSC_FUNCTION_NAME, PETSC_FALSE));
422:   if (set_internal) PetscAssert(n_max == 1, comm, PETSC_ERR_PLIB, "Unexpected: %d != 1 viewers set", (int)n_max);
423:   if (set) *set = set_internal;
424:   PetscFunctionReturn(PETSC_SUCCESS);
425: }

427: /*@C
428:   PetscOptionsRestoreViewer - restore a `PetscViewer` obtained from `PetscOptionsGetViewer()` or `PetscOptionsGetViewers()`

430:   Collective

432:   Input Parameter:
433: . viewer - the viewer

435:   Level: intermediate

437:   Developer Note:
438:   This function exists to handle persistent viewers such as `PETSC_VIEWER_STDOUT_SELF` that may be shared between threads where
439:   changing the reference count would not be thread safe.

441: .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
442:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
443:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
444:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
445:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
446:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
447:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`,
448:           `PetscOptionsGetViewerOff()`
449: @*/
450: PetscErrorCode PetscOptionsRestoreViewer(PetscViewer *viewer)
451: {
452:   PetscFunctionBegin;
453:   if (!*viewer) PetscFunctionReturn(PETSC_SUCCESS);
454:   if (!((PetscObject)*viewer)->persistent) PetscCall(PetscViewerDestroy(viewer));
455:   else *viewer = NULL;
456:   PetscFunctionReturn(PETSC_SUCCESS);
457: }

459: /*@C
460:   PetscOptionsGetViewers - Get multiple viewers from a comma-separated list in the options database

462:   Collective

464:   Input Parameters:
465: + comm    - the communicator to own the viewers
466: . options - options database, use `NULL` for default global database
467: . pre     - the string to prepend to the name or `NULL`
468: . name    - the options database name that will be checked for
469: - n_max   - on input: the maximum number of viewers; on output: the number of viewers in the comma-separated list

471:   Output Parameters:
472: + viewers - an array to hold at least `n_max` `PetscViewer`s, or `NULL` if not needed; on output: if not `NULL`, the
473:              first `n_max` entries are initialized `PetscViewer`s
474: . formats - an array to hold at least `n_max` `PetscViewerFormat`s, or `NULL` if not needed; on output: if not
475:              `NULL`, the first `n_max` entries are valid `PetscViewewFormat`s
476: - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`

478:   Level: intermediate

480:   Note:
481:   See `PetscOptionsGetViewer()` for how the format strings for the viewers are interpreted.  Use `PetscOptionsRestoreViewer()` on each viewer, otherwise a memory leak will occur.

483:   If PETSc is configured with `--with-viewfromoptions=0` this function always returns with `n_max` of 0 and `set` of `PETSC_FALSE`

485: .seealso: [](sec_viewers), `PetscOptionsGetViewer()`
486: @*/
487: PetscErrorCode PetscOptionsGetViewers(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscInt *n_max, PetscViewer viewers[], PetscViewerFormat formats[], PetscBool *set)
488: {
489:   PetscFunctionBegin;
490:   PetscCall(PetscOptionsGetViewers_Internal(comm, options, pre, name, n_max, viewers, formats, set, PETSC_FUNCTION_NAME, PETSC_TRUE));
491:   PetscFunctionReturn(PETSC_SUCCESS);
492: }

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

498:   Collective

500:   Input Parameter:
501: . comm - MPI communicator

503:   Output Parameter:
504: . inviewer - location to put the `PetscViewer` context

506:   Level: advanced

508: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType`
509: @*/
510: PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer)
511: {
512:   PetscViewer viewer;

514:   PetscFunctionBegin;
515:   *inviewer = NULL;
516:   PetscCall(PetscViewerInitializePackage());
517:   PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView));
518:   *inviewer    = viewer;
519:   viewer->data = NULL;
520:   PetscFunctionReturn(PETSC_SUCCESS);
521: }

523: /*@C
524:   PetscViewerSetType - Builds `PetscViewer` for a particular implementation.

526:   Collective

528:   Input Parameters:
529: + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()`
530: - type   - for example, `PETSCVIEWERASCII`

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

535:   Level: advanced

537:   Note:
538:   See `PetscViewerType` for possible values

540: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
541: @*/
542: PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type)
543: {
544:   PetscBool match;
545:   PetscErrorCode (*r)(PetscViewer);

547:   PetscFunctionBegin;
549:   PetscAssertPointer(type, 2);
550:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match));
551:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

553:   /* cleanup any old type that may be there */
554:   PetscTryTypeMethod(viewer, destroy);
555:   viewer->ops->destroy = NULL;
556:   viewer->data         = NULL;

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

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

563:   PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type));
564:   PetscCall((*r)(viewer));
565:   PetscFunctionReturn(PETSC_SUCCESS);
566: }

568: /*@C
569:   PetscViewerRegister - Adds a viewer to those available for use with `PetscViewerSetType()`

571:   Not Collective

573:   Input Parameters:
574: + sname    - name of a new user-defined viewer
575: - function - routine to create method context

577:   Level: developer

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

582:   Example Usage:
583: .vb
584:    PetscViewerRegister("my_viewer_type", MyViewerCreate);
585: .ve

587:   Then, your solver can be chosen with the procedural interface via
588: $     PetscViewerSetType(viewer, "my_viewer_type")
589:   or at runtime via the option
590: $     -viewer_type my_viewer_type

592: .seealso: [](sec_viewers), `PetscViewerRegisterAll()`
593:  @*/
594: PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
595: {
596:   PetscFunctionBegin;
597:   PetscCall(PetscViewerInitializePackage());
598:   PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function));
599:   PetscFunctionReturn(PETSC_SUCCESS);
600: }

602: /*@C
603:   PetscViewerSetFromOptions - Sets various options for a viewer based on values in the options database.

605:   Collective

607:   Input Parameter:
608: . viewer - the viewer context

610:   Level: intermediate

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

615: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
616: @*/
617: PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
618: {
619:   char      vtype[256];
620:   PetscBool flg;

622:   PetscFunctionBegin;

625:   if (!PetscViewerList) PetscCall(PetscViewerRegisterAll());
626:   PetscObjectOptionsBegin((PetscObject)viewer);
627:   PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, 256, &flg));
628:   if (flg) PetscCall(PetscViewerSetType(viewer, vtype));
629:   /* type has not been set? */
630:   if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
631:   PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject);

633:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
634:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject));
635:   PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view"));
636:   PetscOptionsEnd();
637:   PetscFunctionReturn(PETSC_SUCCESS);
638: }

640: PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
641: {
642:   PetscFunctionBegin;
643:   PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt));
644:   PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt));
645:   PetscFunctionReturn(PETSC_SUCCESS);
646: }

648: PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
649: {
650:   MPI_Comm comm;

652:   PetscFunctionBegin;
653:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
654:   if (i >= *mcnt) {
655:     *mcnt += cnt;
656:     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
657:   }
658:   PetscFunctionReturn(PETSC_SUCCESS);
659: }

661: PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
662: {
663:   MPI_Comm comm;

665:   PetscFunctionBegin;
666:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
667:   *mcnt = 0;
668:   PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
669:   PetscFunctionReturn(PETSC_SUCCESS);
670: }

672: PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
673: {
674:   MPI_Comm comm;

676:   PetscFunctionBegin;
677:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
678:   while (PETSC_TRUE) {
679:     if (rank < *mcnt) break;
680:     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
681:   }
682:   PetscFunctionReturn(PETSC_SUCCESS);
683: }

685: PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
686: {
687:   MPI_Comm comm;

689:   PetscFunctionBegin;
690:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
691:   while (PETSC_TRUE) {
692:     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
693:     if (!*mcnt) break;
694:   }
695:   PetscFunctionReturn(PETSC_SUCCESS);
696: }