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;

 27:   if (vu->vecSeen) {
 28:     PetscViewerVUPrintDeferred(viewer, "};\n\n");
 29:   }
 30:   PetscViewerVUFlushDeferred(viewer);
 31:   PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd);
 32:   vu->fd = NULL;
 33:   PetscFree(vu->filename);
 34:   return(0);
 35: }

 37: PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer)
 38: {
 39:   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;

 43:   PetscViewerFileClose_VU(viewer);
 44:   PetscFree(vu);
 45:   return(0);
 46: }

 48: PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer)
 49: {
 50:   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
 51:   PetscMPIInt    rank;
 52:   int            err;

 56:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
 57:   if (!rank) {
 58:     err = fflush(vu->fd);
 59:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
 60:   }
 61:   return(0);
 62: }

 64: static PetscErrorCode  PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode)
 65: {
 66:   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;

 69:   vu->mode = mode;
 70:   return(0);
 71: }

 73: static PetscErrorCode  PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type)
 74: {
 75:   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;

 78:   *type = vu->mode;
 79:   return(0);
 80: }

 82: static PetscErrorCode  PetscViewerFileGetName_VU(PetscViewer viewer, const char **name)
 83: {
 84:   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;

 87:   *name = vu->filename;
 88:   return(0);
 89: }

 91: static PetscErrorCode  PetscViewerFileSetName_VU(PetscViewer viewer, const char name[])
 92: {
 93:   PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data;
 94:   char           fname[PETSC_MAX_PATH_LEN];
 95:   int            rank;

 99:   if (!name) return(0);
100:   PetscViewerFileClose_VU(viewer);
101:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
102:   if (rank != 0) return(0);
103:   PetscStrallocpy(name, &vu->filename);
104:   PetscFixFilename(name, fname);
105:   switch (vu->mode) {
106:   case FILE_MODE_READ:
107:     vu->fd = fopen(fname, "r");
108:     break;
109:   case FILE_MODE_WRITE:
110:     vu->fd = fopen(fname, "w");
111:     break;
112:   case FILE_MODE_APPEND:
113:     vu->fd = fopen(fname, "a");
114:     break;
115:   case FILE_MODE_UPDATE:
116:     vu->fd = fopen(fname, "r+");
117:     if (!vu->fd) vu->fd = fopen(fname, "w+");
118:     break;
119:   case FILE_MODE_APPEND_UPDATE:
120:     /* I really want a file which is opened at the end for updating,
121:        not a+, which opens at the beginning, but makes writes at the end.
122:     */
123:     vu->fd = fopen(fname, "r+");
124:     if (!vu->fd) vu->fd = fopen(fname, "w+");
125:     else {
126:       fseek(vu->fd, 0, SEEK_END);
127:     }
128:     break;
129:   default:
130:     SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[vu->mode]);
131:   }

133:   if (!vu->fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname);
134: #if defined(PETSC_USE_LOG)
135:   PetscLogObjectState((PetscObject) viewer, "File: %s", name);
136: #endif
137:   return(0);
138: }

140: PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer)
141: {
142:   PetscViewer_VU *vu;

146:   PetscNewLog(viewer,&vu);
147:   viewer->data = (void*) vu;

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

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

162:   PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_VU);
163:   PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_VU);
164:   PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_VU);
165:   PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_VU);
166:   return(0);
167: }

169: /*@C
170:   PetscViewerVUGetPointer - Extracts the file pointer from a VU PetscViewer.

172:   Not Collective

174:   Input Parameter:
175: . viewer - The PetscViewer

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

180:   Level: intermediate


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

192:   *fd = vu->fd;
193:   return(0);
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 PetscViewer
204: - vecSeen - The flag which indicates whether we have viewed a vector

206:   Level: advanced

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

215:   vu->vecSeen = vecSeen;
216:   return(0);
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 PetscViewer

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

231:   Level: advanced

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

242:   *vecSeen = vu->vecSeen;
243:   return(0);
244: }

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

249:   Not Collective

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

255:   Level: intermediate

257: .seealso: 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;

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

278:   va_start(Argp, format);
279:   PetscArrayzero(next->string,QUEUESTRINGSIZE);
280:   PetscVSNPrintf(next->string, QUEUESTRINGSIZE,format,&fullLength, Argp);
281:   va_end(Argp);
282:   return(0);
283: }

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

288:   Not Collective

290:   Input Parameter:
291: . viewer - The PetscViewer

293:   Level: intermediate

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

306:   for (i = 0; i < vu->queueLength; i++) {
307:     PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string);
308:     previous = next;
309:     next     = next->next;
310:     PetscFree(previous);
311:   }
312:   vu->queue       = NULL;
313:   vu->queueLength = 0;
314:   return(0);
315: }