Actual source code: viewreg.c


  2: #include <petsc/private/viewerimpl.h>
  3: #include <petsc/private/hashtable.h>
  4: #if defined(PETSC_HAVE_SAWS)
  5: #include <petscviewersaws.h>
  6: #endif

  8: PetscFunctionList PetscViewerList = NULL;

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

 17: PetscErrorCode PetscOptionsHelpPrintedDestroy(PetscOptionsHelpPrinted *hp)
 18: {
 19:   if (!*hp) return 0;
 20:   kh_destroy(HTPrinted, (*hp)->printed);
 21:   PetscSegBufferDestroy(&(*hp)->strings);
 22:   PetscFree(*hp);
 23:   return 0;
 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:      Not collective

 32:     Level: developer

 34: .seealso: `PetscOptionsHelpPrintedCheck()`, `PetscOptionsHelpPrintChecked()`
 35: @*/
 36: PetscErrorCode PetscOptionsHelpPrintedCreate(PetscOptionsHelpPrinted *hp)
 37: {
 38:   PetscNew(hp);
 39:   (*hp)->printed = kh_init(HTPrinted);
 40:   PetscSegBufferCreate(sizeof(char), 10000, &(*hp)->strings);
 41:   return 0;
 42: }

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

 47:      Not collective

 49:     Input Parameters:
 50: +     hp - the object used to manage tracking what help messages have been printed
 51: .     pre - the prefix part of the string, many be NULL
 52: -     name - the string to look for (cannot be NULL)

 54:     Output Parameter:
 55: .     found - PETSC_TRUE if the string was already set

 57:     Level: intermediate

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

 69:   PetscStrlen(pre, &l1);
 70:   PetscStrlen(name, &l2);
 71:   if (l1 + l2 == 0) {
 72:     *found = PETSC_FALSE;
 73:     return 0;
 74:   }
 75: #if !defined(PETSC_HAVE_THREADSAFETY)
 76:   PetscSegBufferGet(hp->strings, l1 + l2 + 1, &both);
 77:   PetscStrcpy(both, pre);
 78:   PetscStrcat(both, name);
 79:   kh_put(HTPrinted, hp->printed, both, &newitem);
 80:   if (!newitem) PetscSegBufferUnuse(hp->strings, l1 + l2 + 1);
 81:   *found = newitem ? PETSC_FALSE : PETSC_TRUE;
 82: #else
 83:   *found = PETSC_FALSE;
 84: #endif
 85:   return 0;
 86: }

 88: static PetscBool noviewer = PETSC_FALSE;
 89: static PetscBool noviewers[PETSCVIEWERGETVIEWEROFFPUSHESMAX];
 90: static PetscInt  inoviewers = 0;

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

 95:   Logically Collective

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

100:   Level: developer

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

106: .seealso: `PetscOptionsGetViewer()`, `PetscOptionsPopGetViewerOff()`
107: @*/
108: PetscErrorCode PetscOptionsPushGetViewerOff(PetscBool flg)
109: {

112:   noviewers[inoviewers++] = noviewer;
113:   noviewer                = flg;
114:   return 0;
115: }

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

120:   Logically Collective

122:   Level: developer

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

128: .seealso: `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()`
129: @*/
130: PetscErrorCode PetscOptionsPopGetViewerOff(void)
131: {
133:   noviewer = noviewers[--inoviewers];
134:   return 0;
135: }

137: /*@
138:   PetscOptionsGetViewerOff - does `PetscOptionsGetViewer()` return a viewer?

140:   Logically Collective

142:   Output Parameter:
143: . flg - whether viewers are returned.

145:   Level: developer

147:   Note:
148:     Calling XXXViewFromOptions in an inner loop can be very expensive.  This can appear, for example, when using
149:    many small subsolves.

151: .seealso: `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`
152: @*/
153: PetscErrorCode PetscOptionsGetViewerOff(PetscBool *flg)
154: {
156:   *flg = noviewer;
157:   return 0;
158: }

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

163:    Collective

165:    Input Parameters:
166: +  comm - the communicator to own the viewer
167: .  options - options database, use NULL for default global database
168: .  pre - the string to prepend to the name or NULL
169: -  name - the option one is seeking

171:    Output Parameters:
172: +  viewer - the viewer, pass NULL if not needed
173: .  format - the `PetscViewerFormat` requested by the user, pass NULL if not needed
174: -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`

176:    Level: intermediate

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

188:    Use `PetscViewerDestroy()` after using the viewer, otherwise a memory leak will occur

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

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

196: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
197:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
198:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
199:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
200:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
201:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
202:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`,
203:           `PetscOptionsGetViewerOff()`
204: @*/
205: PetscErrorCode PetscOptionsGetViewer(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
206: {
207:   const char *value;
208:   PetscBool   flag, hashelp;


212:   if (viewer) *viewer = NULL;
213:   if (format) *format = PETSC_VIEWER_DEFAULT;
214:   if (set) *set = PETSC_FALSE;
215:   PetscOptionsGetViewerOff(&flag);
216:   if (flag) return 0;

218:   PetscOptionsHasHelp(NULL, &hashelp);
219:   if (hashelp) {
220:     PetscBool found;

222:     if (!PetscOptionsHelpPrintedSingleton) PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton);
223:     PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found);
224:     if (!found && viewer) {
225:       (*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1);
226:       (*PetscHelpPrintf)(comm, "  -%s%s ascii[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Prints object to stdout or ASCII file", "PetscOptionsGetViewer");
227:       (*PetscHelpPrintf)(comm, "  -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", "PetscOptionsGetViewer");
228:       (*PetscHelpPrintf)(comm, "  -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", "PetscOptionsGetViewer");
229:       (*PetscHelpPrintf)(comm, "  -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", "PetscOptionsGetViewer");
230:       (*PetscHelpPrintf)(comm, "  -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", "PetscOptionsGetViewer");
231:     }
232:   }

234:   if (format) *format = PETSC_VIEWER_DEFAULT;
235:   PetscOptionsFindPair(options, pre, name, &value, &flag);
236:   if (flag) {
237:     if (set) *set = PETSC_TRUE;
238:     if (!value) {
239:       if (viewer) {
240:         PetscViewerASCIIGetStdout(comm, viewer);
241:         PetscObjectReference((PetscObject)*viewer);
242:       }
243:     } else {
244:       char       *loc0_vtype, *loc1_fname, *loc2_fmt = NULL, *loc3_fmode = NULL;
245:       PetscInt    cnt;
246:       const char *viewers[] = {PETSCVIEWERASCII, PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSOCKET, PETSCVIEWERMATLAB, PETSCVIEWERSAWS, PETSCVIEWERVTK, PETSCVIEWERHDF5, PETSCVIEWERGLVIS, PETSCVIEWEREXODUSII, NULL};

248:       PetscStrallocpy(value, &loc0_vtype);
249:       PetscStrchr(loc0_vtype, ':', &loc1_fname);
250:       if (loc1_fname) {
251:         *loc1_fname++ = 0;
252:         PetscStrchr(loc1_fname, ':', &loc2_fmt);
253:       }
254:       if (loc2_fmt) {
255:         *loc2_fmt++ = 0;
256:         PetscStrchr(loc2_fmt, ':', &loc3_fmode);
257:       }
258:       if (loc3_fmode) *loc3_fmode++ = 0;
259:       PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii", viewers, &cnt);
261:       if (viewer) {
262:         if (!loc1_fname) {
263:           switch (cnt) {
264:           case 0:
265:             PetscViewerASCIIGetStdout(comm, viewer);
266:             break;
267:           case 1:
268:             if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PETSC_ERR_PLIB;
269:             break;
270:           case 2:
271:             if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PETSC_ERR_PLIB;
272:             break;
273: #if defined(PETSC_USE_SOCKET_VIEWER)
274:           case 3:
275:             if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PETSC_ERR_PLIB;
276:             break;
277: #endif
278: #if defined(PETSC_HAVE_MATLAB)
279:           case 4:
280:             if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PETSC_ERR_PLIB;
281:             break;
282: #endif
283: #if defined(PETSC_HAVE_SAWS)
284:           case 5:
285:             if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PETSC_ERR_PLIB;
286:             break;
287: #endif
288: #if defined(PETSC_HAVE_HDF5)
289:           case 7:
290:             if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PETSC_ERR_PLIB;
291:             break;
292: #endif
293:           case 8:
294:             if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PETSC_ERR_PLIB;
295:             break;
296: #if defined(PETSC_HAVE_EXODUSII)
297:           case 9:
298:             if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PETSC_ERR_PLIB;
299:             break;
300: #endif
301:           default:
302:             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported viewer %s", loc0_vtype);
303:           }
304:           PetscObjectReference((PetscObject)*viewer);
305:         } else {
306:           if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
307:             PetscViewerASCIIGetStdout(comm, viewer);
308:             PetscObjectReference((PetscObject)*viewer);
309:           } else {
310:             PetscFileMode fmode;
311:             PetscViewerCreate(comm, viewer);
312:             PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii");
313:             fmode = FILE_MODE_WRITE;
314:             if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
315:               PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag);
317:             }
318:             if (loc2_fmt) {
319:               PetscBool tk, im;
320:               PetscStrcmp(loc1_fname, "tikz", &tk);
321:               PetscStrcmp(loc1_fname, "image", &im);
322:               if (tk || im) {
323:                 PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE);
324:                 *loc2_fmt = 0;
325:               }
326:             }
327:             PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE);
328:             PetscViewerFileSetName(*viewer, loc1_fname);
329:             if (*loc1_fname) PetscViewerDrawSetDrawType(*viewer, loc1_fname);
330:             PetscViewerSetFromOptions(*viewer);
331:           }
332:         }
333:       }
334:       if (viewer) PetscViewerSetUp(*viewer);
335:       if (loc2_fmt && *loc2_fmt) {
336:         PetscViewerFormat tfmt;

338:         PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag);
339:         if (format) *format = tfmt;
341:       } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */
342:         PetscViewerGetFormat(*viewer, format);
343:       }
344:       PetscFree(loc0_vtype);
345:     }
346:   }
347:   return 0;
348: }

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

353:    Collective

355:    Input Parameter:
356: .  comm - MPI communicator

358:    Output Parameter:
359: .  inviewer - location to put the `PetscViewer` context

361:    Level: advanced

363: .seealso: `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType`
364: @*/
365: PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer)
366: {
367:   PetscViewer viewer;

369:   *inviewer = NULL;
370:   PetscViewerInitializePackage();
371:   PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView);
372:   *inviewer    = viewer;
373:   viewer->data = NULL;
374:   return 0;
375: }

377: /*@C
378:    PetscViewerSetType - Builds `PetscViewer` for a particular implementation.

380:    Collective on viewer

382:    Input Parameters:
383: +  viewer      - the `PetscViewer` context obtained with `PetscViewerCreate()`
384: -  type        - for example, `PETSCVIEWERASCII`

386:    Options Database Command:
387: .  -viewer_type  <type> - Sets the type; use -help for a list
388:     of available methods (for instance, ascii)

390:    Level: advanced

392:    Note:
393:    See "include/petscviewer.h" for available methods (for instance,
394:    `PETSCVIEWERSOCKET`)

396: .seealso: `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
397: @*/
398: PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type)
399: {
400:   PetscBool match;
401:   PetscErrorCode (*r)(PetscViewer);

405:   PetscObjectTypeCompare((PetscObject)viewer, type, &match);
406:   if (match) return 0;

408:   /* cleanup any old type that may be there */
409:   PetscTryTypeMethod(viewer, destroy);
410:   viewer->ops->destroy = NULL;
411:   viewer->data         = NULL;

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

415:   PetscFunctionListFind(PetscViewerList, type, &r);

418:   PetscObjectChangeTypeName((PetscObject)viewer, type);
419:   (*r)(viewer);
420:   return 0;
421: }

423: /*@C
424:    PetscViewerRegister - Adds a viewer to those available for use

426:    Not Collective

428:    Input Parameters:
429: +  name_solver - name of a new user-defined viewer
430: -  routine_create - routine to create method context

432:    Level: developer

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

437:    Sample usage:
438: .vb
439:    PetscViewerRegister("my_viewer_type",MyViewerCreate);
440: .ve

442:    Then, your solver can be chosen with the procedural interface via
443: $     PetscViewerSetType(viewer,"my_viewer_type")
444:    or at runtime via the option
445: $     -viewer_type my_viewer_type

447: .seealso: `PetscViewerRegisterAll()`
448:  @*/
449: PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
450: {
451:   PetscViewerInitializePackage();
452:   PetscFunctionListAdd(&PetscViewerList, sname, function);
453:   return 0;
454: }

456: /*@C
457:    PetscViewerSetFromOptions - Sets various options for a viewer from the options database.

459:    Collective on viewer

461:    Input Parameter:
462: .     viewer - the viewer context

464:    Level: intermediate

466:    Note:
467:     Must be called after PetscViewerCreate() before the PetscViewer is used.

469: .seealso: `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
470: @*/
471: PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
472: {
473:   char      vtype[256];
474:   PetscBool flg;


478:   if (!PetscViewerList) PetscViewerRegisterAll();
479:   PetscObjectOptionsBegin((PetscObject)viewer);
480:   PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, 256, &flg);
481:   if (flg) PetscViewerSetType(viewer, vtype);
482:   /* type has not been set? */
483:   if (!((PetscObject)viewer)->type_name) PetscViewerSetType(viewer, PETSCVIEWERASCII);
484:   PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject);

486:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
487:   PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject);
488:   PetscViewerViewFromOptions(viewer, NULL, "-viewer_view");
489:   PetscOptionsEnd();
490:   return 0;
491: }

493: PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
494: {
495:   PetscViewerBinaryGetFlowControl(viewer, mcnt);
496:   PetscViewerBinaryGetFlowControl(viewer, cnt);
497:   return 0;
498: }

500: PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
501: {
502:   MPI_Comm comm;

504:   PetscObjectGetComm((PetscObject)viewer, &comm);
505:   if (i >= *mcnt) {
506:     *mcnt += cnt;
507:     MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm);
508:   }
509:   return 0;
510: }

512: PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
513: {
514:   MPI_Comm comm;
515:   PetscObjectGetComm((PetscObject)viewer, &comm);
516:   *mcnt = 0;
517:   MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm);
518:   return 0;
519: }

521: PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
522: {
523:   MPI_Comm comm;
524:   PetscObjectGetComm((PetscObject)viewer, &comm);
525:   while (PETSC_TRUE) {
526:     if (rank < *mcnt) break;
527:     MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm);
528:   }
529:   return 0;
530: }

532: PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
533: {
534:   MPI_Comm comm;
535:   PetscObjectGetComm((PetscObject)viewer, &comm);
536:   while (PETSC_TRUE) {
537:     MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm);
538:     if (!*mcnt) break;
539:   }
540:   return 0;
541: }