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: int PetscViewerGetSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
 23: {
 24:   int                rank,ierr;
 25:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data,*obinary;

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

 40: int PetscViewerRestoreSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
 41: {
 42:   int           ierr,rank;

 45:   MPI_Comm_rank(viewer->comm,&rank);
 46:   if (!rank) {
 47:     PetscFree((*outviewer)->data);
 48:     PetscLogObjectDestroy((PetscObject)*outviewer);
 49:     PetscHeaderDestroy((PetscObject)*outviewer);
 50:   }
 51:   return(0);
 52: }

 54: /*@C
 55:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

 57:     Not Collective

 59: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
 60: -   fdes - file descriptor

 62:     Level: advanced

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

 73:   Concepts: file descriptor^getting
 74:   Concepts: PetscViewerBinary^accessing file descriptor

 76: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
 77: @*/
 78: int PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
 79: {
 80:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

 83:   *fdes = vbinary->fdes;
 84:   return(0);
 85: }

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

 90:     Not Collective

 92:     Input Paramter:
 93: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

 95:     Options Database:
 96: .   -viewer_binary_skip_info

 98:     Level: advanced

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

102:    Concepts: PetscViewerBinary^accessing info file

104: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
105: @*/
106: int PetscViewerBinarySkipInfo(PetscViewer viewer)
107: {
108:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

111:   vbinary->skipinfo = PETSC_TRUE;
112:   return(0);
113: }

115: /*@C
116:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
117:           info file associated with a binary file.

119:     Not Collective

121: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
122: -   file - file pointer

124:     Level: advanced

126:     Notes:
127:       For writable binary PetscViewers, the descriptor will only be valid for the 
128:     first processor in the communicator that shares the PetscViewer.
129:  
130:     Fortran Note:
131:     This routine is not supported in Fortran.

133:   Concepts: PetscViewerBinary^accessing info file

135: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
136: @*/
137: int PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
138: {
139:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

142:   *file = vbinary->fdes_info;
143:   return(0);
144: }

146: int PetscViewerDestroy_Binary(PetscViewer v)
147: {
148:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
149:   int                ierr,rank;

152:   MPI_Comm_rank(v->comm,&rank);
153:   if (!rank && vbinary->fdes) {
154:     close(vbinary->fdes);
155:     if (vbinary->storecompressed) {
156:       char par[1024],buf[1024];
157:       FILE *fp;
158:       /* compress the file */
159:       PetscStrcpy(par,"gzip ");
160:       PetscStrcat(par,vbinary->filename);
161:       PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,par,"r",&fp);
162:       if (fgets(buf,1024,fp)) {
163:         SETERRQ2(1,"Error from command %sn%s",par,buf);
164:       }
165:       PetscPClose(PETSC_COMM_SELF,fp);
166:     }
167:   }
168:   if (vbinary->fdes_info) fclose(vbinary->fdes_info);
169:   PetscStrfree(vbinary->filename);
170:   PetscFree(vbinary);
171:   return(0);
172: }

174: /*@C
175:    PetscViewerBinaryOpen - Opens a file for binary input/output.

177:    Collective on MPI_Comm

179:    Input Parameters:
180: +  comm - MPI communicator
181: .  name - name of file 
182: -  type - type of file
183: $    PETSC_BINARY_CREATE - create new file for binary output
184: $    PETSC_BINARY_RDONLY - open existing file for binary input
185: $    PETSC_BINARY_WRONLY - open existing file for binary output

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

190:    Level: beginner

192:    Note:
193:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

201:     For writing files it only opens the file on processor 0 in the communicator.
202:     For readable files it opens the file on all nodes that have the file. If 
203:     node 0 does not have the file it generates an error even if other nodes
204:     do have the file.

206:    Concepts: binary files
207:    Concepts: PetscViewerBinary^creating
208:    Concepts: gzip
209:    Concepts: accessing remote file
210:    Concepts: remote file

212: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
213:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
214:           PetscViewerBinaryGetInfoPointer()
215: @*/
216: int PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscViewerBinaryType type,PetscViewer *binv)
217: {
219: 
221:   PetscViewerCreate(comm,binv);
222:   PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
223:   PetscViewerBinarySetType(*binv,type);
224:   PetscViewerSetFilename(*binv,name);
225:   return(0);
226: }

228: /*@C
229:      PetscViewerBinarySetType - Sets the type of binary file to be open

231:     Collective on PetscViewer

233:   Input Parameters:
234: +  viewer - the PetscViewer; must be a binary PetscViewer
235: -  type - type of file
236: $    PETSC_BINARY_CREATE - create new file for binary output
237: $    PETSC_BINARY_RDONLY - open existing file for binary input
238: $    PETSC_BINARY_WRONLY - open existing file for binary output

240:   Level: advanced

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

244: @*/
245: int PetscViewerBinarySetType(PetscViewer viewer,PetscViewerBinaryType type)
246: {
247:   int ierr,(*f)(PetscViewer,PetscViewerBinaryType);

251:   PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerBinarySetType_C",(void (**)(void))&f);
252:   if (f) {
253:     (*f)(viewer,type);
254:   }

256:   return(0);
257: }

259: EXTERN_C_BEGIN
260: int PetscViewerBinarySetType_Binary(PetscViewer viewer,PetscViewerBinaryType type)
261: {
262:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

265:   vbinary->btype = type;
266:   return(0);
267: }
268: EXTERN_C_END

270: /*
271:     PetscViewerBinaryLoadInfo options from the name.info file
272:     if it exists.
273: */
274: int PetscViewerBinaryLoadInfo(PetscViewer viewer)
275: {
276:   FILE       *file;
277:   char       string[128],*first,*second,*final;
278:   int        len,ierr;
279:   PetscTruth flg;
280:   PetscToken *token;

283:   PetscOptionsHasName(PETSC_NULL,"-load_ignore_info",&flg);
284:   if (flg) return(0);

286:   PetscViewerBinaryGetInfoPointer(viewer,&file);
287:   if (!file) return(0);

289:   /* read rows of the file adding them to options database */
290:   while (fgets(string,128,file)) {
291:     /* Comments are indicated by #, ! or % in the first column */
292:     if (string[0] == '#') continue;
293:     if (string[0] == '!') continue;
294:     if (string[0] == '%') continue;
295:     PetscTokenCreate(string,' ',&token);
296:     PetscTokenFind(token,&first);
297:     PetscTokenFind(token,&second);
298:     if (first && first[0] == '-') {
299:       PetscTruth wrongtype;
300:       /*
301:          Check for -mat_complex or -mat_double
302:       */
303: #if defined(PETSC_USE_COMPLEX)
304:       PetscStrncmp(first,"-mat_double",11,&wrongtype);
305:       if (wrongtype) {
306:         SETERRQ(1,"Loading double number matrix with complex number code");
307:       }
308: #else
309:       PetscStrncmp(first,"-mat_complex",12,&wrongtype);
310:       if (wrongtype) {
311:         SETERRQ(1,"Loading complex number matrix with double number code");
312:       }
313: #endif

315:       if (second) {final = second;} else {final = first;}
316:       PetscStrlen(final,&len);
317:       while (len > 0 && (final[len-1] == ' ' || final[len-1] == 'n')) {
318:         len--; final[len] = 0;
319:       }
320:       PetscOptionsSetValue(first,second);
321:     }
322:     PetscTokenDestroy(token);
323:   }
324:   return(0);

326: }

328: /*
329:         Actually opens the file 
330: */
331: EXTERN_C_BEGIN
332: int PetscViewerSetFilename_Binary(PetscViewer viewer,const char name[])
333: {
334:   int                   rank,ierr,len;
335:   PetscViewer_Binary    *vbinary = (PetscViewer_Binary*)viewer->data;
336:   const char            *fname;
337:   char                  bname[1024],*gz;
338:   PetscTruth            found;
339:   PetscViewerBinaryType type = vbinary->btype;

342:   if (type == (PetscViewerBinaryType) -1) {
343:     SETERRQ(1,"Must call PetscViewerBinarySetType() before PetscViewerSetFilename()");
344:   }
345:   PetscOptionsHasName(viewer->prefix,"-viewer_binary_skip_info",&vbinary->skipinfo);

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

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

352:   /* if ends in .gz strip that off and note user wants file compressed */
353:   vbinary->storecompressed = PETSC_FALSE;
354:   if (!rank && type == PETSC_BINARY_CREATE) {
355:     /* remove .gz if it ends library name */
356:     PetscStrstr(vbinary->filename,".gz",&gz);
357:     if (gz) {
358:       PetscStrlen(gz,&len);
359:       if (len == 3) {
360:         *gz = 0;
361:         vbinary->storecompressed = PETSC_TRUE;
362:       }
363:     }
364:   }

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

369:     if (type == PETSC_BINARY_RDONLY){
370:       /* possibly get the file from remote site or compressed file */
371:       ierr  = PetscFileRetrieve(viewer->comm,vbinary->filename,bname,1024,&found);
372:       fname = bname;
373:       if (!rank && !found) {
374:         SETERRQ1(1,"Cannot locate file: %s on node zero",vbinary->filename);
375:       } else if (!found) {
376:         PetscLogInfo(viewer,"Nonzero processor did not locate readonly file");
377:         fname = 0;
378:       }
379:     } else {
380:       fname = vbinary->filename;
381:     }

383: #if defined(PARCH_win32_gnu) || defined(PARCH_win32) 
384:     if (type == PETSC_BINARY_CREATE) {
385:       if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
386:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
387:       }
388:     } else if (type == PETSC_BINARY_RDONLY && fname) {
389:       if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) {
390:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
391:       }
392:     } else if (type == PETSC_BINARY_WRONLY) {
393:       if ((vbinary->fdes = open(fname,O_WRONLY|O_BINARY,0)) == -1) {
394:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
395:       }
396:     } else if (fname) {
397:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
398:     }
399: #else
400:     if (type == PETSC_BINARY_CREATE) {
401:       if ((vbinary->fdes = creat(fname,0666)) == -1) {
402:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
403:       }
404:     } else if (type == PETSC_BINARY_RDONLY && fname) {
405:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) {
406:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
407:       }
408:     } else if (type == PETSC_BINARY_WRONLY) {
409:       if ((vbinary->fdes = open(fname,O_WRONLY,0)) == -1) {
410:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
411:       }
412:     } else if (fname) {
413:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
414:     }
415: #endif
416:   } else vbinary->fdes = -1;
417:   viewer->format = PETSC_VIEWER_NOFORMAT;

419:   /* 
420:       try to open info file: all processors open this file if read only
421:   */
422:   if (!rank || type == PETSC_BINARY_RDONLY) {
423:     char infoname[256],iname[256];
424: 
425:     PetscStrcpy(infoname,name);
426:     /* remove .gz if it ends library name */
427:     PetscStrstr(infoname,".gz",&gz);
428:     if (gz) {
429:       PetscStrlen(gz,&len);
430:       if (len == 3) {
431:         *gz = 0;
432:       }
433:     }
434: 
435:     PetscStrcat(infoname,".info");
436:     PetscFixFilename(infoname,iname);
437:     if (type == PETSC_BINARY_RDONLY) {
438:       PetscFileRetrieve(viewer->comm,iname,infoname,256,&found);
439:       if (found) {
440:         vbinary->fdes_info = fopen(infoname,"r");
441:         if (vbinary->fdes_info) {
442:           PetscViewerBinaryLoadInfo(viewer);
443:           fclose(vbinary->fdes_info);
444:         }
445:         vbinary->fdes_info = fopen(infoname,"r");
446:       }
447:     } else if (!vbinary->skipinfo) {
448:       vbinary->fdes_info = fopen(infoname,"w");
449:       if (!vbinary->fdes_info) {
450:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
451:       }
452:     }
453:   }

455: #if defined(PETSC_USE_LOG)
456:   PetscLogObjectState((PetscObject)viewer,"File: %s",name);
457: #endif
458:   return(0);
459: }
460: EXTERN_C_END

462: EXTERN_C_BEGIN
463: int PetscViewerCreate_Binary(PetscViewer v)
464: {
465:   int                ierr;
466:   PetscViewer_Binary *vbinary;

469:   ierr               = PetscNew(PetscViewer_Binary,&vbinary);
470:   v->data            = (void*)vbinary;
471:   v->ops->destroy    = PetscViewerDestroy_Binary;
472:   v->ops->flush      = 0;
473:   v->iformat         = 0;
474:   vbinary->fdes_info = 0;
475:   vbinary->fdes      = 0;
476:   vbinary->skipinfo  = PETSC_FALSE;
477:   v->ops->getsingleton     = PetscViewerGetSingleton_Binary;
478:   v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
479:   vbinary->btype           = (PetscViewerBinaryType) -1;
480:   vbinary->storecompressed = PETSC_FALSE;
481:   vbinary->filename        = 0;

483:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFilename_C",
484:                                     "PetscViewerSetFilename_Binary",
485:                                      PetscViewerSetFilename_Binary);
486:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerBinarySetType_C",
487:                                     "PetscViewerBinarySetType_Binary",
488:                                      PetscViewerBinarySetType_Binary);
489:   return(0);
490: }
491: EXTERN_C_END


494: /* ---------------------------------------------------------------------*/
495: /*
496:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
497:   is attached to a communicator, in this case the attribute is a PetscViewer.
498: */
499: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

501: /*@C
502:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors 
503:                      in a communicator.

505:      Collective on MPI_Comm

507:      Input Parameter:
508: .    comm - the MPI communicator to share the binary PetscViewer
509:     
510:      Level: intermediate

512:    Options Database Keys:
513: $    -viewer_BINARY_filename <name>

515:    Environmental variables:
516: -   PETSC_VIEWER_BINARY_FILENAME

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

523: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
524:           PetscViewerDestroy()
525: @*/
526: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
527: {
528:   int         ierr;
529:   PetscTruth  flg;
530:   PetscViewer viewer;
531:   char        fname[256];

534:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
535:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
536:     if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
537:   }
538:   MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int *)&flg);
539:   if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
540:   if (!flg) { /* PetscViewer not yet created */
541:     PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,256,&flg);
542:     if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
543:     if (!flg) {
544:       PetscStrcpy(fname,"binaryoutput");
545:       if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
546:     }
547:     PetscViewerBinaryOpen(comm,fname,PETSC_BINARY_CREATE,&viewer);
548:     if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
549:     PetscObjectRegisterDestroy((PetscObject)viewer);
550:     if (ierr) {PetscError(__LINE__,"VIEWER_STDOUT_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
551:     MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
552:     if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
553:   }
554:   PetscFunctionReturn(viewer);
555: }