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\n%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: *fd = vascii->fd;
202: PetscFunctionReturn(PETSC_SUCCESS);
203: }
205: static PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
206: {
207: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
209: PetscFunctionBegin;
210: *mode = vascii->mode;
211: PetscFunctionReturn(PETSC_SUCCESS);
212: }
214: static PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
215: {
216: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
218: PetscFunctionBegin;
219: vascii->mode = mode;
220: PetscFunctionReturn(PETSC_SUCCESS);
221: }
223: /*
224: If petsc_history is on, then all Petsc*Printf() results are saved
225: if the appropriate (usually .petschistory) file.
226: */
227: PETSC_INTERN FILE *petsc_history;
229: /*@
230: PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing
232: Not Collective, but only first processor in set has any effect; No Fortran Support
234: Input Parameters:
235: + viewer - obtained with `PetscViewerASCIIOpen()`
236: - tabs - number of tabs
238: Level: developer
240: Note:
241: `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
243: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
244: `PetscViewerASCIIGetTab()`,
245: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
246: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
247: `PetscViewerASCIIPushTab()`
248: @*/
249: PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
250: {
251: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
252: PetscBool iascii;
254: PetscFunctionBegin;
256: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
257: if (iascii) ascii->tab = tabs;
258: PetscFunctionReturn(PETSC_SUCCESS);
259: }
261: /*@
262: PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
264: Not Collective, meaningful on first processor only; No Fortran Support
266: Input Parameter:
267: . viewer - obtained with `PetscViewerASCIIOpen()`
269: Output Parameter:
270: . tabs - number of tabs
272: Level: developer
274: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
275: `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;
284: PetscFunctionBegin;
286: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
287: if (iascii && tabs) *tabs = ascii->tab;
288: PetscFunctionReturn(PETSC_SUCCESS);
289: }
291: /*@
292: PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing
294: Not Collective, but only first processor in set has any effect; No Fortran Support
296: Input Parameters:
297: + viewer - obtained with `PetscViewerASCIIOpen()`
298: - tabs - number of tabs
300: Level: developer
302: Note:
303: `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
305: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
306: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
307: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
308: @*/
309: PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
310: {
311: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
312: PetscBool iascii;
314: PetscFunctionBegin;
316: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
317: if (iascii) ascii->tab += tabs;
318: PetscFunctionReturn(PETSC_SUCCESS);
319: }
321: /*@
322: PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing
324: Not Collective, but only first processor in set has any effect; No Fortran Support
326: Input Parameters:
327: + viewer - obtained with `PetscViewerASCIIOpen()`
328: - tabs - number of tabs
330: Level: developer
332: Note:
333: `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
335: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
336: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
337: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
338: `PetscViewerASCIIPushTab()`
339: @*/
340: PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
341: {
342: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
343: PetscBool iascii;
345: PetscFunctionBegin;
347: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
348: if (iascii) ascii->tab -= tabs;
349: PetscFunctionReturn(PETSC_SUCCESS);
350: }
352: /*@C
353: PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
355: Collective
357: Input Parameter:
358: . viewer - obtained with `PetscViewerASCIIOpen()`
360: Level: intermediate
362: Note:
363: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
365: .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
366: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
367: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
368: @*/
369: PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
370: {
371: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
372: PetscBool iascii;
374: PetscFunctionBegin;
376: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
377: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
378: if (iascii) ascii->allowsynchronized++;
379: PetscFunctionReturn(PETSC_SUCCESS);
380: }
382: /*@C
383: PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
385: Collective
387: Input Parameter:
388: . viewer - obtained with `PetscViewerASCIIOpen()`
390: Level: intermediate
392: Note:
393: See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
395: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
396: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
397: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
398: @*/
399: PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
400: {
401: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
402: PetscBool iascii;
404: PetscFunctionBegin;
406: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
407: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
408: if (iascii) {
409: ascii->allowsynchronized--;
410: PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
411: }
412: PetscFunctionReturn(PETSC_SUCCESS);
413: }
415: /*@C
416: PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
417: lines are tabbed.
419: Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
421: Input Parameter:
422: . viewer - obtained with `PetscViewerASCIIOpen()`
424: Level: developer
426: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
427: `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
428: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
429: @*/
430: PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
431: {
432: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
433: PetscBool iascii;
435: PetscFunctionBegin;
437: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
438: if (iascii) ascii->tab++;
439: PetscFunctionReturn(PETSC_SUCCESS);
440: }
442: /*@C
443: PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by
444: `PetscViewerASCIIPushTab()`
446: Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
448: Input Parameter:
449: . viewer - obtained with `PetscViewerASCIIOpen()`
451: Level: developer
453: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
454: `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
455: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
456: @*/
457: PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
458: {
459: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
460: PetscBool iascii;
462: PetscFunctionBegin;
464: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
465: if (iascii) {
466: PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
467: ascii->tab--;
468: }
469: PetscFunctionReturn(PETSC_SUCCESS);
470: }
472: /*@
473: PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`
475: Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
477: Input Parameters:
478: + viewer - obtained with `PetscViewerASCIIOpen()`
479: - flg - `PETSC_TRUE` or `PETSC_FALSE`
481: Level: developer
483: .seealso: [](sec_viewers), `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;
492: PetscFunctionBegin;
494: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
495: if (iascii) {
496: if (flg) ascii->tab = ascii->tab_store;
497: else {
498: ascii->tab_store = ascii->tab;
499: ascii->tab = 0;
500: }
501: }
502: PetscFunctionReturn(PETSC_SUCCESS);
503: }
505: #if defined(PETSC_USE_FORTRAN_BINDINGS)
507: #if defined(PETSC_HAVE_FORTRAN_CAPS)
508: #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT
509: #define petscviewerasciisetfilefileunit_ PETSCVIEWERASCIISETFILEUNIT
510: #define petscfortranprinttounit_ PETSCFORTRANPRINTTOUNIT
511: #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
512: #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit
513: #define petscviewerasciisetfileunit_ petscviewerasciisetfileunit
514: #define petscfortranprinttounit_ petscfortranprinttounit
515: #endif
517: #if defined(__cplusplus)
518: extern "C" void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
519: #else
520: extern void petscfortranprinttounit_(PetscInt *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
521: #endif
523: #define PETSCDEFAULTBUFFERSIZE 8 * 1024
525: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
526: /*MC
527: PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` to write to a Fortran IO unit
529: Synopsis:
530: #include <petscviewer.h>
531: void PetscViewerASCIISetFileUnit(PetscViewer lab, PetscInt unit, PetscErrorCode ierr)
533: Input Parameters:
534: + lab - the viewer
535: - unit - the unit number
537: Output Parameter:
538: . ierr - the error code
540: Level: intermediate
542: Note:
543: `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
545: Fortran Notes:
546: Only for Fortran, use `PetscViewerASCIISetFILE()` for C
548: .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`
549: M*/
550: PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *lab, PetscInt *unit, PetscErrorCode *ierr)
551: {
552: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)(*lab)->data;
554: if (vascii->mode == FILE_MODE_READ) {
555: *ierr = PETSC_ERR_ARG_WRONGSTATE;
556: return;
557: }
558: vascii->fileunit = *unit;
559: }
561: // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
562: /*MC
563: PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit
565: Synopsis:
566: #include <petscviewer.h>
567: void PetscViewerASCIIOpenWithFileUnit(MPI_Comm comm, PetscInt unit, PetscViewer viewer, PetscErrorCode ierr)
569: Input Parameters:
570: + comm - the `MPI_Comm` to share the viewer
571: - unit - the unit number
573: Output Parameters:
574: + lab - the viewer
575: - ierr - the error code
577: Level: intermediate
579: Note:
580: `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
582: Fortran Notes:
583: Only for Fortran, use `PetscViewerASCIIOpenWithFILE()` for C
585: .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
586: M*/
587: PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Comm *comm, PetscInt *unit, PetscViewer *lab, PetscErrorCode *ierr)
588: {
589: *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), lab);
590: if (*ierr) return;
591: *ierr = PetscViewerSetType(*lab, PETSCVIEWERASCII);
592: if (*ierr) return;
593: *ierr = PetscViewerFileSetMode(*lab, FILE_MODE_WRITE);
594: if (*ierr) return;
595: petscviewerasciisetfileunit_(lab, unit, ierr);
596: }
598: static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
599: {
600: PetscErrorCode ierr;
601: char str[PETSCDEFAULTBUFFERSIZE];
602: size_t len;
604: PetscFunctionBegin;
605: PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
606: PetscCall(PetscStrlen(str, &len));
607: petscfortranprinttounit_(&unit, str, &ierr, (int)len);
608: PetscFunctionReturn(PETSC_SUCCESS);
609: }
611: static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
612: {
613: PetscErrorCode ierr;
614: size_t len;
616: PetscFunctionBegin;
617: PetscCall(PetscStrlen(str, &len));
618: petscfortranprinttounit_(&unit, str, &ierr, (int)len);
619: PetscFunctionReturn(PETSC_SUCCESS);
620: }
622: #else
624: /* these will never be used; but are needed to link with */
625: static PetscErrorCode PetscVFPrintfFortran(PetscInt unit, const char format[], va_list Argp)
626: {
627: PetscFunctionBegin;
628: PetscFunctionReturn(PETSC_SUCCESS);
629: }
631: static PetscErrorCode PetscFPrintfFortran(PetscInt unit, const char str[])
632: {
633: PetscFunctionBegin;
634: PetscFunctionReturn(PETSC_SUCCESS);
635: }
636: #endif
638: /*@C
639: PetscViewerASCIIPrintf - Prints to a file, only from the first
640: processor in the `PetscViewer` of type `PETSCVIEWERASCII`
642: Not Collective, but only the first MPI rank in the viewer has any effect
644: Input Parameters:
645: + viewer - obtained with `PetscViewerASCIIOpen()`
646: - format - the usual printf() format string
648: Level: developer
650: Fortran Notes:
651: The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr) from Fortran.
652: That is, you can only pass a single character string from Fortran.
654: .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
655: `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
656: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
657: @*/
658: PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
659: {
660: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
661: PetscMPIInt rank;
662: PetscInt tab, intab = ascii->tab;
663: FILE *fd = ascii->fd;
664: PetscBool iascii;
666: PetscFunctionBegin;
668: PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
669: PetscAssertPointer(format, 2);
670: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
671: PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
672: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
673: if (rank) PetscFunctionReturn(PETSC_SUCCESS);
675: if (ascii->bviewer) { /* pass string up to parent viewer */
676: char *string;
677: va_list Argp;
678: size_t fullLength;
680: PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
681: va_start(Argp, format);
682: PetscCall(PetscVSNPrintf(string, QUEUESTRINGSIZE, format, &fullLength, Argp));
683: va_end(Argp);
684: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%s", string));
685: PetscCall(PetscFree(string));
686: } else { /* write directly to file */
687: va_list Argp;
688: /* flush my own messages that I may have queued up */
689: PrintfQueue next = ascii->petsc_printfqueuebase, previous;
690: PetscInt i;
691: for (i = 0; i < ascii->petsc_printfqueuelength; i++) {
692: if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, "%s", next->string));
693: else PetscCall(PetscFPrintfFortran(ascii->fileunit, next->string));
694: previous = next;
695: next = next->next;
696: PetscCall(PetscFree(previous->string));
697: PetscCall(PetscFree(previous));
698: }
699: ascii->petsc_printfqueue = NULL;
700: ascii->petsc_printfqueuelength = 0;
701: tab = intab;
702: while (tab--) {
703: if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " "));
704: else PetscCall(PetscFPrintfFortran(ascii->fileunit, " "));
705: }
707: va_start(Argp, format);
708: if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
709: else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
710: va_end(Argp);
711: PetscCall(PetscFFlush(fd));
712: }
713: PetscFunctionReturn(PETSC_SUCCESS);
714: }
716: /*@C
717: PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
719: Collective
721: Input Parameters:
722: + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
723: - name - the name of the file it should use
725: Level: advanced
727: Note:
728: This will have no effect on viewers that are not related to files
730: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
731: `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
732: @*/
733: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
734: {
735: char filename[PETSC_MAX_PATH_LEN];
737: PetscFunctionBegin;
739: PetscAssertPointer(name, 2);
740: PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
741: PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
742: PetscFunctionReturn(PETSC_SUCCESS);
743: }
745: /*@C
746: PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
748: Not Collective
750: Input Parameter:
751: . viewer - the `PetscViewer`
753: Output Parameter:
754: . name - the name of the file it is using
756: Level: advanced
758: Note:
759: This will have no effect on viewers that are not related to files
761: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
762: @*/
763: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
764: {
765: PetscFunctionBegin;
767: PetscAssertPointer(name, 2);
768: PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
769: PetscFunctionReturn(PETSC_SUCCESS);
770: }
772: static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
773: {
774: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
776: PetscFunctionBegin;
777: *name = vascii->filename;
778: PetscFunctionReturn(PETSC_SUCCESS);
779: }
781: #include <errno.h>
782: static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
783: {
784: size_t len;
785: char fname[PETSC_MAX_PATH_LEN], *gz = NULL;
786: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
787: PetscBool isstderr, isstdout;
788: PetscMPIInt rank;
790: PetscFunctionBegin;
791: PetscCall(PetscViewerFileClose_ASCII(viewer));
792: if (!name) PetscFunctionReturn(PETSC_SUCCESS);
793: PetscCall(PetscStrallocpy(name, &vascii->filename));
795: /* Is this file to be compressed */
796: vascii->storecompressed = PETSC_FALSE;
798: PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
799: if (gz) {
800: PetscCall(PetscStrlen(gz, &len));
801: if (len == 3) {
802: PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
803: *gz = 0;
804: vascii->storecompressed = PETSC_TRUE;
805: }
806: }
807: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
808: if (rank == 0) {
809: PetscCall(PetscStrcmp(name, "stderr", &isstderr));
810: PetscCall(PetscStrcmp(name, "stdout", &isstdout));
811: /* empty filename means stdout */
812: if (name[0] == 0) isstdout = PETSC_TRUE;
813: if (isstderr) vascii->fd = PETSC_STDERR;
814: else if (isstdout) vascii->fd = PETSC_STDOUT;
815: else {
816: PetscCall(PetscFixFilename(name, fname));
817: switch (vascii->mode) {
818: case FILE_MODE_READ:
819: vascii->fd = fopen(fname, "r");
820: break;
821: case FILE_MODE_WRITE:
822: vascii->fd = fopen(fname, "w");
823: break;
824: case FILE_MODE_APPEND:
825: vascii->fd = fopen(fname, "a");
826: break;
827: case FILE_MODE_UPDATE:
828: vascii->fd = fopen(fname, "r+");
829: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
830: break;
831: case FILE_MODE_APPEND_UPDATE:
832: /* I really want a file which is opened at the end for updating,
833: not a+, which opens at the beginning, but makes writes at the end.
834: */
835: vascii->fd = fopen(fname, "r+");
836: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
837: else {
838: int ret = fseek(vascii->fd, 0, SEEK_END);
839: PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
840: }
841: break;
842: default:
843: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
844: }
845: PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
846: }
847: }
848: PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
849: PetscFunctionReturn(PETSC_SUCCESS);
850: }
852: static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
853: {
854: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
856: PetscFunctionBegin;
857: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
858: PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
859: /*
860: The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
861: because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
862: (since the count never gets to zero) in some examples this displays information that otherwise would be lost
864: This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
865: PCView_GASM().
866: */
867: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
868: PetscCall(PetscViewerCreate(subcomm, outviewer));
869: PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
870: PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
871: ovascii = (PetscViewer_ASCII *)(*outviewer)->data;
872: ovascii->fd = vascii->fd;
873: ovascii->tab = vascii->tab;
874: ovascii->closefile = PETSC_FALSE;
876: vascii->sviewer = *outviewer;
877: (*outviewer)->format = viewer->format;
878: ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
879: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
880: PetscFunctionReturn(PETSC_SUCCESS);
881: }
883: static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
884: {
885: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
887: PetscFunctionBegin;
888: PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
889: PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
891: PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
892: ascii->sviewer = NULL;
893: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
894: PetscCall(PetscViewerDestroy(outviewer));
895: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
896: PetscFunctionReturn(PETSC_SUCCESS);
897: }
899: static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
900: {
901: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
903: PetscFunctionBegin;
904: if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
905: PetscFunctionReturn(PETSC_SUCCESS);
906: }
908: /*MC
909: PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
911: Level: beginner
913: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
914: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
915: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
916: M*/
917: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
918: {
919: PetscViewer_ASCII *vascii;
921: PetscFunctionBegin;
922: PetscCall(PetscNew(&vascii));
923: viewer->data = (void *)vascii;
925: viewer->ops->destroy = PetscViewerDestroy_ASCII;
926: viewer->ops->flush = PetscViewerFlush_ASCII;
927: viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII;
928: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
929: viewer->ops->view = PetscViewerView_ASCII;
930: viewer->ops->read = PetscViewerASCIIRead;
932: /* defaults to stdout unless set with PetscViewerFileSetName() */
933: vascii->fd = PETSC_STDOUT;
934: vascii->mode = FILE_MODE_WRITE;
935: vascii->bviewer = NULL;
936: vascii->subviewer = NULL;
937: vascii->sviewer = NULL;
938: vascii->tab = 0;
939: vascii->tab_store = 0;
940: vascii->filename = NULL;
941: vascii->closefile = PETSC_TRUE;
943: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
944: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
945: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
946: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
947: PetscFunctionReturn(PETSC_SUCCESS);
948: }
950: /*@C
951: PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
952: several processors. Output of the first processor is followed by that of the
953: second, etc.
955: Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
957: Input Parameters:
958: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
959: - format - the usual printf() format string
961: Level: intermediate
963: Notes:
964: You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
965: Then you can do multiple independent calls to this routine.
967: The actual synchronized print is then done using `PetscViewerFlush()`.
968: `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
969: to conclude the "synchronized session".
971: So the typical calling sequence looks like
972: .vb
973: PetscViewerASCIIPushSynchronized(viewer);
974: PetscViewerASCIISynchronizedPrintf(viewer, ...);
975: PetscViewerASCIISynchronizedPrintf(viewer, ...);
976: ...
977: PetscViewerFlush(viewer);
978: PetscViewerASCIISynchronizedPrintf(viewer, ...);
979: PetscViewerASCIISynchronizedPrintf(viewer, ...);
980: ...
981: PetscViewerFlush(viewer);
982: PetscViewerASCIIPopSynchronized(viewer);
983: .ve
985: Fortran Notes:
986: Can only print a single character* string
988: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
989: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
990: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
991: @*/
992: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
993: {
994: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
995: PetscMPIInt rank;
996: PetscInt tab = vascii->tab;
997: MPI_Comm comm;
998: FILE *fp;
999: PetscBool iascii, hasbviewer = PETSC_FALSE;
1001: PetscFunctionBegin;
1003: PetscAssertPointer(format, 2);
1004: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
1005: PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
1006: PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
1008: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1009: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1011: if (vascii->bviewer) {
1012: hasbviewer = PETSC_TRUE;
1013: if (rank == 0) {
1014: vascii = (PetscViewer_ASCII *)vascii->bviewer->data;
1015: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1016: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1017: }
1018: }
1020: fp = vascii->fd;
1022: if (rank == 0 && !hasbviewer) { /* First processor prints immediately to fp */
1023: va_list Argp;
1024: /* flush my own messages that I may have queued up */
1025: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
1026: PetscInt i;
1027: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
1028: PetscCall(PetscFPrintf(comm, fp, "%s", next->string));
1029: previous = next;
1030: next = next->next;
1031: PetscCall(PetscFree(previous->string));
1032: PetscCall(PetscFree(previous));
1033: }
1034: vascii->petsc_printfqueue = NULL;
1035: vascii->petsc_printfqueuelength = 0;
1037: while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " "));
1039: va_start(Argp, format);
1040: PetscCall((*PetscVFPrintf)(fp, format, Argp));
1041: va_end(Argp);
1042: PetscCall(PetscFFlush(fp));
1043: if (petsc_history) {
1044: va_start(Argp, format);
1045: PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1046: va_end(Argp);
1047: PetscCall(PetscFFlush(petsc_history));
1048: }
1049: va_end(Argp);
1050: } else { /* other processors add to queue */
1051: char *string;
1052: va_list Argp;
1053: size_t fullLength;
1054: PrintfQueue next;
1056: PetscCall(PetscNew(&next));
1057: if (vascii->petsc_printfqueue) {
1058: vascii->petsc_printfqueue->next = next;
1059: vascii->petsc_printfqueue = next;
1060: } else {
1061: vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1062: }
1063: vascii->petsc_printfqueuelength++;
1064: next->size = QUEUESTRINGSIZE;
1065: PetscCall(PetscCalloc1(next->size, &next->string));
1066: string = next->string;
1067: tab *= 2;
1068: while (tab--) *string++ = ' ';
1069: va_start(Argp, format);
1070: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
1071: va_end(Argp);
1072: if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
1073: PetscCall(PetscFree(next->string));
1074: next->size = fullLength + 2 * vascii->tab;
1075: PetscCall(PetscCalloc1(next->size, &next->string));
1076: string = next->string;
1077: tab = 2 * vascii->tab;
1078: while (tab--) *string++ = ' ';
1079: va_start(Argp, format);
1080: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
1081: va_end(Argp);
1082: }
1083: }
1084: PetscFunctionReturn(PETSC_SUCCESS);
1085: }
1087: /*@C
1088: PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
1090: Only MPI rank 0 in the `PetscViewer` may call this
1092: Input Parameters:
1093: + viewer - the `PETSCVIEWERASCII` viewer
1094: . data - location to write the data, treated as an array of type indicated by `datatype`
1095: . num - number of items of data to read
1096: - dtype - type of data to read
1098: Output Parameter:
1099: . count - number of items of data actually read, or `NULL`
1101: Level: beginner
1103: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1104: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1105: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1106: @*/
1107: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1108: {
1109: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1110: FILE *fd = vascii->fd;
1111: PetscInt i;
1112: int ret = 0;
1113: PetscMPIInt rank;
1115: PetscFunctionBegin;
1117: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1118: PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1119: for (i = 0; i < num; i++) {
1120: if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1121: else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1122: else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1123: else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
1124: else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1125: else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1126: else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1127: else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1128: #if defined(PETSC_USE_REAL___FLOAT128)
1129: else if (dtype == PETSC___FLOAT128) {
1130: double tmp;
1131: ret = fscanf(fd, "%lg", &tmp);
1132: ((__float128 *)data)[i] = tmp;
1133: }
1134: #endif
1135: else
1136: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
1137: PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1138: if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1139: }
1140: if (count) *count = i;
1141: else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1142: PetscFunctionReturn(PETSC_SUCCESS);
1143: }