Actual source code: binv.c

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

 12: typedef struct  {
 13:   int           fdes;            /* file descriptor, ignored if using MPI IO */
 14: #if defined(PETSC_HAVE_MPIIO)
 15:   PetscTruth    MPIIO;
 16:   MPI_File      mfdes;           /* ignored unless using MPI IO */
 17:   MPI_Offset    moff;
 18: #endif
 19:   PetscFileMode btype;           /* read or write? */
 20:   FILE          *fdes_info;      /* optional file containing info on binary file*/
 21:   PetscTruth    storecompressed; /* gzip the write binary file when closing it*/
 22:   char          *filename;
 23:    PetscTruth    skipinfo;        /* Don't create info file for writing; don't use for reading */
 24:   PetscTruth    skipoptions;     /* don't use PETSc options database when loading */
 25: } PetscViewer_Binary;

 29: PetscErrorCode PetscViewerGetSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
 30: {
 31:   int                rank;
 32:   PetscErrorCode     ierr;
 33:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data,*obinary;

 36:   MPI_Comm_rank(((PetscObject)viewer)->comm,&rank);
 37:   if (!rank) {
 38:     PetscViewerCreate(PETSC_COMM_SELF,outviewer);
 39:     PetscViewerSetType(*outviewer,PETSC_VIEWER_BINARY);
 40:     obinary = (PetscViewer_Binary*)(*outviewer)->data;
 41:     PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));
 42:   } else {
 43:     *outviewer = 0;
 44:   }
 45:   return(0);
 46: }

 50: PetscErrorCode PetscViewerRestoreSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
 51: {
 53:   PetscErrorCode rank;

 56:   MPI_Comm_rank(((PetscObject)viewer)->comm,&rank);
 57:   if (!rank) {
 58:     PetscFree((*outviewer)->data);
 59:     PetscHeaderDestroy(*outviewer);
 60:   }
 61:   return(0);
 62: }

 64: #if defined(PETSC_HAVE_MPIIO)
 67: /*@C
 68:     PetscViewerBinaryGetMPIIOOffset - Gets the current offset that should be passed to MPI_File_set_view()

 70:     Not Collective

 72:     Input Parameter:
 73: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

 75:     Output Parameter:
 76: .    off - the current offset

 78:     Level: advanced

 80:     Fortran Note:
 81:     This routine is not supported in Fortran.

 83:     Use PetscViewerBinaryAddMPIIOOffset() to increase this value after you have written a view.

 85:   Concepts: file descriptor^getting
 86:   Concepts: PetscViewerBinary^accessing file descriptor

 88: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
 89: @*/
 90: PetscErrorCode  PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off)
 91: {
 92:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

 95:   *off = vbinary->moff;
 96:   return(0);
 97: }

101: /*@C
102:     PetscViewerBinaryAddMPIIOOffset - Adds to the current offset that should be passed to MPI_File_set_view()

104:     Not Collective

106:     Input Parameters:
107: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
108: -    off - the addition to the offset

110:     Level: advanced

112:     Fortran Note:
113:     This routine is not supported in Fortran.

115:     Use PetscViewerBinaryGetMPIIOOffset() to get the value that you should pass to MPI_File_set_view()

117:   Concepts: file descriptor^getting
118:   Concepts: PetscViewerBinary^accessing file descriptor

120: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
121: @*/
122: PetscErrorCode  PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)
123: {
124:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

127:   vbinary->moff += off;
128:   return(0);
129: }

133: /*@C
134:     PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a PetscViewer.

136:     Not Collective

138:     Input Parameter:
139: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

141:     Output Parameter:
142: .   fdes - file descriptor

144:     Level: advanced

146:     Fortran Note:
147:     This routine is not supported in Fortran.

149:   Concepts: file descriptor^getting
150:   Concepts: PetscViewerBinary^accessing file descriptor

152: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
153: @*/
154: PetscErrorCode  PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
155: {
156:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

159:   *fdes = vbinary->mfdes;
160:   return(0);
161: }

165: /*@C
166:     PetscViewerBinaryGetMPIIO - Returns PETSC_TRUE if the binary viewer is an MPI viewer.

168:     Not Collective

170:     Input Parameter:
171: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

173:     Output Parameter:
174: -   flg - PETSC_TRUE if MPI IO is being used

176:     Level: advanced

178:     Fortran Note:
179:     This routine is not supported in Fortran.

181:   Concepts: file descriptor^getting
182:   Concepts: PetscViewerBinary^accessing file descriptor

184: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer()
185: @*/
186: PetscErrorCode  PetscViewerBinaryGetMPIIO(PetscViewer viewer,PetscTruth *flg)
187: {
188:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

191:   *flg = vbinary->MPIIO;
192:   return(0);
193: }
194: #endif

198: /*@C
199:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

201:     Not Collective

203:     Input Parameter:
204: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

206:     Output Parameter:
207: .   fdes - file descriptor

209:     Level: advanced

211:     Notes:
212:       For writable binary PetscViewers, the descriptor will only be valid for the 
213:     first processor in the communicator that shares the PetscViewer. For readable 
214:     files it will only be valid on nodes that have the file. If node 0 does not
215:     have the file it generates an error even if another node does have the file.
216:  
217:     Fortran Note:
218:     This routine is not supported in Fortran.

220:   Concepts: file descriptor^getting
221:   Concepts: PetscViewerBinary^accessing file descriptor

223: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
224: @*/
225: PetscErrorCode  PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
226: {
227:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

230:   *fdes = vbinary->fdes;
231:   return(0);
232: }

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

239:     Not Collective

241:     Input Paramter:
242: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

244:     Options Database Key:
245: .   -viewer_binary_skip_info

247:     Level: advanced

249:     Notes: This must be called after PetscViewerSetType() but before PetscViewerFileSetName(). If you use PetscViewerBinaryOpen() then 
250:     you can only skip the info file with the -viewer_binary_skip_info flag. To use the function you must open the
251:     viewer with PetscViewerCreate(), PetscViewerSetType(), PetscViewerFileSetName().

253:     The .info contains meta information about the data in the binary file, for example the block size if it was
254:     set for a vector or matrix.

256:    Concepts: PetscViewerBinary^accessing info file

258: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
259:           PetscViewerBinaryGetSkipOptions()
260: @*/
261: PetscErrorCode  PetscViewerBinarySkipInfo(PetscViewer viewer)
262: {
263:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

266:   vbinary->skipinfo = PETSC_TRUE;
267:   return(0);
268: }

272: /*@
273:     PetscViewerBinarySetSkipOptions - do not use the PETSc options database when loading objects

275:     Not Collective

277:     Input Parameters:
278: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
279: -   skip - PETSC_TRUE means do not use

281:     Options Database Key:
282: .   -viewer_binary_skip_options

284:     Level: advanced

286:     Notes: This must be called after PetscViewerSetType()

288:    Concepts: PetscViewerBinary^accessing info file

290: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
291:           PetscViewerBinaryGetSkipOptions()
292: @*/
293: PetscErrorCode  PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscTruth skip)
294: {
295:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

298:   vbinary->skipoptions = skip;
299:   return(0);
300: }

304: /*@
305:     PetscViewerBinaryGetSkipOptions - checks if viewer uses the PETSc options database when loading objects

307:     Not Collective

309:     Input Parameter:
310: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

312:     Output Parameter:
313: .   skip - PETSC_TRUE means do not use

315:     Level: advanced

317:     Notes: This must be called after PetscViewerSetType()

319:    Concepts: PetscViewerBinary^accessing info file

321: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
322:           PetscViewerBinarySetSkipOptions()
323: @*/
324: PetscErrorCode  PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscTruth *skip)
325: {
326:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

329:   *skip = vbinary->skipoptions;
330:   return(0);
331: }

335: /*@C
336:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
337:           info file associated with a binary file.

339:     Not Collective

341:     Input Parameter:
342: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

344:     Output Parameter:
345: .   file - file pointer

347:     Level: advanced

349:     Notes:
350:       For writable binary PetscViewers, the descriptor will only be valid for the 
351:     first processor in the communicator that shares the PetscViewer.
352:  
353:     Fortran Note:
354:     This routine is not supported in Fortran.

356:   Concepts: PetscViewerBinary^accessing info file

358: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
359: @*/
360: PetscErrorCode  PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
361: {
362:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

365:   *file = vbinary->fdes_info;
366:   return(0);
367: }

371: PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
372: {
373:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
374:   PetscErrorCode     ierr;
375:   PetscMPIInt        rank;
376:   int                err;

379:   MPI_Comm_rank(((PetscObject)v)->comm,&rank);
380:   if ((!rank || vbinary->btype == FILE_MODE_READ) && vbinary->fdes) {
381:     close(vbinary->fdes);
382:     if (!rank && vbinary->storecompressed) {
383:       char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
384:       FILE *fp;
385:       /* compress the file */
386:       PetscStrcpy(par,"gzip -f ");
387:       PetscStrcat(par,vbinary->filename);
388: #if defined(PETSC_HAVE_POPEN)
389:       PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,par,"r",&fp);
390:       if (fgets(buf,1024,fp)) {
391:         SETERRQ2(PETSC_ERR_LIB,"Error from command %s\n%s",par,buf);
392:       }
393:       PetscPClose(PETSC_COMM_SELF,fp);
394: #else
395:       SETERRQ(PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
396: #endif
397:     }
398:   }
399:   if (vbinary->fdes_info) {
400:     err = fclose(vbinary->fdes_info);
401:     if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file");
402:   }
403:   PetscStrfree(vbinary->filename);
404:   PetscFree(vbinary);
405:   return(0);
406: }

408: #if defined(PETSC_HAVE_MPIIO)
411: PetscErrorCode PetscViewerDestroy_MPIIO(PetscViewer v)
412: {
413:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
414:   PetscErrorCode     ierr;
415:   int                err;

418:   if (vbinary->mfdes) {
419:     MPI_File_close(&vbinary->mfdes);
420:   }
421:   if (vbinary->fdes_info) {
422:     err = fclose(vbinary->fdes_info);
423:     if (err) SETERRQ(PETSC_ERR_SYS,"fclose() failed on file");
424:   }
425:   PetscStrfree(vbinary->filename);
426:   PetscFree(vbinary);
427:   return(0);
428: }
429: #endif

433: /*@
434:    PetscViewerBinaryCreate - Create a binary viewer.

436:    Collective on MPI_Comm

438:    Input Parameters:
439: .  comm - MPI communicator

441:    Output Parameter:
442: .  binv - PetscViewer for binary input/output

444:    Level: beginner
445: @*/
446: PetscErrorCode  PetscViewerBinaryCreate(MPI_Comm comm,PetscViewer *binv)
447: {
449: 
451:   PetscViewerCreate(comm,binv);
452:   PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
453:   return(0);
454: }

458: /*@C
459:    PetscViewerBinaryOpen - Opens a file for binary input/output.

461:    Collective on MPI_Comm

463:    Input Parameters:
464: +  comm - MPI communicator
465: .  name - name of file 
466: -  type - type of file
467: $    FILE_MODE_WRITE - create new file for binary output
468: $    FILE_MODE_READ - open existing file for binary input
469: $    FILE_MODE_APPEND - open existing file for binary output

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

474:    Level: beginner

476:    Note:
477:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

485:     For writing files it only opens the file on processor 0 in the communicator.
486:     For readable files it opens the file on all nodes that have the file. If 
487:     node 0 does not have the file it generates an error even if other nodes
488:     do have the file.

490:    Concepts: binary files
491:    Concepts: PetscViewerBinary^creating
492:    Concepts: gzip
493:    Concepts: accessing remote file
494:    Concepts: remote file

496: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
497:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
498:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
499: @*/
500: PetscErrorCode  PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
501: {
503: 
505:   PetscViewerCreate(comm,binv);
506:   PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
507:   PetscViewerFileSetMode(*binv,type);
508:   PetscViewerFileSetName(*binv,name);
509:   return(0);
510: }

512: #if defined(PETSC_HAVE_MPIIO)
515: static PetscErrorCode  PetscViewerBinaryMPIIO(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscTruth write)
516: {
517:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
518:   PetscErrorCode     ierr;
519:   MPI_Datatype       mdtype;
520:   PetscMPIInt        cnt = PetscMPIIntCast(count);
521:   MPI_Status         status;
522:   MPI_Aint           ul,dsize;

525:   PetscDataTypeToMPIDataType(dtype,&mdtype);
526:   MPI_File_set_view(vbinary->mfdes,vbinary->moff,mdtype,mdtype,(char *)"native",MPI_INFO_NULL);
527:   if (write) {
528:     MPIU_File_write_all(vbinary->mfdes,data,cnt,mdtype,&status);
529:   } else {
530:     MPIU_File_read_all(vbinary->mfdes,data,cnt,mdtype,&status);
531:   }
532:   MPI_Type_get_extent(mdtype,&ul,&dsize);
533:   vbinary->moff += dsize*cnt;
534:   return(0);
535: }
536: #endif

540: /*@C
541:    PetscViewerBinaryRead - Reads from a binary file, all processors get the same result

543:    Collective on MPI_Comm

545:    Input Parameters:
546: +  viewer - the binary viewer
547: .  data - location to write the data
548: .  count - number of items of data to read
549: -  datatype - type of data to read

551:    Level: beginner

553:    Concepts: binary files

555: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
556:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
557:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
558: @*/
559: PetscErrorCode  PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype)
560: {
561:   PetscErrorCode     ierr;
562:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

564: #if defined(PETSC_HAVE_MPIIO)
565:   if (vbinary->MPIIO) {
566:     PetscViewerBinaryMPIIO(viewer,data,count,dtype,PETSC_FALSE);
567:   } else {
568: #endif
569:     PetscBinarySynchronizedRead(((PetscObject)viewer)->comm,vbinary->fdes,data,count,dtype);
570: #if defined(PETSC_HAVE_MPIIO)
571:   }
572: #endif
573:   return(0);
574: }


579: /*@C
580:    PetscViewerBinaryWrite - writes to a binary file, only from the first process

582:    Collective on MPI_Comm

584:    Input Parameters:
585: +  viewer - the binary viewer
586: .  data - location of data
587: .  count - number of items of data to read
588: .  istemp - data may be overwritten
589: -  datatype - type of data to read

591:    Level: beginner

593:    Notes: because byte-swapping may be done on the values in data it cannot be declared const

595:    Concepts: binary files

597: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
598:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
599:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
600: @*/
601: PetscErrorCode  PetscViewerBinaryWrite(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscTruth istemp)
602: {
603:   PetscErrorCode     ierr;
604:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

606: #if defined(PETSC_HAVE_MPIIO)
607:   if (vbinary->MPIIO) {
608:     PetscViewerBinaryMPIIO(viewer,data,count,dtype,PETSC_TRUE);
609:   } else {
610: #endif
611:     PetscBinarySynchronizedWrite(((PetscObject)viewer)->comm,vbinary->fdes,data,count,dtype,istemp);
612: #if defined(PETSC_HAVE_MPIIO)
613:   }
614: #endif
615:   return(0);
616: }

620: /*@C
621:    PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first process an array of strings

623:    Collective on MPI_Comm

625:    Input Parameters:
626: +  viewer - the binary viewer
627: -  data - location of the array of strings


630:    Level: intermediate

632:    Concepts: binary files

634:     Notes: array of strings is null terminated

636: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
637:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
638:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
639: @*/
640: PetscErrorCode  PetscViewerBinaryWriteStringArray(PetscViewer viewer,char **data)
641: {
642:   PetscErrorCode     ierr;
643:   PetscInt           i,n = 0,*sizes;

645:   /* count number of strings */
646:   while (data[n++]);
647:   n--;
648:   PetscMalloc((n+1)*sizeof(PetscInt),&sizes);
649:   sizes[0] = n;
650:   for (i=0; i<n; i++) {
651:     size_t tmp;
652:     PetscStrlen(data[i],&tmp);
653:     sizes[i+1] = tmp + 1;   /* size includes space for the null terminator */
654:   }
655:   PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT,PETSC_FALSE);
656:   for (i=0; i<n; i++) {
657:     PetscViewerBinaryWrite(viewer,data[i],sizes[i+1],PETSC_CHAR,PETSC_FALSE);
658:   }
659:   PetscFree(sizes);
660:   return(0);
661: }

663: /*@C
664:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

666:    Collective on MPI_Comm

668:    Input Parameter:
669: .  viewer - the binary viewer

671:    Output Parameter:
672: .  data - location of the array of strings

674:    Level: intermediate

676:    Concepts: binary files

678:     Notes: array of strings is null terminated

680: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
681:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
682:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
683: @*/
684: PetscErrorCode  PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
685: {
686:   PetscErrorCode     ierr;
687:   PetscInt           i,n,*sizes,N = 0;

689:   /* count number of strings */
690:   PetscViewerBinaryRead(viewer,&n,1,PETSC_INT);
691:   PetscMalloc(n*sizeof(PetscInt),&sizes);
692:   PetscViewerBinaryRead(viewer,sizes,n,PETSC_INT);
693:   for (i=0; i<n; i++) {
694:     N += sizes[i];
695:   }
696:   PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);
697:   (*data)[0] = (char*)((*data) + n + 1);
698:   for (i=1; i<n; i++) {
699:     (*data)[i] = (*data)[i-1] + sizes[i-1];
700:   }
701:   PetscViewerBinaryRead(viewer,(*data)[0],N,PETSC_CHAR);
702:   (*data)[n] = 0;
703:   PetscFree(sizes);
704:   return(0);
705: }

709: /*@C
710:      PetscViewerFileGetMode - Gets the type of file to be open

712:     Collective on PetscViewer

714:   Input Parameter:
715: .  viewer - the PetscViewer; must be a binary, Matlab, hdf, or netcdf PetscViewer

717:   Output Parameter:
718: .  type - type of file
719: $    FILE_MODE_WRITE - create new file for binary output
720: $    FILE_MODE_READ - open existing file for binary input
721: $    FILE_MODE_APPEND - open existing file for binary output

723:   Level: advanced

725: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()

727: @*/
728: PetscErrorCode  PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
729: {
730:   PetscErrorCode ierr,(*f)(PetscViewer,PetscFileMode*);

735:   PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerFileGetMode_C",(void (**)(void))&f);
736:   if (f) {
737:     (*f)(viewer,type);
738:   }
739:   return(0);
740: }

744: /*@
745:      PetscViewerBinarySetMPIIO - Sets a binary viewer to use MPI IO for reading/writing. Must be called
746:         before PetscViewerFileSetName()

748:     Collective on PetscViewer

750:   Input Parameters:
751: .  viewer - the PetscViewer; must be a binary

753:    Notes: turns off the default usage of the .info file since that is not scalable

755:   Level: advanced

757: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()

759: @*/
760: PetscErrorCode  PetscViewerBinarySetMPIIO(PetscViewer viewer)
761: {
762:   PetscErrorCode ierr,(*f)(PetscViewer);

766:   PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerBinarySetMPIIO_C",(void (**)(void))&f);
767:   if (f) {
768:     (*f)(viewer);
769:   }
770:   return(0);
771: }


774: /*@C
775:      PetscViewerFileSetMode - Sets the type of file to be open

777:     Collective on PetscViewer

779:   Input Parameters:
780: +  viewer - the PetscViewer; must be a binary, Matlab, hdf, or netcdf PetscViewer
781: -  type - type of file
782: $    FILE_MODE_WRITE - create new file for binary output
783: $    FILE_MODE_READ - open existing file for binary input
784: $    FILE_MODE_APPEND - open existing file for binary output

786:   Level: advanced

788: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()

790: @*/
791: PetscErrorCode  PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
792: {
793:   PetscErrorCode ierr,(*f)(PetscViewer,PetscFileMode);

797:   PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",(void (**)(void))&f);
798:   if (f) {
799:     (*f)(viewer,type);
800:   }
801:   return(0);
802: }

807: PetscErrorCode  PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
808: {
809:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

812:   *type = vbinary->btype;
813:   return(0);
814: }

820: PetscErrorCode  PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
821: {
822:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

825:   vbinary->btype = type;
826:   return(0);
827: }

830: /*
831:         Actually opens the file 
832: */
836: PetscErrorCode  PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
837: {
838:   PetscMPIInt         rank;
839:   PetscErrorCode      ierr;
840:   size_t              len;
841:   PetscViewer_Binary  *vbinary = (PetscViewer_Binary*)viewer->data;
842:   const char          *fname;
843:   char                bname[PETSC_MAX_PATH_LEN],*gz;
844:   PetscTruth          found;
845:   PetscFileMode       type = vbinary->btype;

848:   if (type == (PetscFileMode) -1) {
849:     SETERRQ(PETSC_ERR_ORDER,"Must call PetscViewerBinarySetFileType() before PetscViewerFileSetName()");
850:   }
851:   PetscOptionsGetTruth(((PetscObject)viewer)->prefix,"-viewer_binary_skip_info",&vbinary->skipinfo,PETSC_NULL);
852:   PetscOptionsGetTruth(((PetscObject)viewer)->prefix,"-viewer_binary_skip_options",&vbinary->skipoptions,PETSC_NULL);

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

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

859:   /* if ends in .gz strip that off and note user wants file compressed */
860:   vbinary->storecompressed = PETSC_FALSE;
861:   if (!rank && type == FILE_MODE_WRITE) {
862:     /* remove .gz if it ends library name */
863:     PetscStrstr(vbinary->filename,".gz",&gz);
864:     if (gz) {
865:       PetscStrlen(gz,&len);
866:       if (len == 3) {
867:         *gz = 0;
868:         vbinary->storecompressed = PETSC_TRUE;
869:       }
870:     }
871:   }

873:   /* only first processor opens file if writeable */
874:   if (!rank || type == FILE_MODE_READ) {

876:     if (type == FILE_MODE_READ){
877:       /* possibly get the file from remote site or compressed file */
878:       PetscFileRetrieve(((PetscObject)viewer)->comm,vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
879:       fname = bname;
880:       if (!rank && !found) {
881:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
882:       } else if (!found) {
883:         PetscInfo(viewer,"Nonzero processor did not locate readonly file\n");
884:         fname = 0;
885:       }
886:     } else {
887:       fname = vbinary->filename;
888:     }

890: #if defined(PETSC_HAVE_O_BINARY)
891:     if (type == FILE_MODE_WRITE) {
892:       if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
893:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
894:       }
895:     } else if (type == FILE_MODE_READ && fname) {
896:       if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) {
897:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
898:       }
899:     } else if (type == FILE_MODE_APPEND) {
900:       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND|O_BINARY,0)) == -1) {
901:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
902:       }
903:     } else if (fname) {
904:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
905:     }
906: #else
907:     if (type == FILE_MODE_WRITE) {
908:       if ((vbinary->fdes = creat(fname,0666)) == -1) {
909:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
910:       }
911:     } else if (type == FILE_MODE_READ && fname) {
912:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) {
913:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
914:       }
915:     } else if (type == FILE_MODE_APPEND) {
916:       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND,0)) == -1) {
917:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
918:       }
919:     } else if (fname) {
920:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
921:     }
922: #endif
923:   } else vbinary->fdes = -1;
924:   viewer->format = PETSC_VIEWER_NOFORMAT;

926:   /* 
927:       try to open info file: all processors open this file if read only
928:   */
929:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
930:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
931: 
932:     PetscStrcpy(infoname,name);
933:     /* remove .gz if it ends library name */
934:     PetscStrstr(infoname,".gz",&gz);
935:     if (gz) {
936:       PetscStrlen(gz,&len);
937:       if (len == 3) {
938:         *gz = 0;
939:       }
940:     }
941: 
942:     PetscStrcat(infoname,".info");
943:     PetscFixFilename(infoname,iname);
944:     if (type == FILE_MODE_READ) {
945:       PetscFileRetrieve(((PetscObject)viewer)->comm,iname,infoname,PETSC_MAX_PATH_LEN,&found);
946:       PetscOptionsInsertFile(((PetscObject)viewer)->comm,infoname,PETSC_FALSE);
947:     } else {
948:       vbinary->fdes_info = fopen(infoname,"w");
949:       if (!vbinary->fdes_info) {
950:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
951:       }
952:     }
953:   }

955: #if defined(PETSC_USE_LOG)
956:   PetscLogObjectState((PetscObject)viewer,"File: %s",name);
957: #endif
958:   return(0);
959: }

962: #if defined(PETSC_HAVE_MPIIO)
966: PetscErrorCode  PetscViewerFileSetName_MPIIO(PetscViewer viewer,const char name[])
967: {
968:   PetscMPIInt         rank;
969:   PetscErrorCode      ierr;
970:   size_t              len;
971:   PetscViewer_Binary  *vbinary = (PetscViewer_Binary*)viewer->data;
972:   char                *gz;
973:   PetscTruth          found;
974:   PetscFileMode       type = vbinary->btype;

977:   if (type == (PetscFileMode) -1) {
978:     SETERRQ(PETSC_ERR_ORDER,"Must call PetscViewerBinarySetFileType() before PetscViewerFileSetName()");
979:   }
980:   PetscOptionsGetTruth(((PetscObject)viewer)->prefix,"-viewer_binary_skip_info",&vbinary->skipinfo,PETSC_NULL);
981:   PetscOptionsGetTruth(((PetscObject)viewer)->prefix,"-viewer_binary_skip_options",&vbinary->skipoptions,PETSC_NULL);

983:   MPI_Comm_rank(((PetscObject)viewer)->comm,&rank);
984:   PetscStrallocpy(name,&vbinary->filename);
985:   vbinary->storecompressed = PETSC_FALSE;


988:   /* only first processor opens file if writeable */
989:   if (type == FILE_MODE_READ) {
990:     MPI_File_open(((PetscObject)viewer)->comm,vbinary->filename,MPI_MODE_RDONLY,MPI_INFO_NULL,&vbinary->mfdes);
991:   } else if (type == FILE_MODE_WRITE) {
992:     MPI_File_open(((PetscObject)viewer)->comm,vbinary->filename,MPI_MODE_WRONLY | MPI_MODE_CREATE,MPI_INFO_NULL,&vbinary->mfdes);
993:   }
994:   viewer->format = PETSC_VIEWER_NOFORMAT;

996:   /* 
997:       try to open info file: all processors open this file if read only

999:       Below is identical code to the code for Binary above, should be put in seperate routine
1000:   */
1001:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1002:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
1003: 
1004:     PetscStrcpy(infoname,name);
1005:     /* remove .gz if it ends library name */
1006:     PetscStrstr(infoname,".gz",&gz);
1007:     if (gz) {
1008:       PetscStrlen(gz,&len);
1009:       if (len == 3) {
1010:         *gz = 0;
1011:       }
1012:     }
1013: 
1014:     PetscStrcat(infoname,".info");
1015:     PetscFixFilename(infoname,iname);
1016:     if (type == FILE_MODE_READ) {
1017:       PetscFileRetrieve(((PetscObject)viewer)->comm,iname,infoname,PETSC_MAX_PATH_LEN,&found);
1018:       PetscOptionsInsertFile(((PetscObject)viewer)->comm,infoname,PETSC_FALSE);
1019:     } else {
1020:       vbinary->fdes_info = fopen(infoname,"w");
1021:       if (!vbinary->fdes_info) {
1022:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1023:       }
1024:     }
1025:   }

1027: #if defined(PETSC_USE_LOG)
1028:   PetscLogObjectState((PetscObject)viewer,"File: %s",name);
1029: #endif
1030:   return(0);
1031: }

1037: PetscErrorCode  PetscViewerBinarySetMPIIO_Binary(PetscViewer viewer,PetscFileMode *type)
1038: {
1039:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1040:   PetscErrorCode     ierr;

1043:   if (vbinary->filename) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must call before calling PetscViewerFileSetName()");
1044:   viewer->ops->destroy = PetscViewerDestroy_Binary;
1045:   vbinary->MPIIO       = PETSC_TRUE;
1046:   /*  vbinary->skipinfo    = PETSC_TRUE; */
1047:   PetscObjectComposeFunctionDynamic((PetscObject)viewer,"PetscViewerFileSetName_C","PetscViewerFileSetName_MPIIO",PetscViewerFileSetName_MPIIO);
1048:   return(0);
1049: }
1051: #endif

1056: PetscErrorCode  PetscViewerCreate_Binary(PetscViewer v)
1057: {
1058:   PetscErrorCode     ierr;
1059:   PetscViewer_Binary *vbinary;
1060: #if defined(PETSC_HAVE_MPIIO)
1061:   PetscTruth         useMPIIO = PETSC_FALSE;
1062: #endif

1065:   PetscNewLog(v,PetscViewer_Binary,&vbinary);
1066:   v->data            = (void*)vbinary;
1067:   v->ops->destroy    = PetscViewerDestroy_Binary;
1068:   v->ops->flush      = 0;
1069:   v->iformat         = 0;
1070:   vbinary->fdes_info = 0;
1071:   vbinary->fdes      = 0;
1072:   vbinary->skipinfo        = PETSC_FALSE;
1073:   vbinary->skipoptions     = PETSC_TRUE;
1074:   v->ops->getsingleton     = PetscViewerGetSingleton_Binary;
1075:   v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
1076:   vbinary->btype           = (PetscFileMode) -1;
1077:   vbinary->storecompressed = PETSC_FALSE;
1078:   vbinary->filename        = 0;

1080:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerFileSetName_C",
1081:                                     "PetscViewerFileSetName_Binary",
1082:                                      PetscViewerFileSetName_Binary);
1083:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerFileSetMode_C",
1084:                                     "PetscViewerFileSetMode_Binary",
1085:                                      PetscViewerFileSetMode_Binary);
1086:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerFileGetMode_C",
1087:                                     "PetscViewerFileGetMode_Binary",
1088:                                      PetscViewerFileGetMode_Binary);
1089: #if defined(PETSC_HAVE_MPIIO)
1090:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerBinarySetMPIIO_C",
1091:                                     "PetscViewerBinarySetMPIIO_Binary",
1092:                                      PetscViewerBinarySetMPIIO_Binary);
1093: 
1094:   PetscOptionsHasName(PETSC_NULL,"-viewer_binary_mpiio",&useMPIIO);
1095:   if (useMPIIO) {
1096:     PetscViewerBinarySetMPIIO(v);
1097:   }
1098: #endif
1099:   return(0);
1100: }


1104: /* ---------------------------------------------------------------------*/
1105: /*
1106:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1107:   is attached to a communicator, in this case the attribute is a PetscViewer.
1108: */
1109: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

1113: /*@C
1114:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors 
1115:                      in a communicator.

1117:      Collective on MPI_Comm

1119:      Input Parameter:
1120: .    comm - the MPI communicator to share the binary PetscViewer
1121:     
1122:      Level: intermediate

1124:    Options Database Keys:
1125: $    -viewer_binary_filename <name>

1127:    Environmental variables:
1128: -   PETSC_VIEWER_BINARY_FILENAME

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

1135: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1136:           PetscViewerDestroy()
1137: @*/
1138: PetscViewer  PETSC_VIEWER_BINARY_(MPI_Comm comm)
1139: {
1141:   PetscTruth     flg;
1142:   PetscViewer    viewer;
1143:   char           fname[PETSC_MAX_PATH_LEN];

1146:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1147:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
1148:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," ");return(0);}
1149:   }
1150:   MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int*)&flg);
1151:   if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," ");return(0);}
1152:   if (!flg) { /* PetscViewer not yet created */
1153:     PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1154:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," ");return(0);}
1155:     if (!flg) {
1156:       PetscStrcpy(fname,"binaryoutput");
1157:       if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," ");return(0);}
1158:     }
1159:     PetscViewerBinaryOpen(comm,fname,FILE_MODE_WRITE,&viewer);
1160:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," ");return(0);}
1161:     PetscObjectRegisterDestroy((PetscObject)viewer);
1162:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," ");return(0);}
1163:     MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1164:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," ");return(0);}
1165:   }
1166:   PetscFunctionReturn(viewer);
1167: }