Actual source code: filev.c
1: #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>
3: #define QUEUESTRINGSIZE 8192
5: static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
6: {
7: PetscMPIInt rank;
8: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
9: int err;
11: PetscFunctionBegin;
12: PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
13: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
14: if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
15: if (vascii->fd && vascii->closefile) {
16: err = fclose(vascii->fd);
17: PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
18: }
19: if (vascii->storecompressed) {
20: char par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
21: FILE *fp;
22: PetscCall(PetscStrncpy(par, "gzip ", sizeof(par)));
23: PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par)));
24: #if defined(PETSC_HAVE_POPEN)
25: PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp));
26: PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s %s", par, buf);
27: PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
28: #else
29: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
30: #endif
31: }
32: }
33: PetscCall(PetscFree(vascii->filename));
34: PetscFunctionReturn(PETSC_SUCCESS);
35: }
37: static PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
38: {
39: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
40: PetscViewerLink *vlink;
41: PetscMPIInt iflg;
43: PetscFunctionBegin;
44: PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
45: PetscCall(PetscViewerFileClose_ASCII(viewer));
46: PetscCall(PetscFree(vascii));
48: /* remove the viewer from the list in the MPI Communicator */
49: if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, NULL));
51: PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, &iflg));
52: if (iflg) {
53: if (vlink && vlink->viewer == viewer) {
54: if (vlink->next) {
55: PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
56: } else {
57: PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
58: }
59: PetscCall(PetscFree(vlink));
60: } else {
61: while (vlink && vlink->next) {
62: if (vlink->next->viewer == viewer) {
63: PetscViewerLink *nv = vlink->next;
64: vlink->next = vlink->next->next;
65: PetscCall(PetscFree(nv));
66: }
67: vlink = vlink->next;
68: }
69: }
70: }
72: if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
73: PetscViewer aviewer;
74: PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, &iflg));
75: if (iflg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval));
76: }
77: if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
78: PetscViewer aviewer;
79: PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, &iflg));
80: if (iflg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
81: }
82: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
83: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
84: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
85: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
86: PetscFunctionReturn(PETSC_SUCCESS);
87: }
89: static PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
90: {
91: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
93: PetscFunctionBegin;
94: PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
95: PetscFunctionReturn(PETSC_SUCCESS);
96: }
98: /*@C
99: PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
101: Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support
103: Input Parameter:
104: . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`
106: Output Parameter:
107: . fd - file pointer
109: Level: intermediate
111: Note:
112: For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer
114: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
115: `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
116: @*/
117: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
118: {
119: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
121: PetscFunctionBegin;
122: PetscCheck(!vascii->fileunit, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot request file pointer for viewers that use Fortran files");
123: *fd = vascii->fd;
124: PetscFunctionReturn(PETSC_SUCCESS);
125: }
127: static PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
128: {
129: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
131: PetscFunctionBegin;
132: *mode = vascii->mode;
133: PetscFunctionReturn(PETSC_SUCCESS);
134: }
136: static PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
137: {
138: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
140: PetscFunctionBegin;
141: vascii->mode = mode;
142: PetscFunctionReturn(PETSC_SUCCESS);
143: }
145: /*
146: If petsc_history is on, then all Petsc*Printf() results are saved
147: if the appropriate (usually .petschistory) file.
148: */
149: PETSC_INTERN FILE *petsc_history;
151: /*@
152: PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing
154: Not Collective, but only first processor in set has any effect; No Fortran Support
156: Input Parameters:
157: + viewer - obtained with `PetscViewerASCIIOpen()`
158: - tabs - number of tabs
160: Level: developer
162: Note:
163: `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
165: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
166: `PetscViewerASCIIGetTab()`,
167: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
168: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
169: `PetscViewerASCIIPushTab()`
170: @*/
171: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
172: {
173: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
174: PetscBool isascii;
176: PetscFunctionBegin;
178: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
179: if (isascii) ascii->tab = tabs;
180: PetscFunctionReturn(PETSC_SUCCESS);
181: }
183: /*@
184: PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
186: Not Collective, meaningful on first processor only; No Fortran Support
188: Input Parameter:
189: . viewer - obtained with `PetscViewerASCIIOpen()`
191: Output Parameter:
192: . tabs - number of tabs
194: Level: developer
196: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
197: `PetscViewerASCIISetTab()`,
198: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
199: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
200: @*/
201: PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
202: {
203: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
204: PetscBool isascii;
206: PetscFunctionBegin;
208: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
209: if (isascii && tabs) *tabs = ascii->tab;
210: PetscFunctionReturn(PETSC_SUCCESS);
211: }
213: /*@
214: PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing
216: Not Collective, but only first processor in set has any effect; No Fortran Support
218: Input Parameters:
219: + viewer - obtained with `PetscViewerASCIIOpen()`
220: - tabs - number of tabs
222: Level: developer
224: Note:
225: `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
227: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
228: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
229: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
230: @*/
231: PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
232: {
233: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
234: PetscBool isascii;
236: PetscFunctionBegin;
238: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
239: if (isascii) ascii->tab += tabs;
240: PetscFunctionReturn(PETSC_SUCCESS);
241: }
243: /*@
244: PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing
246: Not Collective, but only first processor in set has any effect; No Fortran Support
248: Input Parameters:
249: + viewer - obtained with `PetscViewerASCIIOpen()`
250: - tabs - number of tabs
252: Level: developer
254: Note:
255: `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
257: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
258: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
259: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
260: `PetscViewerASCIIPushTab()`
261: @*/
262: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
263: {
264: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
265: PetscBool isascii;
267: PetscFunctionBegin;
269: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
270: if (isascii) ascii->tab -= tabs;
271: PetscFunctionReturn(PETSC_SUCCESS);
272: }
274: /*@
275: PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
277: Collective
279: Input Parameter:
280: . viewer - obtained with `PetscViewerASCIIOpen()`
282: Level: intermediate
284: Note:
285: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
287: .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
288: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
289: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
290: @*/
291: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
292: {
293: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
294: PetscBool isascii;
296: PetscFunctionBegin;
298: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
299: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
300: if (isascii) ascii->allowsynchronized++;
301: PetscFunctionReturn(PETSC_SUCCESS);
302: }
304: /*@
305: PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
307: Collective
309: Input Parameter:
310: . viewer - obtained with `PetscViewerASCIIOpen()`
312: Level: intermediate
314: Note:
315: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
317: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
318: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
319: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
320: @*/
321: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
322: {
323: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
324: PetscBool isascii;
326: PetscFunctionBegin;
328: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
329: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
330: if (isascii) {
331: ascii->allowsynchronized--;
332: PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
333: }
334: PetscFunctionReturn(PETSC_SUCCESS);
335: }
337: /*@
338: PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
339: lines are tabbed.
341: Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
343: Input Parameter:
344: . viewer - obtained with `PetscViewerASCIIOpen()`
346: Level: developer
348: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
349: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
350: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
351: @*/
352: PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
353: {
354: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
355: PetscBool isascii;
357: PetscFunctionBegin;
359: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
360: if (isascii) ascii->tab++;
361: PetscFunctionReturn(PETSC_SUCCESS);
362: }
364: /*@
365: PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by
366: `PetscViewerASCIIPushTab()`
368: Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
370: Input Parameter:
371: . viewer - obtained with `PetscViewerASCIIOpen()`
373: Level: developer
375: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
376: `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
377: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
378: @*/
379: PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
380: {
381: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
382: PetscBool isascii;
384: PetscFunctionBegin;
386: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
387: if (isascii) {
388: PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
389: ascii->tab--;
390: }
391: PetscFunctionReturn(PETSC_SUCCESS);
392: }
394: /*@
395: PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`
397: Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
399: Input Parameters:
400: + viewer - obtained with `PetscViewerASCIIOpen()`
401: - flg - `PETSC_TRUE` or `PETSC_FALSE`
403: Level: developer
405: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
406: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
407: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
408: @*/
409: PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
410: {
411: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
412: PetscBool isascii;
414: PetscFunctionBegin;
416: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
417: if (isascii) {
418: if (flg) ascii->tab = ascii->tab_store;
419: else {
420: ascii->tab_store = ascii->tab;
421: ascii->tab = 0;
422: }
423: }
424: PetscFunctionReturn(PETSC_SUCCESS);
425: }
427: #if defined(PETSC_USE_FORTRAN_BINDINGS)
429: #if defined(PETSC_HAVE_FORTRAN_CAPS)
430: #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT
431: #define petscviewerasciisetfileunit_ PETSCVIEWERASCIISETFILEUNIT
432: #define petscviewerasciistdoutsetfileunit_ PETSCVIEWERASCIISTDOUTSETFILEUNIT
433: #define petscfortranprinttofileunit_ PETSCFORTRANPRINTTOFILEUNIT
434: #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
435: #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit
436: #define petscviewerasciisetfileunit_ petscviewerasciisetfileunit
437: #define petscviewerasciistdoutsetfileunit_ petscviewerasciistdoutsetfileunit
438: #define petscfortranprinttofileunit_ petscfortranprinttofileunit
439: #endif
441: #if defined(__cplusplus)
442: extern "C" void petscfortranprinttofileunit_(int *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
443: #else
444: extern void petscfortranprinttofileunit_(int *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
445: #endif
447: #define PETSCDEFAULTBUFFERSIZE 8 * 1024
449: static int PETSC_VIEWER_ASCII_STDOUT_fileunit = 0;
451: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
452: /*MC
453: PetscViewerASCIIStdoutSetFileUnit - sets `PETSC_VIEWER_STDOUT_()` to write to a Fortran IO unit
455: Synopsis:
456: #include <petscviewer.h>
457: void PetscViewerASCIIStdoutSetFileUnit(PetscInt unit, PetscErrorCode ierr)
459: Input Parameter:
460: . unit - the unit number
462: Output Parameter:
463: . ierr - the error code
465: Level: intermediate
467: Notes:
468: Can be called before `PetscInitialize()`
470: Immediately changes the output for all `PETSC_VIEWER_STDOUT_()` viewers
472: This may not work currently with some viewers that (improperly) use the `fd` directly instead of `PetscViewerASCIIPrintf()`
474: With this option, for example, `-log_options` results will be saved to the Fortran file
476: Any process may call this but only the unit passed on the first process is used
478: Fortran Note:
479: Only for Fortran
481: Developer Note:
482: `PetscViewerASCIIWORLDSetFilename()` and `PetscViewerASCIIWORLDSetFILE()` could be added
484: .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIStdoutSetFileUnit()`,
485: `PETSC_VIEWER_STDOUT_()`, `PetscViewerASCIIGetStdout()`
486: M*/
487: PETSC_EXTERN void petscviewerasciistdoutsetfileunit_(int *unit, PetscErrorCode *ierr)
488: {
489: #if defined(PETSC_USE_FORTRAN_BINDINGS)
490: PETSC_VIEWER_ASCII_STDOUT_fileunit = *unit;
491: #endif
492: }
494: #include <petsc/private/ftnimpl.h>
496: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
497: /*MC
498: PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` `PetscViewer` to write to a Fortran IO unit
500: Synopsis:
501: #include <petscviewer.h>
502: void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)
504: Input Parameters:
505: + lab - the viewer
506: - unit - the unit number
508: Output Parameter:
509: . ierr - the error code
511: Level: intermediate
513: Note:
514: `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
516: Fortran Notes:
517: Only for Fortran, use `PetscViewerASCIISetFILE()` for C
519: .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIStdoutSetFileUnit()`
520: M*/
521: PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, int *unit, PetscErrorCode *ierr)
522: {
523: PetscViewer_ASCII *vascii;
524: PetscViewer v;
526: PetscPatchDefaultViewers_Fortran(lab, v);
527: vascii = (PetscViewer_ASCII *)v->data;
528: if (vascii->mode == FILE_MODE_READ) {
529: *ierr = PETSC_ERR_ARG_WRONGSTATE;
530: return;
531: }
532: vascii->fileunit = *unit;
533: }
535: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
536: /*MC
537: PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit
539: Synopsis:
540: #include <petscviewer.h>
541: void PetscViewerASCIIOpenWithFileUnit((MPI_Fint comm, integer unit, PetscViewer viewer, PetscErrorCode ierr)
543: Input Parameters:
544: + comm - the `MPI_Comm` to share the viewer
545: - unit - the unit number
547: Output Parameters:
548: + lab - the viewer
549: - ierr - the error code
551: Level: intermediate
553: Note:
554: `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
556: Fortran Notes:
557: Only for Fortran, use `PetscViewerASCIIOpenWithFILE()` for C
559: .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
560: M*/
561: PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Fint *comm, int *unit, PetscViewer *lab, PetscErrorCode *ierr)
562: {
563: *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
564: if (*ierr) return;
565: *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
566: if (*ierr) return;
567: *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
568: if (*ierr) return;
569: petscviewerasciisetfileunit_(lab, unit, ierr);
570: }
572: static PetscErrorCode PetscVFPrintfFortran(int unit, const char format[], va_list Argp)
573: {
574: PetscErrorCode ierr;
575: char str[PETSCDEFAULTBUFFERSIZE];
576: size_t len;
578: PetscFunctionBegin;
579: PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
580: PetscCall(PetscStrlen(str, &len));
581: petscfortranprinttofileunit_(&unit, str, &ierr, (int)len);
582: PetscFunctionReturn(PETSC_SUCCESS);
583: }
585: static PetscErrorCode PetscFPrintfFortran(int unit, const char str[])
586: {
587: PetscErrorCode ierr;
588: size_t len;
590: PetscFunctionBegin;
591: PetscCall(PetscStrlen(str, &len));
592: petscfortranprinttofileunit_(&unit, str, &ierr, (int)len);
593: PetscFunctionReturn(PETSC_SUCCESS);
594: }
596: #else
598: /* these will never be used; but are needed to link with */
599: static PetscErrorCode PetscVFPrintfFortran(int unit, const char format[], va_list Argp)
600: {
601: PetscFunctionBegin;
602: PetscFunctionReturn(PETSC_SUCCESS);
603: }
605: static PetscErrorCode PetscFPrintfFortran(int unit, const char str[])
606: {
607: PetscFunctionBegin;
608: PetscFunctionReturn(PETSC_SUCCESS);
609: }
610: #endif
612: /*@
613: PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processes
614: in a communicator that prints to `stdout`. Error returning version of `PETSC_VIEWER_STDOUT_()`
616: Collective
618: Input Parameter:
619: . comm - the MPI communicator to share the `PetscViewer`
621: Output Parameter:
622: . viewer - the viewer
624: Level: beginner
626: Note:
627: Use `PetscViewerDestroy()` to destroy it
629: Developer Note:
630: This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking
632: .seealso: [](sec_viewers), `PetscViewerASCIIGetStderr()`, `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
633: `PETSC_VIEWER_STDOUT_SELF`
634: @*/
635: PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer)
636: {
637: PetscMPIInt iflg;
638: MPI_Comm ncomm;
640: PetscFunctionBegin;
641: PetscAssertPointer(viewer, 2);
642: PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
643: PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
644: if (Petsc_Viewer_Stdout_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stdout_keyval, NULL));
645: PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, &iflg));
646: if (!iflg) { /* PetscViewer not yet created */
647: #if defined(PETSC_USE_FORTRAN_BINDINGS)
648: PetscCallMPI(MPI_Bcast(&PETSC_VIEWER_ASCII_STDOUT_fileunit, 1, MPI_INT, 0, comm));
649: if (PETSC_VIEWER_ASCII_STDOUT_fileunit) {
650: PetscErrorCode ierr;
651: MPI_Fint fcomm = MPI_Comm_c2f(ncomm);
653: petscviewerasciiopenwithfileunit_(&fcomm, &PETSC_VIEWER_ASCII_STDOUT_fileunit, viewer, &ierr);
654: } else
655: #endif
656: {
657: PetscViewerFormat format;
658: PetscBool set;
660: PetscCall(PetscViewerCreate(ncomm, viewer));
661: PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
662: PetscCall(PetscOptionsGetEnum(NULL, NULL, "-petsc_viewer_stdout_format", PetscViewerFormats, (PetscEnum *)&format, &set));
663: if (set) PetscCall(PetscViewerPushFormat(*viewer, format));
664: PetscCall(PetscViewerFileSetName(*viewer, "stdout"));
665: }
666: PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
667: PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
668: }
669: PetscCall(PetscCommDestroy(&ncomm));
670: PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
671: #if defined(PETSC_USE_FORTRAN_BINDINGS)
672: ((PetscViewer_ASCII *)(*viewer)->data)->fileunit = PETSC_VIEWER_ASCII_STDOUT_fileunit;
673: #endif
674: PetscFunctionReturn(PETSC_SUCCESS);
675: }
677: /*@C
678: PetscViewerASCIIPrintf - Prints to a file, only from the first
679: processor in the `PetscViewer` of type `PETSCVIEWERASCII`
681: Not Collective, but only the first MPI rank in the viewer has any effect
683: Input Parameters:
684: + viewer - obtained with `PetscViewerASCIIOpen()`
685: - format - the usual printf() format string
687: Level: developer
689: Fortran Notes:
690: The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
691: That is, you can only pass a single character string from Fortran.
693: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
694: `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
695: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
696: @*/
697: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
698: {
699: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
700: PetscMPIInt rank;
701: PetscInt tab = 0, intab = ascii->tab;
702: FILE *fd = ascii->fd;
703: PetscBool isascii;
705: PetscFunctionBegin;
707: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
708: PetscAssertPointer(format, 2);
709: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
710: PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
711: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
712: if (rank) PetscFunctionReturn(PETSC_SUCCESS);
714: if (ascii->bviewer) { /* pass string up to parent viewer */
715: char *string;
716: va_list Argp;
717: size_t fullLength;
719: PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
720: for (; tab < ascii->tab; tab++) string[2 * tab] = string[2 * tab + 1] = ' ';
721: va_start(Argp, format);
722: PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp));
723: va_end(Argp);
724: PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string));
725: PetscCall(PetscFree(string));
726: } else { /* write directly to file */
727: va_list Argp;
729: tab = intab;
730: while (tab--) {
731: if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " "));
732: else PetscCall(PetscFPrintfFortran(ascii->fileunit, " "));
733: }
735: va_start(Argp, format);
736: if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
737: else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
738: va_end(Argp);
739: PetscCall(PetscFFlush(fd));
740: }
741: PetscFunctionReturn(PETSC_SUCCESS);
742: }
744: /*@
745: PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
747: Collective
749: Input Parameters:
750: + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
751: - name - the name of the file it should use
753: Level: advanced
755: Note:
756: This will have no effect on viewers that are not related to files
758: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
759: `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
760: @*/
761: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
762: {
763: char filename[PETSC_MAX_PATH_LEN];
765: PetscFunctionBegin;
767: PetscAssertPointer(name, 2);
768: PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
769: PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
770: PetscFunctionReturn(PETSC_SUCCESS);
771: }
773: /*@C
774: PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
776: Not Collective
778: Input Parameter:
779: . viewer - the `PetscViewer`
781: Output Parameter:
782: . name - the name of the file it is using
784: Level: advanced
786: Note:
787: This will have no effect on viewers that are not related to files
789: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
790: @*/
791: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char *name[])
792: {
793: PetscFunctionBegin;
795: PetscAssertPointer(name, 2);
796: PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
797: PetscFunctionReturn(PETSC_SUCCESS);
798: }
800: static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
801: {
802: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
804: PetscFunctionBegin;
805: *name = vascii->filename;
806: PetscFunctionReturn(PETSC_SUCCESS);
807: }
809: #include <errno.h>
810: static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
811: {
812: size_t len;
813: char fname[PETSC_MAX_PATH_LEN], *gz = NULL;
814: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
815: PetscBool isstderr, isstdout;
816: PetscMPIInt rank;
818: PetscFunctionBegin;
819: PetscCall(PetscViewerFileClose_ASCII(viewer));
820: if (!name) PetscFunctionReturn(PETSC_SUCCESS);
821: PetscCall(PetscStrallocpy(name, &vascii->filename));
823: /* Is this file to be compressed */
824: vascii->storecompressed = PETSC_FALSE;
826: PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
827: if (gz) {
828: PetscCall(PetscStrlen(gz, &len));
829: if (len == 3) {
830: PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
831: *gz = 0;
832: vascii->storecompressed = PETSC_TRUE;
833: }
834: }
835: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
836: if (rank == 0) {
837: PetscCall(PetscStrcmp(name, "stderr", &isstderr));
838: PetscCall(PetscStrcmp(name, "stdout", &isstdout));
839: /* empty filename means stdout */
840: if (name[0] == 0) isstdout = PETSC_TRUE;
841: if (isstderr) vascii->fd = PETSC_STDERR;
842: else if (isstdout) vascii->fd = PETSC_STDOUT;
843: else {
844: PetscCall(PetscFixFilename(name, fname));
845: switch (vascii->mode) {
846: case FILE_MODE_READ:
847: vascii->fd = fopen(fname, "r");
848: break;
849: case FILE_MODE_WRITE:
850: vascii->fd = fopen(fname, "w");
851: break;
852: case FILE_MODE_APPEND:
853: vascii->fd = fopen(fname, "a");
854: break;
855: case FILE_MODE_UPDATE:
856: vascii->fd = fopen(fname, "r+");
857: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
858: break;
859: case FILE_MODE_APPEND_UPDATE:
860: /* I really want a file which is opened at the end for updating,
861: not a+, which opens at the beginning, but makes writes at the end.
862: */
863: vascii->fd = fopen(fname, "r+");
864: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
865: else {
866: int ret = fseek(vascii->fd, 0, SEEK_END);
867: PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
868: }
869: break;
870: default:
871: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
872: }
873: PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
874: }
875: }
876: PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
877: PetscFunctionReturn(PETSC_SUCCESS);
878: }
880: static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
881: {
882: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
884: PetscFunctionBegin;
885: PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
886: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
887: /*
888: The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
889: because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
890: (since the count never gets to zero) in some examples this displays information that otherwise would be lost
892: This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
893: PCView_GASM().
894: */
895: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
896: PetscCall(PetscViewerFlush(viewer));
897: PetscCall(PetscViewerCreate(subcomm, outviewer));
898: PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
899: PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
900: ovascii = (PetscViewer_ASCII *)(*outviewer)->data;
901: ovascii->fd = vascii->fd;
902: ovascii->fileunit = vascii->fileunit;
903: ovascii->closefile = PETSC_FALSE;
905: vascii->sviewer = *outviewer;
906: (*outviewer)->format = viewer->format;
907: ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
908: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
909: PetscFunctionReturn(PETSC_SUCCESS);
910: }
912: static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
913: {
914: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
916: PetscFunctionBegin;
917: PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
918: PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
920: PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
921: ascii->sviewer = NULL;
922: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
923: PetscCall(PetscViewerDestroy(outviewer));
924: PetscCall(PetscViewerFlush(viewer));
925: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
926: PetscFunctionReturn(PETSC_SUCCESS);
927: }
929: static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
930: {
931: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
933: PetscFunctionBegin;
934: if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %d\n", ascii->fileunit));
935: else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
936: PetscFunctionReturn(PETSC_SUCCESS);
937: }
939: static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
940: {
941: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
942: MPI_Comm comm;
943: PetscMPIInt rank, size;
944: FILE *fd = vascii->fd;
946: PetscFunctionBegin;
947: PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
948: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
949: PetscCallMPI(MPI_Comm_rank(comm, &rank));
950: PetscCallMPI(MPI_Comm_size(comm, &size));
952: if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));
954: if (vascii->allowsynchronized) {
955: PetscMPIInt tag, i, j, n = 0, dummy = 0;
956: char *message;
957: MPI_Status status;
959: PetscCall(PetscCommDuplicate(comm, &comm, &tag));
961: /* First processor waits for messages from all other processors */
962: if (rank == 0) {
963: /* flush my own messages that I may have queued up */
964: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
965: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
966: if (!vascii->bviewer) {
967: if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
968: else PetscCall(PetscFPrintfFortran(vascii->fileunit, next->string));
969: } else {
970: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
971: }
972: previous = next;
973: next = next->next;
974: PetscCall(PetscFree(previous->string));
975: PetscCall(PetscFree(previous));
976: }
977: vascii->petsc_printfqueue = NULL;
978: vascii->petsc_printfqueuelength = 0;
979: for (i = 1; i < size; i++) {
980: /* to prevent a flood of messages to process zero, request each message separately */
981: PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
982: PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
983: for (j = 0; j < n; j++) {
984: size_t size;
986: PetscCallMPI(MPI_Recv(&size, 1, MPIU_SIZE_T, i, tag, comm, &status));
987: PetscCall(PetscMalloc1(size, &message));
988: PetscCallMPI(MPI_Recv(message, (PetscMPIInt)size, MPI_CHAR, i, tag, comm, &status));
989: if (!vascii->bviewer) {
990: if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", message));
991: else PetscCall(PetscFPrintfFortran(vascii->fileunit, message));
992: } else {
993: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
994: }
995: PetscCall(PetscFree(message));
996: }
997: }
998: } else { /* other processors send queue to processor 0 */
999: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
1001: PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
1002: PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
1003: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
1004: PetscCallMPI(MPI_Send(&next->size, 1, MPIU_SIZE_T, 0, tag, comm));
1005: PetscCallMPI(MPI_Send(next->string, (PetscMPIInt)next->size, MPI_CHAR, 0, tag, comm));
1006: previous = next;
1007: next = next->next;
1008: PetscCall(PetscFree(previous->string));
1009: PetscCall(PetscFree(previous));
1010: }
1011: vascii->petsc_printfqueue = NULL;
1012: vascii->petsc_printfqueuelength = 0;
1013: }
1014: PetscCall(PetscCommDestroy(&comm));
1015: }
1016: PetscFunctionReturn(PETSC_SUCCESS);
1017: }
1019: /*MC
1020: PETSCVIEWERASCII - A viewer that prints to `stdout`, `stderr`, or an ASCII file
1022: Level: beginner
1024: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1025: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
1026: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
1027: M*/
1028: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
1029: {
1030: PetscViewer_ASCII *vascii;
1032: PetscFunctionBegin;
1033: PetscCall(PetscNew(&vascii));
1034: viewer->data = (void *)vascii;
1036: viewer->ops->destroy = PetscViewerDestroy_ASCII;
1037: viewer->ops->flush = PetscViewerFlush_ASCII;
1038: viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII;
1039: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
1040: viewer->ops->view = PetscViewerView_ASCII;
1041: viewer->ops->read = PetscViewerASCIIRead;
1043: /* defaults to stdout unless set with PetscViewerFileSetName() */
1044: vascii->fd = PETSC_STDOUT;
1045: vascii->mode = FILE_MODE_WRITE;
1046: vascii->bviewer = NULL;
1047: vascii->subviewer = NULL;
1048: vascii->sviewer = NULL;
1049: vascii->tab = 0;
1050: vascii->tab_store = 0;
1051: vascii->filename = NULL;
1052: vascii->closefile = PETSC_TRUE;
1054: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
1055: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
1056: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
1057: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
1058: PetscFunctionReturn(PETSC_SUCCESS);
1059: }
1061: /*@C
1062: PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
1063: several processors. Output of the first processor is followed by that of the
1064: second, etc.
1066: Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
1068: Input Parameters:
1069: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
1070: - format - the usual printf() format string
1072: Level: intermediate
1074: Notes:
1075: You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
1076: Then you can do multiple independent calls to this routine.
1078: The actual synchronized print is then done using `PetscViewerFlush()`.
1079: `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
1080: to conclude the "synchronized session".
1082: So the typical calling sequence looks like
1083: .vb
1084: PetscViewerASCIIPushSynchronized(viewer);
1085: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1086: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1087: ...
1088: PetscViewerFlush(viewer);
1089: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1090: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1091: ...
1092: PetscViewerFlush(viewer);
1093: PetscViewerASCIIPopSynchronized(viewer);
1094: .ve
1096: Fortran Notes:
1097: Can only print a single character* string
1099: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
1100: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
1101: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
1102: @*/
1103: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
1104: {
1105: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1106: PetscMPIInt rank;
1107: PetscInt tab = 0;
1108: MPI_Comm comm;
1109: PetscBool isascii;
1111: PetscFunctionBegin;
1113: PetscAssertPointer(format, 2);
1114: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1115: PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
1116: PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
1118: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1119: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1121: if (vascii->bviewer) {
1122: char *string;
1123: va_list Argp;
1124: size_t fullLength;
1126: PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
1127: for (; tab < vascii->tab; tab++) string[2 * tab] = string[2 * tab + 1] = ' ';
1128: va_start(Argp, format);
1129: PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp));
1130: va_end(Argp);
1131: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string));
1132: PetscCall(PetscFree(string));
1133: } else if (rank == 0) { /* First processor prints immediately to fp */
1134: va_list Argp;
1135: FILE *fp = vascii->fd;
1137: tab = vascii->tab;
1138: while (tab--) {
1139: if (!vascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " "));
1140: else PetscCall(PetscFPrintfFortran(vascii->fileunit, " "));
1141: }
1143: va_start(Argp, format);
1144: if (!vascii->fileunit) PetscCall((*PetscVFPrintf)(fp, format, Argp));
1145: else PetscCall(PetscVFPrintfFortran(vascii->fileunit, format, Argp));
1146: va_end(Argp);
1147: PetscCall(PetscFFlush(fp));
1148: if (petsc_history) {
1149: va_start(Argp, format);
1150: PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1151: va_end(Argp);
1152: PetscCall(PetscFFlush(petsc_history));
1153: }
1154: } else { /* other processors add to queue */
1155: char *string;
1156: va_list Argp;
1157: size_t fullLength;
1158: PrintfQueue next;
1160: PetscCall(PetscNew(&next));
1161: if (vascii->petsc_printfqueue) {
1162: vascii->petsc_printfqueue->next = next;
1163: vascii->petsc_printfqueue = next;
1164: } else {
1165: vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1166: }
1167: vascii->petsc_printfqueuelength++;
1168: next->size = QUEUESTRINGSIZE;
1169: PetscCall(PetscCalloc1(next->size, &next->string));
1170: string = next->string;
1172: tab = vascii->tab;
1173: tab *= 2;
1174: while (tab--) *string++ = ' ';
1175: va_start(Argp, format);
1176: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
1177: va_end(Argp);
1178: if (fullLength > next->size - 2 * vascii->tab) {
1179: PetscCall(PetscFree(next->string));
1180: next->size = fullLength + 2 * vascii->tab;
1181: PetscCall(PetscCalloc1(next->size, &next->string));
1182: string = next->string;
1183: tab = 2 * vascii->tab;
1184: while (tab--) *string++ = ' ';
1185: va_start(Argp, format);
1186: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
1187: va_end(Argp);
1188: }
1189: }
1190: PetscFunctionReturn(PETSC_SUCCESS);
1191: }
1193: /*@C
1194: PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
1196: Only MPI rank 0 in the `PetscViewer` may call this
1198: Input Parameters:
1199: + viewer - the `PETSCVIEWERASCII` viewer
1200: . data - location to write the data, treated as an array of type indicated by `datatype`
1201: . num - number of items of data to read
1202: - dtype - type of data to read
1204: Output Parameter:
1205: . count - number of items of data actually read, or `NULL`
1207: Level: beginner
1209: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1210: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1211: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1212: @*/
1213: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1214: {
1215: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1216: FILE *fd = vascii->fd;
1217: PetscInt i;
1218: int ret = 0;
1219: PetscMPIInt rank;
1221: PetscFunctionBegin;
1223: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1224: PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1225: for (i = 0; i < num; i++) {
1226: if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1227: else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1228: else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1229: else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
1230: else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1231: else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1232: else if (dtype == PETSC_COUNT) ret = fscanf(fd, "%" PetscCount_FMT, &(((PetscCount *)data)[i]));
1233: else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1234: else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1235: #if defined(PETSC_USE_REAL___FLOAT128)
1236: else if (dtype == PETSC___FLOAT128) {
1237: double tmp;
1238: ret = fscanf(fd, "%lg", &tmp);
1239: ((__float128 *)data)[i] = tmp;
1240: }
1241: #endif
1242: else
1243: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
1244: PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1245: if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1246: }
1247: if (count) *count = i;
1248: else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1249: PetscFunctionReturn(PETSC_SUCCESS);
1250: }