1
2 #include <petsc/private/viewerimpl.h> /*I "petscsys.h" I*/
3
4 #define QUEUESTRINGSIZE 1024
5
6 typedef struct _PrintfQueue *PrintfQueue;
7 struct _PrintfQueue {
8 char string[QUEUESTRINGSIZE];
9 PrintfQueue next;
10 };
11
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;
20
PetscViewerFileClose_VU(PetscViewer viewer)21 static PetscErrorCode PetscViewerFileClose_VU(PetscViewer viewer)
22 {
23 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
24 PetscErrorCode ierr;
25
26 PetscFunctionBegin;
27 if (vu->vecSeen) {
28 ierr = PetscViewerVUPrintDeferred(viewer, "};\n\n");CHKERRQ(ierr);
29 }
30 ierr = PetscViewerVUFlushDeferred(viewer);CHKERRQ(ierr);
31 ierr = PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd);CHKERRQ(ierr);
32 vu->fd = NULL;
33 ierr = PetscFree(vu->filename);CHKERRQ(ierr);
34 PetscFunctionReturn(0);
35 }
36
PetscViewerDestroy_VU(PetscViewer viewer)37 PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
38 {
39 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
40 PetscErrorCode ierr;
41
42 PetscFunctionBegin;
43 ierr = PetscViewerFileClose_VU(viewer);CHKERRQ(ierr);
44 ierr = PetscFree(vu);CHKERRQ(ierr);
45 PetscFunctionReturn(0);
46 }
47
PetscViewerFlush_VU(PetscViewer viewer)48 PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
49 {
50 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
51 PetscMPIInt rank;
52 int err;
53 PetscErrorCode ierr;
54
55 PetscFunctionBegin;
56 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr);
57 if (!rank) {
58 err = fflush(vu->fd);
59 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
60 }
61 PetscFunctionReturn(0);
62 }
63
PetscViewerFileGetName_VU(PetscViewer viewer,const char ** name)64 PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
65 {
66 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
67
68 PetscFunctionBegin;
69 *name = vu->filename;
70 PetscFunctionReturn(0);
71 }
72
PetscViewerFileSetName_VU(PetscViewer viewer,const char name[])73 PetscErrorCode PetscViewerFileSetName_VU(PetscViewer viewer, const char name[])
74 {
75 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
76 char fname[PETSC_MAX_PATH_LEN];
77 int rank;
78 PetscErrorCode ierr;
79
80 PetscFunctionBegin;
81 if (!name) PetscFunctionReturn(0);
82 ierr = PetscViewerFileClose_VU(viewer);CHKERRQ(ierr);
83 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr);
84 if (rank != 0) PetscFunctionReturn(0);
85 ierr = PetscStrallocpy(name, &vu->filename);CHKERRQ(ierr);
86 ierr = PetscFixFilename(name, fname);CHKERRQ(ierr);
87 switch (vu->mode) {
88 case FILE_MODE_READ:
89 vu->fd = fopen(fname, "r");
90 break;
91 case FILE_MODE_WRITE:
92 vu->fd = fopen(fname, "w");
93 break;
94 case FILE_MODE_APPEND:
95 vu->fd = fopen(fname, "a");
96 break;
97 case FILE_MODE_UPDATE:
98 vu->fd = fopen(fname, "r+");
99 if (!vu->fd) vu->fd = fopen(fname, "w+");
100 break;
101 case FILE_MODE_APPEND_UPDATE:
102 /* I really want a file which is opened at the end for updating,
103 not a+, which opens at the beginning, but makes writes at the end.
104 */
105 vu->fd = fopen(fname, "r+");
106 if (!vu->fd) vu->fd = fopen(fname, "w+");
107 else {
108 ierr = fseek(vu->fd, 0, SEEK_END);CHKERRQ(ierr);
109 }
110 break;
111 default:
112 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid file mode %d", vu->mode);
113 }
114
115 if (!vu->fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
116 #if defined(PETSC_USE_LOG)
117 PetscLogObjectState((PetscObject) viewer, "File: %s", name);
118 #endif
119 PetscFunctionReturn(0);
120 }
121
PetscViewerCreate_VU(PetscViewer viewer)122 PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
123 {
124 PetscViewer_VU *vu;
125 PetscErrorCode ierr;
126
127 PetscFunctionBegin;
128 ierr = PetscNewLog(viewer,&vu);CHKERRQ(ierr);
129 viewer->data = (void*) vu;
130
131 viewer->ops->destroy = PetscViewerDestroy_VU;
132 viewer->ops->flush = PetscViewerFlush_VU;
133 viewer->ops->getsubviewer = NULL;
134 viewer->ops->restoresubviewer = NULL;
135
136 vu->fd = NULL;
137 vu->mode = FILE_MODE_WRITE;
138 vu->filename = NULL;
139 vu->vecSeen = PETSC_FALSE;
140 vu->queue = NULL;
141 vu->queueBase = NULL;
142 vu->queueLength = 0;
143
144 ierr = PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_VU);CHKERRQ(ierr);
145 ierr = PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_VU);CHKERRQ(ierr);
146 PetscFunctionReturn(0);
147 }
148
149 /*@C
150 PetscViewerVUGetPointer - Extracts the file pointer from a VU PetscViewer.
151
152 Not Collective
153
154 Input Parameter:
155 . viewer - The PetscViewer
156
157 Output Parameter:
158 . fd - The file pointer
159
160 Level: intermediate
161
162
163 .seealso: PetscViewerASCIIGetPointer()
164 @*/
PetscViewerVUGetPointer(PetscViewer viewer,FILE ** fd)165 PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
166 {
167 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
168
169 PetscFunctionBegin;
170 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
171 PetscValidPointer(fd,2);
172 *fd = vu->fd;
173 PetscFunctionReturn(0);
174 }
175
176 /*@C
177 PetscViewerVUSetMode - Sets the mode in which to open the file.
178
179 Not Collective
180
181 Input Parameters:
182 + viewer - The PetscViewer
183 - mode - The file mode
184
185 Level: intermediate
186
187 .seealso: PetscViewerASCIISetMode()
188 @*/
PetscViewerVUSetMode(PetscViewer viewer,PetscFileMode mode)189 PetscErrorCode PetscViewerVUSetMode(PetscViewer viewer, PetscFileMode mode)
190 {
191 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
192
193 PetscFunctionBegin;
194 vu->mode = mode;
195 PetscFunctionReturn(0);
196 }
197
198 /*@C
199 PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
200 a vector. This is usually called internally rather than by a user.
201
202 Not Collective
203
204 Input Parameters:
205 + viewer - The PetscViewer
206 - vecSeen - The flag which indicates whether we have viewed a vector
207
208 Level: advanced
209
210 .seealso: PetscViewerVUGetVecSeen()
211 @*/
PetscViewerVUSetVecSeen(PetscViewer viewer,PetscBool vecSeen)212 PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
213 {
214 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
215
216 PetscFunctionBegin;
217 vu->vecSeen = vecSeen;
218 PetscFunctionReturn(0);
219 }
220
221 /*@C
222 PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
223 a vector. This is usually called internally rather than by a user.
224
225 Not Collective
226
227 Input Parameter:
228 . viewer - The PetscViewer
229
230 Output Parameter:
231 . vecSeen - The flag which indicates whether we have viewed a vector
232
233 Level: advanced
234
235 .seealso: PetscViewerVUGetVecSeen()
236 @*/
PetscViewerVUGetVecSeen(PetscViewer viewer,PetscBool * vecSeen)237 PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
238 {
239 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
240
241 PetscFunctionBegin;
242 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
243 PetscValidPointer(vecSeen,2);
244 *vecSeen = vu->vecSeen;
245 PetscFunctionReturn(0);
246 }
247
248 /*@C
249 PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
250
251 Not Collective
252
253 Input Parameters:
254 + viewer - The PetscViewer
255 - format - The format string
256
257 Level: intermediate
258
259 .seealso: PetscViewerVUFlushDeferred()
260 @*/
PetscViewerVUPrintDeferred(PetscViewer viewer,const char format[],...)261 PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
262 {
263 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
264 va_list Argp;
265 size_t fullLength;
266 PrintfQueue next;
267 PetscErrorCode ierr;
268
269 PetscFunctionBegin;
270 ierr = PetscNew(&next);CHKERRQ(ierr);
271 if (vu->queue) {
272 vu->queue->next = next;
273 vu->queue = next;
274 vu->queue->next = NULL;
275 } else {
276 vu->queueBase = vu->queue = next;
277 }
278 vu->queueLength++;
279
280 va_start(Argp, format);
281 ierr = PetscArrayzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr);
282 ierr = PetscVSNPrintf(next->string, QUEUESTRINGSIZE,format,&fullLength, Argp);CHKERRQ(ierr);
283 va_end(Argp);
284 PetscFunctionReturn(0);
285 }
286
287 /*@C
288 PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
289
290 Not Collective
291
292 Input Parameter:
293 . viewer - The PetscViewer
294
295 Level: intermediate
296
297 .seealso: PetscViewerVUPrintDeferred()
298 @*/
PetscViewerVUFlushDeferred(PetscViewer viewer)299 PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer)
300 {
301 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
302 PrintfQueue next = vu->queueBase;
303 PrintfQueue previous;
304 int i;
305 PetscErrorCode ierr;
306
307 PetscFunctionBegin;
308 for (i = 0; i < vu->queueLength; i++) {
309 PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string);
310 previous = next;
311 next = next->next;
312 ierr = PetscFree(previous);CHKERRQ(ierr);
313 }
314 vu->queue = NULL;
315 vu->queueLength = 0;
316 PetscFunctionReturn(0);
317 }
318