Actual source code: binv.c

  1: #include "src/sys/src/viewer/viewerimpl.h"    /*I   "petsc.h"   I*/
 2:  #include petscsys.h
  3: #include <fcntl.h>
  4: #if defined(PETSC_HAVE_UNISTD_H)
  5: #include <unistd.h>
  6: #endif
  7: #if defined (PETSC_HAVE_IO_H)
  8: #include <io.h>
  9: #endif

 11: typedef struct  {
 12:   int                   fdes;            /* file descriptor */
 13:   PetscViewerFileType btype;           /* read or write? */
 14:   FILE                  *fdes_info;      /* optional file containing info on binary file*/
 15:   PetscTruth            storecompressed; /* gzip the write binary file when closing it*/
 16:   char                  *filename;
 17:   PetscTruth            skipinfo;        /* Don't create info file for writing */
 18: } PetscViewer_Binary;

 22: PetscErrorCode PetscViewerGetSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
 23: {
 24:   int                rank;
 25:   PetscErrorCode     ierr;
 26:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data,*obinary;

 29:   MPI_Comm_rank(viewer->comm,&rank);
 30:   if (!rank) {
 31:     PetscViewerCreate(PETSC_COMM_SELF,outviewer);
 32:     PetscViewerSetType(*outviewer,PETSC_VIEWER_BINARY);
 33:     obinary = (PetscViewer_Binary*)(*outviewer)->data;
 34:     PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));
 35:   } else {
 36:     *outviewer = 0;
 37:   }
 38:   return(0);
 39: }

 43: PetscErrorCode PetscViewerRestoreSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
 44: {
 46:   PetscErrorCode rank;

 49:   MPI_Comm_rank(viewer->comm,&rank);
 50:   if (!rank) {
 51:     PetscFree((*outviewer)->data);
 52:     PetscLogObjectDestroy((PetscObject)*outviewer);
 53:     PetscHeaderDestroy((PetscObject)*outviewer);
 54:   }
 55:   return(0);
 56: }

 60: /*@C
 61:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

 63:     Not Collective

 65: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
 66: -   fdes - file descriptor

 68:     Level: advanced

 70:     Notes:
 71:       For writable binary PetscViewers, the descriptor will only be valid for the 
 72:     first processor in the communicator that shares the PetscViewer. For readable 
 73:     files it will only be valid on nodes that have the file. If node 0 does not
 74:     have the file it generates an error even if another node does have the file.
 75:  
 76:     Fortran Note:
 77:     This routine is not supported in Fortran.

 79:   Concepts: file descriptor^getting
 80:   Concepts: PetscViewerBinary^accessing file descriptor

 82: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
 83: @*/
 84: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
 85: {
 86:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

 89:   *fdes = vbinary->fdes;
 90:   return(0);
 91: }

 95: /*@
 96:     PetscViewerBinarySkipInfo - Binary file will not have .info file created with it

 98:     Not Collective

100:     Input Paramter:
101: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

103:     Options Database Key:
104: .   -viewer_binary_skip_info

106:     Level: advanced

108:     Notes: This must be called after PetscViewerSetType() but before PetscViewerBinarySetFilename()

110:    Concepts: PetscViewerBinary^accessing info file

112: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
113: @*/
114: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
115: {
116:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

119:   vbinary->skipinfo = PETSC_TRUE;
120:   return(0);
121: }

125: /*@C
126:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
127:           info file associated with a binary file.

129:     Not Collective

131: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
132: -   file - file pointer

134:     Level: advanced

136:     Notes:
137:       For writable binary PetscViewers, the descriptor will only be valid for the 
138:     first processor in the communicator that shares the PetscViewer.
139:  
140:     Fortran Note:
141:     This routine is not supported in Fortran.

143:   Concepts: PetscViewerBinary^accessing info file

145: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
146: @*/
147: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
148: {
149:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

152:   *file = vbinary->fdes_info;
153:   return(0);
154: }

158: PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
159: {
160:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
161:   PetscErrorCode     ierr;
162:   int                rank;

165:   MPI_Comm_rank(v->comm,&rank);
166:   if (!rank && vbinary->fdes) {
167:     close(vbinary->fdes);
168:     if (vbinary->storecompressed) {
169:       char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
170:       FILE *fp;
171:       /* compress the file */
172:       PetscStrcpy(par,"gzip ");
173:       PetscStrcat(par,vbinary->filename);
174:       PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,par,"r",&fp);
175:       if (fgets(buf,1024,fp)) {
176:         SETERRQ2(PETSC_ERR_LIB,"Error from command %s\n%s",par,buf);
177:       }
178:       PetscPClose(PETSC_COMM_SELF,fp);
179:     }
180:   }
181:   if (vbinary->fdes_info) fclose(vbinary->fdes_info);
182:   PetscStrfree(vbinary->filename);
183:   PetscFree(vbinary);
184:   return(0);
185: }

189: /*@C
190:    PetscViewerBinaryOpen - Opens a file for binary input/output.

192:    Collective on MPI_Comm

194:    Input Parameters:
195: +  comm - MPI communicator
196: .  name - name of file 
197: -  type - type of file
198: $    PETSC_FILE_CREATE - create new file for binary output
199: $    PETSC_FILE_RDONLY - open existing file for binary input
200: $    PETSC_FILE_WRONLY - open existing file for binary output

202:    Output Parameter:
203: .  binv - PetscViewer for binary input/output to use with the specified file

205:    Level: beginner

207:    Note:
208:    This PetscViewer should be destroyed with PetscViewerDestroy().

210:     For reading files, the filename may begin with ftp:// or http:// and/or
211:     end with .gz; in this case file is brought over and uncompressed.

213:     For creating files, if the file name ends with .gz it is automatically 
214:     compressed when closed.

216:     For writing files it only opens the file on processor 0 in the communicator.
217:     For readable files it opens the file on all nodes that have the file. If 
218:     node 0 does not have the file it generates an error even if other nodes
219:     do have the file.

221:    Concepts: binary files
222:    Concepts: PetscViewerBinary^creating
223:    Concepts: gzip
224:    Concepts: accessing remote file
225:    Concepts: remote file

227: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
228:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
229:           PetscViewerBinaryGetInfoPointer(), PetscViewerFileType, PetscViewer
230: @*/
231: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscViewerFileType type,PetscViewer *binv)
232: {
234: 
236:   PetscViewerCreate(comm,binv);
237:   PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
238:   PetscViewerSetFileType(*binv,type);
239:   PetscViewerSetFilename(*binv,name);
240:   return(0);
241: }

245: /*@C
246:      PetscViewerSetFileType - Sets the type of file to be open

248:     Collective on PetscViewer

250:   Input Parameters:
251: +  viewer - the PetscViewer; must be a binary, Matlab, hdf, or netcdf PetscViewer
252: -  type - type of file
253: $    PETSC_FILE_CREATE - create new file for binary output
254: $    PETSC_FILE_RDONLY - open existing file for binary input
255: $    PETSC_FILE_WRONLY - open existing file for binary output

257:   Level: advanced

259: .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()

261: @*/
262: PetscErrorCode PetscViewerSetFileType(PetscViewer viewer,PetscViewerFileType type)
263: {
264:   PetscErrorCode ierr,(*f)(PetscViewer,PetscViewerFileType);

268:   PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerSetFileType_C",(void (**)(void))&f);
269:   if (f) {
270:     (*f)(viewer,type);
271:   }
272:   return(0);
273: }

278: PetscErrorCode PetscViewerSetFileType_Binary(PetscViewer viewer,PetscViewerFileType type)
279: {
280:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

283:   vbinary->btype = type;
284:   return(0);
285: }

290: /*@
291:     PetscViewerBinaryLoadInfo - Loads options from the name.info file
292:        if it exists.

294:    Collective on PetscViewer

296:   Input Parameter:
297: .    viewer - the binary viewer whose options you wish to load

299:    Level: developer

301: @*/
302: PetscErrorCode PetscViewerBinaryLoadInfo(PetscViewer viewer)
303: {
304:   FILE           *file;
305:   char           string[256],*first,*second,*final;
306:   size_t         len;
308:   PetscTruth     flg;
309:   PetscToken     *token;

312:   PetscOptionsHasName(PETSC_NULL,"-load_ignore_info",&flg);
313:   if (flg) return(0);

315:   PetscViewerBinaryGetInfoPointer(viewer,&file);
316:   if (!file) return(0);

318:   /* read rows of the file adding them to options database */
319:   while (fgets(string,256,file)) {
320:     /* Comments are indicated by #, ! or % in the first column */
321:     if (string[0] == '#') continue;
322:     if (string[0] == '!') continue;
323:     if (string[0] == '%') continue;
324:     PetscTokenCreate(string,' ',&token);
325:     PetscTokenFind(token,&first);
326:     PetscTokenFind(token,&second);
327:     if (first && first[0] == '-') {
328:       PetscTruth wrongtype;
329:       /*
330:          Check for -mat_complex or -mat_double
331:       */
332: #if defined(PETSC_USE_COMPLEX)
333:       PetscStrncmp(first,"-mat_double",11,&wrongtype);
334:       if (wrongtype) {
335:         SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Loading double number matrix with complex number code");
336:       }
337: #else
338:       PetscStrncmp(first,"-mat_complex",12,&wrongtype);
339:       if (wrongtype) {
340:         SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Loading complex number matrix with double number code");
341:       }
342: #endif

344:       if (second) {final = second;} else {final = first;}
345:       PetscStrlen(final,&len);
346:       while (len > 0 && (final[len-1] == ' ' || final[len-1] == '\n')) {
347:         len--; final[len] = 0;
348:       }
349:       PetscOptionsSetValue(first,second);
350:     }
351:     PetscTokenDestroy(token);
352:   }
353:   return(0);
354: }

356: /*
357:         Actually opens the file 
358: */
362: PetscErrorCode PetscViewerSetFilename_Binary(PetscViewer viewer,const char name[])
363: {
364:   int                 rank;
365:   PetscErrorCode      ierr;
366:   size_t              len;
367:   PetscViewer_Binary  *vbinary = (PetscViewer_Binary*)viewer->data;
368:   const char          *fname;
369:   char                bname[PETSC_MAX_PATH_LEN],*gz;
370:   PetscTruth          found;
371:   PetscViewerFileType type = vbinary->btype;

374:   if (type == (PetscViewerFileType) -1) {
375:     SETERRQ(PETSC_ERR_ORDER,"Must call PetscViewerBinarySetType() before PetscViewerSetFilename()");
376:   }
377:   PetscOptionsHasName(viewer->prefix,"-viewer_binary_skip_info",&vbinary->skipinfo);

379:   MPI_Comm_rank(viewer->comm,&rank);

381:   /* copy name so we can edit it */
382:   PetscStrallocpy(name,&vbinary->filename);

384:   /* if ends in .gz strip that off and note user wants file compressed */
385:   vbinary->storecompressed = PETSC_FALSE;
386:   if (!rank && type == PETSC_FILE_CREATE) {
387:     /* remove .gz if it ends library name */
388:     PetscStrstr(vbinary->filename,".gz",&gz);
389:     if (gz) {
390:       PetscStrlen(gz,&len);
391:       if (len == 3) {
392:         *gz = 0;
393:         vbinary->storecompressed = PETSC_TRUE;
394:       }
395:     }
396:   }

398:   /* only first processor opens file if writeable */
399:   if (!rank || type == PETSC_FILE_RDONLY) {

401:     if (type == PETSC_FILE_RDONLY){
402:       /* possibly get the file from remote site or compressed file */
403:       PetscFileRetrieve(viewer->comm,vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
404:       fname = bname;
405:       if (!rank && !found) {
406:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
407:       } else if (!found) {
408:         PetscLogInfo(viewer,"Nonzero processor did not locate readonly file");
409:         fname = 0;
410:       }
411:     } else {
412:       fname = vbinary->filename;
413:     }

415: #if defined(PETSC_HAVE_O_BINARY)
416:     if (type == PETSC_FILE_CREATE) {
417:       if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
418:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
419:       }
420:     } else if (type == PETSC_FILE_RDONLY && fname) {
421:       if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) {
422:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
423:       }
424:     } else if (type == PETSC_FILE_WRONLY) {
425:       if ((vbinary->fdes = open(fname,O_WRONLY|O_BINARY,0)) == -1) {
426:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
427:       }
428:     } else if (fname) {
429:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
430:     }
431: #else
432:     if (type == PETSC_FILE_CREATE) {
433:       if ((vbinary->fdes = creat(fname,0666)) == -1) {
434:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
435:       }
436:     } else if (type == PETSC_FILE_RDONLY && fname) {
437:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) {
438:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
439:       }
440:     } else if (type == PETSC_FILE_WRONLY) {
441:       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND,0)) == -1) {
442:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
443:       }
444:     } else if (fname) {
445:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
446:     }
447: #endif
448:   } else vbinary->fdes = -1;
449:   viewer->format = PETSC_VIEWER_NOFORMAT;

451:   /* 
452:       try to open info file: all processors open this file if read only
453:   */
454:   if (!rank || type == PETSC_FILE_RDONLY) {
455:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
456: 
457:     PetscStrcpy(infoname,name);
458:     /* remove .gz if it ends library name */
459:     PetscStrstr(infoname,".gz",&gz);
460:     if (gz) {
461:       PetscStrlen(gz,&len);
462:       if (len == 3) {
463:         *gz = 0;
464:       }
465:     }
466: 
467:     PetscStrcat(infoname,".info");
468:     PetscFixFilename(infoname,iname);
469:     if (type == PETSC_FILE_RDONLY) {
470:       PetscFileRetrieve(viewer->comm,iname,infoname,PETSC_MAX_PATH_LEN,&found);
471:       if (found) {
472:         vbinary->fdes_info = fopen(infoname,"r");
473:         if (vbinary->fdes_info) {
474:           PetscViewerBinaryLoadInfo(viewer);
475:           fclose(vbinary->fdes_info);
476:         }
477:         vbinary->fdes_info = fopen(infoname,"r");
478:       }
479:     } else if (!vbinary->skipinfo) {
480:       vbinary->fdes_info = fopen(infoname,"w");
481:       if (!vbinary->fdes_info) {
482:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
483:       }
484:     }
485:   }

487: #if defined(PETSC_USE_LOG)
488:   PetscLogObjectState((PetscObject)viewer,"File: %s",name);
489: #endif
490:   return(0);
491: }

497: PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
498: {
499:   PetscErrorCode     ierr;
500:   PetscViewer_Binary *vbinary;

503:   PetscNew(PetscViewer_Binary,&vbinary);
504:   v->data            = (void*)vbinary;
505:   v->ops->destroy    = PetscViewerDestroy_Binary;
506:   v->ops->flush      = 0;
507:   v->iformat         = 0;
508:   vbinary->fdes_info = 0;
509:   vbinary->fdes      = 0;
510:   vbinary->skipinfo  = PETSC_FALSE;
511:   v->ops->getsingleton     = PetscViewerGetSingleton_Binary;
512:   v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
513:   vbinary->btype           = (PetscViewerFileType) -1;
514:   vbinary->storecompressed = PETSC_FALSE;
515:   vbinary->filename        = 0;

517:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFilename_C",
518:                                     "PetscViewerSetFilename_Binary",
519:                                      PetscViewerSetFilename_Binary);
520:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFileType_C",
521:                                     "PetscViewerSetFileType_Binary",
522:                                      PetscViewerSetFileType_Binary);
523:   return(0);
524: }


528: /* ---------------------------------------------------------------------*/
529: /*
530:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
531:   is attached to a communicator, in this case the attribute is a PetscViewer.
532: */
533: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

537: /*@C
538:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors 
539:                      in a communicator.

541:      Collective on MPI_Comm

543:      Input Parameter:
544: .    comm - the MPI communicator to share the binary PetscViewer
545:     
546:      Level: intermediate

548:    Options Database Keys:
549: $    -viewer_binary_filename <name>

551:    Environmental variables:
552: -   PETSC_VIEWER_BINARY_FILENAME

554:      Notes:
555:      Unlike almost all other PETSc routines, PETSC_VIEWER_BINARY_ does not return 
556:      an error code.  The binary PetscViewer is usually used in the form
557: $       XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));

559: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
560:           PetscViewerDestroy()
561: @*/
562: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
563: {
565:   PetscTruth     flg;
566:   PetscViewer    viewer;
567:   char           fname[PETSC_MAX_PATH_LEN];

570:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
571:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
572:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
573:   }
574:   MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int*)&flg);
575:   if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
576:   if (!flg) { /* PetscViewer not yet created */
577:     PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
578:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
579:     if (!flg) {
580:       PetscStrcpy(fname,"binaryoutput");
581:       if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
582:     }
583:     PetscViewerBinaryOpen(comm,fname,PETSC_FILE_CREATE,&viewer);
584:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
585:     PetscObjectRegisterDestroy((PetscObject)viewer);
586:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
587:     MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
588:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
589:   }
590:   PetscFunctionReturn(viewer);
591: }