xref: /petsc/src/sys/classes/viewer/impls/vu/petscvu.c (revision 37d05b0256c1e9ba4bc423c4eccb3df226931ef0) !
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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
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(PETSC_SUCCESS);
98   PetscCall(PetscViewerFileClose_VU(viewer));
99   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
100   if (rank != 0) PetscFunctionReturn(PETSC_SUCCESS);
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 {
124       int ret = fseek(vu->fd, 0, SEEK_END);
125       PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
126     }
127     break;
128   default:
129     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vu->mode]);
130   }
131 
132   PetscCheck(vu->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
133 #if defined(PETSC_USE_LOG)
134   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
135 #endif
136   PetscFunctionReturn(PETSC_SUCCESS);
137 }
138 
139 /*MC
140    PETSCVIEWERVU - A viewer that prints to a VU file
141 
142   Level: beginner
143 
144 .seealso: [](sec_viewers), `PetscViewerVUFlushDeferred()`, `PetscViewerVUGetPointer()`, `PetscViewerVUSetVecSeen()`, `PetscViewerVUGetVecSeen()`,
145           `PetscViewerVUPrintDeferred()`, `PetscViewerVUFlushDeferred()`
146 M*/
147 PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
148 {
149   PetscViewer_VU *vu;
150 
151   PetscFunctionBegin;
152   PetscCall(PetscNew(&vu));
153   viewer->data = (void *)vu;
154 
155   viewer->ops->destroy          = PetscViewerDestroy_VU;
156   viewer->ops->flush            = PetscViewerFlush_VU;
157   viewer->ops->getsubviewer     = NULL;
158   viewer->ops->restoresubviewer = NULL;
159 
160   vu->fd          = NULL;
161   vu->mode        = FILE_MODE_WRITE;
162   vu->filename    = NULL;
163   vu->vecSeen     = PETSC_FALSE;
164   vu->queue       = NULL;
165   vu->queueBase   = NULL;
166   vu->queueLength = 0;
167 
168   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_VU));
169   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_VU));
170   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_VU));
171   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_VU));
172   PetscFunctionReturn(PETSC_SUCCESS);
173 }
174 
175 /*@C
176   PetscViewerVUGetPointer - Extracts the file pointer from a `PETSCVIEWERVU` `PetscViewer`.
177 
178   Not Collective
179 
180   Input Parameter:
181 . viewer - The `PetscViewer`
182 
183   Output Parameter:
184 . fd     - The file pointer
185 
186   Level: intermediate
187 
188 .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerASCIIGetPointer()`
189 @*/
190 PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
191 {
192   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
193 
194   PetscFunctionBegin;
195   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
196   PetscValidPointer(fd, 2);
197   *fd = vu->fd;
198   PetscFunctionReturn(PETSC_SUCCESS);
199 }
200 
201 /*@C
202   PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
203   a vector. This is usually called internally rather than by a user.
204 
205   Not Collective
206 
207   Input Parameters:
208 + viewer  - The `PETSCVIEWERVU` `PetscViewer`
209 - vecSeen - The flag which indicates whether we have viewed a vector
210 
211   Level: developer
212 
213 .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
214 @*/
215 PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
216 {
217   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
218 
219   PetscFunctionBegin;
220   vu->vecSeen = vecSeen;
221   PetscFunctionReturn(PETSC_SUCCESS);
222 }
223 
224 /*@C
225   PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
226   a vector. This is usually called internally rather than by a user.
227 
228   Not Collective
229 
230   Input Parameter:
231 . viewer  - The `PETSCVIEWERVU` `PetscViewer`
232 
233   Output Parameter:
234 . vecSeen - The flag which indicates whether we have viewed a vector
235 
236   Level: advanced
237 
238 .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
239 @*/
240 PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
241 {
242   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
243 
244   PetscFunctionBegin;
245   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
246   PetscValidBoolPointer(vecSeen, 2);
247   *vecSeen = vu->vecSeen;
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@C
252   PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
253 
254   Not Collective
255 
256   Input Parameters:
257 + viewer - The `PETSCVIEWERVU` `PetscViewer`
258 - format - The format string
259 
260   Level: intermediate
261 
262 .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUFlushDeferred()`
263 @*/
264 PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
265 {
266   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
267   va_list         Argp;
268   size_t          fullLength;
269   PrintfQueue     next;
270 
271   PetscFunctionBegin;
272   PetscCall(PetscNew(&next));
273   if (vu->queue) {
274     vu->queue->next = next;
275     vu->queue       = next;
276     vu->queue->next = NULL;
277   } else {
278     vu->queueBase = vu->queue = next;
279   }
280   vu->queueLength++;
281 
282   va_start(Argp, format);
283   PetscCall(PetscArrayzero(next->string, QUEUESTRINGSIZE));
284   PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE, format, &fullLength, Argp));
285   va_end(Argp);
286   PetscFunctionReturn(PETSC_SUCCESS);
287 }
288 
289 /*@C
290   PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
291 
292   Not Collective
293 
294   Input Parameter:
295 . viewer - The `PETSCVIEWERVU` `PetscViewer`
296 
297   Level: intermediate
298 
299 .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUPrintDeferred()`
300 @*/
301 PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer)
302 {
303   PetscViewer_VU *vu   = (PetscViewer_VU *)viewer->data;
304   PrintfQueue     next = vu->queueBase;
305   PrintfQueue     previous;
306   int             i;
307 
308   PetscFunctionBegin;
309   for (i = 0; i < vu->queueLength; i++) {
310     PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string));
311     previous = next;
312     next     = next->next;
313     PetscCall(PetscFree(previous));
314   }
315   vu->queue       = NULL;
316   vu->queueLength = 0;
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319