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