Actual source code: petscvu.c

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

  3: #define QUEUESTRINGSIZE 1024

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

 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;

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

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

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

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

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

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

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

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

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

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

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

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

 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;

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

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

131: /*MC
132:    PETSCVIEWERVU - A viewer that prints to a VU file

134:   Level: beginner

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

143:   PetscFunctionBegin;
144:   PetscCall(PetscNew(&vu));
145:   viewer->data = (void *)vu;

147:   viewer->ops->destroy          = PetscViewerDestroy_VU;
148:   viewer->ops->flush            = PetscViewerFlush_VU;
149:   viewer->ops->getsubviewer     = NULL;
150:   viewer->ops->restoresubviewer = NULL;

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;

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

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

170:   Not Collective

172:   Input Parameter:
173: . viewer - The `PetscViewer`

175:   Output Parameter:
176: . fd - The file pointer

178:   Level: intermediate

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

186:   PetscFunctionBegin;
188:   PetscAssertPointer(fd, 2);
189:   *fd = vu->fd;
190:   PetscFunctionReturn(PETSC_SUCCESS);
191: }

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.

197:   Not Collective

199:   Input Parameters:
200: + viewer  - The `PETSCVIEWERVU` `PetscViewer`
201: - vecSeen - The flag which indicates whether we have viewed a vector

203:   Level: developer

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

211:   PetscFunctionBegin;
212:   vu->vecSeen = vecSeen;
213:   PetscFunctionReturn(PETSC_SUCCESS);
214: }

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.

220:   Not Collective

222:   Input Parameter:
223: . viewer - The `PETSCVIEWERVU` `PetscViewer`

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

228:   Level: advanced

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

236:   PetscFunctionBegin;
238:   PetscAssertPointer(vecSeen, 2);
239:   *vecSeen = vu->vecSeen;
240:   PetscFunctionReturn(PETSC_SUCCESS);
241: }

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

246:   Not Collective

248:   Input Parameters:
249: + viewer - The `PETSCVIEWERVU` `PetscViewer`
250: - format - The format string

252:   Level: intermediate

254: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUFlushDeferred()`
255: @*/
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;

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++;

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

281: /*@C
282:   PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file.

284:   Not Collective

286:   Input Parameter:
287: . viewer - The `PETSCVIEWERVU` `PetscViewer`

289:   Level: intermediate

291: .seealso: [](sec_viewers), `PETSCVIEWERVU`, `PetscViewerVUPrintDeferred()`
292: @*/
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;

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