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[PETSCVIEWERCREATEVIEWEROFFPUSHESMAX];
     96: static PetscInt  inoviewers = 0;

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

    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 `PetscOptionsCreateViewer()`, thus removing the expensive `XXXViewFromOptions` calls.

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

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

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

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

    130:   Logically Collective

    132:   Level: developer

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

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

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

    150:   Logically Collective

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

    155:   Level: developer

    157: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`
    158: @*/
    159: PetscErrorCode PetscOptionsGetCreateViewerOff(PetscBool *flg)
    160: {
    161:   PetscFunctionBegin;
    162:   PetscAssertPointer(flg, 1);
    163:   *flg = noviewer;
    164:   PetscFunctionReturn(PETSC_SUCCESS);
    165: }

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

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

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

    269:         PetscCall(PetscViewerCreate(comm, viewer));
    270:         PetscCall(PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii"));
    271:         fmode = FILE_MODE_WRITE;
    272:         if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
    273:           PetscCall(PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag));
    274:           PetscCheck(flag, comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown file mode: %s", loc3_fmode);
    275:         }
    276:         if (loc2_fmt) {
    277:           PetscBool tk, im;
    278:           PetscCall(PetscStrcmp(loc1_fname, "tikz", &tk));
    279:           PetscCall(PetscStrcmp(loc1_fname, "image", &im));
    280:           if (tk || im) {
    281:             PetscCall(PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE));
    282:             *loc2_fmt = 0;
    283:           }
    284:         }
    285:         PetscCall(PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE));
    286:         PetscCall(PetscViewerFileSetName(*viewer, loc1_fname));
    287:         if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer, loc1_fname));
    288:         PetscCall(PetscViewerSetFromOptions(*viewer));
    289:       }
    290:     }
    291:   }
    292:   if (viewer) PetscCall(PetscViewerSetUp(*viewer));
    293:   if (loc2_fmt && *loc2_fmt) {
    294:     PetscViewerFormat tfmt;
    295:     PetscBool         flag;

    297:     PetscCall(PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag));
    298:     if (format) *format = tfmt;
    299:     PetscCheck(flag, comm, PETSC_ERR_SUP, "Unknown viewer format %s", loc2_fmt);
    300:   } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */
    301:     PetscCall(PetscViewerGetFormat(*viewer, format));
    302:   }
    303:   PetscCall(PetscFree(loc0_vtype));
    304:   PetscFunctionReturn(PETSC_SUCCESS);
    305: }

    307: 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)
    308: {
    309:   const char *value;
    310:   PetscBool   flag, hashelp;
    311:   PetscInt    n_max;

    313:   PetscFunctionBegin;
    314:   PetscAssertPointer(name, 4);
    315:   PetscAssertPointer(n_max_p, 5);
    316:   n_max = *n_max_p;
    317:   PetscCheck(n_max >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid size %" PetscInt_FMT " of passed arrays", *n_max_p);
    318:   *n_max_p = 0;

    320:   if (set) *set = PETSC_FALSE;
    321:   PetscCall(PetscOptionsGetCreateViewerOff(&flag));
    322:   if (flag) PetscFunctionReturn(PETSC_SUCCESS);

    324:   PetscCall(PetscOptionsHasHelp(NULL, &hashelp));
    325:   if (hashelp) {
    326:     PetscBool found;

    328:     if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
    329:     PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found));
    330:     if (!found && viewer) {
    331:       PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1));
    332:       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));
    333:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", func_name));
    334:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", func_name));
    335:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", func_name));
    336:       PetscCall((*PetscHelpPrintf)(comm, "  -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", func_name));
    337:       if (allow_multiple) PetscCall((*PetscHelpPrintf)(comm, "  -%s%s v1[,v2,...]: %s (%s)\n", pre ? pre : "", name + 1, "Multiple viewers", func_name));
    338:     }
    339:   }

    341:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
    342:   if (flag) {
    343:     if (set) *set = PETSC_TRUE;
    344:     if (!value) {
    345:       PetscCheck(n_max > 0, comm, PETSC_ERR_ARG_SIZ, "More viewers (1) than max available (0)");
    346:       if (format) *format = PETSC_VIEWER_DEFAULT;
    347:       if (viewer) {
    348:         PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
    349:         PetscCall(PetscObjectReference((PetscObject)*viewer));
    350:       }
    351:       *n_max_p = 1;
    352:     } else {
    353:       char  *loc0_viewer_string = NULL, *this_viewer_string = NULL;
    354:       size_t viewer_string_length;

    356:       PetscCall(PetscStrallocpy(value, &loc0_viewer_string));
    357:       PetscCall(PetscStrlen(loc0_viewer_string, &viewer_string_length));
    358:       this_viewer_string = loc0_viewer_string;

    360:       do {
    361:         PetscViewer       *this_viewer;
    362:         PetscViewerFormat *this_viewer_format;
    363:         char              *next_viewer_string = NULL;
    364:         char              *comma_separator    = NULL;
    365:         PetscInt           n                  = *n_max_p;

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

    369:         PetscCall(PetscStrchr(this_viewer_string, ',', &comma_separator));
    370:         if (comma_separator) {
    371:           PetscCheck(allow_multiple, comm, PETSC_ERR_ARG_OUTOFRANGE, "Trying to pass multiple viewers to %s: only one allowed.  Use PetscOptionsCreateViewers() instead", func_name);
    372:           *comma_separator   = 0;
    373:           next_viewer_string = comma_separator + 1;
    374:         }
    375:         this_viewer = PetscSafePointerPlusOffset(viewer, n);
    376:         if (this_viewer) *this_viewer = NULL;
    377:         this_viewer_format = PetscSafePointerPlusOffset(format, n);
    378:         if (this_viewer_format) *this_viewer_format = PETSC_VIEWER_DEFAULT;
    379:         PetscCall(PetscOptionsCreateViewers_Single(comm, this_viewer_string, this_viewer, this_viewer_format));
    380:         this_viewer_string = next_viewer_string;
    381:         (*n_max_p)++;
    382:       } while (this_viewer_string);
    383:       PetscCall(PetscFree(loc0_viewer_string));
    384:     }
    385:   }
    386:   PetscFunctionReturn(PETSC_SUCCESS);
    387: }

    389: /*@C
    390:   PetscOptionsCreateViewer - Creates a viewer appropriate for the type indicated by the user

    392:   Collective

    394:   Input Parameters:
    395: + comm    - the communicator to own the viewer
    396: . options - options database, use `NULL` for default global database
    397: . pre     - the string to prepend to the name or `NULL`
    398: - name    - the options database name that will be checked for

    400:   Output Parameters:
    401: + viewer - the viewer, pass `NULL` if not needed
    402: . format - the `PetscViewerFormat` requested by the user, pass `NULL` if not needed
    403: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    405:   Level: intermediate

    407:   Notes:
    408:   The argument has the following form
    409: .vb
    410:     type:filename:format:filemode
    411: .ve
    412:   where all parts are optional, but you need to include the colon to access the next part. The mode argument must a valid `PetscFileMode`, i.e. read, write, append, update, or append_update. For example, to read from an HDF5 file, use
    413: .vb
    414:     hdf5:sol.h5::read
    415: .ve

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

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

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

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

    435: .seealso: [](sec_viewers), `PetscViewerDestroy()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
    436:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
    437:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
    438:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    439:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    440:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    441:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`,
    442:           `PetscOptionsCreateViewerOff()`
    443: @*/
    444: PetscErrorCode PetscOptionsCreateViewer(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
    445: {
    446:   PetscInt  n_max = 1;
    447:   PetscBool set_internal;

    449:   PetscFunctionBegin;
    450:   if (viewer) *viewer = NULL;
    451:   if (format) *format = PETSC_VIEWER_DEFAULT;
    452:   PetscCall(PetscOptionsCreateViewers_Internal(comm, options, pre, name, &n_max, viewer, format, &set_internal, PETSC_FUNCTION_NAME, PETSC_FALSE));
    453:   if (set_internal) PetscAssert(n_max == 1, comm, PETSC_ERR_PLIB, "Unexpected: %" PetscInt_FMT " != 1 viewers set", n_max);
    454:   if (set) *set = set_internal;
    455:   PetscFunctionReturn(PETSC_SUCCESS);
    456: }

    458: /*@C
    459:   PetscOptionsCreateViewers - Create multiple viewers from a comma-separated list in the options database

    461:   Collective

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

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

    477:   Level: intermediate

    479:   Note:
    480:   See `PetscOptionsCreateViewer()` for how the format strings for the viewers are interpreted.

    482:   Use `PetscViewerDestroy()` on each viewer, otherwise a memory leak will occur.

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

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

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

    499:   Collective

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

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

    507:   Level: advanced

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

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

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

    527:   Collective

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

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

    536:   Level: advanced

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

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

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

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

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

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

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

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

    572:   Not Collective, No Fortran Support

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

    578:   Level: developer

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

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

    588:   Then, your solver can be chosen with the procedural interface via
    589: .vb
    590:   PetscViewerSetType(viewer, "my_viewer_type")
    591: .ve
    592:   or at runtime via the option
    593: .vb
    594:   -viewer_type my_viewer_type
    595: .ve

    597: .seealso: [](sec_viewers), `PetscViewerRegisterAll()`
    598:  @*/
    599: PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
    600: {
    601:   PetscFunctionBegin;
    602:   PetscCall(PetscViewerInitializePackage());
    603:   PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function));
    604:   PetscFunctionReturn(PETSC_SUCCESS);
    605: }

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

    610:   Collective

    612:   Input Parameter:
    613: . viewer - the viewer context

    615:   Level: intermediate

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

    620: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
    621: @*/
    622: PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
    623: {
    624:   char      vtype[256];
    625:   PetscBool flg;

    627:   PetscFunctionBegin;

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

    638:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
    639:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject));
    640:   PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view"));
    641:   PetscOptionsEnd();
    642:   PetscFunctionReturn(PETSC_SUCCESS);
    643: }

    645: PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
    646: {
    647:   PetscFunctionBegin;
    648:   PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt));
    649:   PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt));
    650:   PetscFunctionReturn(PETSC_SUCCESS);
    651: }

    653: PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
    654: {
    655:   MPI_Comm comm;

    657:   PetscFunctionBegin;
    658:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
    659:   if (i >= *mcnt) {
    660:     *mcnt += cnt;
    661:     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
    662:   }
    663:   PetscFunctionReturn(PETSC_SUCCESS);
    664: }

    666: PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
    667: {
    668:   MPI_Comm comm;

    670:   PetscFunctionBegin;
    671:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
    672:   *mcnt = 0;
    673:   PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
    674:   PetscFunctionReturn(PETSC_SUCCESS);
    675: }

    677: PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
    678: {
    679:   MPI_Comm comm;

    681:   PetscFunctionBegin;
    682:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
    683:   while (PETSC_TRUE) {
    684:     if (rank < *mcnt) break;
    685:     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
    686:   }
    687:   PetscFunctionReturn(PETSC_SUCCESS);
    688: }

    690: PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
    691: {
    692:   MPI_Comm comm;

    694:   PetscFunctionBegin;
    695:   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
    696:   while (PETSC_TRUE) {
    697:     PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
    698:     if (!*mcnt) break;
    699:   }
    700:   PetscFunctionReturn(PETSC_SUCCESS);
    701: }