Actual source code: binv.c

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

 3:  #include petscsys.h
 4:  #include src/sys/src/viewer/viewerimpl.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: } PetscViewer_Binary;

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

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

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

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

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

 56:     Not Collective

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

 61:     Level: advanced

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

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

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

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

 86: /*@C
 87:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
 88:           info file associated with a binary file.

 90:     Not Collective

 92: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
 93: -   file - file pointer

 95:     Level: advanced

 97:     Notes:
 98:       For writable binary PetscViewers, the descriptor will only be valid for the 
 99:     first processor in the communicator that shares the PetscViewer.
100:  
101:     Fortran Note:
102:     This routine is not supported in Fortran.

104:   Concepts: PetscViewerBinary^accessing info file

106: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
107: @*/
108: int PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
109: {
110:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

113:   *file = vbinary->fdes_info;
114:   return(0);
115: }

117: int PetscViewerDestroy_Binary(PetscViewer v)
118: {
119:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
120:   int                ierr,rank;

123:   MPI_Comm_rank(v->comm,&rank);
124:   if (!rank && vbinary->fdes) {
125:     close(vbinary->fdes);
126:     if (vbinary->storecompressed) {
127:       char par[1024],buf[1024];
128:       FILE *fp;
129:       /* compress the file */
130:       PetscStrcpy(par,"gzip ");
131:       PetscStrcat(par,vbinary->filename);
132:       PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,par,"r",&fp);
133:       if (fgets(buf,1024,fp)) {
134:         SETERRQ2(1,"Error from command %sn%s",par,buf);
135:       }
136:       PetscPClose(PETSC_COMM_SELF,fp);
137:     }
138:   }
139:   if (vbinary->fdes_info) fclose(vbinary->fdes_info);
140:   PetscStrfree(vbinary->filename);
141:   PetscFree(vbinary);
142:   return(0);
143: }

145: /*@C
146:    PetscViewerBinaryOpen - Opens a file for binary input/output.

148:    Collective on MPI_Comm

150:    Input Parameters:
151: +  comm - MPI communicator
152: .  name - name of file 
153: -  type - type of file
154: $    PETSC_BINARY_CREATE - create new file for binary output
155: $    PETSC_BINARY_RDONLY - open existing file for binary input
156: $    PETSC_BINARY_WRONLY - open existing file for binary output

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

161:    Level: beginner

163:    Note:
164:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

172:     For writing files it only opens the file on processor 0 in the communicator.
173:     For readable files it opens the file on all nodes that have the file. If 
174:     node 0 does not have the file it generates an error even if other nodes
175:     do have the file.

177:    Concepts: binary files
178:    Concepts: PetscViewerBinary^creating
179:    Concepts: gzip
180:    Concepts: accessing remote file
181:    Concepts: remote file

183: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
184:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
185:           PetscViewerBinaryGetInfoPointer()
186: @*/
187: int PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscViewerBinaryType type,PetscViewer *binv)
188: {
190: 
192:   PetscViewerCreate(comm,binv);
193:   PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
194:   PetscViewerBinarySetType(*binv,type);
195:   PetscViewerSetFilename(*binv,name);
196:   return(0);
197: }

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

202:     Collective on PetscViewer

204:   Input Parameters:
205: +  viewer - the PetscViewer; must be a binary PetscViewer
206: -  type - type of file
207: $    PETSC_BINARY_CREATE - create new file for binary output
208: $    PETSC_BINARY_RDONLY - open existing file for binary input
209: $    PETSC_BINARY_WRONLY - open existing file for binary output

211:   Level: advanced

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

215: @*/
216: int PetscViewerBinarySetType(PetscViewer viewer,PetscViewerBinaryType type)
217: {
218:   int ierr,(*f)(PetscViewer,PetscViewerBinaryType);

222:   PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerBinarySetType_C",(void (**)())&f);
223:   if (f) {
224:     (*f)(viewer,type);
225:   }

227:   return(0);
228: }

230: EXTERN_C_BEGIN
231: int PetscViewerBinarySetType_Binary(PetscViewer viewer,PetscViewerBinaryType type)
232: {
233:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

236:   vbinary->btype = type;
237:   return(0);
238: }
239: EXTERN_C_END

241: /*
242:     PetscViewerBinaryLoadInfo options from the name.info file
243:     if it exists.
244: */
245: int PetscViewerBinaryLoadInfo(PetscViewer viewer)
246: {
247:   FILE       *file;
248:   char       string[128],*first,*second,*final;
249:   int        len,ierr;
250:   PetscTruth flg;

253:   PetscOptionsHasName(PETSC_NULL,"-load_ignore_info",&flg);
254:   if (flg) return(0);

256:   PetscViewerBinaryGetInfoPointer(viewer,&file);
257:   if (!file) return(0);

259:   /* read rows of the file adding them to options database */
260:   while (fgets(string,128,file)) {
261:     /* Comments are indicated by #, ! or % in the first column */
262:     if (string[0] == '#') continue;
263:     if (string[0] == '!') continue;
264:     if (string[0] == '%') continue;
265:     PetscStrtok(string," ",&first);
266:     PetscStrtok(0," ",&second);
267:     if (first && first[0] == '-') {
268:       PetscTruth wrongtype;
269:       /*
270:          Check for -mat_complex or -mat_double
271:       */
272: #if defined(PETSC_USE_COMPLEX)
273:       PetscStrncmp(first,"-mat_double",11,&wrongtype);
274:       if (wrongtype) {
275:         SETERRQ(1,"Loading double number matrix with complex number code");
276:       }
277: #else
278:       PetscStrncmp(first,"-mat_complex",12,&wrongtype);
279:       if (wrongtype) {
280:         SETERRQ(1,"Loading complex number matrix with double number code");
281:       }
282: #endif

284:       if (second) {final = second;} else {final = first;}
285:       PetscStrlen(final,&len);
286:       while (len > 0 && (final[len-1] == ' ' || final[len-1] == 'n')) {
287:         len--; final[len] = 0;
288:       }
289:       PetscOptionsSetValue(first,second);
290:     }
291:   }
292:   return(0);

294: }

296: /*
297:         Actually opens the file 
298: */
299: EXTERN_C_BEGIN
300: int PetscViewerSetFilename_Binary(PetscViewer viewer,const char name[])
301: {
302:   int                   rank,ierr,len;
303:   PetscViewer_Binary    *vbinary = (PetscViewer_Binary*)viewer->data;
304:   const char            *fname;
305:   char                  bname[1024],*gz;
306:   PetscTruth            found;
307:   PetscViewerBinaryType type = vbinary->btype;

310:   if (type == (PetscViewerBinaryType) -1) {
311:     SETERRQ(1,"Must call PetscViewerBinarySetType() before PetscViewerSetFilename()");
312:   }
313:   MPI_Comm_rank(viewer->comm,&rank);

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

318:   /* if ends in .gz strip that off and note user wants file compressed */
319:   vbinary->storecompressed = PETSC_FALSE;
320:   if (!rank && type == PETSC_BINARY_CREATE) {
321:     /* remove .gz if it ends library name */
322:     PetscStrstr(vbinary->filename,".gz",&gz);
323:     if (gz) {
324:       PetscStrlen(gz,&len);
325:       if (len == 3) {
326:         *gz = 0;
327:         vbinary->storecompressed = PETSC_TRUE;
328:       }
329:     }
330:   }

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

335:     if (type == PETSC_BINARY_RDONLY){
336:       /* possibly get the file from remote site or compressed file */
337:       ierr  = PetscFileRetrieve(viewer->comm,vbinary->filename,bname,1024,&found);
338:       fname = bname;
339:       if (!rank && !found) {
340:         SETERRQ1(1,"Cannot locate file: %s on node zero",vbinary->filename);
341:       } else if (!found) {
342:         PetscLogInfo(viewer,"Nonzero processor did not locate readonly file");
343:         fname = 0;
344:       }
345:     } else {
346:       fname = vbinary->filename;
347:     }

349: #if defined(PARCH_win32_gnu) || defined(PARCH_win32) 
350:     if (type == PETSC_BINARY_CREATE) {
351:       if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
352:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
353:       }
354:     } else if (type == PETSC_BINARY_RDONLY && fname) {
355:       if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) {
356:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
357:       }
358:     } else if (type == PETSC_BINARY_WRONLY) {
359:       if ((vbinary->fdes = open(fname,O_WRONLY|O_BINARY,0)) == -1) {
360:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
361:       }
362:     } else if (fname) {
363:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
364:     }
365: #else
366:     if (type == PETSC_BINARY_CREATE) {
367:       if ((vbinary->fdes = creat(fname,0666)) == -1) {
368:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
369:       }
370:     } else if (type == PETSC_BINARY_RDONLY && fname) {
371:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) {
372:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
373:       }
374:     } else if (type == PETSC_BINARY_WRONLY) {
375:       if ((vbinary->fdes = open(fname,O_WRONLY,0)) == -1) {
376:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
377:       }
378:     } else if (fname) {
379:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
380:     }
381: #endif
382:   } else vbinary->fdes = -1;
383:   viewer->format = PETSC_VIEWER_NOFORMAT;

385:   /* 
386:       try to open info file: all processors open this file if read only
387:   */
388:   if (!rank || type == PETSC_BINARY_RDONLY) {
389:     char infoname[256],iname[256];
390: 
391:     PetscStrcpy(infoname,name);
392:     /* remove .gz if it ends library name */
393:     PetscStrstr(infoname,".gz",&gz);
394:     if (gz) {
395:       PetscStrlen(gz,&len);
396:       if (len == 3) {
397:         *gz = 0;
398:       }
399:     }
400: 
401:     PetscStrcat(infoname,".info");
402:     PetscFixFilename(infoname,iname);
403:     if (type == PETSC_BINARY_RDONLY) {
404:       PetscFileRetrieve(viewer->comm,iname,infoname,256,&found);
405:       if (found) {
406:         vbinary->fdes_info = fopen(infoname,"r");
407:         if (vbinary->fdes_info) {
408:           PetscViewerBinaryLoadInfo(viewer);
409:           fclose(vbinary->fdes_info);
410:         }
411:         vbinary->fdes_info = fopen(infoname,"r");
412:       }
413:     } else {
414:       vbinary->fdes_info = fopen(infoname,"w");
415:       if (! vbinary->fdes_info) {
416:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
417:       }
418:     }
419:   }

421: #if defined(PETSC_USE_LOG)
422:   PetscLogObjectState((PetscObject)viewer,"File: %s",name);
423: #endif
424:   return(0);
425: }
426: EXTERN_C_END

428: EXTERN_C_BEGIN
429: int PetscViewerCreate_Binary(PetscViewer v)
430: {
431:   int                ierr;
432:   PetscViewer_Binary *vbinary;

435:   ierr               = PetscNew(PetscViewer_Binary,&vbinary);
436:   v->data            = (void*)vbinary;
437:   v->ops->destroy    = PetscViewerDestroy_Binary;
438:   v->ops->flush      = 0;
439:   v->iformat         = 0;
440:   vbinary->fdes_info = 0;
441:   vbinary->fdes      = 0;
442:   v->ops->getsingleton     = PetscViewerGetSingleton_Binary;
443:   v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
444:   vbinary->btype     = (PetscViewerBinaryType) -1;
445:   vbinary->storecompressed = PETSC_FALSE;
446:   vbinary->filename        = 0;

448:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFilename_C",
449:                                     "PetscViewerSetFilename_Binary",
450:                                      PetscViewerSetFilename_Binary);
451:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerBinarySetType_C",
452:                                     "PetscViewerBinarySetType_Binary",
453:                                      PetscViewerBinarySetType_Binary);
454:   return(0);
455: }
456: EXTERN_C_END


459: /* ---------------------------------------------------------------------*/
460: /*
461:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
462:   is attached to a communicator, in this case the attribute is a PetscViewer.
463: */
464: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

466: /*@C
467:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors 
468:                      in a communicator.

470:      Collective on MPI_Comm

472:      Input Parameter:
473: .    comm - the MPI communicator to share the binary PetscViewer
474:     
475:      Level: intermediate

477:    Options Database Keys:
478: $    -viewer_BINARY_filename <name>

480:    Environmental variables:
481: -   PETSC_VIEWER_BINARY_FILENAME

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

488: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
489:           PetscViewerDestroy()
490: @*/
491: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
492: {
493:   int         ierr;
494:   PetscTruth  flg;
495:   PetscViewer viewer;
496:   char        fname[256];

499:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
500:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
501:     if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
502:   }
503:   MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int *)&flg);
504:   if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
505:   if (!flg) { /* PetscViewer not yet created */
506:     PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,256,&flg);
507:     if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
508:     if (!flg) {
509:       PetscStrcpy(fname,"binaryoutput");
510:       if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
511:     }
512:     PetscViewerBinaryOpen(comm,fname,PETSC_BINARY_CREATE,&viewer);
513:     if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
514:     PetscObjectRegisterDestroy((PetscObject)viewer);
515:     if (ierr) {PetscError(__LINE__,"VIEWER_STDOUT_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
516:     MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
517:     if (ierr) {PetscError(__LINE__,"VIEWER_BINARY_",__FILE__,__SDIR__,1,1,0); viewer = 0;}
518:   }
519:   PetscFunctionReturn(viewer);
520: }