xref: /petsc/src/sys/classes/viewer/impls/vu/petscvu.c (revision ebead697dbf761eb322f829370bbe90b3bd93fa3)
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 
25   PetscFunctionBegin;
26   if (vu->vecSeen) {
27     PetscCall(PetscViewerVUPrintDeferred(viewer, "};\n\n"));
28   }
29   PetscCall(PetscViewerVUFlushDeferred(viewer));
30   PetscCall(PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd));
31   vu->fd = NULL;
32   PetscCall(PetscFree(vu->filename));
33   PetscFunctionReturn(0);
34 }
35 
36 PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
37 {
38   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
39 
40   PetscFunctionBegin;
41   PetscCall(PetscViewerFileClose_VU(viewer));
42   PetscCall(PetscFree(vu));
43   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL));
44   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL));
45   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL));
46   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetMode_C",NULL));
47   PetscFunctionReturn(0);
48 }
49 
50 PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
51 {
52   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
53   PetscMPIInt    rank;
54   int            err;
55 
56   PetscFunctionBegin;
57   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
58   if (rank == 0) {
59     err = fflush(vu->fd);
60     PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
61   }
62   PetscFunctionReturn(0);
63 }
64 
65 static PetscErrorCode  PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
66 {
67   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
68 
69   PetscFunctionBegin;
70   vu->mode = mode;
71   PetscFunctionReturn(0);
72 }
73 
74 static PetscErrorCode  PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
75 {
76   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
77 
78   PetscFunctionBegin;
79   *type = vu->mode;
80   PetscFunctionReturn(0);
81 }
82 
83 static PetscErrorCode  PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
84 {
85   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
86 
87   PetscFunctionBegin;
88   *name = vu->filename;
89   PetscFunctionReturn(0);
90 }
91 
92 static PetscErrorCode  PetscViewerFileSetName_VU(PetscViewer viewer, const char name[])
93 {
94   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
95   char           fname[PETSC_MAX_PATH_LEN];
96   int            rank;
97 
98   PetscFunctionBegin;
99   if (!name) PetscFunctionReturn(0);
100   PetscCall(PetscViewerFileClose_VU(viewer));
101   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
102   if (rank != 0) PetscFunctionReturn(0);
103   PetscCall(PetscStrallocpy(name, &vu->filename));
104   PetscCall(PetscFixFilename(name, fname));
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       PetscCall(fseek(vu->fd, 0, SEEK_END));
127     }
128     break;
129   default:
130     SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[vu->mode]);
131   }
132 
133   PetscCheck(vu->fd,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 
144   PetscFunctionBegin;
145   PetscCall(PetscNewLog(viewer,&vu));
146   viewer->data = (void*) vu;
147 
148   viewer->ops->destroy          = PetscViewerDestroy_VU;
149   viewer->ops->flush            = PetscViewerFlush_VU;
150   viewer->ops->getsubviewer     = NULL;
151   viewer->ops->restoresubviewer = NULL;
152 
153   vu->fd          = NULL;
154   vu->mode        = FILE_MODE_WRITE;
155   vu->filename    = NULL;
156   vu->vecSeen     = PETSC_FALSE;
157   vu->queue       = NULL;
158   vu->queueBase   = NULL;
159   vu->queueLength = 0;
160 
161   PetscCall(PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_VU));
162   PetscCall(PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_VU));
163   PetscCall(PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_VU));
164   PetscCall(PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_VU));
165   PetscFunctionReturn(0);
166 }
167 
168 /*@C
169   PetscViewerVUGetPointer - Extracts the file pointer from a VU PetscViewer.
170 
171   Not Collective
172 
173   Input Parameter:
174 . viewer - The PetscViewer
175 
176   Output Parameter:
177 . fd     - The file pointer
178 
179   Level: intermediate
180 
181 .seealso: `PetscViewerASCIIGetPointer()`
182 @*/
183 PetscErrorCode  PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
184 {
185   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
186 
187   PetscFunctionBegin;
188   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
189   PetscValidPointer(fd,2);
190   *fd = vu->fd;
191   PetscFunctionReturn(0);
192 }
193 
194 /*@C
195   PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
196   a vector. This is usually called internally rather than by a user.
197 
198   Not Collective
199 
200   Input Parameters:
201 + viewer  - The PetscViewer
202 - vecSeen - The flag which indicates whether we have viewed a vector
203 
204   Level: advanced
205 
206 .seealso: `PetscViewerVUGetVecSeen()`
207 @*/
208 PetscErrorCode  PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
209 {
210   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
211 
212   PetscFunctionBegin;
213   vu->vecSeen = vecSeen;
214   PetscFunctionReturn(0);
215 }
216 
217 /*@C
218   PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
219   a vector. This is usually called internally rather than by a user.
220 
221   Not Collective
222 
223   Input Parameter:
224 . viewer  - The PetscViewer
225 
226   Output Parameter:
227 . vecSeen - The flag which indicates whether we have viewed a vector
228 
229   Level: advanced
230 
231 .seealso: `PetscViewerVUGetVecSeen()`
232 @*/
233 PetscErrorCode  PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool  *vecSeen)
234 {
235   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
236 
237   PetscFunctionBegin;
238   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
239   PetscValidBoolPointer(vecSeen,2);
240   *vecSeen = vu->vecSeen;
241   PetscFunctionReturn(0);
242 }
243 
244 /*@C
245   PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
246 
247   Not Collective
248 
249   Input Parameters:
250 + viewer - The PetscViewer
251 - format - The format string
252 
253   Level: intermediate
254 
255 .seealso: `PetscViewerVUFlushDeferred()`
256 @*/
257 PetscErrorCode  PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
258 {
259   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
260   va_list        Argp;
261   size_t         fullLength;
262   PrintfQueue    next;
263 
264   PetscFunctionBegin;
265   PetscCall(PetscNew(&next));
266   if (vu->queue) {
267     vu->queue->next = next;
268     vu->queue       = next;
269     vu->queue->next = NULL;
270   } else {
271     vu->queueBase   = vu->queue = next;
272   }
273   vu->queueLength++;
274 
275   va_start(Argp, format);
276   PetscCall(PetscArrayzero(next->string,QUEUESTRINGSIZE));
277   PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE,format,&fullLength, Argp));
278   va_end(Argp);
279   PetscFunctionReturn(0);
280 }
281 
282 /*@C
283   PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
284 
285   Not Collective
286 
287   Input Parameter:
288 . viewer - The PetscViewer
289 
290   Level: intermediate
291 
292 .seealso: `PetscViewerVUPrintDeferred()`
293 @*/
294 PetscErrorCode  PetscViewerVUFlushDeferred(PetscViewer viewer)
295 {
296   PetscViewer_VU *vu  = (PetscViewer_VU*) viewer->data;
297   PrintfQueue    next = vu->queueBase;
298   PrintfQueue    previous;
299   int            i;
300 
301   PetscFunctionBegin;
302   for (i = 0; i < vu->queueLength; i++) {
303     PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string);
304     previous = next;
305     next     = next->next;
306     PetscCall(PetscFree(previous));
307   }
308   vu->queue       = NULL;
309   vu->queueLength = 0;
310   PetscFunctionReturn(0);
311 }
312