Actual source code: viewreg.c
1: #include <petsc/private/viewerimpl.h>
2: #include <petsc/private/hashtable.h>
3: #if PetscDefined(HAVE_SAWS)
4: #include <petscviewersaws.h>
5: #endif
7: PetscFunctionList PetscViewerList = NULL;
9: PetscOptionsHelpPrinted PetscOptionsHelpPrintedSingleton = NULL;
10: KHASH_SET_INIT_STR(HTPrinted)
11: struct _n_PetscOptionsHelpPrinted {
12: khash_t(HTPrinted) *printed;
13: PetscSegBuffer strings;
14: };
16: /*@
17: PetscOptionsHelpPrintedDestroy - Destroys the object used to track which help messages have already been printed
19: Not Collective
21: Input Parameter:
22: . hp - pointer to the `PetscOptionsHelpPrinted` object to destroy; set to `NULL` on return
24: Level: developer
26: .seealso: `PetscOptionsHelpPrintedCreate()`, `PetscOptionsHelpPrintedCheck()`
27: @*/
28: PetscErrorCode PetscOptionsHelpPrintedDestroy(PetscOptionsHelpPrinted *hp)
29: {
30: PetscFunctionBegin;
31: if (!*hp) PetscFunctionReturn(PETSC_SUCCESS);
32: kh_destroy(HTPrinted, (*hp)->printed);
33: PetscCall(PetscSegBufferDestroy(&(*hp)->strings));
34: PetscCall(PetscFree(*hp));
35: PetscFunctionReturn(PETSC_SUCCESS);
36: }
38: /*@
39: PetscOptionsHelpPrintedCreate - Creates an object used to manage tracking which help messages have
40: been printed so they will not be printed again.
42: Output Parameter:
43: . hp - the created object
45: Not Collective
47: Level: developer
49: .seealso: `PetscOptionsHelpPrintedCheck()`, `PetscOptionsHelpPrintChecked()`
50: @*/
51: PetscErrorCode PetscOptionsHelpPrintedCreate(PetscOptionsHelpPrinted *hp)
52: {
53: PetscFunctionBegin;
54: PetscCall(PetscNew(hp));
55: (*hp)->printed = kh_init(HTPrinted);
56: PetscCall(PetscSegBufferCreate(sizeof(char), 10000, &(*hp)->strings));
57: PetscFunctionReturn(PETSC_SUCCESS);
58: }
60: /*@
61: PetscOptionsHelpPrintedCheck - Checks if a particular pre, name pair has previous been entered (meaning the help message was printed)
63: Not Collective
65: Input Parameters:
66: + hp - the object used to manage tracking what help messages have been printed
67: . pre - the prefix part of the string, many be `NULL`
68: - name - the string to look for (cannot be `NULL`)
70: Output Parameter:
71: . found - `PETSC_TRUE` if the string was already set
73: Level: intermediate
75: .seealso: `PetscOptionsHelpPrintedCreate()`
76: @*/
77: PetscErrorCode PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrinted hp, const char *pre, const char *name, PetscBool *found)
78: {
79: size_t l1, l2;
80: #if !PetscDefined(HAVE_THREADSAFETY)
81: char *both;
82: int newitem;
83: #endif
85: PetscFunctionBegin;
86: PetscCall(PetscStrlen(pre, &l1));
87: PetscCall(PetscStrlen(name, &l2));
88: if (l1 + l2 == 0) {
89: *found = PETSC_FALSE;
90: PetscFunctionReturn(PETSC_SUCCESS);
91: }
92: #if !PetscDefined(HAVE_THREADSAFETY)
93: size_t lboth = l1 + l2 + 1;
94: PetscCall(PetscSegBufferGet(hp->strings, lboth, &both));
95: PetscCall(PetscStrncpy(both, pre, lboth));
96: PetscCall(PetscStrncpy(both + l1, name, l2 + 1));
97: kh_put(HTPrinted, hp->printed, both, &newitem);
98: if (!newitem) PetscCall(PetscSegBufferUnuse(hp->strings, lboth));
99: *found = newitem ? PETSC_FALSE : PETSC_TRUE;
100: #else
101: *found = PETSC_FALSE;
102: #endif
103: PetscFunctionReturn(PETSC_SUCCESS);
104: }
106: static PetscBool noviewer = PETSC_FALSE;
107: static PetscBool noviewers[PETSCVIEWERCREATEVIEWEROFFPUSHESMAX];
108: static PetscInt inoviewers = 0;
110: /*@
111: PetscOptionsPushCreateViewerOff - sets if `PetscOptionsCreateViewer()`, `PetscOptionsViewer()`, and `PetscOptionsCreateViewers()` return viewers.
113: Logically Collective
115: Input Parameter:
116: . flg - `PETSC_TRUE` to turn off viewer creation, `PETSC_FALSE` to turn it on.
118: Options Database Key:
119: . -viewfromoptions (on|off) - Enable or disable `PetscOptionsCreateViewer()` and `XXXViewFromOptions()` calls, for applications with many small solves turn this off
121: Level: developer
123: Note:
124: Calling `XXXViewFromOptions` in an inner loop can be expensive. This can appear, for example, when using
125: many small subsolves. Call this function to control viewer creation in `PetscOptionsCreateViewer()`, thus removing the expensive `XXXViewFromOptions` calls.
127: Developer Notes:
128: Instead of using this approach, the calls to `PetscOptionsCreateViewer()` can be moved into `XXXSetFromOptions()`
130: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPopCreateViewerOff()`
131: @*/
132: PetscErrorCode PetscOptionsPushCreateViewerOff(PetscBool flg)
133: {
134: PetscFunctionBegin;
135: PetscCheck(inoviewers < PETSCVIEWERCREATEVIEWEROFFPUSHESMAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPushCreateViewerOff(), perhaps you forgot PetscOptionsPopCreateViewerOff()?");
137: noviewers[inoviewers++] = noviewer;
138: noviewer = flg;
139: PetscFunctionReturn(PETSC_SUCCESS);
140: }
142: /*@
143: PetscOptionsPopCreateViewerOff - reset whether `PetscOptionsCreateViewer()` returns a viewer.
145: Logically Collective
147: Level: developer
149: Note:
150: See `PetscOptionsPushCreateViewerOff()`
152: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPushCreateViewerOff()`
153: @*/
154: PetscErrorCode PetscOptionsPopCreateViewerOff(void)
155: {
156: PetscFunctionBegin;
157: PetscCheck(inoviewers, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPopCreateViewerOff(), perhaps you forgot PetscOptionsPushCreateViewerOff()?");
158: noviewer = noviewers[--inoviewers];
159: PetscFunctionReturn(PETSC_SUCCESS);
160: }
162: /*@
163: PetscOptionsGetCreateViewerOff - do `PetscOptionsCreateViewer()`, `PetscOptionsViewer()`, and `PetscOptionsCreateViewers()` return viewers
165: Logically Collective
167: Output Parameter:
168: . flg - whether viewers are returned.
170: Level: developer
172: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`
173: @*/
174: PetscErrorCode PetscOptionsGetCreateViewerOff(PetscBool *flg)
175: {
176: PetscFunctionBegin;
177: PetscAssertPointer(flg, 1);
178: *flg = noviewer;
179: PetscFunctionReturn(PETSC_SUCCESS);
180: }
182: static PetscErrorCode PetscOptionsCreateViewers_Single(MPI_Comm comm, const char value[], PetscViewer *viewer, PetscViewerFormat *format)
183: {
184: char *loc0_vtype = NULL, *loc1_fname = NULL, *loc2_fmt = NULL, *loc3_fmode = NULL;
185: PetscInt cnt;
186: size_t viewer_string_length;
187: const char *viewers[] = {PETSCVIEWERASCII, PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSOCKET, PETSCVIEWERMATLAB, PETSCVIEWERSAWS, PETSCVIEWERVTK, PETSCVIEWERHDF5, PETSCVIEWERGLVIS, PETSCVIEWEREXODUSII, PETSCVIEWERPYTHON, PETSCVIEWERPYVISTA, NULL}; /* list should be automatically generated from PetscViewersList */
189: PetscFunctionBegin;
190: PetscCall(PetscStrlen(value, &viewer_string_length));
191: if (!viewer_string_length) {
192: if (format) *format = PETSC_VIEWER_DEFAULT;
193: if (viewer) {
194: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
195: PetscCall(PetscObjectReference((PetscObject)*viewer));
196: }
197: PetscFunctionReturn(PETSC_SUCCESS);
198: }
200: PetscCall(PetscStrallocpy(value, &loc0_vtype));
201: PetscCall(PetscStrchr(loc0_vtype, ':', &loc1_fname));
202: if (loc1_fname) {
203: PetscBool is_daos;
204: *loc1_fname++ = 0;
205: // When using DAOS, the filename will have the form "daos:/path/to/file.h5", so capture the rest of it.
206: PetscCall(PetscStrncmp(loc1_fname, "daos:", 5, &is_daos));
207: PetscCall(PetscStrchr(loc1_fname + (is_daos == PETSC_TRUE ? 5 : 0), ':', &loc2_fmt));
208: }
209: if (loc2_fmt) {
210: *loc2_fmt++ = 0;
211: PetscCall(PetscStrchr(loc2_fmt, ':', &loc3_fmode));
212: }
213: if (loc3_fmode) *loc3_fmode++ = 0;
214: PetscCall(PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii", viewers, &cnt));
215: PetscCheck(cnt <= (PetscInt)sizeof(viewers) - 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Unknown viewer type: %s", loc0_vtype);
216: if (viewer) {
217: if (!loc1_fname) {
218: switch (cnt) {
219: case 0:
220: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
221: PetscCall(PetscObjectReference((PetscObject)*viewer));
222: break;
223: case 1:
224: if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PetscCall(PETSC_ERR_PLIB);
225: PetscCall(PetscObjectReference((PetscObject)*viewer));
226: break;
227: case 2:
228: if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PetscCall(PETSC_ERR_PLIB);
229: PetscCall(PetscObjectReference((PetscObject)*viewer));
230: break;
231: #if PetscDefined(USE_SOCKET_VIEWER)
232: case 3:
233: if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PetscCall(PETSC_ERR_PLIB);
234: PetscCall(PetscObjectReference((PetscObject)*viewer));
235: break;
236: #endif
237: #if PetscDefined(HAVE_MATLAB)
238: case 4:
239: if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PetscCall(PETSC_ERR_PLIB);
240: PetscCall(PetscObjectReference((PetscObject)*viewer));
241: break;
242: #endif
243: #if PetscDefined(HAVE_SAWS)
244: case 5:
245: if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PetscCall(PETSC_ERR_PLIB);
246: PetscCall(PetscObjectReference((PetscObject)*viewer));
247: break;
248: #endif
249: #if PetscDefined(HAVE_HDF5)
250: case 7:
251: if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PetscCall(PETSC_ERR_PLIB);
252: PetscCall(PetscObjectReference((PetscObject)*viewer));
253: break;
254: #endif
255: case 8:
256: if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PetscCall(PETSC_ERR_PLIB);
257: PetscCall(PetscObjectReference((PetscObject)*viewer));
258: break;
259: #if PetscDefined(HAVE_EXODUSII)
260: case 9:
261: if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PetscCall(PETSC_ERR_PLIB);
262: PetscCall(PetscObjectReference((PetscObject)*viewer));
263: break;
264: #endif
265: case 10:
266: if (!(*viewer = PETSC_VIEWER_PYTHON_(comm))) PetscCall(PETSC_ERR_PLIB);
267: PetscCall(PetscObjectReference((PetscObject)*viewer));
268: break;
269: case 11:
270: if (!(*viewer = PETSC_VIEWER_PYVISTA_(comm))) PetscCall(PETSC_ERR_PLIB);
271: PetscCall(PetscObjectReference((PetscObject)*viewer));
272: break;
273: default:
274: SETERRQ(comm, PETSC_ERR_SUP, "Unsupported viewer %s", loc0_vtype);
275: }
276: } else {
277: if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
278: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
279: PetscCall(PetscObjectReference((PetscObject)*viewer));
280: } else {
281: PetscFileMode fmode;
282: PetscBool flag = PETSC_FALSE;
284: PetscCall(PetscViewerCreate(comm, viewer));
285: PetscCall(PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii"));
286: fmode = FILE_MODE_WRITE;
287: if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
288: PetscCall(PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag));
289: PetscCheck(flag, comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown file mode: %s", loc3_fmode);
290: }
291: if (loc2_fmt) {
292: PetscBool tk, im;
293: PetscCall(PetscStrcmp(loc1_fname, "tikz", &tk));
294: PetscCall(PetscStrcmp(loc1_fname, "image", &im));
295: if (tk || im) {
296: PetscCall(PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE));
297: *loc2_fmt = 0;
298: }
299: }
300: PetscCall(PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE));
301: PetscCall(PetscViewerFileSetName(*viewer, loc1_fname));
302: if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer, loc1_fname));
303: PetscCall(PetscViewerSetFromOptions(*viewer));
304: }
305: }
306: }
307: if (viewer) PetscCall(PetscViewerSetUp(*viewer));
308: if (loc2_fmt && *loc2_fmt) {
309: PetscViewerFormat tfmt;
310: PetscBool flag;
312: PetscCall(PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag));
313: if (format) *format = tfmt;
314: PetscCheck(flag, comm, PETSC_ERR_SUP, "Unknown viewer format %s", loc2_fmt);
315: } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */
316: PetscCall(PetscViewerGetFormat(*viewer, format));
317: }
318: PetscCall(PetscFree(loc0_vtype));
319: PetscFunctionReturn(PETSC_SUCCESS);
320: }
322: static PetscErrorCode PetscOptionsCreateViewers_Internal(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscInt *n_max_p, PetscViewer viewer[], PetscViewerFormat format[], PetscBool *set, const char func_name[], PetscBool allow_multiple)
323: {
324: const char *value;
325: PetscBool flag, hashelp;
326: PetscInt n_max;
328: PetscFunctionBegin;
329: PetscAssertPointer(name, 4);
330: PetscAssertPointer(n_max_p, 5);
331: n_max = *n_max_p;
332: PetscCheck(n_max >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid size %" PetscInt_FMT " of passed arrays", *n_max_p);
333: *n_max_p = 0;
335: if (set) *set = PETSC_FALSE;
336: PetscCall(PetscOptionsGetCreateViewerOff(&flag));
337: if (flag) PetscFunctionReturn(PETSC_SUCCESS);
339: PetscCall(PetscOptionsHasHelp(NULL, &hashelp));
340: if (hashelp) {
341: PetscBool found;
343: if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
344: PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found));
345: if (!found && viewer) {
346: PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1));
347: PetscCall((*PetscHelpPrintf)(comm, " -%s%s ascii[:[filename][:[format][:filemode]]]: %s (%s)\n", pre ? pre : "", name + 1, "Prints object to stdout or ASCII file", func_name));
348: PetscCall((*PetscHelpPrintf)(comm, " -%s%s binary[:[filename][:[format][:filemode]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", func_name));
349: PetscCall((*PetscHelpPrintf)(comm, " -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", func_name));
350: PetscCall((*PetscHelpPrintf)(comm, " -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", func_name));
351: PetscCall((*PetscHelpPrintf)(comm, " -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", func_name));
352: if (allow_multiple) PetscCall((*PetscHelpPrintf)(comm, " -%s%s v1[,v2,...]: %s (%s)\n", pre ? pre : "", name + 1, "Multiple viewers", func_name));
353: }
354: }
356: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
357: if (flag) {
358: if (set) *set = PETSC_TRUE;
359: if (!value) {
360: PetscCheck(n_max > 0, comm, PETSC_ERR_ARG_SIZ, "More viewers (1) than max available (0)");
361: if (format) *format = PETSC_VIEWER_DEFAULT;
362: if (viewer) {
363: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
364: PetscCall(PetscObjectReference((PetscObject)*viewer));
365: }
366: *n_max_p = 1;
367: } else {
368: char *loc0_viewer_string = NULL, *this_viewer_string = NULL;
369: size_t viewer_string_length;
371: PetscCall(PetscStrallocpy(value, &loc0_viewer_string));
372: PetscCall(PetscStrlen(loc0_viewer_string, &viewer_string_length));
373: this_viewer_string = loc0_viewer_string;
375: do {
376: PetscViewer *this_viewer;
377: PetscViewerFormat *this_viewer_format;
378: char *next_viewer_string = NULL;
379: char *comma_separator = NULL;
380: PetscInt n = *n_max_p;
382: PetscCheck(n < n_max, comm, PETSC_ERR_PLIB, "More viewers than max available (%" PetscInt_FMT ")", n_max);
384: PetscCall(PetscStrchr(this_viewer_string, ',', &comma_separator));
385: if (comma_separator) {
386: PetscCheck(allow_multiple, comm, PETSC_ERR_ARG_OUTOFRANGE, "Trying to pass multiple viewers to %s: only one allowed. Use PetscOptionsCreateViewers() instead", func_name);
387: *comma_separator = 0;
388: next_viewer_string = comma_separator + 1;
389: }
390: this_viewer = PetscSafePointerPlusOffset(viewer, n);
391: if (this_viewer) *this_viewer = NULL;
392: this_viewer_format = PetscSafePointerPlusOffset(format, n);
393: if (this_viewer_format) *this_viewer_format = PETSC_VIEWER_DEFAULT;
394: PetscCall(PetscOptionsCreateViewers_Single(comm, this_viewer_string, this_viewer, this_viewer_format));
395: this_viewer_string = next_viewer_string;
396: (*n_max_p)++;
397: } while (this_viewer_string);
398: PetscCall(PetscFree(loc0_viewer_string));
399: }
400: }
401: PetscFunctionReturn(PETSC_SUCCESS);
402: }
404: /*@
405: PetscOptionsCreateViewer - Creates a `PetscViewer` and `PetscViewerFormat` based on a viewer specification in the options database
407: Collective
409: Input Parameters:
410: + comm - the communicator to own the viewer
411: . options - options database, use `NULL` for default global database
412: . prefix - the string to prepend to the name (may be `NULL`)
413: - name - the options database name that will be checked for
415: Output Parameters:
416: + viewer - the viewer, pass `NULL` if not needed
417: . format - the `PetscViewerFormat` requested by the user, pass `NULL` if not needed
418: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
420: Level: intermediate
422: Notes:
423: The Viewer specification has the following form
424: .vb
425: ascii[:[filename][:[format][:filemode]]] - filename defaults to stdout
426: binary[:[filename][:[format][:filemode]]] - defaults to the filename of binaryoutput
427: hdf5[:[filename][:[format][:filemode]]] - HDF5 input and output, PETSCVIEWERHDF5
428: pyvista[:[filename][:[format][:filemode]]] - display the object with PyVista, PETSCVIEWERPYVISTA
429: draw[:x] - draw the object to X Windows
430: draw[:tikz[:filename]] - draw the object to a TikZ file
431: draw[:image[:dirname]] - draw the object to an image in memory that gets saved to files in a directory
432: socket[:port] - defaults to the standard socket output port of 5005, see PetscViewerSocketOpen()
433: saws[:communicatorname] - publishes object to the Scientific Application Webserver (SAWs)
434: vtk:filename.vts - VTK output, PETSCVIEWERVTK
435: .ve
437: See `PetscViewerType` for a list of all available viewer types (the string before the first `:`).
439: See `PetscViewerFormat` for the possible values of `format`.
441: See `PetscFileMode` for the possible values of `filemode`.
443: If no viewer type is indicated before the first `:`, then `ascii` is used.
445: Unless `filemode` is `append` or `append_update`, files opened in write mode overwrite any previous file.
447: You can control whether calls to this function return immediately with a value of `set` of `PETSC_FALSE` using `PetscOptionsPushCreateViewerOff()`.
448: This is useful if calling many small subsolves, in which case `XXXViewFromOptions()` calls can take an appreciable fraction of the runtime.
450: This routine is thread-safe for accessing predefined `PetscViewer`s like `PETSC_VIEWER_STDOUT_SELF` but not for accessing
451: files by name.
453: This routine is used by `KSPMonitorSetFromOptions()`, `SNESMonitorSetFromOptions()`, `TSMonitorSetFromOptions()`, `TaoMonitorSetFromOptions()`, and `DMMonitorSetFromOptions()`,
454: as well as `PetscObjectViewFromOptions()` and all functions, such as `VecViewFromOptions()` that call it.
456: Example Usage:
457: .vb
458: ascii:mesh.tex:ascii_latex - View a `DMPLEX` in LaTeX/TikZ
459: draw:tikz:figure.tex - View an object in the file `figure.tex` using TikZ
460: .ve
462: .seealso: [](sec_viewers), `PetscViewerFormat`, `PetscViewerDestroy()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
463: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
464: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
465: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
466: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
467: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
468: `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`,
469: `KSPMonitorSetFromOptions()`, `SNESMonitorSetFromOptions()`, `TSMonitorSetFromOptions()`,
470: `TaoMonitorSetFromOptions()`, `DMMonitorSetFromOptions()`, `PetscObjectViewFromOptions()`, `VecViewFromOptions()`
471: @*/
472: PetscErrorCode PetscOptionsCreateViewer(MPI_Comm comm, PetscOptions options, const char prefix[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
473: {
474: PetscInt n_max = 1;
475: PetscBool set_internal;
477: PetscFunctionBegin;
478: if (viewer) *viewer = NULL;
479: if (format) *format = PETSC_VIEWER_DEFAULT;
480: PetscCall(PetscOptionsCreateViewers_Internal(comm, options, prefix, name, &n_max, viewer, format, &set_internal, PETSC_FUNCTION_NAME, PETSC_FALSE));
481: if (set_internal) PetscAssert(n_max == 1, comm, PETSC_ERR_PLIB, "Unexpected: %" PetscInt_FMT " != 1 viewers set", n_max);
482: if (set) *set = set_internal;
483: PetscFunctionReturn(PETSC_SUCCESS);
484: }
486: /*@
487: PetscOptionsCreateViewers - Create multiple viewers from a comma-separated list of viewer specifications in the options database
489: Collective
491: Input Parameters:
492: + comm - the communicator to own the viewers
493: . options - options database, use `NULL` for default global database
494: . prefix - the string to prepend to the name (may be `NULL`)
495: . name - the options database name that will be checked for
496: - n_max - on input: the maximum number of viewers; on output: the number of viewers found in the comma-separated list
498: Output Parameters:
499: + viewers - an array to hold at least `n_max` `PetscViewer`s, or `NULL` if not needed; on output: if not `NULL`, the
500: first `n_max` entries are initialized `PetscViewer`s
501: . formats - an array to hold at least `n_max` `PetscViewerFormat`s, or `NULL` if not needed; on output: if not
502: `NULL`, the first `n_max` entries are valid `PetscViewewFormat`s
503: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
505: Level: intermediate
507: Notes:
508: See `PetscOptionsCreateViewer()` for how the viewer specifications are interpreted.
510: Use `PetscViewerDestroy()` on each viewer.
512: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`
513: @*/
514: PetscErrorCode PetscOptionsCreateViewers(MPI_Comm comm, PetscOptions options, const char prefix[], const char name[], PetscInt *n_max, PetscViewer viewers[], PetscViewerFormat formats[], PetscBool *set)
515: {
516: PetscFunctionBegin;
517: PetscCall(PetscOptionsCreateViewers_Internal(comm, options, prefix, name, n_max, viewers, formats, set, PETSC_FUNCTION_NAME, PETSC_TRUE));
518: PetscFunctionReturn(PETSC_SUCCESS);
519: }
521: /*@
522: PetscViewerCreate - Creates a viewing context. A `PetscViewer` represents a file, a graphical window, a Unix socket or a variety of other ways
523: of viewing a PETSc object
525: Collective
527: Input Parameter:
528: . comm - MPI communicator
530: Output Parameter:
531: . inviewer - location to put the `PetscViewer` context
533: Level: advanced
535: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType`
536: @*/
537: PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer)
538: {
539: PetscViewer viewer;
541: PetscFunctionBegin;
542: PetscAssertPointer(inviewer, 2);
543: PetscCall(PetscViewerInitializePackage());
544: PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView));
545: *inviewer = viewer;
546: viewer->data = NULL;
547: PetscFunctionReturn(PETSC_SUCCESS);
548: }
550: /*@
551: PetscViewerSetType - Builds `PetscViewer` for a particular implementation.
553: Collective
555: Input Parameters:
556: + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()`
557: - type - for example, `PETSCVIEWERASCII`
559: Options Database Key:
560: . -viewer_type type - Sets the type; use -help for a list of available methods (for instance, ascii)
562: Level: advanced
564: Note:
565: See `PetscViewerType` for possible values
567: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
568: @*/
569: PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type)
570: {
571: PetscBool match;
572: PetscErrorCode (*r)(PetscViewer);
574: PetscFunctionBegin;
576: PetscAssertPointer(type, 2);
577: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match));
578: if (match) PetscFunctionReturn(PETSC_SUCCESS);
580: /* cleanup any old type that may be there */
581: PetscTryTypeMethod(viewer, destroy);
582: viewer->ops->destroy = NULL;
583: viewer->data = NULL;
585: PetscCall(PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps)));
587: PetscCall(PetscFunctionListFind(PetscViewerList, type, &r));
588: PetscCheck(r, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscViewer type given: %s", type);
590: PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type));
591: PetscCall((*r)(viewer));
592: PetscFunctionReturn(PETSC_SUCCESS);
593: }
595: /*@
596: PetscViewerRegister - Adds a viewer to those available for use with `PetscViewerSetType()`
598: Not Collective, No Fortran Support
600: Input Parameters:
601: + sname - name of a new user-defined viewer
602: - function - routine to create method context
604: Level: developer
606: Note:
607: `PetscViewerRegister()` may be called multiple times to add several user-defined viewers.
609: Example Usage:
610: .vb
611: PetscViewerRegister("my_viewer_type", MyViewerCreate);
612: .ve
614: Then, your solver can be chosen with the procedural interface via
615: .vb
616: PetscViewerSetType(viewer, "my_viewer_type")
617: .ve
618: or at runtime via the option
619: .vb
620: -viewer_type my_viewer_type
621: .ve
623: .seealso: [](sec_viewers), `PetscViewerRegisterAll()`
624: @*/
625: PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
626: {
627: PetscFunctionBegin;
628: PetscCall(PetscViewerInitializePackage());
629: PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function));
630: PetscFunctionReturn(PETSC_SUCCESS);
631: }
633: /*@
634: PetscViewerSetFromOptions - Sets various options for a viewer based on values in the options database.
636: Collective
638: Input Parameter:
639: . viewer - the viewer context
641: Level: intermediate
643: Note:
644: Must be called after `PetscViewerCreate()` but before the `PetscViewer` is used.
646: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
647: @*/
648: PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
649: {
650: char vtype[256];
651: PetscBool flg;
653: PetscFunctionBegin;
656: if (!PetscViewerList) PetscCall(PetscViewerRegisterAll());
657: PetscObjectOptionsBegin((PetscObject)viewer);
658: PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, sizeof(vtype), &flg));
659: if (flg) PetscCall(PetscViewerSetType(viewer, vtype));
660: /* type has not been set? */
661: if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
662: PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject);
664: /* process any options handlers added with PetscObjectAddOptionsHandler() */
665: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject));
666: PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view"));
667: PetscOptionsEnd();
668: PetscFunctionReturn(PETSC_SUCCESS);
669: }
671: /*@
672: PetscViewerFlowControlStart - Begin a flow-controlled viewer operation on the main MPI process
674: Collective
676: Input Parameter:
677: . viewer - the binary viewer
679: Output Parameters:
680: + mcnt - the current flow-control counter on the main MPI process
681: - cnt - the flow-control window size (also read from the viewer)
683: Level: developer
685: Note:
686: Used together with `PetscViewerFlowControlStepMain()` and `PetscViewerFlowControlEndMain()` on the main process (rank 0),
687: and with `PetscViewerFlowControlStepWorker()` and `PetscViewerFlowControlEndWorker()` on the other processes, to serialize
688: I/O work through a bounded window so that all processes do not simultaneously flood the main process with data.
690: .seealso: `PetscViewer`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`, `PetscViewerFlowControlStepWorker()`,
691: `PetscViewerFlowControlEndWorker()`, `PetscViewerBinaryGetFlowControl()`
692: @*/
693: PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
694: {
695: PetscFunctionBegin;
696: PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt));
697: PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt));
698: PetscFunctionReturn(PETSC_SUCCESS);
699: }
701: /*@
702: PetscViewerFlowControlStepMain - Advance the flow-control window on the main MPI process during a viewer operation
704: Collective
706: Input Parameters:
707: + viewer - the binary viewer
708: . i - the current MPI rank being served
709: - cnt - the flow-control window size returned by `PetscViewerFlowControlStart()`
711: Input/Output Parameter:
712: . mcnt - the running flow-control counter; incremented and broadcast when `i` reaches it
714: Level: developer
716: Note:
717: Called on the main MPI process (rank 0) once per worker rank in a loop; when the current rank has caught up to `mcnt`
718: the window is advanced by `cnt` and broadcast so waiting workers can proceed.
720: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlEndMain()`, `PetscViewerFlowControlStepWorker()`,
721: `PetscViewerFlowControlEndWorker()`
722: @*/
723: PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
724: {
725: MPI_Comm comm;
727: PetscFunctionBegin;
728: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
729: if (i >= *mcnt) {
730: *mcnt += cnt;
731: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
732: }
733: PetscFunctionReturn(PETSC_SUCCESS);
734: }
736: /*@
737: PetscViewerFlowControlEndMain - Finish a flow-controlled viewer operation on the main MPI process by signalling completion to the workers
739: Collective
741: Input Parameter:
742: . viewer - the binary viewer
744: Input/Output Parameter:
745: . mcnt - the flow-control counter; reset to 0 and broadcast to signal completion
747: Level: developer
749: Note:
750: Broadcasting `mcnt = 0` releases any worker MPI processes still waiting inside `PetscViewerFlowControlEndWorker()`.
752: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlStepWorker()`,
753: `PetscViewerFlowControlEndWorker()`
754: @*/
755: PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
756: {
757: MPI_Comm comm;
759: PetscFunctionBegin;
760: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
761: *mcnt = 0;
762: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
763: PetscFunctionReturn(PETSC_SUCCESS);
764: }
766: /*@
767: PetscViewerFlowControlStepWorker - Wait on a worker MPI process until the flow-control window includes this rank
769: Collective
771: Input Parameters:
772: + viewer - the binary viewer
773: - rank - the calling MPI process rank
775: Input/Output Parameter:
776: . mcnt - the flow-control counter; updated with values broadcast from the main MPI process until it exceeds `rank`
778: Level: developer
780: Note:
781: Blocks in a loop of `MPI_Bcast()` until the main MPI process (through `PetscViewerFlowControlStepMain()`) advances the
782: window past this rank, giving the worker permission to perform its I/O.
784: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`,
785: `PetscViewerFlowControlEndWorker()`
786: @*/
787: PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
788: {
789: MPI_Comm comm;
791: PetscFunctionBegin;
792: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
793: while (PETSC_TRUE) {
794: if (rank < *mcnt) break;
795: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
796: }
797: PetscFunctionReturn(PETSC_SUCCESS);
798: }
800: /*@
801: PetscViewerFlowControlEndWorker - Wait on a worker MPI process for the main MPI process to signal completion of a flow-controlled viewer operation
803: Collective
805: Input Parameter:
806: . viewer - the binary viewer
808: Input/Output Parameter:
809: . mcnt - the flow-control counter; updated with values broadcast from the main MPI process until it becomes 0
811: Level: developer
813: Note:
814: Blocks in a loop of `MPI_Bcast()` until `PetscViewerFlowControlEndMain()` sends a `mcnt = 0` completion signal.
816: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`,
817: `PetscViewerFlowControlStepWorker()`
818: @*/
819: PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
820: {
821: MPI_Comm comm;
823: PetscFunctionBegin;
824: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
825: while (PETSC_TRUE) {
826: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
827: if (!*mcnt) break;
828: }
829: PetscFunctionReturn(PETSC_SUCCESS);
830: }