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: [](sec_viewers), `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: [](sec_viewers), `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: [](sec_viewers), `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: [](sec_viewers), `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: [](sec_viewers), `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
382: Input Parameters:
383: + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()`
384: - type - for example, `PETSCVIEWERASCII`
386: Options Database Key:
387: . -viewer_type <type> - Sets the type; use -help for a list of available methods (for instance, ascii)
389: Level: advanced
391: Note:
392: See "include/petscviewer.h" for available methods (for instance,
393: `PETSCVIEWERSOCKET`)
395: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
396: @*/
397: PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type)
398: {
399: PetscBool match;
400: PetscErrorCode (*r)(PetscViewer);
404: PetscObjectTypeCompare((PetscObject)viewer, type, &match);
405: if (match) return 0;
407: /* cleanup any old type that may be there */
408: PetscTryTypeMethod(viewer, destroy);
409: viewer->ops->destroy = NULL;
410: viewer->data = NULL;
412: PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps));
414: PetscFunctionListFind(PetscViewerList, type, &r);
417: PetscObjectChangeTypeName((PetscObject)viewer, type);
418: (*r)(viewer);
419: return 0;
420: }
422: /*@C
423: PetscViewerRegister - Adds a viewer to those available for use
425: Not Collective
427: Input Parameters:
428: + name_solver - name of a new user-defined viewer
429: - routine_create - routine to create method context
431: Level: developer
433: Note:
434: `PetscViewerRegister()` may be called multiple times to add several user-defined viewers.
436: Sample usage:
437: .vb
438: PetscViewerRegister("my_viewer_type",MyViewerCreate);
439: .ve
441: Then, your solver can be chosen with the procedural interface via
442: $ PetscViewerSetType(viewer,"my_viewer_type")
443: or at runtime via the option
444: $ -viewer_type my_viewer_type
446: .seealso: [](sec_viewers), `PetscViewerRegisterAll()`
447: @*/
448: PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
449: {
450: PetscViewerInitializePackage();
451: PetscFunctionListAdd(&PetscViewerList, sname, function);
452: return 0;
453: }
455: /*@C
456: PetscViewerSetFromOptions - Sets various options for a viewer from the options database.
458: Collective
460: Input Parameter:
461: . viewer - the viewer context
463: Level: intermediate
465: Note:
466: Must be called after PetscViewerCreate() before the PetscViewer is used.
468: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
469: @*/
470: PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
471: {
472: char vtype[256];
473: PetscBool flg;
477: if (!PetscViewerList) PetscViewerRegisterAll();
478: PetscObjectOptionsBegin((PetscObject)viewer);
479: PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, 256, &flg);
480: if (flg) PetscViewerSetType(viewer, vtype);
481: /* type has not been set? */
482: if (!((PetscObject)viewer)->type_name) PetscViewerSetType(viewer, PETSCVIEWERASCII);
483: PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject);
485: /* process any options handlers added with PetscObjectAddOptionsHandler() */
486: PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject);
487: PetscViewerViewFromOptions(viewer, NULL, "-viewer_view");
488: PetscOptionsEnd();
489: return 0;
490: }
492: PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
493: {
494: PetscViewerBinaryGetFlowControl(viewer, mcnt);
495: PetscViewerBinaryGetFlowControl(viewer, cnt);
496: return 0;
497: }
499: PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
500: {
501: MPI_Comm comm;
503: PetscObjectGetComm((PetscObject)viewer, &comm);
504: if (i >= *mcnt) {
505: *mcnt += cnt;
506: MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm);
507: }
508: return 0;
509: }
511: PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
512: {
513: MPI_Comm comm;
514: PetscObjectGetComm((PetscObject)viewer, &comm);
515: *mcnt = 0;
516: MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm);
517: return 0;
518: }
520: PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
521: {
522: MPI_Comm comm;
523: PetscObjectGetComm((PetscObject)viewer, &comm);
524: while (PETSC_TRUE) {
525: if (rank < *mcnt) break;
526: MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm);
527: }
528: return 0;
529: }
531: PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
532: {
533: MPI_Comm comm;
534: PetscObjectGetComm((PetscObject)viewer, &comm);
535: while (PETSC_TRUE) {
536: MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm);
537: if (!*mcnt) break;
538: }
539: return 0;
540: }