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