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: PetscFunctionBegin;
26: if (vu->vecSeen) PetscCall(PetscViewerVUPrintDeferred(viewer, "};\n\n"));
27: PetscCall(PetscViewerVUFlushDeferred(viewer));
28: PetscCall(PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd));
29: vu->fd = NULL;
30: PetscCall(PetscFree(vu->filename));
31: PetscFunctionReturn(PETSC_SUCCESS);
32: }
34: PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
35: {
36: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
38: PetscFunctionBegin;
39: PetscCall(PetscViewerFileClose_VU(viewer));
40: PetscCall(PetscFree(vu));
41: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
42: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
43: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
44: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
45: PetscFunctionReturn(PETSC_SUCCESS);
46: }
48: PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
49: {
50: PetscMPIInt rank;
52: PetscFunctionBegin;
53: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
54: if (rank == 0) PetscCall(PetscFFlush(((PetscViewer_VU *)viewer->data)->fd));
55: PetscFunctionReturn(PETSC_SUCCESS);
56: }
58: static PetscErrorCode PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
59: {
60: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
62: PetscFunctionBegin;
63: vu->mode = mode;
64: PetscFunctionReturn(PETSC_SUCCESS);
65: }
67: static PetscErrorCode PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
68: {
69: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
71: PetscFunctionBegin;
72: *type = vu->mode;
73: PetscFunctionReturn(PETSC_SUCCESS);
74: }
76: static PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
77: {
78: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
80: PetscFunctionBegin;
81: *name = vu->filename;
82: PetscFunctionReturn(PETSC_SUCCESS);
83: }
85: static PetscErrorCode PetscViewerFileSetName_VU(PetscViewer viewer, const char name[])
86: {
87: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
88: char fname[PETSC_MAX_PATH_LEN];
89: int rank;
91: PetscFunctionBegin;
92: if (!name) PetscFunctionReturn(PETSC_SUCCESS);
93: PetscCall(PetscViewerFileClose_VU(viewer));
94: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
95: if (rank != 0) PetscFunctionReturn(PETSC_SUCCESS);
96: PetscCall(PetscStrallocpy(name, &vu->filename));
97: PetscCall(PetscFixFilename(name, fname));
98: switch (vu->mode) {
99: case FILE_MODE_READ:
100: vu->fd = fopen(fname, "r");
101: break;
102: case FILE_MODE_WRITE:
103: vu->fd = fopen(fname, "w");
104: break;
105: case FILE_MODE_APPEND:
106: vu->fd = fopen(fname, "a");
107: break;
108: case FILE_MODE_UPDATE:
109: vu->fd = fopen(fname, "r+");
110: if (!vu->fd) vu->fd = fopen(fname, "w+");
111: break;
112: case FILE_MODE_APPEND_UPDATE:
113: /* I really want a file which is opened at the end for updating,
114: not a+, which opens at the beginning, but makes writes at the end.
115: */
116: vu->fd = fopen(fname, "r+");
117: if (!vu->fd) vu->fd = fopen(fname, "w+");
118: else {
119: int ret = fseek(vu->fd, 0, SEEK_END);
120: PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
121: }
122: break;
123: default:
124: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vu->mode]);
125: }
127: PetscCheck(vu->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
128: #if defined(PETSC_USE_LOG)
129: PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
130: #endif
131: PetscFunctionReturn(PETSC_SUCCESS);
132: }
134: /*MC
135: PETSCVIEWERVU - A viewer that prints to a VU file
137: Level: beginner
139: .seealso: [](sec_viewers), `PetscViewerVUFlushDeferred()`, `PetscViewerVUGetPointer()`, `PetscViewerVUSetVecSeen()`, `PetscViewerVUGetVecSeen()`,
140: `PetscViewerVUPrintDeferred()`, `PetscViewerVUFlushDeferred()`
141: M*/
142: PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
143: {
144: PetscViewer_VU *vu;
146: PetscFunctionBegin;
147: PetscCall(PetscNew(&vu));
148: viewer->data = (void *)vu;
150: viewer->ops->destroy = PetscViewerDestroy_VU;
151: viewer->ops->flush = PetscViewerFlush_VU;
152: viewer->ops->getsubviewer = NULL;
153: viewer->ops->restoresubviewer = NULL;
155: vu->fd = NULL;
156: vu->mode = FILE_MODE_WRITE;
157: vu->filename = NULL;
158: vu->vecSeen = PETSC_FALSE;
159: vu->queue = NULL;
160: vu->queueBase = NULL;
161: vu->queueLength = 0;
163: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_VU));
164: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_VU));
165: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_VU));
166: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_VU));
167: PetscFunctionReturn(PETSC_SUCCESS);
168: }
170: /*@C
171: PetscViewerVUGetPointer - Extracts the file pointer from a `PETSCVIEWERVU` `PetscViewer`.
173: Not Collective
175: Input Parameter:
176: . viewer - The `PetscViewer`
178: Output Parameter:
179: . fd - The file pointer
181: Level: intermediate
183: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerASCIIGetPointer()`
184: @*/
185: PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
186: {
187: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
189: PetscFunctionBegin;
192: *fd = vu->fd;
193: PetscFunctionReturn(PETSC_SUCCESS);
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 `PETSCVIEWERVU` `PetscViewer`
204: - vecSeen - The flag which indicates whether we have viewed a vector
206: Level: developer
208: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
209: @*/
210: PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
211: {
212: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
214: PetscFunctionBegin;
215: vu->vecSeen = vecSeen;
216: PetscFunctionReturn(PETSC_SUCCESS);
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 `PETSCVIEWERVU` `PetscViewer`
228: Output Parameter:
229: . vecSeen - The flag which indicates whether we have viewed a vector
231: Level: advanced
233: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
234: @*/
235: PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
236: {
237: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
239: PetscFunctionBegin;
242: *vecSeen = vu->vecSeen;
243: PetscFunctionReturn(PETSC_SUCCESS);
244: }
246: /*@C
247: PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
249: Not Collective
251: Input Parameters:
252: + viewer - The `PETSCVIEWERVU` `PetscViewer`
253: - format - The format string
255: Level: intermediate
257: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `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;
266: PetscFunctionBegin;
267: PetscCall(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: PetscCall(PetscArrayzero(next->string, QUEUESTRINGSIZE));
279: PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE, format, &fullLength, Argp));
280: va_end(Argp);
281: PetscFunctionReturn(PETSC_SUCCESS);
282: }
284: /*@C
285: PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
287: Not Collective
289: Input Parameter:
290: . viewer - The `PETSCVIEWERVU` `PetscViewer`
292: Level: intermediate
294: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `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;
303: PetscFunctionBegin;
304: for (i = 0; i < vu->queueLength; i++) {
305: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string));
306: previous = next;
307: next = next->next;
308: PetscCall(PetscFree(previous));
309: }
310: vu->queue = NULL;
311: vu->queueLength = 0;
312: PetscFunctionReturn(PETSC_SUCCESS);
313: }