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: /* these options are printed outside any PetscOptionsBegin()/PetscOptionsEnd() block; they are documented
340: in the manual section a PetscViewer belongs to, and the default options database is used here so that
341: this agrees with the rest of the help output */
342: PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Viewer", &hashelp));
343: if (hashelp) {
344: PetscBool found;
346: if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
347: PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found));
348: if (!found && viewer) {
349: PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1));
350: 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));
351: PetscCall((*PetscHelpPrintf)(comm, " -%s%s binary[:[filename][:[format][:filemode]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", func_name));
352: PetscCall((*PetscHelpPrintf)(comm, " -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", func_name));
353: PetscCall((*PetscHelpPrintf)(comm, " -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", func_name));
354: PetscCall((*PetscHelpPrintf)(comm, " -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", func_name));
355: if (allow_multiple) PetscCall((*PetscHelpPrintf)(comm, " -%s%s v1[,v2,...]: %s (%s)\n", pre ? pre : "", name + 1, "Multiple viewers", func_name));
356: }
357: }
359: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
360: if (flag) {
361: if (set) *set = PETSC_TRUE;
362: if (!value) {
363: PetscCheck(n_max > 0, comm, PETSC_ERR_ARG_SIZ, "More viewers (1) than max available (0)");
364: if (format) *format = PETSC_VIEWER_DEFAULT;
365: if (viewer) {
366: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
367: PetscCall(PetscObjectReference((PetscObject)*viewer));
368: }
369: *n_max_p = 1;
370: } else {
371: char *loc0_viewer_string = NULL, *this_viewer_string = NULL;
372: size_t viewer_string_length;
374: PetscCall(PetscStrallocpy(value, &loc0_viewer_string));
375: PetscCall(PetscStrlen(loc0_viewer_string, &viewer_string_length));
376: this_viewer_string = loc0_viewer_string;
378: do {
379: PetscViewer *this_viewer;
380: PetscViewerFormat *this_viewer_format;
381: char *next_viewer_string = NULL;
382: char *comma_separator = NULL;
383: PetscInt n = *n_max_p;
385: PetscCheck(n < n_max, comm, PETSC_ERR_PLIB, "More viewers than max available (%" PetscInt_FMT ")", n_max);
387: PetscCall(PetscStrchr(this_viewer_string, ',', &comma_separator));
388: if (comma_separator) {
389: PetscCheck(allow_multiple, comm, PETSC_ERR_ARG_OUTOFRANGE, "Trying to pass multiple viewers to %s: only one allowed. Use PetscOptionsCreateViewers() instead", func_name);
390: *comma_separator = 0;
391: next_viewer_string = comma_separator + 1;
392: }
393: this_viewer = PetscSafePointerPlusOffset(viewer, n);
394: if (this_viewer) *this_viewer = NULL;
395: this_viewer_format = PetscSafePointerPlusOffset(format, n);
396: if (this_viewer_format) *this_viewer_format = PETSC_VIEWER_DEFAULT;
397: PetscCall(PetscOptionsCreateViewers_Single(comm, this_viewer_string, this_viewer, this_viewer_format));
398: this_viewer_string = next_viewer_string;
399: (*n_max_p)++;
400: } while (this_viewer_string);
401: PetscCall(PetscFree(loc0_viewer_string));
402: }
403: }
404: PetscFunctionReturn(PETSC_SUCCESS);
405: }
407: /*@
408: PetscOptionsCreateViewer - Creates a `PetscViewer` and `PetscViewerFormat` based on a viewer specification in the options database
410: Collective
412: Input Parameters:
413: + comm - the communicator to own the viewer
414: . options - options database, use `NULL` for default global database
415: . prefix - the string to prepend to the name (may be `NULL`)
416: - name - the options database name that will be checked for
418: Output Parameters:
419: + viewer - the viewer, pass `NULL` if not needed
420: . format - the `PetscViewerFormat` requested by the user, pass `NULL` if not needed
421: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
423: Level: intermediate
425: Notes:
426: The Viewer specification has the following form
427: .vb
428: ascii[:[filename][:[format][:filemode]]] - filename defaults to stdout
429: binary[:[filename][:[format][:filemode]]] - defaults to the filename of binaryoutput
430: hdf5[:[filename][:[format][:filemode]]] - HDF5 input and output, PETSCVIEWERHDF5
431: pyvista[:[filename][:[format][:filemode]]] - display the object with PyVista, PETSCVIEWERPYVISTA
432: draw[:x] - draw the object to X Windows
433: draw[:tikz[:filename]] - draw the object to a TikZ file
434: draw[:image[:dirname]] - draw the object to an image in memory that gets saved to files in a directory
435: socket[:port] - defaults to the standard socket output port of 5005, see PetscViewerSocketOpen()
436: saws[:communicatorname] - publishes object to the Scientific Application Webserver (SAWs)
437: vtk:filename.vts - VTK output, PETSCVIEWERVTK
438: .ve
440: See `PetscViewerType` for a list of all available viewer types (the string before the first `:`).
442: See `PetscViewerFormat` for the possible values of `format`.
444: See `PetscFileMode` for the possible values of `filemode`.
446: If no viewer type is indicated before the first `:`, then `ascii` is used.
448: Unless `filemode` is `append` or `append_update`, files opened in write mode overwrite any previous file.
450: You can control whether calls to this function return immediately with a value of `set` of `PETSC_FALSE` using `PetscOptionsPushCreateViewerOff()`.
451: This is useful if calling many small subsolves, in which case `XXXViewFromOptions()` calls can take an appreciable fraction of the runtime.
453: This routine is thread-safe for accessing predefined `PetscViewer`s like `PETSC_VIEWER_STDOUT_SELF` but not for accessing
454: files by name.
456: This routine is used by `KSPMonitorSetFromOptions()`, `SNESMonitorSetFromOptions()`, `TSMonitorSetFromOptions()`, `TaoMonitorSetFromOptions()`, and `DMMonitorSetFromOptions()`,
457: as well as `PetscObjectViewFromOptions()` and all functions, such as `VecViewFromOptions()` that call it.
459: Example Usage:
460: .vb
461: ascii:mesh.tex:ascii_latex - View a `DMPLEX` in LaTeX/TikZ
462: draw:tikz:figure.tex - View an object in the file `figure.tex` using TikZ
463: .ve
465: .seealso: [](sec_viewers), `PetscViewerFormat`, `PetscViewerDestroy()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
466: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
467: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
468: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
469: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
470: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
471: `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`,
472: `KSPMonitorSetFromOptions()`, `SNESMonitorSetFromOptions()`, `TSMonitorSetFromOptions()`,
473: `TaoMonitorSetFromOptions()`, `DMMonitorSetFromOptions()`, `PetscObjectViewFromOptions()`, `VecViewFromOptions()`
474: @*/
475: PetscErrorCode PetscOptionsCreateViewer(MPI_Comm comm, PetscOptions options, const char prefix[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
476: {
477: PetscInt n_max = 1;
478: PetscBool set_internal;
480: PetscFunctionBegin;
481: if (viewer) *viewer = NULL;
482: if (format) *format = PETSC_VIEWER_DEFAULT;
483: PetscCall(PetscOptionsCreateViewers_Internal(comm, options, prefix, name, &n_max, viewer, format, &set_internal, PETSC_FUNCTION_NAME, PETSC_FALSE));
484: if (set_internal) PetscAssert(n_max == 1, comm, PETSC_ERR_PLIB, "Unexpected: %" PetscInt_FMT " != 1 viewers set", n_max);
485: if (set) *set = set_internal;
486: PetscFunctionReturn(PETSC_SUCCESS);
487: }
489: /*@
490: PetscOptionsCreateViewers - Create multiple viewers from a comma-separated list of viewer specifications in the options database
492: Collective
494: Input Parameters:
495: + comm - the communicator to own the viewers
496: . options - options database, use `NULL` for default global database
497: . prefix - the string to prepend to the name (may be `NULL`)
498: . name - the options database name that will be checked for
499: - n_max - on input: the maximum number of viewers; on output: the number of viewers found in the comma-separated list
501: Output Parameters:
502: + viewers - an array to hold at least `n_max` `PetscViewer`s, or `NULL` if not needed; on output: if not `NULL`, the
503: first `n_max` entries are initialized `PetscViewer`s
504: . formats - an array to hold at least `n_max` `PetscViewerFormat`s, or `NULL` if not needed; on output: if not
505: `NULL`, the first `n_max` entries are valid `PetscViewewFormat`s
506: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
508: Level: intermediate
510: Notes:
511: See `PetscOptionsCreateViewer()` for how the viewer specifications are interpreted.
513: Use `PetscViewerDestroy()` on each viewer.
515: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`
516: @*/
517: PetscErrorCode PetscOptionsCreateViewers(MPI_Comm comm, PetscOptions options, const char prefix[], const char name[], PetscInt *n_max, PetscViewer viewers[], PetscViewerFormat formats[], PetscBool *set)
518: {
519: PetscFunctionBegin;
520: PetscCall(PetscOptionsCreateViewers_Internal(comm, options, prefix, name, n_max, viewers, formats, set, PETSC_FUNCTION_NAME, PETSC_TRUE));
521: PetscFunctionReturn(PETSC_SUCCESS);
522: }
524: /*@
525: PetscViewerCreate - Creates a viewing context. A `PetscViewer` represents a file, a graphical window, a Unix socket or a variety of other ways
526: of viewing a PETSc object
528: Collective
530: Input Parameter:
531: . comm - MPI communicator
533: Output Parameter:
534: . inviewer - location to put the `PetscViewer` context
536: Level: advanced
538: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType`
539: @*/
540: PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer)
541: {
542: PetscViewer viewer;
544: PetscFunctionBegin;
545: PetscAssertPointer(inviewer, 2);
546: PetscCall(PetscViewerInitializePackage());
547: PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView));
548: *inviewer = viewer;
549: viewer->data = NULL;
550: PetscFunctionReturn(PETSC_SUCCESS);
551: }
553: /*@
554: PetscViewerSetType - Builds `PetscViewer` for a particular implementation.
556: Collective
558: Input Parameters:
559: + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()`
560: - type - for example, `PETSCVIEWERASCII`
562: Options Database Key:
563: . -viewer_type type - Sets the type; use -help for a list of available methods (for instance, ascii)
565: Level: advanced
567: Note:
568: See `PetscViewerType` for possible values
570: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
571: @*/
572: PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type)
573: {
574: PetscBool match;
575: PetscErrorCode (*r)(PetscViewer);
577: PetscFunctionBegin;
579: PetscAssertPointer(type, 2);
580: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match));
581: if (match) PetscFunctionReturn(PETSC_SUCCESS);
583: /* cleanup any old type that may be there */
584: PetscTryTypeMethod(viewer, destroy);
585: viewer->ops->destroy = NULL;
586: viewer->data = NULL;
588: PetscCall(PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps)));
590: PetscCall(PetscFunctionListFind(PetscViewerList, type, &r));
591: PetscCheck(r, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscViewer type given: %s", type);
593: PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type));
594: PetscCall((*r)(viewer));
595: PetscFunctionReturn(PETSC_SUCCESS);
596: }
598: /*@
599: PetscViewerRegister - Adds a viewer to those available for use with `PetscViewerSetType()`
601: Not Collective, No Fortran Support
603: Input Parameters:
604: + sname - name of a new user-defined viewer
605: - function - routine to create method context
607: Level: developer
609: Note:
610: `PetscViewerRegister()` may be called multiple times to add several user-defined viewers.
612: Example Usage:
613: .vb
614: PetscViewerRegister("my_viewer_type", MyViewerCreate);
615: .ve
617: Then, your solver can be chosen with the procedural interface via
618: .vb
619: PetscViewerSetType(viewer, "my_viewer_type")
620: .ve
621: or at runtime via the option
622: .vb
623: -viewer_type my_viewer_type
624: .ve
626: .seealso: [](sec_viewers), `PetscViewerRegisterAll()`
627: @*/
628: PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
629: {
630: PetscFunctionBegin;
631: PetscCall(PetscViewerInitializePackage());
632: PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function));
633: PetscFunctionReturn(PETSC_SUCCESS);
634: }
636: /*@
637: PetscViewerSetFromOptions - Sets various options for a viewer based on values in the options database.
639: Collective
641: Input Parameter:
642: . viewer - the viewer context
644: Level: intermediate
646: Note:
647: Must be called after `PetscViewerCreate()` but before the `PetscViewer` is used.
649: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
650: @*/
651: PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
652: {
653: char vtype[256];
654: PetscBool flg;
656: PetscFunctionBegin;
659: if (!PetscViewerList) PetscCall(PetscViewerRegisterAll());
660: PetscObjectOptionsBegin((PetscObject)viewer);
661: PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, sizeof(vtype), &flg));
662: if (flg) PetscCall(PetscViewerSetType(viewer, vtype));
663: /* type has not been set? */
664: if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
665: PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject);
667: /* process any options handlers added with PetscObjectAddOptionsHandler() */
668: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject));
669: PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view"));
670: PetscOptionsEnd();
671: PetscFunctionReturn(PETSC_SUCCESS);
672: }
674: /*@
675: PetscViewerFlowControlStart - Begin a flow-controlled viewer operation on the main MPI process
677: Collective
679: Input Parameter:
680: . viewer - the binary viewer
682: Output Parameters:
683: + mcnt - the current flow-control counter on the main MPI process
684: - cnt - the flow-control window size (also read from the viewer)
686: Level: developer
688: Note:
689: Used together with `PetscViewerFlowControlStepMain()` and `PetscViewerFlowControlEndMain()` on the main process (rank 0),
690: and with `PetscViewerFlowControlStepWorker()` and `PetscViewerFlowControlEndWorker()` on the other processes, to serialize
691: I/O work through a bounded window so that all processes do not simultaneously flood the main process with data.
693: .seealso: `PetscViewer`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`, `PetscViewerFlowControlStepWorker()`,
694: `PetscViewerFlowControlEndWorker()`, `PetscViewerBinaryGetFlowControl()`
695: @*/
696: PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
697: {
698: PetscFunctionBegin;
699: PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt));
700: PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt));
701: PetscFunctionReturn(PETSC_SUCCESS);
702: }
704: /*@
705: PetscViewerFlowControlStepMain - Advance the flow-control window on the main MPI process during a viewer operation
707: Collective
709: Input Parameters:
710: + viewer - the binary viewer
711: . i - the current MPI rank being served
712: - cnt - the flow-control window size returned by `PetscViewerFlowControlStart()`
714: Input/Output Parameter:
715: . mcnt - the running flow-control counter; incremented and broadcast when `i` reaches it
717: Level: developer
719: Note:
720: Called on the main MPI process (rank 0) once per worker rank in a loop; when the current rank has caught up to `mcnt`
721: the window is advanced by `cnt` and broadcast so waiting workers can proceed.
723: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlEndMain()`, `PetscViewerFlowControlStepWorker()`,
724: `PetscViewerFlowControlEndWorker()`
725: @*/
726: PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
727: {
728: MPI_Comm comm;
730: PetscFunctionBegin;
731: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
732: if (i >= *mcnt) {
733: *mcnt += cnt;
734: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
735: }
736: PetscFunctionReturn(PETSC_SUCCESS);
737: }
739: /*@
740: PetscViewerFlowControlEndMain - Finish a flow-controlled viewer operation on the main MPI process by signalling completion to the workers
742: Collective
744: Input Parameter:
745: . viewer - the binary viewer
747: Input/Output Parameter:
748: . mcnt - the flow-control counter; reset to 0 and broadcast to signal completion
750: Level: developer
752: Note:
753: Broadcasting `mcnt = 0` releases any worker MPI processes still waiting inside `PetscViewerFlowControlEndWorker()`.
755: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlStepWorker()`,
756: `PetscViewerFlowControlEndWorker()`
757: @*/
758: PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
759: {
760: MPI_Comm comm;
762: PetscFunctionBegin;
763: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
764: *mcnt = 0;
765: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
766: PetscFunctionReturn(PETSC_SUCCESS);
767: }
769: /*@
770: PetscViewerFlowControlStepWorker - Wait on a worker MPI process until the flow-control window includes this rank
772: Collective
774: Input Parameters:
775: + viewer - the binary viewer
776: - rank - the calling MPI process rank
778: Input/Output Parameter:
779: . mcnt - the flow-control counter; updated with values broadcast from the main MPI process until it exceeds `rank`
781: Level: developer
783: Note:
784: Blocks in a loop of `MPI_Bcast()` until the main MPI process (through `PetscViewerFlowControlStepMain()`) advances the
785: window past this rank, giving the worker permission to perform its I/O.
787: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`,
788: `PetscViewerFlowControlEndWorker()`
789: @*/
790: PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
791: {
792: MPI_Comm comm;
794: PetscFunctionBegin;
795: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
796: while (PETSC_TRUE) {
797: if (rank < *mcnt) break;
798: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
799: }
800: PetscFunctionReturn(PETSC_SUCCESS);
801: }
803: /*@
804: PetscViewerFlowControlEndWorker - Wait on a worker MPI process for the main MPI process to signal completion of a flow-controlled viewer operation
806: Collective
808: Input Parameter:
809: . viewer - the binary viewer
811: Input/Output Parameter:
812: . mcnt - the flow-control counter; updated with values broadcast from the main MPI process until it becomes 0
814: Level: developer
816: Note:
817: Blocks in a loop of `MPI_Bcast()` until `PetscViewerFlowControlEndMain()` sends a `mcnt = 0` completion signal.
819: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`,
820: `PetscViewerFlowControlStepWorker()`
821: @*/
822: PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
823: {
824: MPI_Comm comm;
826: PetscFunctionBegin;
827: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
828: while (PETSC_TRUE) {
829: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
830: if (!*mcnt) break;
831: }
832: PetscFunctionReturn(PETSC_SUCCESS);
833: }