xref: /petsc/src/sys/classes/viewer/impls/vu/petscvu.c (revision 009bbdc485cd9ad46be9940d3549e2dde9cdc322)
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   PetscFunctionReturn(0);
137 }
138 EXTERN_C_END
139 
140 EXTERN_C_BEGIN
141 #undef __FUNCT__
142 #define __FUNCT__ "PetscViewerCreate_VU"
143 PetscErrorCode  PetscViewerCreate_VU(PetscViewer viewer)
144 {
145   PetscViewer_VU *vu;
146   PetscErrorCode ierr;
147 
148   PetscFunctionBegin;
149   ierr         = PetscNewLog(viewer,PetscViewer_VU, &vu);CHKERRQ(ierr);
150   viewer->data = (void*) vu;
151 
152   viewer->ops->destroy          = PetscViewerDestroy_VU;
153   viewer->ops->flush            = PetscViewerFlush_VU;
154   viewer->ops->getsingleton     = PETSC_NULL;
155   viewer->ops->restoresingleton = PETSC_NULL;
156   viewer->format                = PETSC_VIEWER_DEFAULT;
157   viewer->iformat               = 0;
158 
159   vu->fd          = PETSC_NULL;
160   vu->mode        = FILE_MODE_WRITE;
161   vu->filename    = PETSC_NULL;
162   vu->vecSeen     = PETSC_FALSE;
163   vu->queue       = PETSC_NULL;
164   vu->queueBase   = PETSC_NULL;
165   vu->queueLength = 0;
166 
167   ierr = PetscObjectComposeFunctionDynamic((PetscObject) viewer,"PetscViewerFileSetName_C", "PetscViewerFileSetName_VU",
168                                            PetscViewerFileSetName_VU);CHKERRQ(ierr);
169   ierr = PetscObjectComposeFunctionDynamic((PetscObject) viewer,"PetscViewerFileGetName_C", "PetscViewerFileGetName_VU",
170                                            PetscViewerFileGetName_VU);CHKERRQ(ierr);
171   PetscFunctionReturn(0);
172 }
173 EXTERN_C_END
174 
175 #undef __FUNCT__
176 #define __FUNCT__ "PetscViewerVUGetPointer"
177 /*@C
178   PetscViewerVUGetPointer - Extracts the file pointer from a VU PetscViewer.
179 
180   Not Collective
181 
182   Input Parameter:
183 . viewer - The PetscViewer
184 
185   Output Parameter:
186 . fd     - The file pointer
187 
188   Level: intermediate
189 
190   Concepts: PetscViewer^file pointer
191   Concepts: file pointer^getting from PetscViewer
192 
193 .seealso: PetscViewerASCIIGetPointer()
194 @*/
195 PetscErrorCode  PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
196 {
197   PetscViewer_VU *vu = (PetscViewer_VU *) viewer->data;
198 
199   PetscFunctionBegin;
200   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
201   PetscValidPointer(fd,2);
202   *fd = vu->fd;
203   PetscFunctionReturn(0);
204 }
205 
206 #undef __FUNCT__
207 #define __FUNCT__ "PetscViewerVUSetMode"
208 /*@C
209   PetscViewerVUSetMode - Sets the mode in which to open the file.
210 
211   Not Collective
212 
213   Input Parameters:
214 + viewer - The PetscViewer
215 - mode   - The file mode
216 
217   Level: intermediate
218 
219 .keywords: Viewer, file, get, pointer
220 .seealso: PetscViewerASCIISetMode()
221 @*/
222 PetscErrorCode  PetscViewerVUSetMode(PetscViewer viewer, PetscFileMode mode)
223 {
224   PetscViewer_VU *vu = (PetscViewer_VU *) viewer->data;
225 
226   PetscFunctionBegin;
227   vu->mode = mode;
228   PetscFunctionReturn(0);
229 }
230 
231 #undef __FUNCT__
232 #define __FUNCT__ "PetscViewerVUSetVecSeen"
233 /*@C
234   PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
235   a vector. This is usually called internally rather than by a user.
236 
237   Not Collective
238 
239   Input Parameters:
240 + viewer  - The PetscViewer
241 - vecSeen - The flag which indicates whether we have viewed a vector
242 
243   Level: advanced
244 
245 .keywords: Viewer, Vec
246 .seealso: PetscViewerVUGetVecSeen()
247 @*/
248 PetscErrorCode  PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool  vecSeen)
249 {
250   PetscViewer_VU *vu = (PetscViewer_VU *) viewer->data;
251 
252   PetscFunctionBegin;
253   vu->vecSeen = vecSeen;
254   PetscFunctionReturn(0);
255 }
256 
257 #undef __FUNCT__
258 #define __FUNCT__ "PetscViewerVUGetVecSeen"
259 /*@C
260   PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
261   a vector. This is usually called internally rather than by a user.
262 
263   Not Collective
264 
265   Input Parameter:
266 . viewer  - The PetscViewer
267 
268   Output Parameter:
269 . vecSeen - The flag which indicates whether we have viewed a vector
270 
271   Level: advanced
272 
273 .keywords: Viewer, Vec
274 .seealso: PetscViewerVUGetVecSeen()
275 @*/
276 PetscErrorCode  PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool  *vecSeen)
277 {
278   PetscViewer_VU *vu = (PetscViewer_VU *) viewer->data;
279 
280   PetscFunctionBegin;
281   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
282   PetscValidPointer(vecSeen,2);
283   *vecSeen = vu->vecSeen;
284   PetscFunctionReturn(0);
285 }
286 
287 #undef __FUNCT__
288 #define __FUNCT__ "PetscViewerVUPrintDeferred"
289 /*@C
290   PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
291 
292   Not Collective
293 
294   Input Parameters:
295 + viewer - The PetscViewer
296 - format - The format string
297 
298   Level: intermediate
299 
300 .keywords: Viewer, print, deferred
301 .seealso: PetscViewerVUFlushDeferred()
302 @*/
303 PetscErrorCode  PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
304 {
305   PetscViewer_VU *vu = (PetscViewer_VU *) viewer->data;
306   va_list        Argp;
307   size_t         fullLength;
308   PrintfQueue    next;
309   PetscErrorCode ierr;
310 
311   PetscFunctionBegin;
312   ierr = PetscNew(struct _PrintfQueue, &next);CHKERRQ(ierr);
313   if (vu->queue) {
314     vu->queue->next = next;
315     vu->queue       = next;
316     vu->queue->next = PETSC_NULL;
317   } else {
318     vu->queueBase   = vu->queue = next;
319   }
320   vu->queueLength++;
321 
322   va_start(Argp, format);
323   ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr);
324   ierr = PetscVSNPrintf(next->string, QUEUESTRINGSIZE,format,&fullLength, Argp);CHKERRQ(ierr);
325   va_end(Argp);
326   PetscFunctionReturn(0);
327 }
328 
329 #undef __FUNCT__
330 #define __FUNCT__ "PetscViewerVUFlushDeferred"
331 /*@C
332   PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
333 
334   Not Collective
335 
336   Input Parameter:
337 + viewer - The PetscViewer
338 
339   Level: intermediate
340 
341 .keywords: Viewer, flush, deferred
342 .seealso: PetscViewerVUPrintDeferred()
343 @*/
344 PetscErrorCode  PetscViewerVUFlushDeferred(PetscViewer viewer)
345 {
346   PetscViewer_VU *vu   = (PetscViewer_VU *) viewer->data;
347   PrintfQueue    next = vu->queueBase;
348   PrintfQueue    previous;
349   int            i;
350   PetscErrorCode ierr;
351 
352   PetscFunctionBegin;
353   for (i = 0; i < vu->queueLength; i++) {
354     PetscFPrintf(((PetscObject)viewer)->comm, vu->fd, "%s", next->string);
355     previous = next;
356     next     = next->next;
357     ierr     = PetscFree(previous);CHKERRQ(ierr);
358   }
359   vu->queue       = PETSC_NULL;
360   vu->queueLength = 0;
361   PetscFunctionReturn(0);
362 }
363