Actual source code: filev.c
1: #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h>
3: #define QUEUESTRINGSIZE 8192
5: static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
6: {
7: PetscMPIInt rank;
8: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
9: int err;
11: PetscFunctionBegin;
12: PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
13: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
14: if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
15: if (vascii->fd && vascii->closefile) {
16: err = fclose(vascii->fd);
17: PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
18: }
19: if (vascii->storecompressed) {
20: char par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
21: FILE *fp;
22: PetscCall(PetscStrncpy(par, "gzip ", sizeof(par)));
23: PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par)));
24: #if defined(PETSC_HAVE_POPEN)
25: PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp));
26: PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s %s", par, buf);
27: PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
28: #else
29: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
30: #endif
31: }
32: }
33: PetscCall(PetscFree(vascii->filename));
34: PetscFunctionReturn(PETSC_SUCCESS);
35: }
37: /* ----------------------------------------------------------------------*/
38: static PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
39: {
40: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
41: PetscViewerLink *vlink;
42: PetscBool flg;
44: PetscFunctionBegin;
45: PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
46: PetscCall(PetscViewerFileClose_ASCII(viewer));
47: PetscCall(PetscFree(vascii));
49: /* remove the viewer from the list in the MPI Communicator */
50: if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0));
52: PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg));
53: if (flg) {
54: if (vlink && vlink->viewer == viewer) {
55: if (vlink->next) {
56: PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
57: } else {
58: PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
59: }
60: PetscCall(PetscFree(vlink));
61: } else {
62: while (vlink && vlink->next) {
63: if (vlink->next->viewer == viewer) {
64: PetscViewerLink *nv = vlink->next;
65: vlink->next = vlink->next->next;
66: PetscCall(PetscFree(nv));
67: }
68: vlink = vlink->next;
69: }
70: }
71: }
73: if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
74: PetscViewer aviewer;
75: PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
76: if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval));
77: }
78: if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
79: PetscViewer aviewer;
80: PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, (PetscMPIInt *)&flg));
81: if (flg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
82: }
83: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
84: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
85: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
86: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
87: PetscFunctionReturn(PETSC_SUCCESS);
88: }
90: static PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
91: {
92: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
94: PetscFunctionBegin;
95: PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
96: PetscFunctionReturn(PETSC_SUCCESS);
97: }
99: static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
100: {
101: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
102: MPI_Comm comm;
103: PetscMPIInt rank, size;
104: FILE *fd = vascii->fd;
106: PetscFunctionBegin;
107: PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
108: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
109: PetscCallMPI(MPI_Comm_rank(comm, &rank));
110: PetscCallMPI(MPI_Comm_size(comm, &size));
112: if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));
114: if (vascii->allowsynchronized) {
115: PetscMPIInt tag, i, j, n = 0, dummy = 0;
116: char *message;
117: MPI_Status status;
119: PetscCall(PetscCommDuplicate(comm, &comm, &tag));
121: /* First processor waits for messages from all other processors */
122: if (rank == 0) {
123: /* flush my own messages that I may have queued up */
124: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
125: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
126: if (!vascii->bviewer) {
127: PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
128: } else {
129: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
130: }
131: previous = next;
132: next = next->next;
133: PetscCall(PetscFree(previous->string));
134: PetscCall(PetscFree(previous));
135: }
136: vascii->petsc_printfqueue = NULL;
137: vascii->petsc_printfqueuelength = 0;
138: for (i = 1; i < size; i++) {
139: /* to prevent a flood of messages to process zero, request each message separately */
140: PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
141: PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
142: for (j = 0; j < n; j++) {
143: PetscMPIInt size = 0;
145: PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
146: PetscCall(PetscMalloc1(size, &message));
147: PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
148: if (!vascii->bviewer) {
149: PetscCall(PetscFPrintf(comm, fd, "%s", message));
150: } else {
151: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
152: }
153: PetscCall(PetscFree(message));
154: }
155: }
156: } else { /* other processors send queue to processor 0 */
157: PrintfQueue next = vascii->petsc_printfqueuebase, previous;
159: PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
160: PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
161: for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
162: PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
163: PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
164: previous = next;
165: next = next->next;
166: PetscCall(PetscFree(previous->string));
167: PetscCall(PetscFree(previous));
168: }
169: vascii->petsc_printfqueue = NULL;
170: vascii->petsc_printfqueuelength = 0;
171: }
172: PetscCall(PetscCommDestroy(&comm));
173: }
174: PetscFunctionReturn(PETSC_SUCCESS);
175: }
177: /*@C
178: PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
180: Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support
182: Input Parameter:
183: . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`
185: Output Parameter:
186: . fd - file pointer
188: Level: intermediate
190: Note:
191: For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer
193: .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
194: `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
195: @*/
196: PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
197: {
198: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
200: PetscFunctionBegin;
201: *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 = 0, 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: for (; tab < ascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
682: va_start(Argp, format);
683: PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp));
684: va_end(Argp);
685: PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string));
686: PetscCall(PetscFree(string));
687: } else { /* write directly to file */
688: va_list Argp;
690: tab = intab;
691: while (tab--) {
692: if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " "));
693: else PetscCall(PetscFPrintfFortran(ascii->fileunit, " "));
694: }
696: va_start(Argp, format);
697: if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
698: else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
699: va_end(Argp);
700: PetscCall(PetscFFlush(fd));
701: }
702: PetscFunctionReturn(PETSC_SUCCESS);
703: }
705: /*@C
706: PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
708: Collective
710: Input Parameters:
711: + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
712: - name - the name of the file it should use
714: Level: advanced
716: Note:
717: This will have no effect on viewers that are not related to files
719: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
720: `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
721: @*/
722: PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
723: {
724: char filename[PETSC_MAX_PATH_LEN];
726: PetscFunctionBegin;
728: PetscAssertPointer(name, 2);
729: PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
730: PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
731: PetscFunctionReturn(PETSC_SUCCESS);
732: }
734: /*@C
735: PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
737: Not Collective
739: Input Parameter:
740: . viewer - the `PetscViewer`
742: Output Parameter:
743: . name - the name of the file it is using
745: Level: advanced
747: Note:
748: This will have no effect on viewers that are not related to files
750: .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
751: @*/
752: PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char **name)
753: {
754: PetscFunctionBegin;
756: PetscAssertPointer(name, 2);
757: PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
758: PetscFunctionReturn(PETSC_SUCCESS);
759: }
761: static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
762: {
763: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
765: PetscFunctionBegin;
766: *name = vascii->filename;
767: PetscFunctionReturn(PETSC_SUCCESS);
768: }
770: #include <errno.h>
771: static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
772: {
773: size_t len;
774: char fname[PETSC_MAX_PATH_LEN], *gz = NULL;
775: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
776: PetscBool isstderr, isstdout;
777: PetscMPIInt rank;
779: PetscFunctionBegin;
780: PetscCall(PetscViewerFileClose_ASCII(viewer));
781: if (!name) PetscFunctionReturn(PETSC_SUCCESS);
782: PetscCall(PetscStrallocpy(name, &vascii->filename));
784: /* Is this file to be compressed */
785: vascii->storecompressed = PETSC_FALSE;
787: PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
788: if (gz) {
789: PetscCall(PetscStrlen(gz, &len));
790: if (len == 3) {
791: PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
792: *gz = 0;
793: vascii->storecompressed = PETSC_TRUE;
794: }
795: }
796: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
797: if (rank == 0) {
798: PetscCall(PetscStrcmp(name, "stderr", &isstderr));
799: PetscCall(PetscStrcmp(name, "stdout", &isstdout));
800: /* empty filename means stdout */
801: if (name[0] == 0) isstdout = PETSC_TRUE;
802: if (isstderr) vascii->fd = PETSC_STDERR;
803: else if (isstdout) vascii->fd = PETSC_STDOUT;
804: else {
805: PetscCall(PetscFixFilename(name, fname));
806: switch (vascii->mode) {
807: case FILE_MODE_READ:
808: vascii->fd = fopen(fname, "r");
809: break;
810: case FILE_MODE_WRITE:
811: vascii->fd = fopen(fname, "w");
812: break;
813: case FILE_MODE_APPEND:
814: vascii->fd = fopen(fname, "a");
815: break;
816: case FILE_MODE_UPDATE:
817: vascii->fd = fopen(fname, "r+");
818: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
819: break;
820: case FILE_MODE_APPEND_UPDATE:
821: /* I really want a file which is opened at the end for updating,
822: not a+, which opens at the beginning, but makes writes at the end.
823: */
824: vascii->fd = fopen(fname, "r+");
825: if (!vascii->fd) vascii->fd = fopen(fname, "w+");
826: else {
827: int ret = fseek(vascii->fd, 0, SEEK_END);
828: PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
829: }
830: break;
831: default:
832: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
833: }
834: PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
835: }
836: }
837: PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
838: PetscFunctionReturn(PETSC_SUCCESS);
839: }
841: static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
842: {
843: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
845: PetscFunctionBegin;
846: PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
847: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
848: /*
849: The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
850: because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
851: (since the count never gets to zero) in some examples this displays information that otherwise would be lost
853: This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
854: PCView_GASM().
855: */
856: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
857: PetscCall(PetscViewerFlush(viewer));
858: PetscCall(PetscViewerCreate(subcomm, outviewer));
859: PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
860: PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
861: ovascii = (PetscViewer_ASCII *)(*outviewer)->data;
862: ovascii->fd = vascii->fd;
863: ovascii->closefile = PETSC_FALSE;
865: vascii->sviewer = *outviewer;
866: (*outviewer)->format = viewer->format;
867: ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
868: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
869: PetscFunctionReturn(PETSC_SUCCESS);
870: }
872: static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
873: {
874: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
876: PetscFunctionBegin;
877: PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
878: PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
880: PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
881: ascii->sviewer = NULL;
882: (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
883: PetscCall(PetscViewerDestroy(outviewer));
884: PetscCall(PetscViewerFlush(viewer));
885: PetscCall(PetscViewerASCIIPopSynchronized(viewer));
886: PetscFunctionReturn(PETSC_SUCCESS);
887: }
889: static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
890: {
891: PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
893: PetscFunctionBegin;
894: if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
895: PetscFunctionReturn(PETSC_SUCCESS);
896: }
898: /*MC
899: PETSCVIEWERASCII - A viewer that prints to stdout or an ASCII file
901: Level: beginner
903: .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
904: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
905: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
906: M*/
907: PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
908: {
909: PetscViewer_ASCII *vascii;
911: PetscFunctionBegin;
912: PetscCall(PetscNew(&vascii));
913: viewer->data = (void *)vascii;
915: viewer->ops->destroy = PetscViewerDestroy_ASCII;
916: viewer->ops->flush = PetscViewerFlush_ASCII;
917: viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII;
918: viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
919: viewer->ops->view = PetscViewerView_ASCII;
920: viewer->ops->read = PetscViewerASCIIRead;
922: /* defaults to stdout unless set with PetscViewerFileSetName() */
923: vascii->fd = PETSC_STDOUT;
924: vascii->mode = FILE_MODE_WRITE;
925: vascii->bviewer = NULL;
926: vascii->subviewer = NULL;
927: vascii->sviewer = NULL;
928: vascii->tab = 0;
929: vascii->tab_store = 0;
930: vascii->filename = NULL;
931: vascii->closefile = PETSC_TRUE;
933: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
934: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
935: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
936: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
937: PetscFunctionReturn(PETSC_SUCCESS);
938: }
940: /*@C
941: PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
942: several processors. Output of the first processor is followed by that of the
943: second, etc.
945: Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
947: Input Parameters:
948: + viewer - the `PETSCVIEWERASCII` `PetscViewer`
949: - format - the usual printf() format string
951: Level: intermediate
953: Notes:
954: You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
955: Then you can do multiple independent calls to this routine.
957: The actual synchronized print is then done using `PetscViewerFlush()`.
958: `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
959: to conclude the "synchronized session".
961: So the typical calling sequence looks like
962: .vb
963: PetscViewerASCIIPushSynchronized(viewer);
964: PetscViewerASCIISynchronizedPrintf(viewer, ...);
965: PetscViewerASCIISynchronizedPrintf(viewer, ...);
966: ...
967: PetscViewerFlush(viewer);
968: PetscViewerASCIISynchronizedPrintf(viewer, ...);
969: PetscViewerASCIISynchronizedPrintf(viewer, ...);
970: ...
971: PetscViewerFlush(viewer);
972: PetscViewerASCIIPopSynchronized(viewer);
973: .ve
975: Fortran Notes:
976: Can only print a single character* string
978: .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
979: `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
980: `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
981: @*/
982: PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
983: {
984: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
985: PetscMPIInt rank;
986: PetscInt tab = 0;
987: MPI_Comm comm;
988: PetscBool iascii;
990: PetscFunctionBegin;
992: PetscAssertPointer(format, 2);
993: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
994: PetscCheck(iascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
995: PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
997: PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
998: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1000: if (vascii->bviewer) {
1001: char *string;
1002: va_list Argp;
1003: size_t fullLength;
1005: PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
1006: for (; tab < vascii->tab; tab++) { string[2 * tab] = string[2 * tab + 1] = ' '; }
1007: va_start(Argp, format);
1008: PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp));
1009: va_end(Argp);
1010: PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string));
1011: PetscCall(PetscFree(string));
1012: } else if (rank == 0) { /* First processor prints immediately to fp */
1013: va_list Argp;
1014: FILE *fp = vascii->fd;
1016: tab = vascii->tab;
1017: while (tab--) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " "));
1019: va_start(Argp, format);
1020: PetscCall((*PetscVFPrintf)(fp, format, Argp));
1021: va_end(Argp);
1022: PetscCall(PetscFFlush(fp));
1023: if (petsc_history) {
1024: va_start(Argp, format);
1025: PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1026: va_end(Argp);
1027: PetscCall(PetscFFlush(petsc_history));
1028: }
1029: va_end(Argp);
1030: } else { /* other processors add to queue */
1031: char *string;
1032: va_list Argp;
1033: size_t fullLength;
1034: PrintfQueue next;
1036: PetscCall(PetscNew(&next));
1037: if (vascii->petsc_printfqueue) {
1038: vascii->petsc_printfqueue->next = next;
1039: vascii->petsc_printfqueue = next;
1040: } else {
1041: vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1042: }
1043: vascii->petsc_printfqueuelength++;
1044: next->size = QUEUESTRINGSIZE;
1045: PetscCall(PetscCalloc1(next->size, &next->string));
1046: string = next->string;
1048: tab = vascii->tab;
1049: tab *= 2;
1050: while (tab--) *string++ = ' ';
1051: va_start(Argp, format);
1052: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
1053: va_end(Argp);
1054: if (fullLength > (size_t)(next->size - 2 * vascii->tab)) {
1055: PetscCall(PetscFree(next->string));
1056: next->size = fullLength + 2 * vascii->tab;
1057: PetscCall(PetscCalloc1(next->size, &next->string));
1058: string = next->string;
1059: tab = 2 * vascii->tab;
1060: while (tab--) *string++ = ' ';
1061: va_start(Argp, format);
1062: PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
1063: va_end(Argp);
1064: }
1065: }
1066: PetscFunctionReturn(PETSC_SUCCESS);
1067: }
1069: /*@C
1070: PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
1072: Only MPI rank 0 in the `PetscViewer` may call this
1074: Input Parameters:
1075: + viewer - the `PETSCVIEWERASCII` viewer
1076: . data - location to write the data, treated as an array of type indicated by `datatype`
1077: . num - number of items of data to read
1078: - dtype - type of data to read
1080: Output Parameter:
1081: . count - number of items of data actually read, or `NULL`
1083: Level: beginner
1085: .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1086: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1087: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1088: @*/
1089: PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1090: {
1091: PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1092: FILE *fd = vascii->fd;
1093: PetscInt i;
1094: int ret = 0;
1095: PetscMPIInt rank;
1097: PetscFunctionBegin;
1099: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1100: PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1101: for (i = 0; i < num; i++) {
1102: if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1103: else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1104: else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1105: else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
1106: else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1107: else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1108: else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1109: else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1110: #if defined(PETSC_USE_REAL___FLOAT128)
1111: else if (dtype == PETSC___FLOAT128) {
1112: double tmp;
1113: ret = fscanf(fd, "%lg", &tmp);
1114: ((__float128 *)data)[i] = tmp;
1115: }
1116: #endif
1117: else
1118: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
1119: PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1120: if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1121: }
1122: if (count) *count = i;
1123: else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1124: PetscFunctionReturn(PETSC_SUCCESS);
1125: }