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