Actual source code: petscvu.c
2: #include <petsc/private/viewerimpl.h>
4: #define QUEUESTRINGSIZE 1024
6: typedef struct _PrintfQueue *PrintfQueue;
7: struct _PrintfQueue {
8: char string[QUEUESTRINGSIZE];
9: PrintfQueue next;
10: };
12: typedef struct {
13: FILE *fd;
14: PetscFileMode mode; /* The mode in which to open the file */
15: char *filename;
16: PetscBool vecSeen; /* The flag indicating whether any vector has been viewed so far */
17: PrintfQueue queue, queueBase;
18: int queueLength;
19: } PetscViewer_VU;
21: static PetscErrorCode PetscViewerFileClose_VU(PetscViewer viewer)
22: {
23: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
25: if (vu->vecSeen) PetscViewerVUPrintDeferred(viewer, "};\n\n");
26: PetscViewerVUFlushDeferred(viewer);
27: PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd);
28: vu->fd = NULL;
29: PetscFree(vu->filename);
30: return 0;
31: }
33: PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
34: {
35: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
37: PetscViewerFileClose_VU(viewer);
38: PetscFree(vu);
39: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL);
40: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL);
41: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL);
42: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL);
43: return 0;
44: }
46: PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
47: {
48: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
49: PetscMPIInt rank;
50: int err;
52: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
53: if (rank == 0) {
54: err = fflush(vu->fd);
56: }
57: return 0;
58: }
60: static PetscErrorCode PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
61: {
62: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
64: vu->mode = mode;
65: return 0;
66: }
68: static PetscErrorCode PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
69: {
70: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
72: *type = vu->mode;
73: return 0;
74: }
76: static PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
77: {
78: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
80: *name = vu->filename;
81: return 0;
82: }
84: static PetscErrorCode PetscViewerFileSetName_VU(PetscViewer viewer, const char name[])
85: {
86: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
87: char fname[PETSC_MAX_PATH_LEN];
88: int rank;
90: if (!name) return 0;
91: PetscViewerFileClose_VU(viewer);
92: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
93: if (rank != 0) return 0;
94: PetscStrallocpy(name, &vu->filename);
95: PetscFixFilename(name, fname);
96: switch (vu->mode) {
97: case FILE_MODE_READ:
98: vu->fd = fopen(fname, "r");
99: break;
100: case FILE_MODE_WRITE:
101: vu->fd = fopen(fname, "w");
102: break;
103: case FILE_MODE_APPEND:
104: vu->fd = fopen(fname, "a");
105: break;
106: case FILE_MODE_UPDATE:
107: vu->fd = fopen(fname, "r+");
108: if (!vu->fd) vu->fd = fopen(fname, "w+");
109: break;
110: case FILE_MODE_APPEND_UPDATE:
111: /* I really want a file which is opened at the end for updating,
112: not a+, which opens at the beginning, but makes writes at the end.
113: */
114: vu->fd = fopen(fname, "r+");
115: if (!vu->fd) vu->fd = fopen(fname, "w+");
116: else fseek(vu->fd, 0, SEEK_END);
117: break;
118: default:
119: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vu->mode]);
120: }
123: #if defined(PETSC_USE_LOG)
124: PetscLogObjectState((PetscObject)viewer, "File: %s", name);
125: #endif
126: return 0;
127: }
129: /*MC
130: PETSCVIEWERVU - A viewer that prints to a VU file
132: Level: beginner
134: .seealso: [](sec_viewers), `PetscViewerVUFlushDeferred()`, `PetscViewerVUGetPointer()`, `PetscViewerVUSetVecSeen()`, `PetscViewerVUGetVecSeen()`,
135: `PetscViewerVUPrintDeferred()`, `PetscViewerVUFlushDeferred()`
136: M*/
137: PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
138: {
139: PetscViewer_VU *vu;
141: PetscNew(&vu);
142: viewer->data = (void *)vu;
144: viewer->ops->destroy = PetscViewerDestroy_VU;
145: viewer->ops->flush = PetscViewerFlush_VU;
146: viewer->ops->getsubviewer = NULL;
147: viewer->ops->restoresubviewer = NULL;
149: vu->fd = NULL;
150: vu->mode = FILE_MODE_WRITE;
151: vu->filename = NULL;
152: vu->vecSeen = PETSC_FALSE;
153: vu->queue = NULL;
154: vu->queueBase = NULL;
155: vu->queueLength = 0;
157: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_VU);
158: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_VU);
159: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_VU);
160: PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_VU);
161: return 0;
162: }
164: /*@C
165: PetscViewerVUGetPointer - Extracts the file pointer from a `PETSCVIEWERVU` `PetscViewer`.
167: Not Collective
169: Input Parameter:
170: . viewer - The `PetscViewer`
172: Output Parameter:
173: . fd - The file pointer
175: Level: intermediate
177: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerASCIIGetPointer()`
178: @*/
179: PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
180: {
181: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
185: *fd = vu->fd;
186: return 0;
187: }
189: /*@C
190: PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
191: a vector. This is usually called internally rather than by a user.
193: Not Collective
195: Input Parameters:
196: + viewer - The `PETSCVIEWERVU` `PetscViewer`
197: - vecSeen - The flag which indicates whether we have viewed a vector
199: Level: developer
201: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
202: @*/
203: PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
204: {
205: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
207: vu->vecSeen = vecSeen;
208: return 0;
209: }
211: /*@C
212: PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
213: a vector. This is usually called internally rather than by a user.
215: Not Collective
217: Input Parameter:
218: . viewer - The `PETSCVIEWERVU` `PetscViewer`
220: Output Parameter:
221: . vecSeen - The flag which indicates whether we have viewed a vector
223: Level: advanced
225: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
226: @*/
227: PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
228: {
229: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
233: *vecSeen = vu->vecSeen;
234: return 0;
235: }
237: /*@C
238: PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
240: Not Collective
242: Input Parameters:
243: + viewer - The `PETSCVIEWERVU` `PetscViewer`
244: - format - The format string
246: Level: intermediate
248: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUFlushDeferred()`
249: @*/
250: PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
251: {
252: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
253: va_list Argp;
254: size_t fullLength;
255: PrintfQueue next;
257: PetscNew(&next);
258: if (vu->queue) {
259: vu->queue->next = next;
260: vu->queue = next;
261: vu->queue->next = NULL;
262: } else {
263: vu->queueBase = vu->queue = next;
264: }
265: vu->queueLength++;
267: va_start(Argp, format);
268: PetscArrayzero(next->string, QUEUESTRINGSIZE);
269: PetscVSNPrintf(next->string, QUEUESTRINGSIZE, format, &fullLength, Argp);
270: va_end(Argp);
271: return 0;
272: }
274: /*@C
275: PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
277: Not Collective
279: Input Parameter:
280: . viewer - The `PETSCVIEWERVU` `PetscViewer`
282: Level: intermediate
284: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUPrintDeferred()`
285: @*/
286: PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer)
287: {
288: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
289: PrintfQueue next = vu->queueBase;
290: PrintfQueue previous;
291: int i;
293: for (i = 0; i < vu->queueLength; i++) {
294: PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string);
295: previous = next;
296: next = next->next;
297: PetscFree(previous);
298: }
299: vu->queue = NULL;
300: vu->queueLength = 0;
301: return 0;
302: }