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: PetscBool flg;
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, (PetscMPIInt *)&flg));
52: if (flg) {
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, (PetscMPIInt *)&flg));
75: if (flg && 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, (PetscMPIInt *)&flg));
80: if (flg && 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 iascii;
176: PetscFunctionBegin;
178: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
179: if (iascii) 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 iascii;
206: PetscFunctionBegin;
208: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
209: if (iascii && 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 iascii;
236: PetscFunctionBegin;
238: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
239: if (iascii) 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 iascii;
267: PetscFunctionBegin;
269: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
270: if (iascii) 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 iascii;
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, &iascii));
300: if (iascii) 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 iascii;
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, &iascii));
330: if (iascii) {
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 iascii;
357: PetscFunctionBegin;
359: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
360: if (iascii) 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 iascii;
384: PetscFunctionBegin;
386: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
387: if (iascii) {
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 iascii;
414: PetscFunctionBegin;
416: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
417: if (iascii) {
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/fortranimpl.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: PetscBool flg;
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, (PetscMPIInt *)&flg));
646: if (!flg) { /* 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: PetscCall(PetscViewerCreate(ncomm, viewer));
658: PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
659: PetscCall(PetscViewerFileSetName(*viewer, "stdout"));
660: }
661: PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
662: PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
663: }
664: PetscCall(PetscCommDestroy(&ncomm));
665: PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
666: #if defined(PETSC_USE_FORTRAN_BINDINGS)
667: ((PetscViewer_ASCII *)(*viewer)->data)->fileunit = PETSC_VIEWER_ASCII_STDOUT_fileunit;
668: #endif
669: PetscFunctionReturn(PETSC_SUCCESS);
670: }
672: /*@C
673: PetscViewerASCIIPrintf - Prints to a file, only from the first
674: processor in the `PetscViewer` of type `PETSCVIEWERASCII`
676: Not Collective, but only the first MPI rank in the viewer has any effect
678: Input Parameters:
679: + viewer - obtained with `PetscViewerASCIIOpen()`
680: - format - the usual printf() format string
682: Level: developer
684: Fortran Notes:
685: The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
686: That is, you can only pass a single character string from Fortran.
688: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
689: `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
690: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
691: @*/
692: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
693: {
694: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
695: PetscMPIInt rank;
696: PetscInt tab = 0, intab = ascii->tab;
697: FILE *fd = ascii->fd;
698: PetscBool iascii;
700: PetscFunctionBegin;
702: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
703: PetscAssertPointer(format, 2);
704: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
705: PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
706: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
707: if (rank) PetscFunctionReturn(PETSC_SUCCESS);
709: if (ascii->bviewer) { /* pass string up to parent viewer */
710: char *string;
711: va_list Argp;
712: size_t fullLength;
714: PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
715: for (; tab < ascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
716: va_start(Argp, format);
717: PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp));
718: va_end(Argp);
719: PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string));
720: PetscCall(PetscFree(string));
721: } else { /* write directly to file */
722: va_list Argp;
724: tab = intab;
725: while (tab--) {
726: if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " "));
727: else PetscCall(PetscFPrintfFortran(ascii->fileunit, " "));
728: }
730: va_start(Argp, format);
731: if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
732: else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
733: va_end(Argp);
734: PetscCall(PetscFFlush(fd));
735: }
736: PetscFunctionReturn(PETSC_SUCCESS);
737: }
739: /*@
740: PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
742: Collective
744: Input Parameters:
745: + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
746: - name - the name of the file it should use
748: Level: advanced
750: Note:
751: This will have no effect on viewers that are not related to files
753: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
754: `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
755: @*/
756: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
757: {
758: char filename[PETSC_MAX_PATH_LEN];
760: PetscFunctionBegin;
762: PetscAssertPointer(name, 2);
763: PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
764: PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
765: PetscFunctionReturn(PETSC_SUCCESS);
766: }
768: /*@C
769: PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
771: Not Collective
773: Input Parameter:
774: . viewer - the `PetscViewer`
776: Output Parameter:
777: . name - the name of the file it is using
779: Level: advanced
781: Note:
782: This will have no effect on viewers that are not related to files
784: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
785: @*/
786: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char *name[])
787: {
788: PetscFunctionBegin;
790: PetscAssertPointer(name, 2);
791: PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
792: PetscFunctionReturn(PETSC_SUCCESS);
793: }
795: static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
796: {
797: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
799: PetscFunctionBegin;
800: *name = vascii->filename;
801: PetscFunctionReturn(PETSC_SUCCESS);
802: }
804: #include <errno.h>
805: static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
806: {
807: size_t len;
808: char fname[PETSC_MAX_PATH_LEN], *gz = NULL;
809: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
810: PetscBool isstderr, isstdout;
811: PetscMPIInt rank;
813: PetscFunctionBegin;
814: PetscCall(PetscViewerFileClose_ASCII(viewer));
815: if (!name) PetscFunctionReturn(PETSC_SUCCESS);
816: PetscCall(PetscStrallocpy(name, &vascii->filename));
818: /* Is this file to be compressed */
819: vascii->storecompressed = PETSC_FALSE;
821: PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
822: if (gz) {
823: PetscCall(PetscStrlen(gz, &len));
824: if (len == 3) {
825: PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
826: *gz = 0;
827: vascii->storecompressed = PETSC_TRUE;
828: }
829: }
830: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
831: if (rank == 0) {
832: PetscCall(PetscStrcmp(name, "stderr", &isstderr));
833: PetscCall(PetscStrcmp(name, "stdout", &isstdout));
834: /* empty filename means stdout */
835: if (name[0] == 0) isstdout = PETSC_TRUE;
836: if (isstderr) vascii->fd = PETSC_STDERR;
837: else if (isstdout) vascii->fd = PETSC_STDOUT;
838: else {
839: PetscCall(PetscFixFilename(name, fname));
840: switch (vascii->mode) {
841: case FILE_MODE_READ:
842: vascii->fd = fopen(fname, "r");
843: break;
844: case FILE_MODE_WRITE:
845: vascii->fd = fopen(fname, "w");
846: break;
847: case FILE_MODE_APPEND:
848: vascii->fd = fopen(fname, "a");
849: break;
850: case FILE_MODE_UPDATE:
851: vascii->fd = fopen(fname, "r+");
852: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
853: break;
854: case FILE_MODE_APPEND_UPDATE:
855: /* I really want a file which is opened at the end for updating,
856: not a+, which opens at the beginning, but makes writes at the end.
857: */
858: vascii->fd = fopen(fname, "r+");
859: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
860: else {
861: int ret = fseek(vascii->fd, 0, SEEK_END);
862: PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
863: }
864: break;
865: default:
866: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
867: }
868: PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
869: }
870: }
871: PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
872: PetscFunctionReturn(PETSC_SUCCESS);
873: }
875: static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
876: {
877: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
879: PetscFunctionBegin;
880: PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
881: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
882: /*
883: The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
884: because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
885: (since the count never gets to zero) in some examples this displays information that otherwise would be lost
887: This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
888: PCView_GASM().
889: */
890: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
891: PetscCall(PetscViewerFlush(viewer));
892: PetscCall(PetscViewerCreate(subcomm, outviewer));
893: PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
894: PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
895: ovascii = (PetscViewer_ASCII *)(*outviewer)->data;
896: ovascii->fd = vascii->fd;
897: ovascii->fileunit = vascii->fileunit;
898: ovascii->closefile = PETSC_FALSE;
900: vascii->sviewer = *outviewer;
901: (*outviewer)->format = viewer->format;
902: ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
903: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
904: PetscFunctionReturn(PETSC_SUCCESS);
905: }
907: static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
908: {
909: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
911: PetscFunctionBegin;
912: PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
913: PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
915: PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
916: ascii->sviewer = NULL;
917: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
918: PetscCall(PetscViewerDestroy(outviewer));
919: PetscCall(PetscViewerFlush(viewer));
920: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
921: PetscFunctionReturn(PETSC_SUCCESS);
922: }
924: static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
925: {
926: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
928: PetscFunctionBegin;
929: if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %d\n", ascii->fileunit));
930: else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
931: PetscFunctionReturn(PETSC_SUCCESS);
932: }
934: static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
935: {
936: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
937: MPI_Comm comm;
938: PetscMPIInt rank, size;
939: FILE *fd = vascii->fd;
941: PetscFunctionBegin;
942: PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
943: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
944: PetscCallMPI(MPI_Comm_rank(comm, &rank));
945: PetscCallMPI(MPI_Comm_size(comm, &size));
947: if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));
949: if (vascii->allowsynchronized) {
950: PetscMPIInt tag, i, j, n = 0, dummy = 0;
951: char *message;
952: MPI_Status status;
954: PetscCall(PetscCommDuplicate(comm, &comm, &tag));
956: /* First processor waits for messages from all other processors */
957: if (rank == 0) {
958: /* flush my own messages that I may have queued up */
959: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
960: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
961: if (!vascii->bviewer) {
962: if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
963: else PetscCall(PetscFPrintfFortran(vascii->fileunit, next->string));
964: } else {
965: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
966: }
967: previous = next;
968: next = next->next;
969: PetscCall(PetscFree(previous->string));
970: PetscCall(PetscFree(previous));
971: }
972: vascii->petsc_printfqueue = NULL;
973: vascii->petsc_printfqueuelength = 0;
974: for (i = 1; i < size; i++) {
975: /* to prevent a flood of messages to process zero, request each message separately */
976: PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
977: PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
978: for (j = 0; j < n; j++) {
979: size_t size;
981: PetscCallMPI(MPI_Recv(&size, 1, MPIU_SIZE_T, i, tag, comm, &status));
982: PetscCall(PetscMalloc1(size, &message));
983: PetscCallMPI(MPI_Recv(message, (PetscMPIInt)size, MPI_CHAR, i, tag, comm, &status));
984: if (!vascii->bviewer) {
985: if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", message));
986: else PetscCall(PetscFPrintfFortran(vascii->fileunit, message));
987: } else {
988: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
989: }
990: PetscCall(PetscFree(message));
991: }
992: }
993: } else { /* other processors send queue to processor 0 */
994: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
996: PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
997: PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
998: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
999: PetscCallMPI(MPI_Send(&next->size, 1, MPIU_SIZE_T, 0, tag, comm));
1000: PetscCallMPI(MPI_Send(next->string, (PetscMPIInt)next->size, MPI_CHAR, 0, tag, comm));
1001: previous = next;
1002: next = next->next;
1003: PetscCall(PetscFree(previous->string));
1004: PetscCall(PetscFree(previous));
1005: }
1006: vascii->petsc_printfqueue = NULL;
1007: vascii->petsc_printfqueuelength = 0;
1008: }
1009: PetscCall(PetscCommDestroy(&comm));
1010: }
1011: PetscFunctionReturn(PETSC_SUCCESS);
1012: }
1014: /*MC
1015: PETSCVIEWERASCII - A viewer that prints to `stdout`, `stderr`, or an ASCII file
1017: Level: beginner
1019: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1020: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
1021: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
1022: M*/
1023: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
1024: {
1025: PetscViewer_ASCII *vascii;
1027: PetscFunctionBegin;
1028: PetscCall(PetscNew(&vascii));
1029: viewer->data = (void *)vascii;
1031: viewer->ops->destroy = PetscViewerDestroy_ASCII;
1032: viewer->ops->flush = PetscViewerFlush_ASCII;
1033: viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII;
1034: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
1035: viewer->ops->view = PetscViewerView_ASCII;
1036: viewer->ops->read = PetscViewerASCIIRead;
1038: /* defaults to stdout unless set with PetscViewerFileSetName() */
1039: vascii->fd = PETSC_STDOUT;
1040: vascii->mode = FILE_MODE_WRITE;
1041: vascii->bviewer = NULL;
1042: vascii->subviewer = NULL;
1043: vascii->sviewer = NULL;
1044: vascii->tab = 0;
1045: vascii->tab_store = 0;
1046: vascii->filename = NULL;
1047: vascii->closefile = PETSC_TRUE;
1049: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
1050: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
1051: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
1052: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
1053: PetscFunctionReturn(PETSC_SUCCESS);
1054: }
1056: /*@C
1057: PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
1058: several processors. Output of the first processor is followed by that of the
1059: second, etc.
1061: Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
1063: Input Parameters:
1064: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
1065: - format - the usual printf() format string
1067: Level: intermediate
1069: Notes:
1070: You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
1071: Then you can do multiple independent calls to this routine.
1073: The actual synchronized print is then done using `PetscViewerFlush()`.
1074: `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
1075: to conclude the "synchronized session".
1077: So the typical calling sequence looks like
1078: .vb
1079: PetscViewerASCIIPushSynchronized(viewer);
1080: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1081: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1082: ...
1083: PetscViewerFlush(viewer);
1084: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1085: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1086: ...
1087: PetscViewerFlush(viewer);
1088: PetscViewerASCIIPopSynchronized(viewer);
1089: .ve
1091: Fortran Notes:
1092: Can only print a single character* string
1094: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
1095: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
1096: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
1097: @*/
1098: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
1099: {
1100: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1101: PetscMPIInt rank;
1102: PetscInt tab = 0;
1103: MPI_Comm comm;
1104: PetscBool iascii;
1106: PetscFunctionBegin;
1108: PetscAssertPointer(format, 2);
1109: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1110: PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
1111: PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
1113: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1114: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1116: if (vascii->bviewer) {
1117: char *string;
1118: va_list Argp;
1119: size_t fullLength;
1121: PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
1122: for (; tab < vascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
1123: va_start(Argp, format);
1124: PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp));
1125: va_end(Argp);
1126: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string));
1127: PetscCall(PetscFree(string));
1128: } else if (rank == 0) { /* First processor prints immediately to fp */
1129: va_list Argp;
1130: FILE *fp = vascii->fd;
1132: tab = vascii->tab;
1133: while (tab--) {
1134: if (!vascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " "));
1135: else PetscCall(PetscFPrintfFortran(vascii->fileunit, " "));
1136: }
1138: va_start(Argp, format);
1139: if (!vascii->fileunit) PetscCall((*PetscVFPrintf)(fp, format, Argp));
1140: else PetscCall(PetscVFPrintfFortran(vascii->fileunit, format, Argp));
1141: va_end(Argp);
1142: PetscCall(PetscFFlush(fp));
1143: if (petsc_history) {
1144: va_start(Argp, format);
1145: PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1146: va_end(Argp);
1147: PetscCall(PetscFFlush(petsc_history));
1148: }
1149: } else { /* other processors add to queue */
1150: char *string;
1151: va_list Argp;
1152: size_t fullLength;
1153: PrintfQueue next;
1155: PetscCall(PetscNew(&next));
1156: if (vascii->petsc_printfqueue) {
1157: vascii->petsc_printfqueue->next = next;
1158: vascii->petsc_printfqueue = next;
1159: } else {
1160: vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1161: }
1162: vascii->petsc_printfqueuelength++;
1163: next->size = QUEUESTRINGSIZE;
1164: PetscCall(PetscCalloc1(next->size, &next->string));
1165: string = next->string;
1167: tab = vascii->tab;
1168: tab *= 2;
1169: while (tab--) *string++ = ' ';
1170: va_start(Argp, format);
1171: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
1172: va_end(Argp);
1173: if (fullLength > next->size - 2 * vascii->tab) {
1174: PetscCall(PetscFree(next->string));
1175: next->size = fullLength + 2 * vascii->tab;
1176: PetscCall(PetscCalloc1(next->size, &next->string));
1177: string = next->string;
1178: tab = 2 * vascii->tab;
1179: while (tab--) *string++ = ' ';
1180: va_start(Argp, format);
1181: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
1182: va_end(Argp);
1183: }
1184: }
1185: PetscFunctionReturn(PETSC_SUCCESS);
1186: }
1188: /*@C
1189: PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
1191: Only MPI rank 0 in the `PetscViewer` may call this
1193: Input Parameters:
1194: + viewer - the `PETSCVIEWERASCII` viewer
1195: . data - location to write the data, treated as an array of type indicated by `datatype`
1196: . num - number of items of data to read
1197: - dtype - type of data to read
1199: Output Parameter:
1200: . count - number of items of data actually read, or `NULL`
1202: Level: beginner
1204: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1205: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1206: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1207: @*/
1208: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1209: {
1210: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1211: FILE *fd = vascii->fd;
1212: PetscInt i;
1213: int ret = 0;
1214: PetscMPIInt rank;
1216: PetscFunctionBegin;
1218: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1219: PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1220: for (i = 0; i < num; i++) {
1221: if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1222: else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1223: else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1224: else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
1225: else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1226: else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1227: else if (dtype == PETSC_COUNT) ret = fscanf(fd, "%" PetscCount_FMT, &(((PetscCount *)data)[i]));
1228: else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1229: else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1230: #if defined(PETSC_USE_REAL___FLOAT128)
1231: else if (dtype == PETSC___FLOAT128) {
1232: double tmp;
1233: ret = fscanf(fd, "%lg", &tmp);
1234: ((__float128 *)data)[i] = tmp;
1235: }
1236: #endif
1237: else
1238: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
1239: PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1240: if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1241: }
1242: if (count) *count = i;
1243: else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1244: PetscFunctionReturn(PETSC_SUCCESS);
1245: }