1 #include <petsc/private/viewerimpl.h> /*I "petscsys.h" I*/
2
3 #define QUEUESTRINGSIZE 1024
4
5 typedef struct _PrintfQueue *PrintfQueue;
6 struct _PrintfQueue {
7 char string[QUEUESTRINGSIZE];
8 PrintfQueue next;
9 };
10
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;
19
PetscViewerFileClose_VU(PetscViewer viewer)20 static PetscErrorCode PetscViewerFileClose_VU(PetscViewer viewer)
21 {
22 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
23
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 }
32
PetscViewerDestroy_VU(PetscViewer viewer)33 static PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
34 {
35 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
36
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 }
46
PetscViewerFlush_VU(PetscViewer viewer)47 static PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
48 {
49 PetscMPIInt rank;
50
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 }
56
PetscViewerFileSetMode_VU(PetscViewer viewer,PetscFileMode mode)57 static PetscErrorCode PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
58 {
59 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
60
61 PetscFunctionBegin;
62 vu->mode = mode;
63 PetscFunctionReturn(PETSC_SUCCESS);
64 }
65
PetscViewerFileGetMode_VU(PetscViewer viewer,PetscFileMode * type)66 static PetscErrorCode PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
67 {
68 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
69
70 PetscFunctionBegin;
71 *type = vu->mode;
72 PetscFunctionReturn(PETSC_SUCCESS);
73 }
74
PetscViewerFileGetName_VU(PetscViewer viewer,const char ** name)75 static PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
76 {
77 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
78
79 PetscFunctionBegin;
80 *name = vu->filename;
81 PetscFunctionReturn(PETSC_SUCCESS);
82 }
83
PetscViewerFileSetName_VU(PetscViewer viewer,const char name[])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;
89
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 }
125
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 }
130
131 /*MC
132 PETSCVIEWERVU - A viewer that prints to a VU file
133
134 Level: beginner
135
136 .seealso: [](sec_viewers), `PetscViewerVUFlushDeferred()`, `PetscViewerVUGetPointer()`, `PetscViewerVUSetVecSeen()`, `PetscViewerVUGetVecSeen()`,
137 `PetscViewerVUPrintDeferred()`, `PetscViewerVUFlushDeferred()`
138 M*/
PetscViewerCreate_VU(PetscViewer viewer)139 PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
140 {
141 PetscViewer_VU *vu;
142
143 PetscFunctionBegin;
144 PetscCall(PetscNew(&vu));
145 viewer->data = (void *)vu;
146
147 viewer->ops->destroy = PetscViewerDestroy_VU;
148 viewer->ops->flush = PetscViewerFlush_VU;
149 viewer->ops->getsubviewer = NULL;
150 viewer->ops->restoresubviewer = NULL;
151
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;
159
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 }
166
167 /*@C
168 PetscViewerVUGetPointer - Extracts the file pointer from a `PETSCVIEWERVU` `PetscViewer`.
169
170 Not Collective
171
172 Input Parameter:
173 . viewer - The `PetscViewer`
174
175 Output Parameter:
176 . fd - The file pointer
177
178 Level: intermediate
179
180 .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerASCIIGetPointer()`
181 @*/
PetscViewerVUGetPointer(PetscViewer viewer,FILE ** fd)182 PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
183 {
184 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
185
186 PetscFunctionBegin;
187 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
188 PetscAssertPointer(fd, 2);
189 *fd = vu->fd;
190 PetscFunctionReturn(PETSC_SUCCESS);
191 }
192
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.
196
197 Not Collective
198
199 Input Parameters:
200 + viewer - The `PETSCVIEWERVU` `PetscViewer`
201 - vecSeen - The flag which indicates whether we have viewed a vector
202
203 Level: developer
204
205 .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
206 @*/
PetscViewerVUSetVecSeen(PetscViewer viewer,PetscBool vecSeen)207 PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
208 {
209 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
210
211 PetscFunctionBegin;
212 vu->vecSeen = vecSeen;
213 PetscFunctionReturn(PETSC_SUCCESS);
214 }
215
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.
219
220 Not Collective
221
222 Input Parameter:
223 . viewer - The `PETSCVIEWERVU` `PetscViewer`
224
225 Output Parameter:
226 . vecSeen - The flag which indicates whether we have viewed a vector
227
228 Level: advanced
229
230 .seealso: [](sec_viewers), `PETSCVIEWERVU`
231 @*/
PetscViewerVUGetVecSeen(PetscViewer viewer,PetscBool * vecSeen)232 PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
233 {
234 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
235
236 PetscFunctionBegin;
237 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
238 PetscAssertPointer(vecSeen, 2);
239 *vecSeen = vu->vecSeen;
240 PetscFunctionReturn(PETSC_SUCCESS);
241 }
242
243 /*@C
244 PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
245
246 Not Collective
247
248 Input Parameters:
249 + viewer - The `PETSCVIEWERVU` `PetscViewer`
250 - format - The format string
251
252 Level: intermediate
253
254 .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUFlushDeferred()`
255 @*/
PetscViewerVUPrintDeferred(PetscViewer viewer,const char format[],...)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;
262
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++;
273
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 }
280
281 /*@C
282 PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
283
284 Not Collective
285
286 Input Parameter:
287 . viewer - The `PETSCVIEWERVU` `PetscViewer`
288
289 Level: intermediate
290
291 .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUPrintDeferred()`
292 @*/
PetscViewerVUFlushDeferred(PetscViewer viewer)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;
299
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 }
311