Actual source code: binv.c

  1: /*$Id: binv.c,v 1.99 2001/04/10 19:34:06 bsmith Exp $*/

 3:  #include src/sys/src/viewer/viewerimpl.h
 4:  #include petscsys.h
  5: #include <fcntl.h>
  6: #if defined(PETSC_HAVE_UNISTD_H)
  7: #include <unistd.h>
  8: #endif
  9: #if defined (PETSC_HAVE_IO_H)
 10: #include <io.h>
 11: #endif

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

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

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

 42: #undef __FUNCT__  
 44: int PetscViewerRestoreSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
 45: {
 46:   int           ierr,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: }

 58: #undef __FUNCT__  
 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: int PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
 85: {
 86:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

 93: #undef __FUNCT__  
 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: int PetscViewerBinarySkipInfo(PetscViewer viewer)
115: {
116:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

123: #undef __FUNCT__  
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: int PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
148: {
149:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

156: #undef __FUNCT__  
158: int PetscViewerDestroy_Binary(PetscViewer v)
159: {
160:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
161:   int                ierr,rank;

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

186: #undef __FUNCT__  
188: /*@C
189:    PetscViewerBinaryOpen - Opens a file for binary input/output.

191:    Collective on MPI_Comm

193:    Input Parameters:
194: +  comm - MPI communicator
195: .  name - name of file 
196: -  type - type of file
197: $    PETSC_BINARY_CREATE - create new file for binary output
198: $    PETSC_BINARY_RDONLY - open existing file for binary input
199: $    PETSC_BINARY_WRONLY - open existing file for binary output

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

204:    Level: beginner

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

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

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

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

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

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

242: #undef __FUNCT__  
244: /*@C
245:      PetscViewerBinarySetType - Sets the type of binary file to be open

247:     Collective on PetscViewer

249:   Input Parameters:
250: +  viewer - the PetscViewer; must be a binary PetscViewer
251: -  type - type of file
252: $    PETSC_BINARY_CREATE - create new file for binary output
253: $    PETSC_BINARY_RDONLY - open existing file for binary input
254: $    PETSC_BINARY_WRONLY - open existing file for binary output

256:   Level: advanced

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

260: @*/
261: int PetscViewerBinarySetType(PetscViewer viewer,PetscViewerBinaryType type)
262: {
263:   int ierr,(*f)(PetscViewer,PetscViewerBinaryType);

267:   PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerBinarySetType_C",(void (**)(void))&f);
268:   if (f) {
269:     (*f)(viewer,type);
270:   }

272:   return(0);
273: }

275: EXTERN_C_BEGIN
276: #undef __FUNCT__  
278: int PetscViewerBinarySetType_Binary(PetscViewer viewer,PetscViewerBinaryType type)
279: {
280:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

288: #undef __FUNCT__  
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: int PetscViewerBinaryLoadInfo(PetscViewer viewer)
303: {
304:   FILE       *file;
305:   char       string[256],*first,*second,*final;
306:   int        len,ierr;
307:   PetscTruth flg;
308:   PetscToken *token;

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

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

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

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

354: }

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

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

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

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

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

396:   /* only first processor opens file if writeable */
397:   if (!rank || type == PETSC_BINARY_RDONLY) {

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

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

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

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

492: EXTERN_C_BEGIN
493: #undef __FUNCT__  
495: int PetscViewerCreate_Binary(PetscViewer v)
496: {
497:   int                ierr;
498:   PetscViewer_Binary *vbinary;

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

515:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFilename_C",
516:                                     "PetscViewerSetFilename_Binary",
517:                                      PetscViewerSetFilename_Binary);
518:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerBinarySetType_C",
519:                                     "PetscViewerBinarySetType_Binary",
520:                                      PetscViewerBinarySetType_Binary);
521:   return(0);
522: }
523: EXTERN_C_END


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

533: /*MC
534:   PETSC_VIEWER_BINARY_WORLD  - same as PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD)

536:   Level: intermediate
537: M*/

539: /*MC
540:   PETSC_VIEWER_BINARY_SELF  - same as PETSC_VIEWER_BINARY_(PETSC_COMM_SELF)

542:   Level: intermediate
543: M*/


546: #undef __FUNCT__  
548: /*@C
549:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors 
550:                      in a communicator.

552:      Collective on MPI_Comm

554:      Input Parameter:
555: .    comm - the MPI communicator to share the binary PetscViewer
556:     
557:      Level: intermediate

559:    Options Database Keys:
560: $    -viewer_binary_filename <name>

562:    Environmental variables:
563: -   PETSC_VIEWER_BINARY_FILENAME

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

570: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
571:           PetscViewerDestroy()
572: @*/
573: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
574: {
575:   int         ierr;
576:   PetscTruth  flg;
577:   PetscViewer viewer;
578:   char        fname[PETSC_MAX_PATH_LEN];

581:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
582:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
583:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
584:   }
585:   MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int *)&flg);
586:   if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
587:   if (!flg) { /* PetscViewer not yet created */
588:     PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
589:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
590:     if (!flg) {
591:       PetscStrcpy(fname,"binaryoutput");
592:       if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
593:     }
594:     PetscViewerBinaryOpen(comm,fname,PETSC_BINARY_CREATE,&viewer);
595:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
596:     PetscObjectRegisterDestroy((PetscObject)viewer);
597:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_STDOUT_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
598:     MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
599:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
600:   }
601:   PetscFunctionReturn(viewer);
602: }