xref: /petsc/src/sys/classes/viewer/impls/vu/petscvu.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer) {
123   PetscViewer_VU *vu;
124 
125   PetscFunctionBegin;
126   PetscCall(PetscNewLog(viewer, &vu));
127   viewer->data = (void *)vu;
128 
129   viewer->ops->destroy          = PetscViewerDestroy_VU;
130   viewer->ops->flush            = PetscViewerFlush_VU;
131   viewer->ops->getsubviewer     = NULL;
132   viewer->ops->restoresubviewer = NULL;
133 
134   vu->fd          = NULL;
135   vu->mode        = FILE_MODE_WRITE;
136   vu->filename    = NULL;
137   vu->vecSeen     = PETSC_FALSE;
138   vu->queue       = NULL;
139   vu->queueBase   = NULL;
140   vu->queueLength = 0;
141 
142   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_VU));
143   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_VU));
144   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_VU));
145   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_VU));
146   PetscFunctionReturn(0);
147 }
148 
149 /*@C
150   PetscViewerVUGetPointer - Extracts the file pointer from a VU PetscViewer.
151 
152   Not Collective
153 
154   Input Parameter:
155 . viewer - The PetscViewer
156 
157   Output Parameter:
158 . fd     - The file pointer
159 
160   Level: intermediate
161 
162 .seealso: `PetscViewerASCIIGetPointer()`
163 @*/
164 PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd) {
165   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
166 
167   PetscFunctionBegin;
168   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
169   PetscValidPointer(fd, 2);
170   *fd = vu->fd;
171   PetscFunctionReturn(0);
172 }
173 
174 /*@C
175   PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
176   a vector. This is usually called internally rather than by a user.
177 
178   Not Collective
179 
180   Input Parameters:
181 + viewer  - The PetscViewer
182 - vecSeen - The flag which indicates whether we have viewed a vector
183 
184   Level: advanced
185 
186 .seealso: `PetscViewerVUGetVecSeen()`
187 @*/
188 PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen) {
189   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
190 
191   PetscFunctionBegin;
192   vu->vecSeen = vecSeen;
193   PetscFunctionReturn(0);
194 }
195 
196 /*@C
197   PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
198   a vector. This is usually called internally rather than by a user.
199 
200   Not Collective
201 
202   Input Parameter:
203 . viewer  - The PetscViewer
204 
205   Output Parameter:
206 . vecSeen - The flag which indicates whether we have viewed a vector
207 
208   Level: advanced
209 
210 .seealso: `PetscViewerVUGetVecSeen()`
211 @*/
212 PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen) {
213   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
214 
215   PetscFunctionBegin;
216   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
217   PetscValidBoolPointer(vecSeen, 2);
218   *vecSeen = vu->vecSeen;
219   PetscFunctionReturn(0);
220 }
221 
222 /*@C
223   PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.
224 
225   Not Collective
226 
227   Input Parameters:
228 + viewer - The PetscViewer
229 - format - The format string
230 
231   Level: intermediate
232 
233 .seealso: `PetscViewerVUFlushDeferred()`
234 @*/
235 PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...) {
236   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
237   va_list         Argp;
238   size_t          fullLength;
239   PrintfQueue     next;
240 
241   PetscFunctionBegin;
242   PetscCall(PetscNew(&next));
243   if (vu->queue) {
244     vu->queue->next = next;
245     vu->queue       = next;
246     vu->queue->next = NULL;
247   } else {
248     vu->queueBase = vu->queue = next;
249   }
250   vu->queueLength++;
251 
252   va_start(Argp, format);
253   PetscCall(PetscArrayzero(next->string, QUEUESTRINGSIZE));
254   PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE, format, &fullLength, Argp));
255   va_end(Argp);
256   PetscFunctionReturn(0);
257 }
258 
259 /*@C
260   PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.
261 
262   Not Collective
263 
264   Input Parameter:
265 . viewer - The PetscViewer
266 
267   Level: intermediate
268 
269 .seealso: `PetscViewerVUPrintDeferred()`
270 @*/
271 PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer) {
272   PetscViewer_VU *vu   = (PetscViewer_VU *)viewer->data;
273   PrintfQueue     next = vu->queueBase;
274   PrintfQueue     previous;
275   int             i;
276 
277   PetscFunctionBegin;
278   for (i = 0; i < vu->queueLength; i++) {
279     PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string);
280     previous = next;
281     next     = next->next;
282     PetscCall(PetscFree(previous));
283   }
284   vu->queue       = NULL;
285   vu->queueLength = 0;
286   PetscFunctionReturn(0);
287 }
288