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: /* ----------------------------------------------------------------------*/
38: static PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
39: {
40: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
41: PetscViewerLink *vlink;
42: PetscBool flg;
44: PetscFunctionBegin;
45: PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
46: PetscCall(PetscViewerFileClose_ASCII(viewer));
47: PetscCall(PetscFree(vascii));
49: /* remove the viewer from the list in the MPI Communicator */
50: if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0));
52: PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
53: if (flg) {
54: if (vlink && vlink->viewer == viewer) {
55: if (vlink->next) {
56: PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
57: } else {
58: PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
59: }
60: PetscCall(PetscFree(vlink));
61: } else {
62: while (vlink && vlink->next) {
63: if (vlink->next->viewer == viewer) {
64: PetscViewerLink *nv = vlink->next;
65: vlink->next = vlink->next->next;
66: PetscCall(PetscFree(nv));
67: }
68: vlink = vlink->next;
69: }
70: }
71: }
73: if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
74: PetscViewer aviewer;
75: PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
76: if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval));
77: }
78: if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
79: PetscViewer aviewer;
80: PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
81: if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
82: }
83: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
84: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
85: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
86: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
87: PetscFunctionReturn(PETSC_SUCCESS);
88: }
90: static PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
91: {
92: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
94: PetscFunctionBegin;
95: PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
96: PetscFunctionReturn(PETSC_SUCCESS);
97: }
99: static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
100: {
101: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
102: MPI_Comm comm;
103: PetscMPIInt rank, size;
104: FILE *fd = vascii->fd;
106: PetscFunctionBegin;
107: PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
108: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
109: PetscCallMPI(MPI_Comm_rank(comm, &rank));
110: PetscCallMPI(MPI_Comm_size(comm, &size));
112: if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));
114: if (vascii->allowsynchronized) {
115: PetscMPIInt tag, i, j, n = 0, dummy = 0;
116: char *message;
117: MPI_Status status;
119: PetscCall(PetscCommDuplicate(comm, &comm, &tag));
121: /* First processor waits for messages from all other processors */
122: if (rank == 0) {
123: /* flush my own messages that I may have queued up */
124: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
125: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
126: if (!vascii->bviewer) {
127: PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
128: } else {
129: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
130: }
131: previous = next;
132: next = next->next;
133: PetscCall(PetscFree(previous->string));
134: PetscCall(PetscFree(previous));
135: }
136: vascii->petsc_printfqueue = NULL;
137: vascii->petsc_printfqueuelength = 0;
138: for (i = 1; i < size; i++) {
139: /* to prevent a flood of messages to process zero, request each message separately */
140: PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
141: PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
142: for (j = 0; j < n; j++) {
143: PetscMPIInt size = 0;
145: PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
146: PetscCall(PetscMalloc1(size, &message));
147: PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
148: if (!vascii->bviewer) {
149: PetscCall(PetscFPrintf(comm, fd, "%s", message));
150: } else {
151: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
152: }
153: PetscCall(PetscFree(message));
154: }
155: }
156: } else { /* other processors send queue to processor 0 */
157: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
159: PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
160: PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
161: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
162: PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
163: PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
164: previous = next;
165: next = next->next;
166: PetscCall(PetscFree(previous->string));
167: PetscCall(PetscFree(previous));
168: }
169: vascii->petsc_printfqueue = NULL;
170: vascii->petsc_printfqueuelength = 0;
171: }
172: PetscCall(PetscCommDestroy(&comm));
173: }
174: PetscFunctionReturn(PETSC_SUCCESS);
175: }
177: /*@C
178: PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
180: Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support
182: Input Parameter:
183: . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`
185: Output Parameter:
186: . fd - file pointer
188: Level: intermediate
190: Note:
191: For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer
193: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
194: `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
195: @*/
196: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
197: {
198: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
200: PetscFunctionBegin;
201: PetscCheck(!vascii->fileunit, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot request file pointer for viewers that use Fortran files");
202: *fd = vascii->fd;
203: PetscFunctionReturn(PETSC_SUCCESS);
204: }
206: static PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
207: {
208: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
210: PetscFunctionBegin;
211: *mode = vascii->mode;
212: PetscFunctionReturn(PETSC_SUCCESS);
213: }
215: static PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
216: {
217: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
219: PetscFunctionBegin;
220: vascii->mode = mode;
221: PetscFunctionReturn(PETSC_SUCCESS);
222: }
224: /*
225: If petsc_history is on, then all Petsc*Printf() results are saved
226: if the appropriate (usually .petschistory) file.
227: */
228: PETSC_INTERN FILE *petsc_history;
230: /*@
231: PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing
233: Not Collective, but only first processor in set has any effect; No Fortran Support
235: Input Parameters:
236: + viewer - obtained with `PetscViewerASCIIOpen()`
237: - tabs - number of tabs
239: Level: developer
241: Note:
242: `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
244: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
245: `PetscViewerASCIIGetTab()`,
246: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
247: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
248: `PetscViewerASCIIPushTab()`
249: @*/
250: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
251: {
252: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
253: PetscBool iascii;
255: PetscFunctionBegin;
257: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
258: if (iascii) ascii->tab = tabs;
259: PetscFunctionReturn(PETSC_SUCCESS);
260: }
262: /*@
263: PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
265: Not Collective, meaningful on first processor only; No Fortran Support
267: Input Parameter:
268: . viewer - obtained with `PetscViewerASCIIOpen()`
270: Output Parameter:
271: . tabs - number of tabs
273: Level: developer
275: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
276: `PetscViewerASCIISetTab()`,
277: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
278: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
279: @*/
280: PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
281: {
282: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
283: PetscBool iascii;
285: PetscFunctionBegin;
287: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
288: if (iascii && tabs) *tabs = ascii->tab;
289: PetscFunctionReturn(PETSC_SUCCESS);
290: }
292: /*@
293: PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing
295: Not Collective, but only first processor in set has any effect; No Fortran Support
297: Input Parameters:
298: + viewer - obtained with `PetscViewerASCIIOpen()`
299: - tabs - number of tabs
301: Level: developer
303: Note:
304: `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
306: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
307: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
308: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
309: @*/
310: PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
311: {
312: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
313: PetscBool iascii;
315: PetscFunctionBegin;
317: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
318: if (iascii) ascii->tab += tabs;
319: PetscFunctionReturn(PETSC_SUCCESS);
320: }
322: /*@
323: PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing
325: Not Collective, but only first processor in set has any effect; No Fortran Support
327: Input Parameters:
328: + viewer - obtained with `PetscViewerASCIIOpen()`
329: - tabs - number of tabs
331: Level: developer
333: Note:
334: `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
336: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
337: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
338: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
339: `PetscViewerASCIIPushTab()`
340: @*/
341: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
342: {
343: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
344: PetscBool iascii;
346: PetscFunctionBegin;
348: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
349: if (iascii) ascii->tab -= tabs;
350: PetscFunctionReturn(PETSC_SUCCESS);
351: }
353: /*@C
354: PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
356: Collective
358: Input Parameter:
359: . viewer - obtained with `PetscViewerASCIIOpen()`
361: Level: intermediate
363: Note:
364: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
366: .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
367: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
368: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
369: @*/
370: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
371: {
372: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
373: PetscBool iascii;
375: PetscFunctionBegin;
377: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
378: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
379: if (iascii) ascii->allowsynchronized++;
380: PetscFunctionReturn(PETSC_SUCCESS);
381: }
383: /*@C
384: PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
386: Collective
388: Input Parameter:
389: . viewer - obtained with `PetscViewerASCIIOpen()`
391: Level: intermediate
393: Note:
394: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
396: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
397: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
398: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
399: @*/
400: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
401: {
402: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
403: PetscBool iascii;
405: PetscFunctionBegin;
407: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
408: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
409: if (iascii) {
410: ascii->allowsynchronized--;
411: PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
412: }
413: PetscFunctionReturn(PETSC_SUCCESS);
414: }
416: /*@C
417: PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
418: lines are tabbed.
420: Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
422: Input Parameter:
423: . viewer - obtained with `PetscViewerASCIIOpen()`
425: Level: developer
427: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
428: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
429: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
430: @*/
431: PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
432: {
433: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
434: PetscBool iascii;
436: PetscFunctionBegin;
438: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
439: if (iascii) ascii->tab++;
440: PetscFunctionReturn(PETSC_SUCCESS);
441: }
443: /*@C
444: PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by
445: `PetscViewerASCIIPushTab()`
447: Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
449: Input Parameter:
450: . viewer - obtained with `PetscViewerASCIIOpen()`
452: Level: developer
454: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
455: `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
456: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
457: @*/
458: PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
459: {
460: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
461: PetscBool iascii;
463: PetscFunctionBegin;
465: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
466: if (iascii) {
467: PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
468: ascii->tab--;
469: }
470: PetscFunctionReturn(PETSC_SUCCESS);
471: }
473: /*@
474: PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`
476: Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
478: Input Parameters:
479: + viewer - obtained with `PetscViewerASCIIOpen()`
480: - flg - `PETSC_TRUE` or `PETSC_FALSE`
482: Level: developer
484: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
485: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
486: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
487: @*/
488: PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
489: {
490: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
491: PetscBool iascii;
493: PetscFunctionBegin;
495: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
496: if (iascii) {
497: if (flg) ascii->tab = ascii->tab_store;
498: else {
499: ascii->tab_store = ascii->tab;
500: ascii->tab = 0;
501: }
502: }
503: PetscFunctionReturn(PETSC_SUCCESS);
504: }
506: #if defined(PETSC_USE_FORTRAN_BINDINGS)
508: #if defined(PETSC_HAVE_FORTRAN_CAPS)
509: #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT
510: #define petscviewerasciisetfileunit_ PETSCVIEWERASCIISETFILEUNIT
511: #define petscviewerasciiworldsetfileunit_ PETSCVIEWERASCIIWORLDSETFILEUNIT
512: #define petscfortranprinttounit_ PETSCFORTRANPRINTTOUNIT
513: #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
514: #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit
515: #define petscviewerasciisetfileunit_ petscviewerasciisetfileunit
516: #define petscviewerasciiworldsetfileunit_ petscviewerasciiworldsetfileunit
517: #define petscfortranprinttounit_ petscfortranprinttounit
518: #endif
520: #if defined(__cplusplus)
521: extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
522: #else
523: extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
524: #endif
526: #define PETSCDEFAULTBUFFERSIZE 8 * 1024
528: static PetscInt PETSC_VIEWER_ASCII_WORLD_fileunit = 0;
530: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
531: /*MC
532: PetscViewerASCIIWORLDSetFileUnit - sets `PETSC_VIEWER_STDOUT_WORLD` to write to a Fortran IO unit
534: Synopsis:
535: #include <petscviewer.h>
536: void PetscViewerASCIIWORLDSetFileUnit(PetscInt unit, PetscErrorCode ierr)
538: Input Parameter:
539: . unit - the unit number
541: Output Parameter:
542: . ierr - the error code
544: Level: intermediate
546: Notes:
547: Must be called before `PetscInitialize()`
549: This may not work currently with some viewers that (improperly) use the `fd` directly instead of `PetscViewerASCIIPrintf()`
551: With this option, for example, `-log_options` results will be saved to the Fortran file
553: Any process may call this but only the unit passed on the first process is used
555: Fortran Note:
556: Only for Fortran
558: Developer Note:
559: `PetscViewerASCIIWORLDSetFilename()` could be added in the future
561: .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()`
562: M*/
563: PETSC_EXTERN void petscviewerasciiworldsetfileunit_(PetscInt *unit, PetscErrorCode *ierr)
564: {
565: PETSC_VIEWER_ASCII_WORLD_fileunit = *unit;
566: }
568: #include <petsc/private/fortranimpl.h>
570: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
571: /*MC
572: PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` to write to a Fortran IO unit
574: Synopsis:
575: #include <petscviewer.h>
576: void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)
578: Input Parameters:
579: + lab - the viewer
580: - unit - the unit number
582: Output Parameter:
583: . ierr - the error code
585: Level: intermediate
587: Note:
588: `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
590: Fortran Notes:
591: Only for Fortran, use `PetscViewerASCIISetFILE()` for C
593: .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIWORLDSetFileUnit()`
594: M*/
595: PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr)
596: {
597: PetscViewer_ASCII *vascii;
598: PetscViewer v;
600: PetscPatchDefaultViewers_Fortran(lab, v);
601: vascii = (PetscViewer_ASCII *)v->data;
602: if (vascii->mode == FILE_MODE_READ) {
603: *ierr = PETSC_ERR_ARG_WRONGSTATE;
604: return;
605: }
606: vascii->fileunit = *unit;
607: }
609: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
610: /*MC
611: PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit
613: Synopsis:
614: #include <petscviewer.h>
615: void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr)
617: Input Parameters:
618: + comm - the `MPI_Comm` to share the viewer
619: - unit - the unit number
621: Output Parameters:
622: + lab - the viewer
623: - ierr - the error code
625: Level: intermediate
627: Note:
628: `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
630: Fortran Notes:
631: Only for Fortran, use `PetscViewerASCIIOpenWithFILE()` for C
633: .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
634: M*/
635: PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr)
636: {
637: *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
638: if (*ierr) return;
639: *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
640: if (*ierr) return;
641: *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
642: if (*ierr) return;
643: petscviewerasciisetfileunit_(lab, unit, ierr);
644: }
646: static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
647: {
648: PetscErrorCode ierr;
649: char str[PETSCDEFAULTBUFFERSIZE];
650: size_t len;
652: PetscFunctionBegin;
653: PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
654: PetscCall(PetscStrlen(str, &len));
655: petscfortranprinttounit_(&unit, str, &ierr, (int)len);
656: PetscFunctionReturn(PETSC_SUCCESS);
657: }
659: static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
660: {
661: PetscErrorCode ierr;
662: size_t len;
664: PetscFunctionBegin;
665: PetscCall(PetscStrlen(str, &len));
666: petscfortranprinttounit_(&unit, str, &ierr, (int)len);
667: PetscFunctionReturn(PETSC_SUCCESS);
668: }
670: #else
672: /* these will never be used; but are needed to link with */
673: static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
674: {
675: PetscFunctionBegin;
676: PetscFunctionReturn(PETSC_SUCCESS);
677: }
679: static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
680: {
681: PetscFunctionBegin;
682: PetscFunctionReturn(PETSC_SUCCESS);
683: }
684: #endif
686: /*@
687: PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processes
688: in a communicator. Error returning version of `PETSC_VIEWER_STDOUT_()`
690: Collective
692: Input Parameter:
693: . comm - the MPI communicator to share the `PetscViewer`
695: Output Parameter:
696: . viewer - the viewer
698: Level: beginner
700: Note:
701: This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
703: Developer Note:
704: This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking
706: .seealso: [](sec_viewers), `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
707: `PETSC_VIEWER_STDOUT_SELF`
708: @*/
709: PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer)
710: {
711: PetscBool flg;
712: MPI_Comm ncomm;
714: PetscFunctionBegin;
715: PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
716: PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
717: 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));
718: PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, (PetscMPIInt *)&flg));
719: if (!flg) { /* PetscViewer not yet created */
720: #if defined(PETSC_USE_FORTRAN_BINDINGS)
721: PetscMPIInt size, gsize;
723: PetscCallMPI(MPI_Comm_size(comm, &size));
724: PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &gsize));
725: if (size == gsize) { PetscCallMPI(MPI_Bcast(&PETSC_VIEWER_ASCII_WORLD_fileunit, 1, MPIU_INT, 0, comm)); }
726: if (PETSC_VIEWER_ASCII_WORLD_fileunit) {
727: PetscErrorCode ierr;
729: petscviewerasciiopenwithfileunit_(&ncomm, &PETSC_VIEWER_ASCII_WORLD_fileunit, viewer, &ierr);
730: } else
731: #endif
732: PetscCall(PetscViewerASCIIOpen(ncomm, "stdout", viewer));
733: ((PetscObject)*viewer)->persistent = PETSC_TRUE;
734: PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
735: PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
736: }
737: PetscCall(PetscCommDestroy(&ncomm));
738: PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
739: PetscFunctionReturn(PETSC_SUCCESS);
740: }
742: /*@C
743: PetscViewerASCIIPrintf - Prints to a file, only from the first
744: processor in the `PetscViewer` of type `PETSCVIEWERASCII`
746: Not Collective, but only the first MPI rank in the viewer has any effect
748: Input Parameters:
749: + viewer - obtained with `PetscViewerASCIIOpen()`
750: - format - the usual printf() format string
752: Level: developer
754: Fortran Notes:
755: The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
756: That is, you can only pass a single character string from Fortran.
758: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
759: `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
760: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
761: @*/
762: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
763: {
764: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
765: PetscMPIInt rank;
766: PetscInt tab = 0, intab = ascii->tab;
767: FILE *fd = ascii->fd;
768: PetscBool iascii;
770: PetscFunctionBegin;
772: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
773: PetscAssertPointer(format, 2);
774: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
775: PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
776: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
777: if (rank) PetscFunctionReturn(PETSC_SUCCESS);
779: if (ascii->bviewer) { /* pass string up to parent viewer */
780: char *string;
781: va_list Argp;
782: size_t fullLength;
784: PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
785: for (; tab < ascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
786: va_start(Argp, format);
787: PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp));
788: va_end(Argp);
789: PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string));
790: PetscCall(PetscFree(string));
791: } else { /* write directly to file */
792: va_list Argp;
794: tab = intab;
795: while (tab--) {
796: if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " "));
797: else PetscCall(PetscFPrintfFortran(ascii->fileunit, " "));
798: }
800: va_start(Argp, format);
801: if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
802: else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
803: va_end(Argp);
804: PetscCall(PetscFFlush(fd));
805: }
806: PetscFunctionReturn(PETSC_SUCCESS);
807: }
809: /*@C
810: PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
812: Collective
814: Input Parameters:
815: + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
816: - name - the name of the file it should use
818: Level: advanced
820: Note:
821: This will have no effect on viewers that are not related to files
823: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
824: `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
825: @*/
826: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
827: {
828: char filename[PETSC_MAX_PATH_LEN];
830: PetscFunctionBegin;
832: PetscAssertPointer(name, 2);
833: PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
834: PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
835: PetscFunctionReturn(PETSC_SUCCESS);
836: }
838: /*@C
839: PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
841: Not Collective
843: Input Parameter:
844: . viewer - the `PetscViewer`
846: Output Parameter:
847: . name - the name of the file it is using
849: Level: advanced
851: Note:
852: This will have no effect on viewers that are not related to files
854: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
855: @*/
856: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
857: {
858: PetscFunctionBegin;
860: PetscAssertPointer(name, 2);
861: PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
862: PetscFunctionReturn(PETSC_SUCCESS);
863: }
865: static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
866: {
867: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
869: PetscFunctionBegin;
870: *name = vascii->filename;
871: PetscFunctionReturn(PETSC_SUCCESS);
872: }
874: #include <errno.h>
875: static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
876: {
877: size_t len;
878: char fname[PETSC_MAX_PATH_LEN], *gz = NULL;
879: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
880: PetscBool isstderr, isstdout;
881: PetscMPIInt rank;
883: PetscFunctionBegin;
884: PetscCall(PetscViewerFileClose_ASCII(viewer));
885: if (!name) PetscFunctionReturn(PETSC_SUCCESS);
886: PetscCall(PetscStrallocpy(name, &vascii->filename));
888: /* Is this file to be compressed */
889: vascii->storecompressed = PETSC_FALSE;
891: PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
892: if (gz) {
893: PetscCall(PetscStrlen(gz, &len));
894: if (len == 3) {
895: PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
896: *gz = 0;
897: vascii->storecompressed = PETSC_TRUE;
898: }
899: }
900: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
901: if (rank == 0) {
902: PetscCall(PetscStrcmp(name, "stderr", &isstderr));
903: PetscCall(PetscStrcmp(name, "stdout", &isstdout));
904: /* empty filename means stdout */
905: if (name[0] == 0) isstdout = PETSC_TRUE;
906: if (isstderr) vascii->fd = PETSC_STDERR;
907: else if (isstdout) vascii->fd = PETSC_STDOUT;
908: else {
909: PetscCall(PetscFixFilename(name, fname));
910: switch (vascii->mode) {
911: case FILE_MODE_READ:
912: vascii->fd = fopen(fname, "r");
913: break;
914: case FILE_MODE_WRITE:
915: vascii->fd = fopen(fname, "w");
916: break;
917: case FILE_MODE_APPEND:
918: vascii->fd = fopen(fname, "a");
919: break;
920: case FILE_MODE_UPDATE:
921: vascii->fd = fopen(fname, "r+");
922: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
923: break;
924: case FILE_MODE_APPEND_UPDATE:
925: /* I really want a file which is opened at the end for updating,
926: not a+, which opens at the beginning, but makes writes at the end.
927: */
928: vascii->fd = fopen(fname, "r+");
929: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
930: else {
931: int ret = fseek(vascii->fd, 0, SEEK_END);
932: PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
933: }
934: break;
935: default:
936: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
937: }
938: PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
939: }
940: }
941: PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
942: PetscFunctionReturn(PETSC_SUCCESS);
943: }
945: static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
946: {
947: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
949: PetscFunctionBegin;
950: PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
951: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
952: /*
953: The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
954: because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
955: (since the count never gets to zero) in some examples this displays information that otherwise would be lost
957: This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
958: PCView_GASM().
959: */
960: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
961: PetscCall(PetscViewerFlush(viewer));
962: PetscCall(PetscViewerCreate(subcomm, outviewer));
963: PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
964: PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
965: ovascii = (PetscViewer_ASCII *)(*outviewer)->data;
966: ovascii->fd = vascii->fd;
967: ovascii->closefile = PETSC_FALSE;
969: vascii->sviewer = *outviewer;
970: (*outviewer)->format = viewer->format;
971: ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
972: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
973: PetscFunctionReturn(PETSC_SUCCESS);
974: }
976: static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
977: {
978: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
980: PetscFunctionBegin;
981: PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
982: PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
984: PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
985: ascii->sviewer = NULL;
986: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
987: PetscCall(PetscViewerDestroy(outviewer));
988: PetscCall(PetscViewerFlush(viewer));
989: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
990: PetscFunctionReturn(PETSC_SUCCESS);
991: }
993: static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
994: {
995: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
997: PetscFunctionBegin;
998: if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %" PetscInt_FMT "\n", ascii->fileunit));
999: else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
1000: PetscFunctionReturn(PETSC_SUCCESS);
1001: }
1003: /*MC
1004: PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
1006: Level: beginner
1008: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1009: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
1010: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
1011: M*/
1012: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
1013: {
1014: PetscViewer_ASCII *vascii;
1016: PetscFunctionBegin;
1017: PetscCall(PetscNew(&vascii));
1018: viewer->data = (void *)vascii;
1020: viewer->ops->destroy = PetscViewerDestroy_ASCII;
1021: viewer->ops->flush = PetscViewerFlush_ASCII;
1022: viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII;
1023: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
1024: viewer->ops->view = PetscViewerView_ASCII;
1025: viewer->ops->read = PetscViewerASCIIRead;
1027: /* defaults to stdout unless set with PetscViewerFileSetName() */
1028: vascii->fd = PETSC_STDOUT;
1029: vascii->mode = FILE_MODE_WRITE;
1030: vascii->bviewer = NULL;
1031: vascii->subviewer = NULL;
1032: vascii->sviewer = NULL;
1033: vascii->tab = 0;
1034: vascii->tab_store = 0;
1035: vascii->filename = NULL;
1036: vascii->closefile = PETSC_TRUE;
1038: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
1039: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
1040: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
1041: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
1042: PetscFunctionReturn(PETSC_SUCCESS);
1043: }
1045: /*@C
1046: PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
1047: several processors. Output of the first processor is followed by that of the
1048: second, etc.
1050: Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
1052: Input Parameters:
1053: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
1054: - format - the usual printf() format string
1056: Level: intermediate
1058: Notes:
1059: You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
1060: Then you can do multiple independent calls to this routine.
1062: The actual synchronized print is then done using `PetscViewerFlush()`.
1063: `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
1064: to conclude the "synchronized session".
1066: So the typical calling sequence looks like
1067: .vb
1068: PetscViewerASCIIPushSynchronized(viewer);
1069: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1070: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1071: ...
1072: PetscViewerFlush(viewer);
1073: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1074: PetscViewerASCIISynchronizedPrintf(viewer, ...);
1075: ...
1076: PetscViewerFlush(viewer);
1077: PetscViewerASCIIPopSynchronized(viewer);
1078: .ve
1080: Fortran Notes:
1081: Can only print a single character* string
1083: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
1084: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
1085: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
1086: @*/
1087: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
1088: {
1089: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1090: PetscMPIInt rank;
1091: PetscInt tab = 0;
1092: MPI_Comm comm;
1093: PetscBool iascii;
1095: PetscFunctionBegin;
1097: PetscAssertPointer(format, 2);
1098: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1099: PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
1100: PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
1102: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1103: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1105: if (vascii->bviewer) {
1106: char *string;
1107: va_list Argp;
1108: size_t fullLength;
1110: PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
1111: for (; tab < vascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
1112: va_start(Argp, format);
1113: PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp));
1114: va_end(Argp);
1115: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string));
1116: PetscCall(PetscFree(string));
1117: } else if (rank == 0) { /* First processor prints immediately to fp */
1118: va_list Argp;
1119: FILE *fp = vascii->fd;
1121: tab = vascii->tab;
1122: while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " "));
1124: va_start(Argp, format);
1125: PetscCall((*PetscVFPrintf)(fp, format, Argp));
1126: va_end(Argp);
1127: PetscCall(PetscFFlush(fp));
1128: if (petsc_history) {
1129: va_start(Argp, format);
1130: PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1131: va_end(Argp);
1132: PetscCall(PetscFFlush(petsc_history));
1133: }
1134: va_end(Argp);
1135: } else { /* other processors add to queue */
1136: char *string;
1137: va_list Argp;
1138: size_t fullLength;
1139: PrintfQueue next;
1141: PetscCall(PetscNew(&next));
1142: if (vascii->petsc_printfqueue) {
1143: vascii->petsc_printfqueue->next = next;
1144: vascii->petsc_printfqueue = next;
1145: } else {
1146: vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1147: }
1148: vascii->petsc_printfqueuelength++;
1149: next->size = QUEUESTRINGSIZE;
1150: PetscCall(PetscCalloc1(next->size, &next->string));
1151: string = next->string;
1153: tab = vascii->tab;
1154: tab *= 2;
1155: while (tab--) *string++ = ' ';
1156: va_start(Argp, format);
1157: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
1158: va_end(Argp);
1159: if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
1160: PetscCall(PetscFree(next->string));
1161: next->size = fullLength + 2 * vascii->tab;
1162: PetscCall(PetscCalloc1(next->size, &next->string));
1163: string = next->string;
1164: tab = 2 * vascii->tab;
1165: while (tab--) *string++ = ' ';
1166: va_start(Argp, format);
1167: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
1168: va_end(Argp);
1169: }
1170: }
1171: PetscFunctionReturn(PETSC_SUCCESS);
1172: }
1174: /*@C
1175: PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
1177: Only MPI rank 0 in the `PetscViewer` may call this
1179: Input Parameters:
1180: + viewer - the `PETSCVIEWERASCII` viewer
1181: . data - location to write the data, treated as an array of type indicated by `datatype`
1182: . num - number of items of data to read
1183: - dtype - type of data to read
1185: Output Parameter:
1186: . count - number of items of data actually read, or `NULL`
1188: Level: beginner
1190: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1191: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1192: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1193: @*/
1194: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1195: {
1196: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1197: FILE *fd = vascii->fd;
1198: PetscInt i;
1199: int ret = 0;
1200: PetscMPIInt rank;
1202: PetscFunctionBegin;
1204: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1205: PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1206: for (i = 0; i < num; i++) {
1207: if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1208: else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1209: else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1210: else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
1211: else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1212: else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1213: else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1214: else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1215: #if defined(PETSC_USE_REAL___FLOAT128)
1216: else if (dtype == PETSC___FLOAT128) {
1217: double tmp;
1218: ret = fscanf(fd, "%lg", &tmp);
1219: ((__float128 *)data)[i] = tmp;
1220: }
1221: #endif
1222: else
1223: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
1224: PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1225: if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1226: }
1227: if (count) *count = i;
1228: else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1229: PetscFunctionReturn(PETSC_SUCCESS);
1230: }