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