Actual source code: petscvu.c


  2: #include <petsc/private/viewerimpl.h>

  4: #define QUEUESTRINGSIZE 1024

  6: typedef struct _PrintfQueue *PrintfQueue;
  7: struct _PrintfQueue {
  8:   char        string[QUEUESTRINGSIZE];
  9:   PrintfQueue next;
 10: };

 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;

 21: static PetscErrorCode PetscViewerFileClose_VU(PetscViewer viewer)
 22: {
 23:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

 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: }

 34: PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
 35: {
 36:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

 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: }

 48: PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
 49: {
 50:   PetscMPIInt rank;

 52:   PetscFunctionBegin;
 53:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
 54:   if (rank == 0) PetscCall(PetscFFlush(((PetscViewer_VU *)viewer->data)->fd));
 55:   PetscFunctionReturn(PETSC_SUCCESS);
 56: }

 58: static PetscErrorCode PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
 59: {
 60:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

 62:   PetscFunctionBegin;
 63:   vu->mode = mode;
 64:   PetscFunctionReturn(PETSC_SUCCESS);
 65: }

 67: static PetscErrorCode PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
 68: {
 69:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

 71:   PetscFunctionBegin;
 72:   *type = vu->mode;
 73:   PetscFunctionReturn(PETSC_SUCCESS);
 74: }

 76: static PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
 77: {
 78:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

 80:   PetscFunctionBegin;
 81:   *name = vu->filename;
 82:   PetscFunctionReturn(PETSC_SUCCESS);
 83: }

 85: static PetscErrorCode PetscViewerFileSetName_VU(PetscViewer viewer, const char name[])
 86: {
 87:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
 88:   char            fname[PETSC_MAX_PATH_LEN];
 89:   int             rank;

 91:   PetscFunctionBegin;
 92:   if (!name) PetscFunctionReturn(PETSC_SUCCESS);
 93:   PetscCall(PetscViewerFileClose_VU(viewer));
 94:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
 95:   if (rank != 0) PetscFunctionReturn(PETSC_SUCCESS);
 96:   PetscCall(PetscStrallocpy(name, &vu->filename));
 97:   PetscCall(PetscFixFilename(name, fname));
 98:   switch (vu->mode) {
 99:   case FILE_MODE_READ:
100:     vu->fd = fopen(fname, "r");
101:     break;
102:   case FILE_MODE_WRITE:
103:     vu->fd = fopen(fname, "w");
104:     break;
105:   case FILE_MODE_APPEND:
106:     vu->fd = fopen(fname, "a");
107:     break;
108:   case FILE_MODE_UPDATE:
109:     vu->fd = fopen(fname, "r+");
110:     if (!vu->fd) vu->fd = fopen(fname, "w+");
111:     break;
112:   case FILE_MODE_APPEND_UPDATE:
113:     /* I really want a file which is opened at the end for updating,
114:        not a+, which opens at the beginning, but makes writes at the end.
115:     */
116:     vu->fd = fopen(fname, "r+");
117:     if (!vu->fd) vu->fd = fopen(fname, "w+");
118:     else {
119:       int ret = fseek(vu->fd, 0, SEEK_END);
120:       PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
121:     }
122:     break;
123:   default:
124:     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vu->mode]);
125:   }

127:   PetscCheck(vu->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
128: #if defined(PETSC_USE_LOG)
129:   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
130: #endif
131:   PetscFunctionReturn(PETSC_SUCCESS);
132: }

134: /*MC
135:    PETSCVIEWERVU - A viewer that prints to a VU file

137:   Level: beginner

139: .seealso: [](sec_viewers), `PetscViewerVUFlushDeferred()`, `PetscViewerVUGetPointer()`, `PetscViewerVUSetVecSeen()`, `PetscViewerVUGetVecSeen()`,
140:           `PetscViewerVUPrintDeferred()`, `PetscViewerVUFlushDeferred()`
141: M*/
142: PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
143: {
144:   PetscViewer_VU *vu;

146:   PetscFunctionBegin;
147:   PetscCall(PetscNew(&vu));
148:   viewer->data = (void *)vu;

150:   viewer->ops->destroy          = PetscViewerDestroy_VU;
151:   viewer->ops->flush            = PetscViewerFlush_VU;
152:   viewer->ops->getsubviewer     = NULL;
153:   viewer->ops->restoresubviewer = NULL;

155:   vu->fd          = NULL;
156:   vu->mode        = FILE_MODE_WRITE;
157:   vu->filename    = NULL;
158:   vu->vecSeen     = PETSC_FALSE;
159:   vu->queue       = NULL;
160:   vu->queueBase   = NULL;
161:   vu->queueLength = 0;

163:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_VU));
164:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_VU));
165:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_VU));
166:   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_VU));
167:   PetscFunctionReturn(PETSC_SUCCESS);
168: }

170: /*@C
171:   PetscViewerVUGetPointer - Extracts the file pointer from a `PETSCVIEWERVU` `PetscViewer`.

173:   Not Collective

175:   Input Parameter:
176: . viewer - The `PetscViewer`

178:   Output Parameter:
179: . fd     - The file pointer

181:   Level: intermediate

183: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerASCIIGetPointer()`
184: @*/
185: PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd)
186: {
187:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

189:   PetscFunctionBegin;
192:   *fd = vu->fd;
193:   PetscFunctionReturn(PETSC_SUCCESS);
194: }

196: /*@C
197:   PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed
198:   a vector. This is usually called internally rather than by a user.

200:   Not Collective

202:   Input Parameters:
203: + viewer  - The `PETSCVIEWERVU` `PetscViewer`
204: - vecSeen - The flag which indicates whether we have viewed a vector

206:   Level: developer

208: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
209: @*/
210: PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen)
211: {
212:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

214:   PetscFunctionBegin;
215:   vu->vecSeen = vecSeen;
216:   PetscFunctionReturn(PETSC_SUCCESS);
217: }

219: /*@C
220:   PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed
221:   a vector. This is usually called internally rather than by a user.

223:   Not Collective

225:   Input Parameter:
226: . viewer  - The `PETSCVIEWERVU` `PetscViewer`

228:   Output Parameter:
229: . vecSeen - The flag which indicates whether we have viewed a vector

231:   Level: advanced

233: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()`
234: @*/
235: PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen)
236: {
237:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;

239:   PetscFunctionBegin;
242:   *vecSeen = vu->vecSeen;
243:   PetscFunctionReturn(PETSC_SUCCESS);
244: }

246: /*@C
247:   PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file.

249:   Not Collective

251:   Input Parameters:
252: + viewer - The `PETSCVIEWERVU` `PetscViewer`
253: - format - The format string

255:   Level: intermediate

257: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUFlushDeferred()`
258: @*/
259: PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...)
260: {
261:   PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data;
262:   va_list         Argp;
263:   size_t          fullLength;
264:   PrintfQueue     next;

266:   PetscFunctionBegin;
267:   PetscCall(PetscNew(&next));
268:   if (vu->queue) {
269:     vu->queue->next = next;
270:     vu->queue       = next;
271:     vu->queue->next = NULL;
272:   } else {
273:     vu->queueBase = vu->queue = next;
274:   }
275:   vu->queueLength++;

277:   va_start(Argp, format);
278:   PetscCall(PetscArrayzero(next->string, QUEUESTRINGSIZE));
279:   PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE, format, &fullLength, Argp));
280:   va_end(Argp);
281:   PetscFunctionReturn(PETSC_SUCCESS);
282: }

284: /*@C
285:   PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.

287:   Not Collective

289:   Input Parameter:
290: . viewer - The `PETSCVIEWERVU` `PetscViewer`

292:   Level: intermediate

294: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUPrintDeferred()`
295: @*/
296: PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer)
297: {
298:   PetscViewer_VU *vu   = (PetscViewer_VU *)viewer->data;
299:   PrintfQueue     next = vu->queueBase;
300:   PrintfQueue     previous;
301:   int             i;

303:   PetscFunctionBegin;
304:   for (i = 0; i < vu->queueLength; i++) {
305:     PetscCall(PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string));
306:     previous = next;
307:     next     = next->next;
308:     PetscCall(PetscFree(previous));
309:   }
310:   vu->queue       = NULL;
311:   vu->queueLength = 0;
312:   PetscFunctionReturn(PETSC_SUCCESS);
313: }