Actual source code: viewreg.c
1: #include <petsc/private/viewerimpl.h>
2: #include <petsc/private/hashtable.h>
3: #if defined(PETSC_HAVE_SAWS)
4: #include <petscviewersaws.h>
5: #endif
7: PetscFunctionList PetscViewerList = NULL;
9: PetscOptionsHelpPrinted PetscOptionsHelpPrintedSingleton = NULL;
10: KHASH_SET_INIT_STR(HTPrinted)
11: struct _n_PetscOptionsHelpPrinted {
12: khash_t(HTPrinted) *printed;
13: PetscSegBuffer strings;
14: };
16: /*@
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: /*@C
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: /*@C
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 !defined(PETSC_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 !defined(PETSC_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: Level: developer
120: Note:
121: Calling `XXXViewFromOptions` in an inner loop can be expensive. This can appear, for example, when using
122: many small subsolves. Call this function to control viewer creation in `PetscOptionsCreateViewer()`, thus removing the expensive `XXXViewFromOptions` calls.
124: Developer Notes:
125: Instead of using this approach, the calls to `PetscOptionsCreateViewer()` can be moved into `XXXSetFromOptions()`
127: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPopCreateViewerOff()`
128: @*/
129: PetscErrorCode PetscOptionsPushCreateViewerOff(PetscBool flg)
130: {
131: PetscFunctionBegin;
132: PetscCheck(inoviewers < PETSCVIEWERCREATEVIEWEROFFPUSHESMAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPushCreateViewerOff(), perhaps you forgot PetscOptionsPopCreateViewerOff()?");
134: noviewers[inoviewers++] = noviewer;
135: noviewer = flg;
136: PetscFunctionReturn(PETSC_SUCCESS);
137: }
139: /*@
140: PetscOptionsPopCreateViewerOff - reset whether `PetscOptionsCreateViewer()` returns a viewer.
142: Logically Collective
144: Level: developer
146: Note:
147: See `PetscOptionsPushCreateViewerOff()`
149: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPushCreateViewerOff()`
150: @*/
151: PetscErrorCode PetscOptionsPopCreateViewerOff(void)
152: {
153: PetscFunctionBegin;
154: PetscCheck(inoviewers, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPopCreateViewerOff(), perhaps you forgot PetscOptionsPushCreateViewerOff()?");
155: noviewer = noviewers[--inoviewers];
156: PetscFunctionReturn(PETSC_SUCCESS);
157: }
159: /*@
160: PetscOptionsGetCreateViewerOff - do `PetscOptionsCreateViewer()`, `PetscOptionsViewer()`, and `PetscOptionsCreateViewers()` return viewers
162: Logically Collective
164: Output Parameter:
165: . flg - whether viewers are returned.
167: Level: developer
169: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`
170: @*/
171: PetscErrorCode PetscOptionsGetCreateViewerOff(PetscBool *flg)
172: {
173: PetscFunctionBegin;
174: PetscAssertPointer(flg, 1);
175: *flg = noviewer;
176: PetscFunctionReturn(PETSC_SUCCESS);
177: }
179: static PetscErrorCode PetscOptionsCreateViewers_Single(MPI_Comm comm, const char value[], PetscViewer *viewer, PetscViewerFormat *format)
180: {
181: char *loc0_vtype = NULL, *loc1_fname = NULL, *loc2_fmt = NULL, *loc3_fmode = NULL;
182: PetscInt cnt;
183: size_t viewer_string_length;
184: const char *viewers[] = {PETSCVIEWERASCII, PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSOCKET, PETSCVIEWERMATLAB, PETSCVIEWERSAWS, PETSCVIEWERVTK, PETSCVIEWERHDF5, PETSCVIEWERGLVIS, PETSCVIEWEREXODUSII, PETSCVIEWERPYTHON, PETSCVIEWERPYVISTA, NULL}; /* list should be automatically generated from PetscViewersList */
186: PetscFunctionBegin;
187: PetscCall(PetscStrlen(value, &viewer_string_length));
188: if (!viewer_string_length) {
189: if (format) *format = PETSC_VIEWER_DEFAULT;
190: if (viewer) {
191: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
192: PetscCall(PetscObjectReference((PetscObject)*viewer));
193: }
194: PetscFunctionReturn(PETSC_SUCCESS);
195: }
197: PetscCall(PetscStrallocpy(value, &loc0_vtype));
198: PetscCall(PetscStrchr(loc0_vtype, ':', &loc1_fname));
199: if (loc1_fname) {
200: PetscBool is_daos;
201: *loc1_fname++ = 0;
202: // When using DAOS, the filename will have the form "daos:/path/to/file.h5", so capture the rest of it.
203: PetscCall(PetscStrncmp(loc1_fname, "daos:", 5, &is_daos));
204: PetscCall(PetscStrchr(loc1_fname + (is_daos == PETSC_TRUE ? 5 : 0), ':', &loc2_fmt));
205: }
206: if (loc2_fmt) {
207: *loc2_fmt++ = 0;
208: PetscCall(PetscStrchr(loc2_fmt, ':', &loc3_fmode));
209: }
210: if (loc3_fmode) *loc3_fmode++ = 0;
211: PetscCall(PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii", viewers, &cnt));
212: PetscCheck(cnt <= (PetscInt)sizeof(viewers) - 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Unknown viewer type: %s", loc0_vtype);
213: if (viewer) {
214: if (!loc1_fname) {
215: switch (cnt) {
216: case 0:
217: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
218: PetscCall(PetscObjectReference((PetscObject)*viewer));
219: break;
220: case 1:
221: if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PetscCall(PETSC_ERR_PLIB);
222: PetscCall(PetscObjectReference((PetscObject)*viewer));
223: break;
224: case 2:
225: if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PetscCall(PETSC_ERR_PLIB);
226: PetscCall(PetscObjectReference((PetscObject)*viewer));
227: break;
228: #if defined(PETSC_USE_SOCKET_VIEWER)
229: case 3:
230: if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PetscCall(PETSC_ERR_PLIB);
231: PetscCall(PetscObjectReference((PetscObject)*viewer));
232: break;
233: #endif
234: #if defined(PETSC_HAVE_MATLAB)
235: case 4:
236: if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PetscCall(PETSC_ERR_PLIB);
237: PetscCall(PetscObjectReference((PetscObject)*viewer));
238: break;
239: #endif
240: #if defined(PETSC_HAVE_SAWS)
241: case 5:
242: if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PetscCall(PETSC_ERR_PLIB);
243: PetscCall(PetscObjectReference((PetscObject)*viewer));
244: break;
245: #endif
246: #if defined(PETSC_HAVE_HDF5)
247: case 7:
248: if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PetscCall(PETSC_ERR_PLIB);
249: PetscCall(PetscObjectReference((PetscObject)*viewer));
250: break;
251: #endif
252: case 8:
253: if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PetscCall(PETSC_ERR_PLIB);
254: PetscCall(PetscObjectReference((PetscObject)*viewer));
255: break;
256: #if defined(PETSC_HAVE_EXODUSII)
257: case 9:
258: if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PetscCall(PETSC_ERR_PLIB);
259: PetscCall(PetscObjectReference((PetscObject)*viewer));
260: break;
261: #endif
262: case 10:
263: if (!(*viewer = PETSC_VIEWER_PYTHON_(comm))) PetscCall(PETSC_ERR_PLIB);
264: PetscCall(PetscObjectReference((PetscObject)*viewer));
265: break;
266: case 11:
267: if (!(*viewer = PETSC_VIEWER_PYVISTA_(comm))) PetscCall(PETSC_ERR_PLIB);
268: PetscCall(PetscObjectReference((PetscObject)*viewer));
269: break;
270: default:
271: SETERRQ(comm, PETSC_ERR_SUP, "Unsupported viewer %s", loc0_vtype);
272: }
273: } else {
274: if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
275: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
276: PetscCall(PetscObjectReference((PetscObject)*viewer));
277: } else {
278: PetscFileMode fmode;
279: PetscBool flag = PETSC_FALSE;
281: PetscCall(PetscViewerCreate(comm, viewer));
282: PetscCall(PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii"));
283: fmode = FILE_MODE_WRITE;
284: if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
285: PetscCall(PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag));
286: PetscCheck(flag, comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown file mode: %s", loc3_fmode);
287: }
288: if (loc2_fmt) {
289: PetscBool tk, im;
290: PetscCall(PetscStrcmp(loc1_fname, "tikz", &tk));
291: PetscCall(PetscStrcmp(loc1_fname, "image", &im));
292: if (tk || im) {
293: PetscCall(PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE));
294: *loc2_fmt = 0;
295: }
296: }
297: PetscCall(PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE));
298: PetscCall(PetscViewerFileSetName(*viewer, loc1_fname));
299: if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer, loc1_fname));
300: PetscCall(PetscViewerSetFromOptions(*viewer));
301: }
302: }
303: }
304: if (viewer) PetscCall(PetscViewerSetUp(*viewer));
305: if (loc2_fmt && *loc2_fmt) {
306: PetscViewerFormat tfmt;
307: PetscBool flag;
309: PetscCall(PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag));
310: if (format) *format = tfmt;
311: PetscCheck(flag, comm, PETSC_ERR_SUP, "Unknown viewer format %s", loc2_fmt);
312: } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */
313: PetscCall(PetscViewerGetFormat(*viewer, format));
314: }
315: PetscCall(PetscFree(loc0_vtype));
316: PetscFunctionReturn(PETSC_SUCCESS);
317: }
319: 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)
320: {
321: const char *value;
322: PetscBool flag, hashelp;
323: PetscInt n_max;
325: PetscFunctionBegin;
326: PetscAssertPointer(name, 4);
327: PetscAssertPointer(n_max_p, 5);
328: n_max = *n_max_p;
329: PetscCheck(n_max >= 0, comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid size %" PetscInt_FMT " of passed arrays", *n_max_p);
330: *n_max_p = 0;
332: if (set) *set = PETSC_FALSE;
333: PetscCall(PetscOptionsGetCreateViewerOff(&flag));
334: if (flag) PetscFunctionReturn(PETSC_SUCCESS);
336: PetscCall(PetscOptionsHasHelp(NULL, &hashelp));
337: if (hashelp) {
338: PetscBool found;
340: if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
341: PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found));
342: if (!found && viewer) {
343: PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1));
344: PetscCall((*PetscHelpPrintf)(comm, " -%s%s ascii[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Prints object to stdout or ASCII file", func_name));
345: PetscCall((*PetscHelpPrintf)(comm, " -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", func_name));
346: PetscCall((*PetscHelpPrintf)(comm, " -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", func_name));
347: PetscCall((*PetscHelpPrintf)(comm, " -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", func_name));
348: PetscCall((*PetscHelpPrintf)(comm, " -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", func_name));
349: if (allow_multiple) PetscCall((*PetscHelpPrintf)(comm, " -%s%s v1[,v2,...]: %s (%s)\n", pre ? pre : "", name + 1, "Multiple viewers", func_name));
350: }
351: }
353: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
354: if (flag) {
355: if (set) *set = PETSC_TRUE;
356: if (!value) {
357: PetscCheck(n_max > 0, comm, PETSC_ERR_ARG_SIZ, "More viewers (1) than max available (0)");
358: if (format) *format = PETSC_VIEWER_DEFAULT;
359: if (viewer) {
360: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
361: PetscCall(PetscObjectReference((PetscObject)*viewer));
362: }
363: *n_max_p = 1;
364: } else {
365: char *loc0_viewer_string = NULL, *this_viewer_string = NULL;
366: size_t viewer_string_length;
368: PetscCall(PetscStrallocpy(value, &loc0_viewer_string));
369: PetscCall(PetscStrlen(loc0_viewer_string, &viewer_string_length));
370: this_viewer_string = loc0_viewer_string;
372: do {
373: PetscViewer *this_viewer;
374: PetscViewerFormat *this_viewer_format;
375: char *next_viewer_string = NULL;
376: char *comma_separator = NULL;
377: PetscInt n = *n_max_p;
379: PetscCheck(n < n_max, comm, PETSC_ERR_PLIB, "More viewers than max available (%" PetscInt_FMT ")", n_max);
381: PetscCall(PetscStrchr(this_viewer_string, ',', &comma_separator));
382: if (comma_separator) {
383: PetscCheck(allow_multiple, comm, PETSC_ERR_ARG_OUTOFRANGE, "Trying to pass multiple viewers to %s: only one allowed. Use PetscOptionsCreateViewers() instead", func_name);
384: *comma_separator = 0;
385: next_viewer_string = comma_separator + 1;
386: }
387: this_viewer = PetscSafePointerPlusOffset(viewer, n);
388: if (this_viewer) *this_viewer = NULL;
389: this_viewer_format = PetscSafePointerPlusOffset(format, n);
390: if (this_viewer_format) *this_viewer_format = PETSC_VIEWER_DEFAULT;
391: PetscCall(PetscOptionsCreateViewers_Single(comm, this_viewer_string, this_viewer, this_viewer_format));
392: this_viewer_string = next_viewer_string;
393: (*n_max_p)++;
394: } while (this_viewer_string);
395: PetscCall(PetscFree(loc0_viewer_string));
396: }
397: }
398: PetscFunctionReturn(PETSC_SUCCESS);
399: }
401: /*@C
402: PetscOptionsCreateViewer - Creates a viewer appropriate for the type indicated by the user
404: Collective
406: Input Parameters:
407: + comm - the communicator to own the viewer
408: . options - options database, use `NULL` for default global database
409: . pre - the string to prepend to the name or `NULL`
410: - name - the options database name that will be checked for
412: Output Parameters:
413: + viewer - the viewer, pass `NULL` if not needed
414: . format - the `PetscViewerFormat` requested by the user, pass `NULL` if not needed
415: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
417: Level: intermediate
419: Notes:
420: The argument has the following form
421: .vb
422: type:filename:format:filemode
423: .ve
424: where all parts are optional, but you need to include the colon to access the next part. The mode argument must a valid `PetscFileMode`, i.e. read, write, append, update, or append_update. For example, to read from an HDF5 file, use
425: .vb
426: hdf5:sol.h5::read
427: .ve
429: If no value is provided ascii:stdout is used
430: + ascii[:[filename][:[format][:append]]] - defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
431: for example ascii::ascii_info prints just the information about the object not all details
432: unless :append is given filename opens in write mode, overwriting what was already there
433: . binary[:[filename][:[format][:append]]] - defaults to the file binaryoutput
434: . draw[:drawtype[:filename]] - for example, draw:tikz, draw:tikz:figure.tex or draw:x
435: . socket[:port] - defaults to the standard output port
436: - saws[:communicatorname] - publishes object to the Scientific Application Webserver (SAWs)
438: You can control whether calls to this function create a viewer (or return early with *set of `PETSC_FALSE`) with
439: `PetscOptionsPushCreateViewerOff()`. This is useful if calling many small subsolves, in which case XXXViewFromOptions can take
440: an appreciable fraction of the runtime.
442: If PETSc is configured with `--with-viewfromoptions=0` this function always returns with *set of `PETSC_FALSE`
444: This routine is thread-safe for accessing predefined `PetscViewer`s like `PETSC_VIEWER_STDOUT_SELF` but not for accessing
445: files by name.
447: .seealso: [](sec_viewers), `PetscViewerDestroy()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
448: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
449: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
450: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
451: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
452: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
453: `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushCreateViewerOff()`, `PetscOptionsPopCreateViewerOff()`,
454: `PetscOptionsCreateViewerOff()`
455: @*/
456: PetscErrorCode PetscOptionsCreateViewer(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
457: {
458: PetscInt n_max = 1;
459: PetscBool set_internal;
461: PetscFunctionBegin;
462: if (viewer) *viewer = NULL;
463: if (format) *format = PETSC_VIEWER_DEFAULT;
464: PetscCall(PetscOptionsCreateViewers_Internal(comm, options, pre, name, &n_max, viewer, format, &set_internal, PETSC_FUNCTION_NAME, PETSC_FALSE));
465: if (set_internal) PetscAssert(n_max == 1, comm, PETSC_ERR_PLIB, "Unexpected: %" PetscInt_FMT " != 1 viewers set", n_max);
466: if (set) *set = set_internal;
467: PetscFunctionReturn(PETSC_SUCCESS);
468: }
470: /*@C
471: PetscOptionsCreateViewers - Create multiple viewers from a comma-separated list in the options database
473: Collective
475: Input Parameters:
476: + comm - the communicator to own the viewers
477: . options - options database, use `NULL` for default global database
478: . pre - the string to prepend to the name or `NULL`
479: . name - the options database name that will be checked for
480: - n_max - on input: the maximum number of viewers; on output: the number of viewers in the comma-separated list
482: Output Parameters:
483: + viewers - an array to hold at least `n_max` `PetscViewer`s, or `NULL` if not needed; on output: if not `NULL`, the
484: first `n_max` entries are initialized `PetscViewer`s
485: . formats - an array to hold at least `n_max` `PetscViewerFormat`s, or `NULL` if not needed; on output: if not
486: `NULL`, the first `n_max` entries are valid `PetscViewewFormat`s
487: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
489: Level: intermediate
491: Note:
492: See `PetscOptionsCreateViewer()` for how the format strings for the viewers are interpreted.
494: Use `PetscViewerDestroy()` on each viewer, otherwise a memory leak will occur.
496: If PETSc is configured with `--with-viewfromoptions=0` this function always returns with `n_max` of 0 and `set` of `PETSC_FALSE`
498: .seealso: [](sec_viewers), `PetscOptionsCreateViewer()`
499: @*/
500: PetscErrorCode PetscOptionsCreateViewers(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscInt *n_max, PetscViewer viewers[], PetscViewerFormat formats[], PetscBool *set)
501: {
502: PetscFunctionBegin;
503: PetscCall(PetscOptionsCreateViewers_Internal(comm, options, pre, name, n_max, viewers, formats, set, PETSC_FUNCTION_NAME, PETSC_TRUE));
504: PetscFunctionReturn(PETSC_SUCCESS);
505: }
507: /*@
508: PetscViewerCreate - Creates a viewing context. A `PetscViewer` represents a file, a graphical window, a Unix socket or a variety of other ways
509: of viewing a PETSc object
511: Collective
513: Input Parameter:
514: . comm - MPI communicator
516: Output Parameter:
517: . inviewer - location to put the `PetscViewer` context
519: Level: advanced
521: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType`
522: @*/
523: PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer)
524: {
525: PetscViewer viewer;
527: PetscFunctionBegin;
528: PetscAssertPointer(inviewer, 2);
529: PetscCall(PetscViewerInitializePackage());
530: PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView));
531: *inviewer = viewer;
532: viewer->data = NULL;
533: PetscFunctionReturn(PETSC_SUCCESS);
534: }
536: /*@
537: PetscViewerSetType - Builds `PetscViewer` for a particular implementation.
539: Collective
541: Input Parameters:
542: + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()`
543: - type - for example, `PETSCVIEWERASCII`
545: Options Database Key:
546: . -viewer_type type - Sets the type; use -help for a list of available methods (for instance, ascii)
548: Level: advanced
550: Note:
551: See `PetscViewerType` for possible values
553: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
554: @*/
555: PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type)
556: {
557: PetscBool match;
558: PetscErrorCode (*r)(PetscViewer);
560: PetscFunctionBegin;
562: PetscAssertPointer(type, 2);
563: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match));
564: if (match) PetscFunctionReturn(PETSC_SUCCESS);
566: /* cleanup any old type that may be there */
567: PetscTryTypeMethod(viewer, destroy);
568: viewer->ops->destroy = NULL;
569: viewer->data = NULL;
571: PetscCall(PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps)));
573: PetscCall(PetscFunctionListFind(PetscViewerList, type, &r));
574: PetscCheck(r, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscViewer type given: %s", type);
576: PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type));
577: PetscCall((*r)(viewer));
578: PetscFunctionReturn(PETSC_SUCCESS);
579: }
581: /*@C
582: PetscViewerRegister - Adds a viewer to those available for use with `PetscViewerSetType()`
584: Not Collective, No Fortran Support
586: Input Parameters:
587: + sname - name of a new user-defined viewer
588: - function - routine to create method context
590: Level: developer
592: Note:
593: `PetscViewerRegister()` may be called multiple times to add several user-defined viewers.
595: Example Usage:
596: .vb
597: PetscViewerRegister("my_viewer_type", MyViewerCreate);
598: .ve
600: Then, your solver can be chosen with the procedural interface via
601: .vb
602: PetscViewerSetType(viewer, "my_viewer_type")
603: .ve
604: or at runtime via the option
605: .vb
606: -viewer_type my_viewer_type
607: .ve
609: .seealso: [](sec_viewers), `PetscViewerRegisterAll()`
610: @*/
611: PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
612: {
613: PetscFunctionBegin;
614: PetscCall(PetscViewerInitializePackage());
615: PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function));
616: PetscFunctionReturn(PETSC_SUCCESS);
617: }
619: /*@C
620: PetscViewerSetFromOptions - Sets various options for a viewer based on values in the options database.
622: Collective
624: Input Parameter:
625: . viewer - the viewer context
627: Level: intermediate
629: Note:
630: Must be called after `PetscViewerCreate()` but before the `PetscViewer` is used.
632: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
633: @*/
634: PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
635: {
636: char vtype[256];
637: PetscBool flg;
639: PetscFunctionBegin;
642: if (!PetscViewerList) PetscCall(PetscViewerRegisterAll());
643: PetscObjectOptionsBegin((PetscObject)viewer);
644: PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, 256, &flg));
645: if (flg) PetscCall(PetscViewerSetType(viewer, vtype));
646: /* type has not been set? */
647: if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
648: PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject);
650: /* process any options handlers added with PetscObjectAddOptionsHandler() */
651: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject));
652: PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view"));
653: PetscOptionsEnd();
654: PetscFunctionReturn(PETSC_SUCCESS);
655: }
657: /*@
658: PetscViewerFlowControlStart - Begin a flow-controlled viewer operation on the main MPI process
660: Collective
662: Input Parameter:
663: . viewer - the binary viewer
665: Output Parameters:
666: + mcnt - the current flow-control counter on the main MPI process
667: - cnt - the flow-control window size (also read from the viewer)
669: Level: developer
671: Note:
672: Used together with `PetscViewerFlowControlStepMain()` and `PetscViewerFlowControlEndMain()` on the main process (rank 0),
673: and with `PetscViewerFlowControlStepWorker()` and `PetscViewerFlowControlEndWorker()` on the other processes, to serialize
674: I/O work through a bounded window so that all processes do not simultaneously flood the main process with data.
676: .seealso: `PetscViewer`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`, `PetscViewerFlowControlStepWorker()`,
677: `PetscViewerFlowControlEndWorker()`, `PetscViewerBinaryGetFlowControl()`
678: @*/
679: PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
680: {
681: PetscFunctionBegin;
682: PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt));
683: PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt));
684: PetscFunctionReturn(PETSC_SUCCESS);
685: }
687: /*@
688: PetscViewerFlowControlStepMain - Advance the flow-control window on the main MPI process during a viewer operation
690: Collective
692: Input Parameters:
693: + viewer - the binary viewer
694: . i - the current MPI rank being served
695: - cnt - the flow-control window size returned by `PetscViewerFlowControlStart()`
697: Input/Output Parameter:
698: . mcnt - the running flow-control counter; incremented and broadcast when `i` reaches it
700: Level: developer
702: Note:
703: Called on the main MPI process (rank 0) once per worker rank in a loop; when the current rank has caught up to `mcnt`
704: the window is advanced by `cnt` and broadcast so waiting workers can proceed.
706: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlEndMain()`, `PetscViewerFlowControlStepWorker()`,
707: `PetscViewerFlowControlEndWorker()`
708: @*/
709: PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
710: {
711: MPI_Comm comm;
713: PetscFunctionBegin;
714: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
715: if (i >= *mcnt) {
716: *mcnt += cnt;
717: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
718: }
719: PetscFunctionReturn(PETSC_SUCCESS);
720: }
722: /*@
723: PetscViewerFlowControlEndMain - Finish a flow-controlled viewer operation on the main MPI process by signalling completion to the workers
725: Collective
727: Input Parameter:
728: . viewer - the binary viewer
730: Input/Output Parameter:
731: . mcnt - the flow-control counter; reset to 0 and broadcast to signal completion
733: Level: developer
735: Note:
736: Broadcasting `mcnt = 0` releases any worker MPI processes still waiting inside `PetscViewerFlowControlEndWorker()`.
738: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlStepWorker()`,
739: `PetscViewerFlowControlEndWorker()`
740: @*/
741: PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
742: {
743: MPI_Comm comm;
745: PetscFunctionBegin;
746: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
747: *mcnt = 0;
748: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
749: PetscFunctionReturn(PETSC_SUCCESS);
750: }
752: /*@
753: PetscViewerFlowControlStepWorker - Wait on a worker MPI process until the flow-control window includes this rank
755: Collective
757: Input Parameters:
758: + viewer - the binary viewer
759: - rank - the calling MPI process rank
761: Input/Output Parameter:
762: . mcnt - the flow-control counter; updated with values broadcast from the main MPI process until it exceeds `rank`
764: Level: developer
766: Note:
767: Blocks in a loop of `MPI_Bcast()` until the main MPI process (through `PetscViewerFlowControlStepMain()`) advances the
768: window past this rank, giving the worker permission to perform its I/O.
770: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`,
771: `PetscViewerFlowControlEndWorker()`
772: @*/
773: PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
774: {
775: MPI_Comm comm;
777: PetscFunctionBegin;
778: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
779: while (PETSC_TRUE) {
780: if (rank < *mcnt) break;
781: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
782: }
783: PetscFunctionReturn(PETSC_SUCCESS);
784: }
786: /*@
787: PetscViewerFlowControlEndWorker - Wait on a worker MPI process for the main MPI process to signal completion of a flow-controlled viewer operation
789: Collective
791: Input Parameter:
792: . viewer - the binary viewer
794: Input/Output Parameter:
795: . mcnt - the flow-control counter; updated with values broadcast from the main MPI process until it becomes 0
797: Level: developer
799: Note:
800: Blocks in a loop of `MPI_Bcast()` until `PetscViewerFlowControlEndMain()` sends a `mcnt = 0` completion signal.
802: .seealso: `PetscViewer`, `PetscViewerFlowControlStart()`, `PetscViewerFlowControlStepMain()`, `PetscViewerFlowControlEndMain()`,
803: `PetscViewerFlowControlStepWorker()`
804: @*/
805: PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
806: {
807: MPI_Comm comm;
809: PetscFunctionBegin;
810: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
811: while (PETSC_TRUE) {
812: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
813: if (!*mcnt) break;
814: }
815: PetscFunctionReturn(PETSC_SUCCESS);
816: }