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; No Fortran Support
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: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`,
195: `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
196: @*/
197: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
198: {
199: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
201: *fd = vascii->fd;
202: return 0;
203: }
205: PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
206: {
207: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
209: *mode = vascii->mode;
210: return 0;
211: }
213: PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
214: {
215: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
217: vascii->mode = mode;
218: return 0;
219: }
221: /*
222: If petsc_history is on, then all Petsc*Printf() results are saved
223: if the appropriate (usually .petschistory) file.
224: */
225: PETSC_INTERN FILE *petsc_history;
227: /*@
228: PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times
230: Not Collective, but only first processor in set has any effect; No Fortran Support
232: Input Parameters:
233: + viewer - obtained with `PetscViewerASCIIOpen()`
234: - tabs - number of tabs
236: Level: developer
238: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIGetTab()`,
239: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
240: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
241: @*/
242: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
243: {
244: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
245: PetscBool iascii;
248: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
249: if (iascii) ascii->tab = tabs;
250: return 0;
251: }
253: /*@
254: PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
256: Not Collective, meaningful on first processor only; No Fortran Support
258: Input Parameters:
259: . viewer - obtained with `PetscViewerASCIIOpen()`
261: Output Parameters:
262: . tabs - number of tabs
264: Level: developer
266: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISetTab()`,
267: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
268: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
269: @*/
270: PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
271: {
272: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
273: PetscBool iascii;
276: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
277: if (iascii && tabs) *tabs = ascii->tab;
278: return 0;
279: }
281: /*@
282: PetscViewerASCIIAddTab - Add to the number of times an ASCII viewer tabs before printing
284: Not Collective, but only first processor in set has any effect; No Fortran Support
286: Input Parameters:
287: + viewer - obtained with `PetscViewerASCIIOpen()`
288: - tabs - number of tabs
290: Level: developer
292: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
293: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
294: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
295: @*/
296: PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
297: {
298: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
299: PetscBool iascii;
302: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
303: if (iascii) ascii->tab += tabs;
304: return 0;
305: }
307: /*@
308: PetscViewerASCIISubtractTab - Subtracts from the number of times an ASCII viewer tabs before printing
310: Not Collective, but only first processor in set has any effect; No Fortran Support
312: Input Parameters:
313: + viewer - obtained with `PetscViewerASCIIOpen()`
314: - tabs - number of tabs
316: Level: developer
318: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
319: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
320: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
321: @*/
322: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
323: {
324: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
325: PetscBool iascii;
328: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
329: if (iascii) ascii->tab -= tabs;
330: return 0;
331: }
333: /*@C
334: PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
336: Collective
338: Input Parameters:
339: . viewer - obtained with `PetscViewerASCIIOpen()`
341: Level: intermediate
343: Note:
344: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
346: .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
347: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
348: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
349: @*/
350: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
351: {
352: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
353: PetscBool iascii;
357: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
358: if (iascii) ascii->allowsynchronized++;
359: return 0;
360: }
362: /*@C
363: PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
365: Collective
367: Input Parameters:
368: . viewer - obtained with `PetscViewerASCIIOpen()`
370: Level: intermediate
372: Note:
373: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
375: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
376: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
377: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
378: @*/
379: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
380: {
381: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
382: PetscBool iascii;
386: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
387: if (iascii) {
388: ascii->allowsynchronized--;
390: }
391: return 0;
392: }
394: /*@C
395: PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
396: lines are tabbed.
398: Not Collective, but only first processor in set has any effect; No Fortran Support
400: Input Parameters:
401: . viewer - obtained with `PetscViewerASCIIOpen()`
403: Level: developer
405: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
406: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
407: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
408: @*/
409: PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
410: {
411: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
412: PetscBool iascii;
415: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
416: if (iascii) ascii->tab++;
417: return 0;
418: }
420: /*@C
421: PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by `PetscViewerASCIIPushTab()`
423: Not Collective, but only first processor in set has any effect; No Fortran Support
425: Input Parameters:
426: . viewer - obtained with `PetscViewerASCIIOpen()`
428: Level: developer
430: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
431: `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
432: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
433: @*/
434: PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
435: {
436: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
437: PetscBool iascii;
440: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
441: if (iascii) {
443: ascii->tab--;
444: }
445: return 0;
446: }
448: /*@
449: PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the ASCII `PetscViewer`
451: Not Collective, but only first processor in set has any effect; No Fortran Support
453: Input Parameters:
454: + viewer - obtained with `PetscViewerASCIIOpen()`
455: - flg - `PETSC_TRUE` or `PETSC_FALSE`
457: Level: developer
459: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
460: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
461: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
462: @*/
463: PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
464: {
465: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
466: PetscBool iascii;
469: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
470: if (iascii) {
471: if (flg) ascii->tab = ascii->tab_store;
472: else {
473: ascii->tab_store = ascii->tab;
474: ascii->tab = 0;
475: }
476: }
477: return 0;
478: }
480: /* ----------------------------------------------------------------------- */
482: /*@C
483: PetscViewerASCIIPrintf - Prints to a file, only from the first
484: processor in the PetscViewer
486: Not Collective, but only first processor in set has any effect
488: Input Parameters:
489: + viewer - obtained with `PetscViewerASCIIOpen()`
490: - format - the usual printf() format string
492: Level: developer
494: Fortran Note:
495: The call sequence is `PetscViewerASCIIPrintf`(PetscViewer, character(*), int ierr) from Fortran.
496: That is, you can only pass a single character string from Fortran.
498: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
499: `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
500: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
501: @*/
502: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
503: {
504: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
505: PetscMPIInt rank;
506: PetscInt tab, intab = ascii->tab;
507: FILE *fd = ascii->fd;
508: PetscBool iascii;
509: int err;
514: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
516: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
517: if (rank) return 0;
519: if (ascii->bviewer) { /* pass string up to parent viewer */
520: char *string;
521: va_list Argp;
522: size_t fullLength;
524: PetscCalloc1(QUEUESTRINGSIZE, &string);
525: va_start(Argp, format);
526: PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp);
527: va_end(Argp);
528: PetscViewerASCIISynchronizedPrintf(viewer, "%s", string);
529: PetscFree(string);
530: } else { /* write directly to file */
531: va_list Argp;
532: /* flush my own messages that I may have queued up */
533: PrintfQueue next = ascii->petsc_printfqueuebase, previous;
534: PetscInt i;
535: for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
536: PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string);
537: previous = next;
538: next = next->next;
539: PetscFree(previous->string);
540: PetscFree(previous);
541: }
542: ascii->petsc_printfqueue = NULL;
543: ascii->petsc_printfqueuelength = 0;
544: tab = intab;
545: while (tab--) PetscFPrintf(PETSC_COMM_SELF, fd, " ");
547: va_start(Argp, format);
548: (*PetscVFPrintf)(fd, format, Argp);
549: err = fflush(fd);
551: if (petsc_history) {
552: va_start(Argp, format);
553: tab = intab;
554: while (tab--) PetscFPrintf(PETSC_COMM_SELF, petsc_history, " ");
555: (*PetscVFPrintf)(petsc_history, format, Argp);
556: err = fflush(petsc_history);
558: }
559: va_end(Argp);
560: }
561: return 0;
562: }
564: /*@C
565: PetscViewerFileSetName - Sets the name of the file the `PetscViewer` uses.
567: Collective
569: Input Parameters:
570: + viewer - the PetscViewer; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
571: - name - the name of the file it should use
573: Level: advanced
575: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
576: `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
577: @*/
578: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
579: {
580: char filename[PETSC_MAX_PATH_LEN];
584: PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename));
585: PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
586: return 0;
587: }
589: /*@C
590: PetscViewerFileGetName - Gets the name of the file the `PetscViewer` uses.
592: Not Collective
594: Input Parameter:
595: . viewer - the `PetscViewer`; either `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
597: Output Parameter:
598: . name - the name of the file it is using
600: Level: advanced
602: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
603: @*/
604: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
605: {
608: PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
609: return 0;
610: }
612: PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
613: {
614: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
616: *name = vascii->filename;
617: return 0;
618: }
620: PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
621: {
622: size_t len;
623: char fname[PETSC_MAX_PATH_LEN], *gz;
624: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
625: PetscBool isstderr, isstdout;
626: PetscMPIInt rank;
628: PetscViewerFileClose_ASCII(viewer);
629: if (!name) return 0;
630: PetscStrallocpy(name, &vascii->filename);
632: /* Is this file to be compressed */
633: vascii->storecompressed = PETSC_FALSE;
635: PetscStrstr(vascii->filename, ".gz", &gz);
636: if (gz) {
637: PetscStrlen(gz, &len);
638: if (len == 3) {
640: *gz = 0;
641: vascii->storecompressed = PETSC_TRUE;
642: }
643: }
644: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
645: if (rank == 0) {
646: PetscStrcmp(name, "stderr", &isstderr);
647: PetscStrcmp(name, "stdout", &isstdout);
648: /* empty filename means stdout */
649: if (name[0] == 0) isstdout = PETSC_TRUE;
650: if (isstderr) vascii->fd = PETSC_STDERR;
651: else if (isstdout) vascii->fd = PETSC_STDOUT;
652: else {
653: PetscFixFilename(name, fname);
654: switch (vascii->mode) {
655: case FILE_MODE_READ:
656: vascii->fd = fopen(fname, "r");
657: break;
658: case FILE_MODE_WRITE:
659: vascii->fd = fopen(fname, "w");
660: break;
661: case FILE_MODE_APPEND:
662: vascii->fd = fopen(fname, "a");
663: break;
664: case FILE_MODE_UPDATE:
665: vascii->fd = fopen(fname, "r+");
666: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
667: break;
668: case FILE_MODE_APPEND_UPDATE:
669: /* I really want a file which is opened at the end for updating,
670: not a+, which opens at the beginning, but makes writes at the end.
671: */
672: vascii->fd = fopen(fname, "r+");
673: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
674: else fseek(vascii->fd, 0, SEEK_END);
675: break;
676: default:
677: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
678: }
680: }
681: }
682: #if defined(PETSC_USE_LOG)
683: PetscLogObjectState((PetscObject)viewer, "File: %s", name);
684: #endif
685: return 0;
686: }
688: PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
689: {
690: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
692: PetscViewerASCIIPushSynchronized(viewer);
694: /*
695: The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
696: because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
697: (since the count never gets to zero) in some examples this displays information that otherwise would be lost
699: This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
700: PCView_GASM().
701: */
702: PetscViewerASCIIPushSynchronized(viewer);
703: PetscViewerCreate(subcomm, outviewer);
704: PetscViewerSetType(*outviewer, PETSCVIEWERASCII);
705: PetscViewerASCIIPushSynchronized(*outviewer);
706: ovascii = (PetscViewer_ASCII *)(*outviewer)->data;
707: ovascii->fd = vascii->fd;
708: ovascii->tab = vascii->tab;
709: ovascii->closefile = PETSC_FALSE;
711: vascii->sviewer = *outviewer;
712: (*outviewer)->format = viewer->format;
713: ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
714: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
715: return 0;
716: }
718: PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
719: {
720: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
725: PetscViewerASCIIPopSynchronized(*outviewer);
726: ascii->sviewer = NULL;
727: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
728: PetscViewerDestroy(outviewer);
729: PetscViewerASCIIPopSynchronized(viewer);
730: return 0;
731: }
733: PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
734: {
735: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
737: if (ascii->filename) PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename);
738: return 0;
739: }
741: /*MC
742: PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
744: Level: beginner
746: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
747: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
748: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
749: M*/
750: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
751: {
752: PetscViewer_ASCII *vascii;
754: PetscNew(&vascii);
755: viewer->data = (void *)vascii;
757: viewer->ops->destroy = PetscViewerDestroy_ASCII;
758: viewer->ops->flush = PetscViewerFlush_ASCII;
759: viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII;
760: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
761: viewer->ops->view = PetscViewerView_ASCII;
762: viewer->ops->read = PetscViewerASCIIRead;
764: /* defaults to stdout unless set with PetscViewerFileSetName() */
765: vascii->fd = PETSC_STDOUT;
766: vascii->mode = FILE_MODE_WRITE;
767: vascii->bviewer = NULL;
768: vascii->subviewer = NULL;
769: vascii->sviewer = NULL;
770: vascii->tab = 0;
771: vascii->tab_store = 0;
772: vascii->filename = NULL;
773: vascii->closefile = PETSC_TRUE;
775: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII);
776: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII);
777: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII);
778: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII);
779: return 0;
780: }
782: /*@C
783: PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified file from
784: several processors. Output of the first processor is followed by that of the
785: second, etc.
787: Not Collective, must call collective `PetscViewerFlush()` to get the results out
789: Input Parameters:
790: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
791: - format - the usual printf() format string
793: Level: intermediate
795: Notes:
796: You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
797: Then you can do multiple independent calls to this routine.
799: The actual synchronized print is then done using `PetscViewerFlush()`.
800: `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
801: to conclude the "synchronized session".
803: So the typical calling sequence looks like
804: .vb
805: PetscViewerASCIIPushSynchronized(viewer);
806: PetscViewerASCIISynchronizedPrintf(viewer, ...);
807: PetscViewerASCIISynchronizedPrintf(viewer, ...);
808: ...
809: PetscViewerFlush(viewer);
810: PetscViewerASCIISynchronizedPrintf(viewer, ...);
811: PetscViewerASCIISynchronizedPrintf(viewer, ...);
812: ...
813: PetscViewerFlush(viewer);
814: PetscViewerASCIIPopSynchronized(viewer);
815: .ve
817: Fortran Note:
818: Can only print a single character* string
820: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
821: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
822: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
823: @*/
824: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
825: {
826: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
827: PetscMPIInt rank;
828: PetscInt tab = vascii->tab;
829: MPI_Comm comm;
830: FILE *fp;
831: PetscBool iascii, hasbviewer = PETSC_FALSE;
832: int err;
836: PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);
840: PetscObjectGetComm((PetscObject)viewer, &comm);
841: MPI_Comm_rank(comm, &rank);
843: if (vascii->bviewer) {
844: hasbviewer = PETSC_TRUE;
845: if (rank == 0) {
846: vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
847: PetscObjectGetComm((PetscObject)viewer, &comm);
848: MPI_Comm_rank(comm, &rank);
849: }
850: }
852: fp = vascii->fd;
854: if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
855: va_list Argp;
856: /* flush my own messages that I may have queued up */
857: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
858: PetscInt i;
859: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
860: PetscFPrintf(comm, fp, "%s", next->string);
861: previous = next;
862: next = next->next;
863: PetscFree(previous->string);
864: PetscFree(previous);
865: }
866: vascii->petsc_printfqueue = NULL;
867: vascii->petsc_printfqueuelength = 0;
869: while (tab--) PetscFPrintf(PETSC_COMM_SELF, fp, " ");
871: va_start(Argp, format);
872: (*PetscVFPrintf)(fp, format, Argp);
873: err = fflush(fp);
875: if (petsc_history) {
876: va_start(Argp, format);
877: (*PetscVFPrintf)(petsc_history, format, Argp);
878: err = fflush(petsc_history);
880: }
881: va_end(Argp);
882: } else { /* other processors add to queue */
883: char *string;
884: va_list Argp;
885: size_t fullLength;
886: PrintfQueue next;
888: PetscNew(&next);
889: if (vascii->petsc_printfqueue) {
890: vascii->petsc_printfqueue->next = next;
891: vascii->petsc_printfqueue = next;
892: } else {
893: vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
894: }
895: vascii->petsc_printfqueuelength++;
896: next->size = QUEUESTRINGSIZE;
897: PetscCalloc1(next->size, &next->string);
898: string = next->string;
899: tab *= 2;
900: while (tab--) *string++ = ' ';
901: va_start(Argp, format);
902: PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp);
903: va_end(Argp);
904: if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
905: PetscFree(next->string);
906: next->size = fullLength + 2 * vascii->tab;
907: PetscCalloc1(next->size, &next->string);
908: string = next->string;
909: tab = 2 * vascii->tab;
910: while (tab--) *string++ = ' ';
911: va_start(Argp, format);
912: PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp);
913: va_end(Argp);
914: }
915: }
916: return 0;
917: }
919: /*@C
920: PetscViewerASCIIRead - Reads from a ASCII file
922: Only process 0 in the `PetscViewer` may call this
924: Input Parameters:
925: + viewer - the ascii viewer
926: . data - location to write the data
927: . num - number of items of data to read
928: - datatype - type of data to read
930: Output Parameters:
931: . count - number of items of data actually read, or NULL
933: Level: beginner
935: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
936: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
937: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
938: @*/
939: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
940: {
941: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
942: FILE *fd = vascii->fd;
943: PetscInt i;
944: int ret = 0;
945: PetscMPIInt rank;
948: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
950: for (i = 0; i < num; i++) {
951: if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
952: else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
953: else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
954: else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
955: else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
956: else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
957: else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
958: else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
959: #if defined(PETSC_USE_REAL___FLOAT128)
960: else if (dtype == PETSC___FLOAT128) {
961: double tmp;
962: ret = fscanf(fd, "%lg", &tmp);
963: ((__float128 *)data)[i] = tmp;
964: }
965: #endif
966: else
967: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
969: if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
970: }
971: if (count) *count = i;
973: return 0;
974: }