Actual source code: petscvu.c
1: #include <petsc/private/viewerimpl.h>
3: #define QUEUESTRINGSIZE 1024
5: typedef struct _PrintfQueue *PrintfQueue;
6: struct _PrintfQueue {
7: char string[QUEUESTRINGSIZE];
8: PrintfQueue next;
9: };
11: typedef struct {
12: FILE *fd;
13: PetscFileMode mode; /* The mode in which to open the file */
14: char *filename;
15: PetscBool vecSeen; /* The flag indicating whether any vector has been viewed so far */
16: PrintfQueue queue, queueBase;
17: int queueLength;
18: } PetscViewer_VU;
20: static PetscErrorCode PetscViewerFileClose_VU(PetscViewer viewer)
21: {
22: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
24: PetscFunctionBegin;
25: if (vu->vecSeen) PetscCall(PetscViewerVUPrintDeferred(viewer, "};\n\n"));
26: PetscCall(PetscViewerVUFlushDeferred(viewer));
27: PetscCall(PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd));
28: vu->fd = NULL;
29: PetscCall(PetscFree(vu->filename));
30: PetscFunctionReturn(PETSC_SUCCESS);
31: }
33: static PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
34: {
35: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
37: PetscFunctionBegin;
38: PetscCall(PetscViewerFileClose_VU(viewer));
39: PetscCall(PetscFree(vu));
40: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
41: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
42: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
43: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
44: PetscFunctionReturn(PETSC_SUCCESS);
45: }
47: static PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
48: {
49: PetscMPIInt rank;
51: PetscFunctionBegin;
52: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
53: if (rank == 0) PetscCall(PetscFFlush(((PetscViewer_VU *)viewer->data)->fd));
54: PetscFunctionReturn(PETSC_SUCCESS);
55: }
57: static PetscErrorCode PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
58: {
59: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
61: PetscFunctionBegin;
62: vu->mode = mode;
63: PetscFunctionReturn(PETSC_SUCCESS);
64: }
66: static PetscErrorCode PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
67: {
68: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
70: PetscFunctionBegin;
71: *type = vu->mode;
72: PetscFunctionReturn(PETSC_SUCCESS);
73: }
75: static PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
76: {
77: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
79: PetscFunctionBegin;
80: *name = vu->filename;
81: PetscFunctionReturn(PETSC_SUCCESS);
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: PetscFunctionBegin;
91: if (!name) PetscFunctionReturn(PETSC_SUCCESS);
92: PetscCall(PetscViewerFileClose_VU(viewer));
93: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
94: if (rank != 0) PetscFunctionReturn(PETSC_SUCCESS);
95: PetscCall(PetscStrallocpy(name, &vu->filename));
96: PetscCall(PetscFixFilename(name, fname));
97: switch (vu->mode) {
98: case FILE_MODE_READ:
99: vu->fd = fopen(fname, "r");
100: break;
101: case FILE_MODE_WRITE:
102: vu->fd = fopen(fname, "w");
103: break;
104: case FILE_MODE_APPEND:
105: vu->fd = fopen(fname, "a");
106: break;
107: case FILE_MODE_UPDATE:
108: vu->fd = fopen(fname, "r+");
109: if (!vu->fd) vu->fd = fopen(fname, "w+");
110: break;
111: case FILE_MODE_APPEND_UPDATE:
112: /* I really want a file which is opened at the end for updating,
113: not a+, which opens at the beginning, but makes writes at the end.
114: */
115: vu->fd = fopen(fname, "r+");
116: if (!vu->fd) vu->fd = fopen(fname, "w+");
117: else {
118: int ret = fseek(vu->fd, 0, SEEK_END);
119: PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
120: }
121: break;
122: default:
123: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vu->mode]);
124: }
126: PetscCheck(vu->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
127: PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
128: PetscFunctionReturn(PETSC_SUCCESS);
129: }
131: /*MC
132: PETSCVIEWERVU - A viewer that prints to a VU file
134: Level: beginner
136: .seealso: [](sec_viewers), `PetscViewerVUFlushDeferred()`, `PetscViewerVUGetPointer()`, `PetscViewerVUSetVecSeen()`, `PetscViewerVUGetVecSeen()`,
137: `PetscViewerVUPrintDeferred()`, `PetscViewerVUFlushDeferred()`
138: M*/
139: PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
140: {
141: PetscViewer_VU *vu;
143: PetscFunctionBegin;
144: PetscCall(PetscNew(&vu));
145: viewer->data = (void *)vu;
147: viewer->ops->destroy = PetscViewerDestroy_VU;
148: viewer->ops->flush = PetscViewerFlush_VU;
149: viewer->ops->getsubviewer = NULL;
150: viewer->ops->restoresubviewer = NULL;
152: vu->fd = NULL;
153: vu->mode = FILE_MODE_WRITE;
154: vu->filename = NULL;
155: vu->vecSeen = PETSC_FALSE;
156: vu->queue = NULL;
157: vu->queueBase = NULL;
158: vu->queueLength = 0;
160: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_VU));
161: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_VU));
162: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_VU));
163: PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_VU));
164: PetscFunctionReturn(PETSC_SUCCESS);
165: }
167: /*@C
168: PetscViewerVUGetPointer - Extracts the file pointer from a `PETSCVIEWERVU` `PetscViewer`.
170: Not Collective
172: Input Parameter:
173: . viewer - The `PetscViewer`
175: Output Parameter:
176: . fd - The file pointer
178: Level: intermediate
180: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerASCIIGetPointer()`
181: @*/
182: PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
183: {
184: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
186: PetscFunctionBegin;
188: PetscAssertPointer(fd, 2);
189: *fd = vu->fd;
190: PetscFunctionReturn(PETSC_SUCCESS);
191: }
193: /*@C
194: PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
195: a vector. This is usually called internally rather than by a user.
197: Not Collective
199: Input Parameters:
200: + viewer - The `PETSCVIEWERVU` `PetscViewer`
201: - vecSeen - The flag which indicates whether we have viewed a vector
203: Level: developer
205: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
206: @*/
207: PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
208: {
209: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
211: PetscFunctionBegin;
212: vu->vecSeen = vecSeen;
213: PetscFunctionReturn(PETSC_SUCCESS);
214: }
216: /*@C
217: PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
218: a vector. This is usually called internally rather than by a user.
220: Not Collective
222: Input Parameter:
223: . viewer - The `PETSCVIEWERVU` `PetscViewer`
225: Output Parameter:
226: . vecSeen - The flag which indicates whether we have viewed a vector
228: Level: advanced
230: .seealso: [](sec_viewers), `PETSCVIEWERVU`
231: @*/
232: PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
233: {
234: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
236: PetscFunctionBegin;
238: PetscAssertPointer(vecSeen, 2);
239: *vecSeen = vu->vecSeen;
240: PetscFunctionReturn(PETSC_SUCCESS);
241: }
243: /*@C
244: PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
246: Not Collective
248: Input Parameters:
249: + viewer - The `PETSCVIEWERVU` `PetscViewer`
250: - format - The format string
252: Level: intermediate
254: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUFlushDeferred()`
255: @*/
256: PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
257: {
258: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
259: va_list Argp;
260: size_t fullLength;
261: PrintfQueue next;
263: PetscFunctionBegin;
264: PetscCall(PetscNew(&next));
265: if (vu->queue) {
266: vu->queue->next = next;
267: vu->queue = next;
268: vu->queue->next = NULL;
269: } else {
270: vu->queueBase = vu->queue = next;
271: }
272: vu->queueLength++;
274: va_start(Argp, format);
275: PetscCall(PetscArrayzero(next->string, QUEUESTRINGSIZE));
276: PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE, format, &fullLength, Argp));
277: va_end(Argp);
278: PetscFunctionReturn(PETSC_SUCCESS);
279: }
281: /*@C
282: PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
284: Not Collective
286: Input Parameter:
287: . viewer - The `PETSCVIEWERVU` `PetscViewer`
289: Level: intermediate
291: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUPrintDeferred()`
292: @*/
293: PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer)
294: {
295: PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
296: PrintfQueue next = vu->queueBase;
297: PrintfQueue previous;
298: int i;
300: PetscFunctionBegin;
301: for (i = 0; i < vu->queueLength; i++) {
302: PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string));
303: previous = next;
304: next = next->next;
305: PetscCall(PetscFree(previous));
306: }
307: vu->queue = NULL;
308: vu->queueLength = 0;
309: PetscFunctionReturn(PETSC_SUCCESS);
310: }