Actual source code: filev.c
2: #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>
4: #define QUEUESTRINGSIZE 8192
6: static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
7: {
8: PetscMPIInt rank;
9: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
10: int err;
13: 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);
18: }
19: if (vascii->storecompressed) {
20: char par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
21: FILE *fp;
22: PetscStrncpy(par, "gzip ", sizeof(par));
23: PetscStrlcat(par, vascii->filename, sizeof(par));
24: #if defined(PETSC_HAVE_POPEN)
25: PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp);
27: 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: PetscFree(vascii->filename);
34: return 0;
35: }
37: /* ----------------------------------------------------------------------*/
38: PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
39: {
40: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
41: PetscViewerLink *vlink;
42: PetscBool flg;
45: PetscViewerFileClose_ASCII(viewer);
46: PetscFree(vascii);
48: /* remove the viewer from the list in the MPI Communicator */
49: if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0);
51: 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: MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next);
56: } else {
57: MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval);
58: }
59: 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: PetscFree(nv);
66: }
67: vlink = vlink->next;
68: }
69: }
70: }
72: if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
73: PetscViewer aviewer;
74: MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg);
75: if (flg && aviewer == viewer) 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: MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg);
80: if (flg && aviewer == viewer) MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval);
81: }
82: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL);
83: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL);
84: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL);
85: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL);
86: return 0;
87: }
89: PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
90: {
91: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
93: PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer);
94: return 0;
95: }
97: PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
98: {
99: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
100: int err;
101: MPI_Comm comm;
102: PetscMPIInt rank, size;
103: FILE *fd = vascii->fd;
106: PetscObjectGetComm((PetscObject)viewer, &comm);
107: MPI_Comm_rank(comm, &rank);
108: MPI_Comm_size(comm, &size);
110: if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) {
111: err = fflush(vascii->fd);
113: }
115: if (vascii->allowsynchronized) {
116: PetscMPIInt tag, i, j, n = 0, dummy = 0;
117: char *message;
118: MPI_Status status;
120: PetscCommDuplicate(comm, &comm, &tag);
122: /* First processor waits for messages from all other processors */
123: if (rank == 0) {
124: /* flush my own messages that I may have queued up */
125: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
126: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
127: if (!vascii->bviewer) {
128: PetscFPrintf(comm, fd, "%s", next->string);
129: } else {
130: PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string);
131: }
132: previous = next;
133: next = next->next;
134: PetscFree(previous->string);
135: PetscFree(previous);
136: }
137: vascii->petsc_printfqueue = NULL;
138: vascii->petsc_printfqueuelength = 0;
139: for (i = 1; i < size; i++) {
140: /* to prevent a flood of messages to process zero, request each message separately */
141: MPI_Send(&dummy, 1, MPI_INT, i, tag, comm);
142: MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status);
143: for (j = 0; j < n; j++) {
144: PetscMPIInt size = 0;
146: MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status);
147: PetscMalloc1(size, &message);
148: MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status);
149: if (!vascii->bviewer) {
150: PetscFPrintf(comm, fd, "%s", message);
151: } else {
152: PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message);
153: }
154: PetscFree(message);
155: }
156: }
157: } else { /* other processors send queue to processor 0 */
158: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
160: MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status);
161: MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm);
162: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
163: MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm);
164: MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm);
165: previous = next;
166: next = next->next;
167: PetscFree(previous->string);
168: PetscFree(previous);
169: }
170: vascii->petsc_printfqueue = NULL;
171: vascii->petsc_printfqueuelength = 0;
172: }
173: PetscCommDestroy(&comm);
174: }
175: return 0;
176: }
178: /*@C
179: PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
181: Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer
183: Input Parameter:
184: . viewer - PetscViewer context, obtained from `PetscViewerASCIIOpen()`
186: Output Parameter:
187: . fd - file pointer
189: Level: intermediate
191: Note:
192: For the standard `PETSCVIEWERASCII` the value is valid only on process 0 of the viewer
194: Fortran Note:
195: This routine is not supported in Fortran.
197: .seealso: `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`,
198: `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
199: @*/
200: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
201: {
202: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
204: *fd = vascii->fd;
205: return 0;
206: }
208: PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
209: {
210: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
212: *mode = vascii->mode;
213: return 0;
214: }
216: PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
217: {
218: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
220: vascii->mode = mode;
221: return 0;
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
233: Not Collective, but only first processor in set has any effect
235: Input Parameters:
236: + viewer - obtained with `PetscViewerASCIIOpen()`
237: - tabs - number of tabs
239: Level: developer
241: Fortran Note:
242: This routine is not supported in Fortran.
244: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIGetTab()`,
245: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
246: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
247: @*/
248: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
249: {
250: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
251: PetscBool iascii;
254: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
255: if (iascii) ascii->tab = tabs;
256: return 0;
257: }
259: /*@
260: PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
262: Not Collective, meaningful on first processor only.
264: Input Parameters:
265: . viewer - obtained with `PetscViewerASCIIOpen()`
267: Output Parameters:
268: . tabs - number of tabs
270: Level: developer
272: Fortran Note:
273: This routine is not supported in Fortran.
275: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISetTab()`,
276: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
277: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
278: @*/
279: PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
280: {
281: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
282: PetscBool iascii;
285: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
286: if (iascii && tabs) *tabs = ascii->tab;
287: return 0;
288: }
290: /*@
291: PetscViewerASCIIAddTab - Add to the number of times an ASCII viewer tabs before printing
293: Not Collective, but only first processor in set has any effect
295: Input Parameters:
296: + viewer - obtained with `PetscViewerASCIIOpen()`
297: - tabs - number of tabs
299: Level: developer
301: Fortran Note:
302: This routine is not supported in Fortran.
304: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
305: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
306: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
307: @*/
308: PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
309: {
310: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
311: PetscBool iascii;
314: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
315: if (iascii) ascii->tab += tabs;
316: return 0;
317: }
319: /*@
320: PetscViewerASCIISubtractTab - Subtracts from the number of times an ASCII viewer tabs before printing
322: Not Collective, but only first processor in set has any effect
324: Input Parameters:
325: + viewer - obtained with `PetscViewerASCIIOpen()`
326: - tabs - number of tabs
328: Level: developer
330: Fortran Note:
331: This routine is not supported in Fortran.
333: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
334: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
335: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
336: @*/
337: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
338: {
339: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
340: PetscBool iascii;
343: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
344: if (iascii) ascii->tab -= tabs;
345: return 0;
346: }
348: /*@C
349: PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
351: Collective on viewer
353: Input Parameters:
354: . viewer - obtained with `PetscViewerASCIIOpen()`
356: Level: intermediate
358: Note:
359: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
361: .seealso: `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
362: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
363: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
364: @*/
365: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
366: {
367: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
368: PetscBool iascii;
372: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
373: if (iascii) ascii->allowsynchronized++;
374: return 0;
375: }
377: /*@C
378: PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
380: Collective on viewer
382: Input Parameters:
383: . viewer - obtained with `PetscViewerASCIIOpen()`
385: Level: intermediate
387: Note:
388: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
390: .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
391: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
392: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
393: @*/
394: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
395: {
396: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
397: PetscBool iascii;
401: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
402: if (iascii) {
403: ascii->allowsynchronized--;
405: }
406: return 0;
407: }
409: /*@C
410: PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
411: lines are tabbed.
413: Not Collective, but only first processor in set has any effect
415: Input Parameters:
416: . viewer - obtained with `PetscViewerASCIIOpen()`
418: Level: developer
420: Fortran Note:
421: This routine is not supported in Fortran.
423: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
424: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
425: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
426: @*/
427: PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
428: {
429: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
430: PetscBool iascii;
433: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
434: if (iascii) ascii->tab++;
435: return 0;
436: }
438: /*@C
439: PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by `PetscViewerASCIIPushTab()`
441: Not Collective, but only first processor in set has any effect
443: Input Parameters:
444: . viewer - obtained with `PetscViewerASCIIOpen()`
446: Level: developer
448: Fortran Note:
449: This routine is not supported in Fortran.
451: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
452: `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
453: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
454: @*/
455: PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
456: {
457: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
458: PetscBool iascii;
461: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
462: if (iascii) {
464: ascii->tab--;
465: }
466: return 0;
467: }
469: /*@
470: PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the ASCII `PetscViewer`
472: Not Collective, but only first processor in set has any effect
474: Input Parameters:
475: + viewer - obtained with `PetscViewerASCIIOpen()`
476: - flg - `PETSC_TRUE` or `PETSC_FALSE`
478: Level: developer
480: Fortran Note:
481: This routine is not supported in Fortran.
483: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
484: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
485: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
486: @*/
487: PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
488: {
489: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
490: PetscBool iascii;
493: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
494: if (iascii) {
495: if (flg) ascii->tab = ascii->tab_store;
496: else {
497: ascii->tab_store = ascii->tab;
498: ascii->tab = 0;
499: }
500: }
501: return 0;
502: }
504: /* ----------------------------------------------------------------------- */
506: /*@C
507: PetscViewerASCIIPrintf - Prints to a file, only from the first
508: processor in the PetscViewer
510: Not Collective, but only first processor in set has any effect
512: Input Parameters:
513: + viewer - obtained with `PetscViewerASCIIOpen()`
514: - format - the usual printf() format string
516: Level: developer
518: Fortran Note:
519: The call sequence is `PetscViewerASCIIPrintf`(PetscViewer, character(*), int ierr) from Fortran.
520: That is, you can only pass a single character string from Fortran.
522: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
523: `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
524: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
525: @*/
526: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
527: {
528: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
529: PetscMPIInt rank;
530: PetscInt tab, intab = ascii->tab;
531: FILE *fd = ascii->fd;
532: PetscBool iascii;
533: int err;
538: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
540: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
541: if (rank) return 0;
543: if (ascii->bviewer) { /* pass string up to parent viewer */
544: char *string;
545: va_list Argp;
546: size_t fullLength;
548: PetscCalloc1(QUEUESTRINGSIZE, &string);
549: va_start(Argp, format);
550: PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp);
551: va_end(Argp);
552: PetscViewerASCIISynchronizedPrintf(viewer, "%s", string);
553: PetscFree(string);
554: } else { /* write directly to file */
555: va_list Argp;
556: /* flush my own messages that I may have queued up */
557: PrintfQueue next = ascii->petsc_printfqueuebase, previous;
558: PetscInt i;
559: for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
560: PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string);
561: previous = next;
562: next = next->next;
563: PetscFree(previous->string);
564: PetscFree(previous);
565: }
566: ascii->petsc_printfqueue = NULL;
567: ascii->petsc_printfqueuelength = 0;
568: tab = intab;
569: while (tab--) PetscFPrintf(PETSC_COMM_SELF, fd, " ");
571: va_start(Argp, format);
572: (*PetscVFPrintf)(fd, format, Argp);
573: err = fflush(fd);
575: if (petsc_history) {
576: va_start(Argp, format);
577: tab = intab;
578: while (tab--) PetscFPrintf(PETSC_COMM_SELF, petsc_history, " ");
579: (*PetscVFPrintf)(petsc_history, format, Argp);
580: err = fflush(petsc_history);
582: }
583: va_end(Argp);
584: }
585: return 0;
586: }
588: /*@C
589: PetscViewerFileSetName - Sets the name of the file the `PetscViewer` uses.
591: Collective on viewer
593: Input Parameters:
594: + viewer - the PetscViewer; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
595: - name - the name of the file it should use
597: Level: advanced
599: .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
600: `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
601: @*/
602: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
603: {
604: char filename[PETSC_MAX_PATH_LEN];
608: PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename));
609: PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
610: return 0;
611: }
613: /*@C
614: PetscViewerFileGetName - Gets the name of the file the `PetscViewer` uses.
616: Not Collective
618: Input Parameter:
619: . viewer - the `PetscViewer`; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
621: Output Parameter:
622: . name - the name of the file it is using
624: Level: advanced
626: .seealso: `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
627: @*/
628: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
629: {
632: PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
633: return 0;
634: }
636: PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
637: {
638: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
640: *name = vascii->filename;
641: return 0;
642: }
644: PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
645: {
646: size_t len;
647: char fname[PETSC_MAX_PATH_LEN], *gz;
648: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
649: PetscBool isstderr, isstdout;
650: PetscMPIInt rank;
652: PetscViewerFileClose_ASCII(viewer);
653: if (!name) return 0;
654: PetscStrallocpy(name, &vascii->filename);
656: /* Is this file to be compressed */
657: vascii->storecompressed = PETSC_FALSE;
659: PetscStrstr(vascii->filename, ".gz", &gz);
660: if (gz) {
661: PetscStrlen(gz, &len);
662: if (len == 3) {
664: *gz = 0;
665: vascii->storecompressed = PETSC_TRUE;
666: }
667: }
668: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
669: if (rank == 0) {
670: PetscStrcmp(name, "stderr", &isstderr);
671: PetscStrcmp(name, "stdout", &isstdout);
672: /* empty filename means stdout */
673: if (name[0] == 0) isstdout = PETSC_TRUE;
674: if (isstderr) vascii->fd = PETSC_STDERR;
675: else if (isstdout) vascii->fd = PETSC_STDOUT;
676: else {
677: PetscFixFilename(name, fname);
678: switch (vascii->mode) {
679: case FILE_MODE_READ:
680: vascii->fd = fopen(fname, "r");
681: break;
682: case FILE_MODE_WRITE:
683: vascii->fd = fopen(fname, "w");
684: break;
685: case FILE_MODE_APPEND:
686: vascii->fd = fopen(fname, "a");
687: break;
688: case FILE_MODE_UPDATE:
689: vascii->fd = fopen(fname, "r+");
690: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
691: break;
692: case FILE_MODE_APPEND_UPDATE:
693: /* I really want a file which is opened at the end for updating,
694: not a+, which opens at the beginning, but makes writes at the end.
695: */
696: vascii->fd = fopen(fname, "r+");
697: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
698: else fseek(vascii->fd, 0, SEEK_END);
699: break;
700: default:
701: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
702: }
704: }
705: }
706: #if defined(PETSC_USE_LOG)
707: PetscLogObjectState((PetscObject)viewer, "File: %s", name);
708: #endif
709: return 0;
710: }
712: PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
713: {
714: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
716: PetscViewerASCIIPushSynchronized(viewer);
718: /*
719: The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
720: because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
721: (since the count never gets to zero) in some examples this displays information that otherwise would be lost
723: This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
724: PCView_GASM().
725: */
726: PetscViewerASCIIPushSynchronized(viewer);
727: PetscViewerCreate(subcomm, outviewer);
728: PetscViewerSetType(*outviewer, PETSCVIEWERASCII);
729: PetscViewerASCIIPushSynchronized(*outviewer);
730: ovascii = (PetscViewer_ASCII *)(*outviewer)->data;
731: ovascii->fd = vascii->fd;
732: ovascii->tab = vascii->tab;
733: ovascii->closefile = PETSC_FALSE;
735: vascii->sviewer = *outviewer;
736: (*outviewer)->format = viewer->format;
737: ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
738: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
739: return 0;
740: }
742: PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
743: {
744: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
749: PetscViewerASCIIPopSynchronized(*outviewer);
750: ascii->sviewer = NULL;
751: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
752: PetscViewerDestroy(outviewer);
753: PetscViewerASCIIPopSynchronized(viewer);
754: return 0;
755: }
757: PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
758: {
759: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
761: if (ascii->filename) PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename);
762: return 0;
763: }
765: /*MC
766: PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
768: Level: beginner
770: .seealso: `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
771: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
772: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
773: M*/
774: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
775: {
776: PetscViewer_ASCII *vascii;
778: PetscNew(&vascii);
779: viewer->data = (void *)vascii;
781: viewer->ops->destroy = PetscViewerDestroy_ASCII;
782: viewer->ops->flush = PetscViewerFlush_ASCII;
783: viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII;
784: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
785: viewer->ops->view = PetscViewerView_ASCII;
786: viewer->ops->read = PetscViewerASCIIRead;
788: /* defaults to stdout unless set with PetscViewerFileSetName() */
789: vascii->fd = PETSC_STDOUT;
790: vascii->mode = FILE_MODE_WRITE;
791: vascii->bviewer = NULL;
792: vascii->subviewer = NULL;
793: vascii->sviewer = NULL;
794: vascii->tab = 0;
795: vascii->tab_store = 0;
796: vascii->filename = NULL;
797: vascii->closefile = PETSC_TRUE;
799: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII);
800: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII);
801: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII);
802: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII);
803: return 0;
804: }
806: /*@C
807: PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from
808: several processors. Output of the first processor is followed by that of the
809: second, etc.
811: Not Collective, must call collective `PetscViewerFlush()` to get the results out
813: Input Parameters:
814: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
815: - format - the usual printf() format string
817: Level: intermediate
819: Notes:
820: You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
821: Then you can do multiple independent calls to this routine.
823: The actual synchronized print is then done using `PetscViewerFlush()`.
824: `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
825: to conclude the "synchronized session".
827: So the typical calling sequence looks like
828: .vb
829: PetscViewerASCIIPushSynchronized(viewer);
830: PetscViewerASCIISynchronizedPrintf(viewer, ...);
831: PetscViewerASCIISynchronizedPrintf(viewer, ...);
832: ...
833: PetscViewerFlush(viewer);
834: PetscViewerASCIISynchronizedPrintf(viewer, ...);
835: PetscViewerASCIISynchronizedPrintf(viewer, ...);
836: ...
837: PetscViewerFlush(viewer);
838: PetscViewerASCIIPopSynchronized(viewer);
839: .ve
841: Fortran Note:
842: Can only print a single character* string
844: .seealso: `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
845: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
846: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
847: @*/
848: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
849: {
850: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
851: PetscMPIInt rank;
852: PetscInt tab = vascii->tab;
853: MPI_Comm comm;
854: FILE *fp;
855: PetscBool iascii, hasbviewer = PETSC_FALSE;
856: int err;
860: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
864: PetscObjectGetComm((PetscObject)viewer, &comm);
865: MPI_Comm_rank(comm, &rank);
867: if (vascii->bviewer) {
868: hasbviewer = PETSC_TRUE;
869: if (rank == 0) {
870: vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
871: PetscObjectGetComm((PetscObject)viewer, &comm);
872: MPI_Comm_rank(comm, &rank);
873: }
874: }
876: fp = vascii->fd;
878: if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
879: va_list Argp;
880: /* flush my own messages that I may have queued up */
881: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
882: PetscInt i;
883: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
884: PetscFPrintf(comm, fp, "%s", next->string);
885: previous = next;
886: next = next->next;
887: PetscFree(previous->string);
888: PetscFree(previous);
889: }
890: vascii->petsc_printfqueue = NULL;
891: vascii->petsc_printfqueuelength = 0;
893: while (tab--) PetscFPrintf(PETSC_COMM_SELF, fp, " ");
895: va_start(Argp, format);
896: (*PetscVFPrintf)(fp, format, Argp);
897: err = fflush(fp);
899: if (petsc_history) {
900: va_start(Argp, format);
901: (*PetscVFPrintf)(petsc_history, format, Argp);
902: err = fflush(petsc_history);
904: }
905: va_end(Argp);
906: } else { /* other processors add to queue */
907: char *string;
908: va_list Argp;
909: size_t fullLength;
910: PrintfQueue next;
912: PetscNew(&next);
913: if (vascii->petsc_printfqueue) {
914: vascii->petsc_printfqueue->next = next;
915: vascii->petsc_printfqueue = next;
916: } else {
917: vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
918: }
919: vascii->petsc_printfqueuelength++;
920: next->size = QUEUESTRINGSIZE;
921: PetscCalloc1(next->size, &next->string);
922: string = next->string;
923: tab *= 2;
924: while (tab--) *string++ = ' ';
925: va_start(Argp, format);
926: PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp);
927: va_end(Argp);
928: if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
929: PetscFree(next->string);
930: next->size = fullLength + 2 * vascii->tab;
931: PetscCalloc1(next->size, &next->string);
932: string = next->string;
933: tab = 2 * vascii->tab;
934: while (tab--) *string++ = ' ';
935: va_start(Argp, format);
936: PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp);
937: va_end(Argp);
938: }
939: }
940: return 0;
941: }
943: /*@C
944: PetscViewerASCIIRead - Reads from a ASCII file
946: Only process 0 in the `PetscViewer` may call this
948: Input Parameters:
949: + viewer - the ascii viewer
950: . data - location to write the data
951: . num - number of items of data to read
952: - datatype - type of data to read
954: Output Parameters:
955: . count - number of items of data actually read, or NULL
957: Level: beginner
959: .seealso: `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
960: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
961: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
962: @*/
963: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
964: {
965: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
966: FILE *fd = vascii->fd;
967: PetscInt i;
968: int ret = 0;
969: PetscMPIInt rank;
972: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
974: for (i = 0; i < num; i++) {
975: if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
976: else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
977: else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
978: else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
979: else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
980: else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
981: else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
982: else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
983: #if defined(PETSC_USE_REAL___FLOAT128)
984: else if (dtype == PETSC___FLOAT128) {
985: double tmp;
986: ret = fscanf(fd, "%lg", &tmp);
987: ((__float128 *)data)[i] = tmp;
988: }
989: #endif
990: else
991: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
993: if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
994: }
995: if (count) *count = i;
997: return 0;
998: }