Actual source code: viewreg.c
2: #include <petsc/private/viewerimpl.h>
3: #include <petsc/private/hashtable.h>
4: #if defined(PETSC_HAVE_SAWS)
5: #include <petscviewersaws.h>
6: #endif
8: PetscFunctionList PetscViewerList = NULL;
10: PetscOptionsHelpPrinted PetscOptionsHelpPrintedSingleton = NULL;
11: KHASH_SET_INIT_STR(HTPrinted)
12: struct _n_PetscOptionsHelpPrinted {
13: khash_t(HTPrinted) *printed;
14: PetscSegBuffer strings;
15: };
17: PetscErrorCode PetscOptionsHelpPrintedDestroy(PetscOptionsHelpPrinted *hp)
18: {
19: PetscFunctionBegin;
20: if (!*hp) PetscFunctionReturn(PETSC_SUCCESS);
21: kh_destroy(HTPrinted, (*hp)->printed);
22: PetscCall(PetscSegBufferDestroy(&(*hp)->strings));
23: PetscCall(PetscFree(*hp));
24: PetscFunctionReturn(PETSC_SUCCESS);
25: }
27: /*@C
28: PetscOptionsHelpPrintedCreate - Creates an object used to manage tracking which help messages have
29: been printed so they will not be printed again.
31: Not Collective
33: Level: developer
35: .seealso: `PetscOptionsHelpPrintedCheck()`, `PetscOptionsHelpPrintChecked()`
36: @*/
37: PetscErrorCode PetscOptionsHelpPrintedCreate(PetscOptionsHelpPrinted *hp)
38: {
39: PetscFunctionBegin;
40: PetscCall(PetscNew(hp));
41: (*hp)->printed = kh_init(HTPrinted);
42: PetscCall(PetscSegBufferCreate(sizeof(char), 10000, &(*hp)->strings));
43: PetscFunctionReturn(PETSC_SUCCESS);
44: }
46: /*@C
47: PetscOptionsHelpPrintedCheck - Checks if a particular pre, name pair has previous been entered (meaning the help message was printed)
49: Not Collective
51: Input Parameters:
52: + hp - the object used to manage tracking what help messages have been printed
53: . pre - the prefix part of the string, many be `NULL`
54: - name - the string to look for (cannot be `NULL`)
56: Output Parameter:
57: . found - `PETSC_TRUE` if the string was already set
59: Level: intermediate
61: .seealso: `PetscOptionsHelpPrintedCreate()`
62: @*/
63: PetscErrorCode PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrinted hp, const char *pre, const char *name, PetscBool *found)
64: {
65: size_t l1, l2;
66: #if !defined(PETSC_HAVE_THREADSAFETY)
67: char *both;
68: int newitem;
69: #endif
71: PetscFunctionBegin;
72: PetscCall(PetscStrlen(pre, &l1));
73: PetscCall(PetscStrlen(name, &l2));
74: if (l1 + l2 == 0) {
75: *found = PETSC_FALSE;
76: PetscFunctionReturn(PETSC_SUCCESS);
77: }
78: #if !defined(PETSC_HAVE_THREADSAFETY)
79: size_t lboth = l1 + l2 + 1;
80: PetscCall(PetscSegBufferGet(hp->strings, lboth, &both));
81: PetscCall(PetscStrncpy(both, pre, lboth));
82: PetscCall(PetscStrncpy(both + l1, name, l2 + 1));
83: kh_put(HTPrinted, hp->printed, both, &newitem);
84: if (!newitem) PetscCall(PetscSegBufferUnuse(hp->strings, lboth));
85: *found = newitem ? PETSC_FALSE : PETSC_TRUE;
86: #else
87: *found = PETSC_FALSE;
88: #endif
89: PetscFunctionReturn(PETSC_SUCCESS);
90: }
92: static PetscBool noviewer = PETSC_FALSE;
93: static PetscBool noviewers[PETSCVIEWERGETVIEWEROFFPUSHESMAX];
94: static PetscInt inoviewers = 0;
96: /*@
97: PetscOptionsPushGetViewerOff - sets if a `PetscOptionsGetViewer()` returns a viewer.
99: Logically Collective
101: Input Parameter:
102: . flg - `PETSC_TRUE` to turn off viewer creation, `PETSC_FALSE` to turn it on.
104: Level: developer
106: Note:
107: Calling XXXViewFromOptions in an inner loop can be very expensive. This can appear, for example, when using
108: many small subsolves. Call this function to control viewer creation in `PetscOptionsGetViewer()`, thus removing the expensive XXXViewFromOptions calls.
110: .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsPopGetViewerOff()`
111: @*/
112: PetscErrorCode PetscOptionsPushGetViewerOff(PetscBool flg)
113: {
114: PetscFunctionBegin;
115: PetscCheck(inoviewers < PETSCVIEWERGETVIEWEROFFPUSHESMAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPushGetViewerOff(), perhaps you forgot PetscOptionsPopGetViewerOff()?");
117: noviewers[inoviewers++] = noviewer;
118: noviewer = flg;
119: PetscFunctionReturn(PETSC_SUCCESS);
120: }
122: /*@
123: PetscOptionsPopGetViewerOff - reset whether `PetscOptionsGetViewer()` returns a viewer.
125: Logically Collective
127: Level: developer
129: Note:
130: Calling XXXViewFromOptions in an inner loop can be very expensive. This can appear, for example, when using
131: many small subsolves. Call this function to control viewer creation in `PetscOptionsGetViewer()`, thus removing the expensive XXXViewFromOptions calls.
133: .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()`
134: @*/
135: PetscErrorCode PetscOptionsPopGetViewerOff(void)
136: {
137: PetscFunctionBegin;
138: PetscCheck(inoviewers, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptionsPopGetViewerOff(), perhaps you forgot PetscOptionsPushGetViewerOff()?");
139: noviewer = noviewers[--inoviewers];
140: PetscFunctionReturn(PETSC_SUCCESS);
141: }
143: /*@
144: PetscOptionsGetViewerOff - does `PetscOptionsGetViewer()` return a viewer?
146: Logically Collective
148: Output Parameter:
149: . flg - whether viewers are returned.
151: Level: developer
153: Note:
154: Calling XXXViewFromOptions in an inner loop can be very expensive. This can appear, for example, when using
155: many small subsolves.
157: .seealso: [](sec_viewers), `PetscOptionsGetViewer()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`
158: @*/
159: PetscErrorCode PetscOptionsGetViewerOff(PetscBool *flg)
160: {
161: PetscFunctionBegin;
163: *flg = noviewer;
164: PetscFunctionReturn(PETSC_SUCCESS);
165: }
167: /*@C
168: PetscOptionsGetViewer - Gets a viewer appropriate for the type indicated by the user
170: Collective
172: Input Parameters:
173: + comm - the communicator to own the viewer
174: . options - options database, use `NULL` for default global database
175: . pre - the string to prepend to the name or `NULL`
176: - name - the option one is seeking
178: Output Parameters:
179: + viewer - the viewer, pass `NULL` if not needed
180: . format - the `PetscViewerFormat` requested by the user, pass `NULL` if not needed
181: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
183: Level: intermediate
185: Notes:
186: If no value is provided ascii:stdout is used
187: + ascii[:[filename][:[format][:append]]] - defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
188: for example ascii::ascii_info prints just the information about the object not all details
189: unless :append is given filename opens in write mode, overwriting what was already there
190: . binary[:[filename][:[format][:append]]] - defaults to the file binaryoutput
191: . draw[:drawtype[:filename]] - for example, draw:tikz, draw:tikz:figure.tex or draw:x
192: . socket[:port] - defaults to the standard output port
193: - saws[:communicatorname] - publishes object to the Scientific Application Webserver (SAWs)
195: Use `PetscViewerDestroy()` after using the viewer, otherwise a memory leak will occur
197: You can control whether calls to this function create a viewer (or return early with *set of `PETSC_FALSE`) with
198: `PetscOptionsPushGetViewerOff()`. This is useful if calling many small subsolves, in which case XXXViewFromOptions can take
199: an appreciable fraction of the runtime.
201: If PETSc is configured with `--with-viewfromoptions=0` this function always returns with *set of `PETSC_FALSE`
203: .seealso: [](sec_viewers), `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
204: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
205: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
206: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
207: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
208: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
209: `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsPushGetViewerOff()`, `PetscOptionsPopGetViewerOff()`,
210: `PetscOptionsGetViewerOff()`
211: @*/
212: PetscErrorCode PetscOptionsGetViewer(MPI_Comm comm, PetscOptions options, const char pre[], const char name[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
213: {
214: const char *value;
215: PetscBool flag, hashelp;
217: PetscFunctionBegin;
220: if (viewer) *viewer = NULL;
221: if (format) *format = PETSC_VIEWER_DEFAULT;
222: if (set) *set = PETSC_FALSE;
223: PetscCall(PetscOptionsGetViewerOff(&flag));
224: if (flag) PetscFunctionReturn(PETSC_SUCCESS);
226: PetscCall(PetscOptionsHasHelp(NULL, &hashelp));
227: if (hashelp) {
228: PetscBool found;
230: if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
231: PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, pre, name, &found));
232: if (!found && viewer) {
233: PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\nViewer (-%s%s) options:\n", pre ? pre : "", name + 1));
234: PetscCall((*PetscHelpPrintf)(comm, " -%s%s ascii[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Prints object to stdout or ASCII file", "PetscOptionsGetViewer"));
235: PetscCall((*PetscHelpPrintf)(comm, " -%s%s binary[:[filename][:[format][:append]]]: %s (%s)\n", pre ? pre : "", name + 1, "Saves object to a binary file", "PetscOptionsGetViewer"));
236: PetscCall((*PetscHelpPrintf)(comm, " -%s%s draw[:[drawtype][:filename|format]] %s (%s)\n", pre ? pre : "", name + 1, "Draws object", "PetscOptionsGetViewer"));
237: PetscCall((*PetscHelpPrintf)(comm, " -%s%s socket[:port]: %s (%s)\n", pre ? pre : "", name + 1, "Pushes object to a Unix socket", "PetscOptionsGetViewer"));
238: PetscCall((*PetscHelpPrintf)(comm, " -%s%s saws[:communicatorname]: %s (%s)\n", pre ? pre : "", name + 1, "Publishes object to SAWs", "PetscOptionsGetViewer"));
239: }
240: }
242: if (format) *format = PETSC_VIEWER_DEFAULT;
243: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
244: if (flag) {
245: if (set) *set = PETSC_TRUE;
246: if (!value) {
247: if (viewer) {
248: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
249: PetscCall(PetscObjectReference((PetscObject)*viewer));
250: }
251: } else {
252: char *loc0_vtype = NULL, *loc1_fname = NULL, *loc2_fmt = NULL, *loc3_fmode = NULL;
253: PetscInt cnt;
254: const char *viewers[] = {PETSCVIEWERASCII, PETSCVIEWERBINARY, PETSCVIEWERDRAW, PETSCVIEWERSOCKET, PETSCVIEWERMATLAB, PETSCVIEWERSAWS, PETSCVIEWERVTK, PETSCVIEWERHDF5, PETSCVIEWERGLVIS, PETSCVIEWEREXODUSII, NULL};
256: PetscCall(PetscStrallocpy(value, &loc0_vtype));
257: PetscCall(PetscStrchr(loc0_vtype, ':', &loc1_fname));
258: if (loc1_fname) {
259: *loc1_fname++ = 0;
260: PetscCall(PetscStrchr(loc1_fname, ':', &loc2_fmt));
261: }
262: if (loc2_fmt) {
263: *loc2_fmt++ = 0;
264: PetscCall(PetscStrchr(loc2_fmt, ':', &loc3_fmode));
265: }
266: if (loc3_fmode) *loc3_fmode++ = 0;
267: PetscCall(PetscStrendswithwhich(*loc0_vtype ? loc0_vtype : "ascii", viewers, &cnt));
268: PetscCheck(cnt <= (PetscInt)sizeof(viewers) - 1, comm, PETSC_ERR_ARG_OUTOFRANGE, "Unknown viewer type: %s", loc0_vtype);
269: if (viewer) {
270: if (!loc1_fname) {
271: switch (cnt) {
272: case 0:
273: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
274: break;
275: case 1:
276: if (!(*viewer = PETSC_VIEWER_BINARY_(comm))) PetscCall(PETSC_ERR_PLIB);
277: break;
278: case 2:
279: if (!(*viewer = PETSC_VIEWER_DRAW_(comm))) PetscCall(PETSC_ERR_PLIB);
280: break;
281: #if defined(PETSC_USE_SOCKET_VIEWER)
282: case 3:
283: if (!(*viewer = PETSC_VIEWER_SOCKET_(comm))) PetscCall(PETSC_ERR_PLIB);
284: break;
285: #endif
286: #if defined(PETSC_HAVE_MATLAB)
287: case 4:
288: if (!(*viewer = PETSC_VIEWER_MATLAB_(comm))) PetscCall(PETSC_ERR_PLIB);
289: break;
290: #endif
291: #if defined(PETSC_HAVE_SAWS)
292: case 5:
293: if (!(*viewer = PETSC_VIEWER_SAWS_(comm))) PetscCall(PETSC_ERR_PLIB);
294: break;
295: #endif
296: #if defined(PETSC_HAVE_HDF5)
297: case 7:
298: if (!(*viewer = PETSC_VIEWER_HDF5_(comm))) PetscCall(PETSC_ERR_PLIB);
299: break;
300: #endif
301: case 8:
302: if (!(*viewer = PETSC_VIEWER_GLVIS_(comm))) PetscCall(PETSC_ERR_PLIB);
303: break;
304: #if defined(PETSC_HAVE_EXODUSII)
305: case 9:
306: if (!(*viewer = PETSC_VIEWER_EXODUSII_(comm))) PetscCall(PETSC_ERR_PLIB);
307: break;
308: #endif
309: default:
310: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported viewer %s", loc0_vtype);
311: }
312: PetscCall(PetscObjectReference((PetscObject)*viewer));
313: } else {
314: if (loc2_fmt && !*loc1_fname && (cnt == 0)) { /* ASCII format without file name */
315: PetscCall(PetscViewerASCIIGetStdout(comm, viewer));
316: PetscCall(PetscObjectReference((PetscObject)*viewer));
317: } else {
318: PetscFileMode fmode;
319: PetscCall(PetscViewerCreate(comm, viewer));
320: PetscCall(PetscViewerSetType(*viewer, *loc0_vtype ? loc0_vtype : "ascii"));
321: fmode = FILE_MODE_WRITE;
322: if (loc3_fmode && *loc3_fmode) { /* Has non-empty file mode ("write" or "append") */
323: PetscCall(PetscEnumFind(PetscFileModes, loc3_fmode, (PetscEnum *)&fmode, &flag));
324: PetscCheck(flag, comm, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown file mode: %s", loc3_fmode);
325: }
326: if (loc2_fmt) {
327: PetscBool tk, im;
328: PetscCall(PetscStrcmp(loc1_fname, "tikz", &tk));
329: PetscCall(PetscStrcmp(loc1_fname, "image", &im));
330: if (tk || im) {
331: PetscCall(PetscViewerDrawSetInfo(*viewer, NULL, loc2_fmt, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE));
332: *loc2_fmt = 0;
333: }
334: }
335: PetscCall(PetscViewerFileSetMode(*viewer, flag ? fmode : FILE_MODE_WRITE));
336: PetscCall(PetscViewerFileSetName(*viewer, loc1_fname));
337: if (*loc1_fname) PetscCall(PetscViewerDrawSetDrawType(*viewer, loc1_fname));
338: PetscCall(PetscViewerSetFromOptions(*viewer));
339: }
340: }
341: }
342: if (viewer) PetscCall(PetscViewerSetUp(*viewer));
343: if (loc2_fmt && *loc2_fmt) {
344: PetscViewerFormat tfmt;
346: PetscCall(PetscEnumFind(PetscViewerFormats, loc2_fmt, (PetscEnum *)&tfmt, &flag));
347: if (format) *format = tfmt;
348: PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unknown viewer format %s", loc2_fmt);
349: } else if (viewer && (cnt == 6) && format) { /* Get format from VTK viewer */
350: PetscCall(PetscViewerGetFormat(*viewer, format));
351: }
352: PetscCall(PetscFree(loc0_vtype));
353: }
354: }
355: PetscFunctionReturn(PETSC_SUCCESS);
356: }
358: /*@
359: PetscViewerCreate - Creates a viewing context. A `PetscViewer` represents a file, a graphical window, a Unix socket or a variety of other ways of viewing a PETSc object
361: Collective
363: Input Parameter:
364: . comm - MPI communicator
366: Output Parameter:
367: . inviewer - location to put the `PetscViewer` context
369: Level: advanced
371: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerType`
372: @*/
373: PetscErrorCode PetscViewerCreate(MPI_Comm comm, PetscViewer *inviewer)
374: {
375: PetscViewer viewer;
377: PetscFunctionBegin;
378: *inviewer = NULL;
379: PetscCall(PetscViewerInitializePackage());
380: PetscCall(PetscHeaderCreate(viewer, PETSC_VIEWER_CLASSID, "PetscViewer", "PetscViewer", "Viewer", comm, PetscViewerDestroy, PetscViewerView));
381: *inviewer = viewer;
382: viewer->data = NULL;
383: PetscFunctionReturn(PETSC_SUCCESS);
384: }
386: /*@C
387: PetscViewerSetType - Builds `PetscViewer` for a particular implementation.
389: Collective
391: Input Parameters:
392: + viewer - the `PetscViewer` context obtained with `PetscViewerCreate()`
393: - type - for example, `PETSCVIEWERASCII`
395: Options Database Key:
396: . -viewer_type <type> - Sets the type; use -help for a list of available methods (for instance, ascii)
398: Level: advanced
400: Note:
401: See `PetscViewerType` for possible values
403: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerGetType()`, `PetscViewerType`, `PetscViewerPushFormat()`
404: @*/
405: PetscErrorCode PetscViewerSetType(PetscViewer viewer, PetscViewerType type)
406: {
407: PetscBool match;
408: PetscErrorCode (*r)(PetscViewer);
410: PetscFunctionBegin;
413: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, type, &match));
414: if (match) PetscFunctionReturn(PETSC_SUCCESS);
416: /* cleanup any old type that may be there */
417: PetscTryTypeMethod(viewer, destroy);
418: viewer->ops->destroy = NULL;
419: viewer->data = NULL;
421: PetscCall(PetscMemzero(viewer->ops, sizeof(struct _PetscViewerOps)));
423: PetscCall(PetscFunctionListFind(PetscViewerList, type, &r));
424: PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscViewer type given: %s", type);
426: PetscCall(PetscObjectChangeTypeName((PetscObject)viewer, type));
427: PetscCall((*r)(viewer));
428: PetscFunctionReturn(PETSC_SUCCESS);
429: }
431: /*@C
432: PetscViewerRegister - Adds a viewer to those available for use
434: Not Collective
436: Input Parameters:
437: + sname - name of a new user-defined viewer
438: - function - routine to create method context
440: Level: developer
442: Note:
443: `PetscViewerRegister()` may be called multiple times to add several user-defined viewers.
445: Sample usage:
446: .vb
447: PetscViewerRegister("my_viewer_type",MyViewerCreate);
448: .ve
450: Then, your solver can be chosen with the procedural interface via
451: $ PetscViewerSetType(viewer,"my_viewer_type")
452: or at runtime via the option
453: $ -viewer_type my_viewer_type
455: .seealso: [](sec_viewers), `PetscViewerRegisterAll()`
456: @*/
457: PetscErrorCode PetscViewerRegister(const char *sname, PetscErrorCode (*function)(PetscViewer))
458: {
459: PetscFunctionBegin;
460: PetscCall(PetscViewerInitializePackage());
461: PetscCall(PetscFunctionListAdd(&PetscViewerList, sname, function));
462: PetscFunctionReturn(PETSC_SUCCESS);
463: }
465: /*@C
466: PetscViewerSetFromOptions - Sets various options for a viewer based on values in the options database.
468: Collective
470: Input Parameter:
471: . viewer - the viewer context
473: Level: intermediate
475: Note:
476: Must be called after `PetscViewerCreate()` before the `PetscViewer` is used.
478: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
479: @*/
480: PetscErrorCode PetscViewerSetFromOptions(PetscViewer viewer)
481: {
482: char vtype[256];
483: PetscBool flg;
485: PetscFunctionBegin;
488: if (!PetscViewerList) PetscCall(PetscViewerRegisterAll());
489: PetscObjectOptionsBegin((PetscObject)viewer);
490: PetscCall(PetscOptionsFList("-viewer_type", "Type of PetscViewer", "None", PetscViewerList, (char *)(((PetscObject)viewer)->type_name ? ((PetscObject)viewer)->type_name : PETSCVIEWERASCII), vtype, 256, &flg));
491: if (flg) PetscCall(PetscViewerSetType(viewer, vtype));
492: /* type has not been set? */
493: if (!((PetscObject)viewer)->type_name) PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
494: PetscTryTypeMethod(viewer, setfromoptions, PetscOptionsObject);
496: /* process any options handlers added with PetscObjectAddOptionsHandler() */
497: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)viewer, PetscOptionsObject));
498: PetscCall(PetscViewerViewFromOptions(viewer, NULL, "-viewer_view"));
499: PetscOptionsEnd();
500: PetscFunctionReturn(PETSC_SUCCESS);
501: }
503: PetscErrorCode PetscViewerFlowControlStart(PetscViewer viewer, PetscInt *mcnt, PetscInt *cnt)
504: {
505: PetscFunctionBegin;
506: PetscCall(PetscViewerBinaryGetFlowControl(viewer, mcnt));
507: PetscCall(PetscViewerBinaryGetFlowControl(viewer, cnt));
508: PetscFunctionReturn(PETSC_SUCCESS);
509: }
511: PetscErrorCode PetscViewerFlowControlStepMain(PetscViewer viewer, PetscInt i, PetscInt *mcnt, PetscInt cnt)
512: {
513: MPI_Comm comm;
515: PetscFunctionBegin;
516: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
517: if (i >= *mcnt) {
518: *mcnt += cnt;
519: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
520: }
521: PetscFunctionReturn(PETSC_SUCCESS);
522: }
524: PetscErrorCode PetscViewerFlowControlEndMain(PetscViewer viewer, PetscInt *mcnt)
525: {
526: MPI_Comm comm;
527: PetscFunctionBegin;
528: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
529: *mcnt = 0;
530: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
531: PetscFunctionReturn(PETSC_SUCCESS);
532: }
534: PetscErrorCode PetscViewerFlowControlStepWorker(PetscViewer viewer, PetscMPIInt rank, PetscInt *mcnt)
535: {
536: MPI_Comm comm;
537: PetscFunctionBegin;
538: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
539: while (PETSC_TRUE) {
540: if (rank < *mcnt) break;
541: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
542: }
543: PetscFunctionReturn(PETSC_SUCCESS);
544: }
546: PetscErrorCode PetscViewerFlowControlEndWorker(PetscViewer viewer, PetscInt *mcnt)
547: {
548: MPI_Comm comm;
549: PetscFunctionBegin;
550: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
551: while (PETSC_TRUE) {
552: PetscCallMPI(MPI_Bcast(mcnt, 1, MPIU_INT, 0, comm));
553: if (!*mcnt) break;
554: }
555: PetscFunctionReturn(PETSC_SUCCESS);
556: }