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