xref: /petsc/src/sys/classes/viewer/impls/vu/petscvu.c (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc) !
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) PetscCall(PetscViewerVUPrintDeferred(viewer, "};\n\n"));
27   PetscCall(PetscViewerVUFlushDeferred(viewer));
28   PetscCall(PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd));
29   vu->fd = NULL;
30   PetscCall(PetscFree(vu->filename));
31   PetscFunctionReturn(0);
32 }
33 
34 PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
35 {
36   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
37 
38   PetscFunctionBegin;
39   PetscCall(PetscViewerFileClose_VU(viewer));
40   PetscCall(PetscFree(vu));
41   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
42   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
43   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
44   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
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 
54   PetscFunctionBegin;
55   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
56   if (rank == 0) {
57     err = fflush(vu->fd);
58     PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
59   }
60   PetscFunctionReturn(0);
61 }
62 
63 static PetscErrorCode PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
64 {
65   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
66 
67   PetscFunctionBegin;
68   vu->mode = mode;
69   PetscFunctionReturn(0);
70 }
71 
72 static PetscErrorCode PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
73 {
74   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
75 
76   PetscFunctionBegin;
77   *type = vu->mode;
78   PetscFunctionReturn(0);
79 }
80 
81 static PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
82 {
83   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
84 
85   PetscFunctionBegin;
86   *name = vu->filename;
87   PetscFunctionReturn(0);
88 }
89 
90 static PetscErrorCode PetscViewerFileSetName_VU(PetscViewer viewer, const char name[])
91 {
92   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
93   char            fname[PETSC_MAX_PATH_LEN];
94   int             rank;
95 
96   PetscFunctionBegin;
97   if (!name) PetscFunctionReturn(0);
98   PetscCall(PetscViewerFileClose_VU(viewer));
99   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
100   if (rank != 0) PetscFunctionReturn(0);
101   PetscCall(PetscStrallocpy(name, &vu->filename));
102   PetscCall(PetscFixFilename(name, fname));
103   switch (vu->mode) {
104   case FILE_MODE_READ:
105     vu->fd = fopen(fname, "r");
106     break;
107   case FILE_MODE_WRITE:
108     vu->fd = fopen(fname, "w");
109     break;
110   case FILE_MODE_APPEND:
111     vu->fd = fopen(fname, "a");
112     break;
113   case FILE_MODE_UPDATE:
114     vu->fd = fopen(fname, "r+");
115     if (!vu->fd) vu->fd = fopen(fname, "w+");
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) vu->fd = fopen(fname, "w+");
123     else PetscCall(fseek(vu->fd, 0, SEEK_END));
124     break;
125   default:
126     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vu->mode]);
127   }
128 
129   PetscCheck(vu->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
130 #if defined(PETSC_USE_LOG)
131   PetscLogObjectState((PetscObject)viewer, "File: %s", name);
132 #endif
133   PetscFunctionReturn(0);
134 }
135 
136 /*MC
137    PETSCVIEWERVU - A viewer that prints to a VU file
138 
139   Level: beginner
140 
141 .seealso: `PetscViewerVUFlushDeferred()`, `PetscViewerVUGetPointer()`, `PetscViewerVUSetVecSeen()`, `PetscViewerVUGetVecSeen()`,
142           `PetscViewerVUPrintDeferred()`, `PetscViewerVUFlushDeferred()`
143 M*/
144 PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
145 {
146   PetscViewer_VU *vu;
147 
148   PetscFunctionBegin;
149   PetscCall(PetscNew(&vu));
150   viewer->data = (void *)vu;
151 
152   viewer->ops->destroy          = PetscViewerDestroy_VU;
153   viewer->ops->flush            = PetscViewerFlush_VU;
154   viewer->ops->getsubviewer     = NULL;
155   viewer->ops->restoresubviewer = NULL;
156 
157   vu->fd          = NULL;
158   vu->mode        = FILE_MODE_WRITE;
159   vu->filename    = NULL;
160   vu->vecSeen     = PETSC_FALSE;
161   vu->queue       = NULL;
162   vu->queueBase   = NULL;
163   vu->queueLength = 0;
164 
165   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_VU));
166   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_VU));
167   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_VU));
168   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_VU));
169   PetscFunctionReturn(0);
170 }
171 
172 /*@C
173   PetscViewerVUGetPointer - Extracts the file pointer from a `PETSCVIEWERVU` `PetscViewer`.
174 
175   Not Collective
176 
177   Input Parameter:
178 . viewer - The `PetscViewer`
179 
180   Output Parameter:
181 . fd     - The file pointer
182 
183   Level: intermediate
184 
185 .seealso: `PETSCVIEWERVU`, `PetscViewerASCIIGetPointer()`
186 @*/
187 PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
188 {
189   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
190 
191   PetscFunctionBegin;
192   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
193   PetscValidPointer(fd, 2);
194   *fd = vu->fd;
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 `PETSCVIEWERVU` `PetscViewer`
206 - vecSeen - The flag which indicates whether we have viewed a vector
207 
208   Level: developer
209 
210 .seealso: `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
211 @*/
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 `PETSCVIEWERVU` `PetscViewer`
229 
230   Output Parameter:
231 . vecSeen - The flag which indicates whether we have viewed a vector
232 
233   Level: advanced
234 
235 .seealso: `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
236 @*/
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   PetscValidBoolPointer(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 `PETSCVIEWERVU` `PetscViewer`
255 - format - The format string
256 
257   Level: intermediate
258 
259 .seealso: `PETSCVIEWERVU`, `PetscViewerVUFlushDeferred()`
260 @*/
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 
268   PetscFunctionBegin;
269   PetscCall(PetscNew(&next));
270   if (vu->queue) {
271     vu->queue->next = next;
272     vu->queue       = next;
273     vu->queue->next = NULL;
274   } else {
275     vu->queueBase = vu->queue = next;
276   }
277   vu->queueLength++;
278 
279   va_start(Argp, format);
280   PetscCall(PetscArrayzero(next->string, QUEUESTRINGSIZE));
281   PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE, format, &fullLength, Argp));
282   va_end(Argp);
283   PetscFunctionReturn(0);
284 }
285 
286 /*@C
287   PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
288 
289   Not Collective
290 
291   Input Parameter:
292 . viewer - The `PETSCVIEWERVU` `PetscViewer`
293 
294   Level: intermediate
295 
296 .seealso: `PETSCVIEWERVU`, `PetscViewerVUPrintDeferred()`
297 @*/
298 PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer)
299 {
300   PetscViewer_VU *vu   = (PetscViewer_VU *)viewer->data;
301   PrintfQueue     next = vu->queueBase;
302   PrintfQueue     previous;
303   int             i;
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     PetscCall(PetscFree(previous));
311   }
312   vu->queue       = NULL;
313   vu->queueLength = 0;
314   PetscFunctionReturn(0);
315 }
316