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