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 == 0) {
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
182: .seealso: PetscViewerASCIIGetPointer()
183: @*/
184: PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
185: {
186: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
191: *fd = vu->fd;
192: return(0);
193: }
195: /*@C
196: PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
197: a vector. This is usually called internally rather than by a user.
199: Not Collective
201: Input Parameters:
202: + viewer - The PetscViewer
203: - vecSeen - The flag which indicates whether we have viewed a vector
205: Level: advanced
207: .seealso: PetscViewerVUGetVecSeen()
208: @*/
209: PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
210: {
211: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
214: vu->vecSeen = vecSeen;
215: return(0);
216: }
218: /*@C
219: PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
220: a vector. This is usually called internally rather than by a user.
222: Not Collective
224: Input Parameter:
225: . viewer - The PetscViewer
227: Output Parameter:
228: . vecSeen - The flag which indicates whether we have viewed a vector
230: Level: advanced
232: .seealso: PetscViewerVUGetVecSeen()
233: @*/
234: PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
235: {
236: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
241: *vecSeen = vu->vecSeen;
242: return(0);
243: }
245: /*@C
246: PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
248: Not Collective
250: Input Parameters:
251: + viewer - The PetscViewer
252: - format - The format string
254: Level: intermediate
256: .seealso: PetscViewerVUFlushDeferred()
257: @*/
258: PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
259: {
260: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
261: va_list Argp;
262: size_t fullLength;
263: PrintfQueue next;
267: PetscNew(&next);
268: if (vu->queue) {
269: vu->queue->next = next;
270: vu->queue = next;
271: vu->queue->next = NULL;
272: } else {
273: vu->queueBase = vu->queue = next;
274: }
275: vu->queueLength++;
277: va_start(Argp, format);
278: PetscArrayzero(next->string,QUEUESTRINGSIZE);
279: PetscVSNPrintf(next->string, QUEUESTRINGSIZE,format,&fullLength, Argp);
280: va_end(Argp);
281: return(0);
282: }
284: /*@C
285: PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
287: Not Collective
289: Input Parameter:
290: . viewer - The PetscViewer
292: Level: intermediate
294: .seealso: PetscViewerVUPrintDeferred()
295: @*/
296: PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer)
297: {
298: PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
299: PrintfQueue next = vu->queueBase;
300: PrintfQueue previous;
301: int i;
305: for (i = 0; i < vu->queueLength; i++) {
306: PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string);
307: previous = next;
308: next = next->next;
309: PetscFree(previous);
310: }
311: vu->queue = NULL;
312: vu->queueLength = 0;
313: return(0);
314: }