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;
27: if (vu->vecSeen) {
28: PetscViewerVUPrintDeferred(viewer, "};\n\n");
29: }
30: PetscViewerVUFlushDeferred(viewer);
31: PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd);
32: vu->fd = NULL;
33: PetscFree(vu->filename);
34: return(0);
35: }
37: PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
38: {
39: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
43: PetscViewerFileClose_VU(viewer);
44: PetscFree(vu);
45: return(0);
46: }
48: PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
49: {
50: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
51: PetscMPIInt rank;
52: int err;
56: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
57: if (!rank) {
58: err = fflush(vu->fd);
59: if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
60: }
61: return(0);
62: }
64: static PetscErrorCode PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
65: {
66: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
69: vu->mode = mode;
70: return(0);
71: }
73: static PetscErrorCode PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
74: {
75: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
78: *type = vu->mode;
79: return(0);
80: }
82: static PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
83: {
84: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
87: *name = vu->filename;
88: return(0);
89: }
91: static PetscErrorCode PetscViewerFileSetName_VU(PetscViewer viewer, const char name[])
92: {
93: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
94: char fname[PETSC_MAX_PATH_LEN];
95: int rank;
99: if (!name) return(0);
100: PetscViewerFileClose_VU(viewer);
101: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
102: if (rank != 0) return(0);
103: PetscStrallocpy(name, &vu->filename);
104: PetscFixFilename(name, fname);
105: switch (vu->mode) {
106: case FILE_MODE_READ:
107: vu->fd = fopen(fname, "r");
108: break;
109: case FILE_MODE_WRITE:
110: vu->fd = fopen(fname, "w");
111: break;
112: case FILE_MODE_APPEND:
113: vu->fd = fopen(fname, "a");
114: break;
115: case FILE_MODE_UPDATE:
116: vu->fd = fopen(fname, "r+");
117: if (!vu->fd) vu->fd = fopen(fname, "w+");
118: break;
119: case FILE_MODE_APPEND_UPDATE:
120: /* I really want a file which is opened at the end for updating,
121: not a+, which opens at the beginning, but makes writes at the end.
122: */
123: vu->fd = fopen(fname, "r+");
124: if (!vu->fd) vu->fd = fopen(fname, "w+");
125: else {
126: fseek(vu->fd, 0, SEEK_END);
127: }
128: break;
129: default:
130: SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[vu->mode]);
131: }
133: if (!vu->fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
134: #if defined(PETSC_USE_LOG)
135: PetscLogObjectState((PetscObject) viewer, "File: %s", name);
136: #endif
137: return(0);
138: }
140: PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
141: {
142: PetscViewer_VU *vu;
146: PetscNewLog(viewer,&vu);
147: viewer->data = (void*) vu;
149: viewer->ops->destroy = PetscViewerDestroy_VU;
150: viewer->ops->flush = PetscViewerFlush_VU;
151: viewer->ops->getsubviewer = NULL;
152: viewer->ops->restoresubviewer = NULL;
154: vu->fd = NULL;
155: vu->mode = FILE_MODE_WRITE;
156: vu->filename = NULL;
157: vu->vecSeen = PETSC_FALSE;
158: vu->queue = NULL;
159: vu->queueBase = NULL;
160: vu->queueLength = 0;
162: PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_VU);
163: PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_VU);
164: PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_VU);
165: PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_VU);
166: return(0);
167: }
169: /*@C
170: PetscViewerVUGetPointer - Extracts the file pointer from a VU PetscViewer.
172: Not Collective
174: Input Parameter:
175: . viewer - The PetscViewer
177: Output Parameter:
178: . fd - The file pointer
180: Level: intermediate
183: .seealso: PetscViewerASCIIGetPointer()
184: @*/
185: PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
186: {
187: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
192: *fd = vu->fd;
193: return(0);
194: }
196: /*@C
197: PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
198: a vector. This is usually called internally rather than by a user.
200: Not Collective
202: Input Parameters:
203: + viewer - The PetscViewer
204: - vecSeen - The flag which indicates whether we have viewed a vector
206: Level: advanced
208: .seealso: PetscViewerVUGetVecSeen()
209: @*/
210: PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
211: {
212: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
215: vu->vecSeen = vecSeen;
216: return(0);
217: }
219: /*@C
220: PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
221: a vector. This is usually called internally rather than by a user.
223: Not Collective
225: Input Parameter:
226: . viewer - The PetscViewer
228: Output Parameter:
229: . vecSeen - The flag which indicates whether we have viewed a vector
231: Level: advanced
233: .seealso: PetscViewerVUGetVecSeen()
234: @*/
235: PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
236: {
237: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
242: *vecSeen = vu->vecSeen;
243: return(0);
244: }
246: /*@C
247: PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
249: Not Collective
251: Input Parameters:
252: + viewer - The PetscViewer
253: - format - The format string
255: Level: intermediate
257: .seealso: PetscViewerVUFlushDeferred()
258: @*/
259: PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
260: {
261: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
262: va_list Argp;
263: size_t fullLength;
264: PrintfQueue next;
268: PetscNew(&next);
269: if (vu->queue) {
270: vu->queue->next = next;
271: vu->queue = next;
272: vu->queue->next = NULL;
273: } else {
274: vu->queueBase = vu->queue = next;
275: }
276: vu->queueLength++;
278: va_start(Argp, format);
279: PetscArrayzero(next->string,QUEUESTRINGSIZE);
280: PetscVSNPrintf(next->string, QUEUESTRINGSIZE,format,&fullLength, Argp);
281: va_end(Argp);
282: return(0);
283: }
285: /*@C
286: PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
288: Not Collective
290: Input Parameter:
291: . viewer - The PetscViewer
293: Level: intermediate
295: .seealso: PetscViewerVUPrintDeferred()
296: @*/
297: PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer)
298: {
299: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
300: PrintfQueue next = vu->queueBase;
301: PrintfQueue previous;
302: int i;
306: for (i = 0; i < vu->queueLength; i++) {
307: PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string);
308: previous = next;
309: next = next->next;
310: PetscFree(previous);
311: }
312: vu->queue = NULL;
313: vu->queueLength = 0;
314: return(0);
315: }