Actual source code: binv.c

      1: #define PETSC_DLL
     2:  #include src/sys/src/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 */
     14:   PetscViewerFileType btype;           /* read or write? */
     15:   FILE                *fdes_info;      /* optional file containing info on binary file*/
     16:   PetscTruth          storecompressed; /* gzip the write binary file when closing it*/
     17:   char                *filename;
     18:   PetscTruth          skipinfo;        /* Don't create info file for writing; don't use for reading */
     19:   PetscTruth          skipoptions;     /* don't use PETSc options database when loading */
     20: } PetscViewer_Binary;

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

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

     45: PetscErrorCode PetscViewerRestoreSingleton_Binary(PetscViewer viewer,PetscViewer *outviewer)
     46: {
     48:   PetscErrorCode rank;

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

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

     64:     Not Collective

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

     69:     Level: advanced

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

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

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

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

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

     99:     Not Collective

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

    104:     Options Database Key:
    105: .   -viewer_binary_skip_info

    107:     Level: advanced

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

    111:    Concepts: PetscViewerBinary^accessing info file

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

    121:   vbinary->skipinfo = PETSC_TRUE;
    122:   return(0);
    123: }

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

    130:     Not Collective

    132:     Input Paramter:
    133: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    134: -   skip - PETSC_TRUE means do not use

    136:     Options Database Key:
    137: .   -viewer_binary_skip_options

    139:     Level: advanced

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

    143:    Concepts: PetscViewerBinary^accessing info file

    145: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    146:           PetscViewerBinaryGetSkipOptions()
    147: @*/
    148: PetscErrorCode PETSC_DLLEXPORT PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscTruth skip)
    149: {
    150:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    153:   vbinary->skipoptions = skip;
    154:   return(0);
    155: }

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

    162:     Not Collective

    164:     Input Paramter:
    165: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    167:     Output Parameter:
    168: .   skip - PETSC_TRUE means do not use

    170:     Level: advanced

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

    174:    Concepts: PetscViewerBinary^accessing info file

    176: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    177:           PetscViewerBinarySetSkipOptions()
    178: @*/
    179: PetscErrorCode PETSC_DLLEXPORT PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscTruth *skip)
    180: {
    181:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    184:   *skip = vbinary->skipoptions;
    185:   return(0);
    186: }

    190: /*@C
    191:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
    192:           info file associated with a binary file.

    194:     Not Collective

    196: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    197: -   file - file pointer

    199:     Level: advanced

    201:     Notes:
    202:       For writable binary PetscViewers, the descriptor will only be valid for the
    203:     first processor in the communicator that shares the PetscViewer.
    204:
    205:     Fortran Note:
    206:     This routine is not supported in Fortran.

    208:   Concepts: PetscViewerBinary^accessing info file

    210: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
    211: @*/
    212: PetscErrorCode PETSC_DLLEXPORT PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
    213: {
    214:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    217:   *file = vbinary->fdes_info;
    218:   return(0);
    219: }

    223: PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
    224: {
    225:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    226:   PetscErrorCode     ierr;
    227:   int                rank;

    230:   MPI_Comm_rank(v->comm,&rank);
    231:   if ((!rank || vbinary->btype == PETSC_FILE_RDONLY ) && vbinary->fdes) {
    232:     close(vbinary->fdes);
    233:     if (!rank && vbinary->storecompressed) {
    234:       char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
    235:       FILE *fp;
    236:       /* compress the file */
    237:       PetscStrcpy(par,"gzip ");
    238:       PetscStrcat(par,vbinary->filename);
    239: #if defined(PETSC_HAVE_POPEN)
    240:       PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,par,"r",&fp);
    241:       if (fgets(buf,1024,fp)) {
    242:         SETERRQ2(PETSC_ERR_LIB,"Error from command %s\n%s",par,buf);
    243:       }
    244:       PetscPClose(PETSC_COMM_SELF,fp);
    245: #else
    246:       SETERRQ(PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
    247: #endif
    248:     }
    249:   }
    250:   if (vbinary->fdes_info) fclose(vbinary->fdes_info);
    251:   PetscStrfree(vbinary->filename);
    252:   PetscFree(vbinary);
    253:   return(0);
    254: }

    258: /*@C
    259:    PetscViewerBinaryOpen - Opens a file for binary input/output.

    261:    Collective on MPI_Comm

    263:    Input Parameters:
    264: +  comm - MPI communicator
    265: .  name - name of file
    266: -  type - type of file
    267: $    PETSC_FILE_CREATE - create new file for binary output
    268: $    PETSC_FILE_RDONLY - open existing file for binary input
    269: $    PETSC_FILE_WRONLY - open existing file for binary output

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

    274:    Level: beginner

    276:    Note:
    277:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

    285:     For writing files it only opens the file on processor 0 in the communicator.
    286:     For readable files it opens the file on all nodes that have the file. If
    287:     node 0 does not have the file it generates an error even if other nodes
    288:     do have the file.

    290:    Concepts: binary files
    291:    Concepts: PetscViewerBinary^creating
    292:    Concepts: gzip
    293:    Concepts: accessing remote file
    294:    Concepts: remote file

    296: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
    297:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    298:           PetscViewerBinaryGetInfoPointer(), PetscViewerFileType, PetscViewer, PetscBinaryViewerRead()
    299: @*/
    300: PetscErrorCode PETSC_DLLEXPORT PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscViewerFileType type,PetscViewer *binv)
    301: {
    303:
    305:   PetscViewerCreate(comm,binv);
    306:   PetscViewerSetType(*binv,PETSC_VIEWER_BINARY);
    307:   PetscViewerSetFileType(*binv,type);
    308:   PetscViewerSetFilename(*binv,name);
    309:   return(0);
    310: }

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

    317:    Collective on MPI_Comm

    319:    Input Parameters:
    320: +  viewer - the binary viewer
    321: .  data - location to write the data
    322: .  count - number of items of data to read
    323: -  datatype - type of data to read

    325:    Level: beginner

    327:    Concepts: binary files

    329: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
    330:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    331:           PetscViewerBinaryGetInfoPointer(), PetscViewerFileType, PetscViewer, PetscBinaryViewerRead()
    332: @*/
    333: PetscErrorCode PETSC_DLLEXPORT PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype)
    334: {
    335:   PetscErrorCode     ierr;
    336:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    338:   PetscSynchronizedBinaryRead(viewer->comm,vbinary->fdes,data,count,dtype);
    339:   return(0);
    340: }

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

    347:    Collective on MPI_Comm

    349:    Input Parameters:
    350: +  viewer - the binary viewer
    351: .  data - location of data
    352: .  count - number of items of data to read
    353: .  istemp - data may be overwritten
    354: -  datatype - type of data to read

    356:    Level: beginner

    358:    Concepts: binary files

    360: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
    361:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    362:           PetscViewerBinaryGetInfoPointer(), PetscViewerFileType, PetscViewer, PetscBinaryViewerRead()
    363: @*/
    364: PetscErrorCode PETSC_DLLEXPORT PetscViewerBinaryWrite(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscTruth istemp)
    365: {
    366:   PetscErrorCode     ierr;
    367:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    369:   PetscSynchronizedBinaryWrite(viewer->comm,vbinary->fdes,data,count,dtype,istemp);
    370:   return(0);
    371: }

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

    378:    Collective on MPI_Comm

    380:    Input Parameters:
    381: +  viewer - the binary viewer
    382: -  data - location of the array of strings

    385:    Level: intermediate

    387:    Concepts: binary files

    389:     Notes: array of strings is null terminated

    391: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
    392:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    393:           PetscViewerBinaryGetInfoPointer(), PetscViewerFileType, PetscViewer, PetscBinaryViewerRead()
    394: @*/
    395: PetscErrorCode PETSC_DLLEXPORT PetscViewerBinaryWriteStringArray(PetscViewer viewer,char **data)
    396: {
    397:   PetscErrorCode     ierr;
    398:   PetscInt           i,n = 0,*sizes;

    400:   /* count number of strings */
    401:   while (data[n++]);
    402:   n--;
    403:   PetscMalloc((n+1)*sizeof(PetscInt),&sizes);
    404:   sizes[0] = n;
    405:   for (i=0; i<n; i++) {
    406:     size_t tmp;
    407:     PetscStrlen(data[i],&tmp);
    408:     sizes[i+1] = tmp + 1;   /* size includes space for the null terminator */
    409:   }
    410:   PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT,PETSC_FALSE);
    411:   for (i=0; i<n; i++) {
    412:     PetscViewerBinaryWrite(viewer,data[i],sizes[i+1],PETSC_CHAR,PETSC_FALSE);
    413:   }
    414:   PetscFree(sizes);
    415:   return(0);
    416: }

    418: /*@C
    419:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

    421:    Collective on MPI_Comm

    423:    Input Parameter:
    424: .  viewer - the binary viewer

    426:    Output Parameter:
    427: .  data - location of the array of strings

    429:    Level: intermediate

    431:    Concepts: binary files

    433:     Notes: array of strings is null terminated

    435: .seealso: PetscViewerASCIIOpen(), PetscViewerSetFormat(), PetscViewerDestroy(),
    436:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    437:           PetscViewerBinaryGetInfoPointer(), PetscViewerFileType, PetscViewer, PetscBinaryViewerRead()
    438: @*/
    439: PetscErrorCode PETSC_DLLEXPORT PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
    440: {
    441:   PetscErrorCode     ierr;
    442:   PetscInt           i,n,*sizes,N = 0;

    444:   /* count number of strings */
    445:   PetscViewerBinaryRead(viewer,&n,1,PETSC_INT);
    446:   PetscMalloc(n*sizeof(PetscInt),&sizes);
    447:   PetscViewerBinaryRead(viewer,sizes,n,PETSC_INT);
    448:   for (i=0; i<n; i++) {
    449:     N += sizes[i];
    450:   }
    451:   PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);
    452:   (*data)[0] = (char*)((*data) + n + 1);
    453:   for (i=1; i<n; i++) {
    454:     (*data)[i] = (*data)[i-1] + sizes[i-1];
    455:   }
    456:   PetscViewerBinaryRead(viewer,(*data)[0],N,PETSC_CHAR);
    457:   (*data)[n] = 0;
    458:   PetscFree(sizes);
    459:   return(0);
    460: }

    464: /*@C
    465:      PetscViewerSetFileType - Sets the type of file to be open

    467:     Collective on PetscViewer

    469:   Input Parameters:
    470: +  viewer - the PetscViewer; must be a binary, Matlab, hdf, or netcdf PetscViewer
    471: -  type - type of file
    472: $    PETSC_FILE_CREATE - create new file for binary output
    473: $    PETSC_FILE_RDONLY - open existing file for binary input
    474: $    PETSC_FILE_WRONLY - open existing file for binary output

    476:   Level: advanced

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

    480: @*/
    481: PetscErrorCode PETSC_DLLEXPORT PetscViewerSetFileType(PetscViewer viewer,PetscViewerFileType type)
    482: {
    483:   PetscErrorCode ierr,(*f)(PetscViewer,PetscViewerFileType);

    487:   PetscObjectQueryFunction((PetscObject)viewer,"PetscViewerSetFileType_C",(void (**)(void))&f);
    488:   if (f) {
    489:     (*f)(viewer,type);
    490:   }
    491:   return(0);
    492: }

    497: PetscErrorCode PETSC_DLLEXPORT PetscViewerSetFileType_Binary(PetscViewer viewer,PetscViewerFileType type)
    498: {
    499:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    502:   vbinary->btype = type;
    503:   return(0);
    504: }

    509: /*@
    510:     PetscViewerBinaryLoadInfo - Loads options from the name.info file
    511:        if it exists.

    513:    Collective on PetscViewer

    515:   Input Parameter:
    516: .    viewer - the binary viewer whose options you wish to load

    518:    Level: developer

    520: @*/
    521: PetscErrorCode PETSC_DLLEXPORT PetscViewerBinaryLoadInfo(PetscViewer viewer)
    522: {
    523:   FILE               *file;
    524:   char               string[256],*first,*second,*final;
    525:   size_t             len;
    526:   PetscErrorCode     ierr;
    527:   PetscToken         *token;
    528:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    531:   if (vbinary->skipinfo) return(0);

    533:   PetscViewerBinaryGetInfoPointer(viewer,&file);
    534:   if (!file) return(0);

    536:   /* read rows of the file adding them to options database */
    537:   while (fgets(string,256,file)) {
    538:     /* Comments are indicated by #, ! or % in the first column */
    539:     if (string[0] == '#') continue;
    540:     if (string[0] == '!') continue;
    541:     if (string[0] == '%') continue;
    542:     PetscTokenCreate(string,' ',&token);
    543:     PetscTokenFind(token,&first);
    544:     PetscTokenFind(token,&second);
    545:     if (first && first[0] == '-') {
    546:       PetscTruth wrongtype;
    547:       /*
    548:          Check for -mat_complex or -mat_double
    549:       */
    550: #if defined(PETSC_USE_COMPLEX)
    551:       PetscStrncmp(first,"-mat_double",11,&wrongtype);
    552:       if (wrongtype) {
    553:         SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Loading double number matrix with complex number code");
    554:       }
    555: #else
    556:       PetscStrncmp(first,"-mat_complex",12,&wrongtype);
    557:       if (wrongtype) {
    558:         SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Loading complex number matrix with double number code");
    559:       }
    560: #endif

    562:       if (second) {final = second;} else {final = first;}
    563:       PetscStrlen(final,&len);
    564:       while (len > 0 && (final[len-1] == ' ' || final[len-1] == '\n')) {
    565:         len--; final[len] = 0;
    566:       }
    567:       PetscOptionsSetValue(first,second);
    568:     }
    569:     PetscTokenDestroy(token);
    570:   }
    571:   return(0);
    572: }

    574: /*
    575:         Actually opens the file
    576: */
    580: PetscErrorCode PETSC_DLLEXPORT PetscViewerSetFilename_Binary(PetscViewer viewer,const char name[])
    581: {
    582:   int                 rank;
    583:   PetscErrorCode      ierr;
    584:   size_t              len;
    585:   PetscViewer_Binary  *vbinary = (PetscViewer_Binary*)viewer->data;
    586:   const char          *fname;
    587:   char                bname[PETSC_MAX_PATH_LEN],*gz;
    588:   PetscTruth          found;
    589:   PetscViewerFileType type = vbinary->btype;

    592:   if (type == (PetscViewerFileType) -1) {
    593:     SETERRQ(PETSC_ERR_ORDER,"Must call PetscViewerBinarySetType() before PetscViewerSetFilename()");
    594:   }
    595:   PetscOptionsGetTruth(viewer->prefix,"-viewer_binary_skip_info",&vbinary->skipinfo,PETSC_NULL);
    596:   PetscOptionsGetTruth(viewer->prefix,"-viewer_binary_skip_options",&vbinary->skipoptions,PETSC_NULL);

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

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

    603:   /* if ends in .gz strip that off and note user wants file compressed */
    604:   vbinary->storecompressed = PETSC_FALSE;
    605:   if (!rank && type == PETSC_FILE_CREATE) {
    606:     /* remove .gz if it ends library name */
    607:     PetscStrstr(vbinary->filename,".gz",&gz);
    608:     if (gz) {
    609:       PetscStrlen(gz,&len);
    610:       if (len == 3) {
    611:         *gz = 0;
    612:         vbinary->storecompressed = PETSC_TRUE;
    613:       }
    614:     }
    615:   }

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

    620:     if (type == PETSC_FILE_RDONLY){
    621:       /* possibly get the file from remote site or compressed file */
    622:       PetscFileRetrieve(viewer->comm,vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
    623:       fname = bname;
    624:       if (!rank && !found) {
    625:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
    626:       } else if (!found) {
    627:         PetscLogInfo((viewer,"PetscViewerSetFilename_Binary:Nonzero processor did not locate readonly file\n"));
    628:         fname = 0;
    629:       }
    630:     } else {
    631:       fname = vbinary->filename;
    632:     }

    634: #if defined(PETSC_HAVE_O_BINARY)
    635:     if (type == PETSC_FILE_CREATE) {
    636:       if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
    637:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
    638:       }
    639:     } else if (type == PETSC_FILE_RDONLY && fname) {
    640:       if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) {
    641:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
    642:       }
    643:     } else if (type == PETSC_FILE_WRONLY) {
    644:       if ((vbinary->fdes = open(fname,O_WRONLY|O_BINARY,0)) == -1) {
    645:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
    646:       }
    647:     } else if (fname) {
    648:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
    649:     }
    650: #else
    651:     if (type == PETSC_FILE_CREATE) {
    652:       if ((vbinary->fdes = creat(fname,0666)) == -1) {
    653:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
    654:       }
    655:     } else if (type == PETSC_FILE_RDONLY && fname) {
    656:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) {
    657:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
    658:       }
    659:     } else if (type == PETSC_FILE_WRONLY) {
    660:       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND,0)) == -1) {
    661:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
    662:       }
    663:     } else if (fname) {
    664:       SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
    665:     }
    666: #endif
    667:   } else vbinary->fdes = -1;
    668:   viewer->format = PETSC_VIEWER_NOFORMAT;

    670:   /*
    671:       try to open info file: all processors open this file if read only
    672:   */
    673:   if (!rank || type == PETSC_FILE_RDONLY) {
    674:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];
    675:
    676:     PetscStrcpy(infoname,name);
    677:     /* remove .gz if it ends library name */
    678:     PetscStrstr(infoname,".gz",&gz);
    679:     if (gz) {
    680:       PetscStrlen(gz,&len);
    681:       if (len == 3) {
    682:         *gz = 0;
    683:       }
    684:     }
    685:
    686:     PetscStrcat(infoname,".info");
    687:     PetscFixFilename(infoname,iname);
    688:     if (type == PETSC_FILE_RDONLY) {
    689:       PetscFileRetrieve(viewer->comm,iname,infoname,PETSC_MAX_PATH_LEN,&found);
    690:       if (found) {
    691:         vbinary->fdes_info = fopen(infoname,"r");
    692:         if (vbinary->fdes_info) {
    693:           PetscViewerBinaryLoadInfo(viewer);
    694:           fclose(vbinary->fdes_info);
    695:         }
    696:         vbinary->fdes_info = fopen(infoname,"r");
    697:       }
    698:     } else if (!vbinary->skipinfo) {
    699:       vbinary->fdes_info = fopen(infoname,"w");
    700:       if (!vbinary->fdes_info) {
    701:         SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
    702:       }
    703:     }
    704:   }

    706: #if defined(PETSC_USE_LOG)
    707:   PetscLogObjectState((PetscObject)viewer,"File: %s",name);
    708: #endif
    709:   return(0);
    710: }

    716: PetscErrorCode PETSC_DLLEXPORT PetscViewerCreate_Binary(PetscViewer v)
    717: {
    718:   PetscErrorCode     ierr;
    719:   PetscViewer_Binary *vbinary;

    722:   PetscNew(PetscViewer_Binary,&vbinary);
    723:   v->data            = (void*)vbinary;
    724:   v->ops->destroy    = PetscViewerDestroy_Binary;
    725:   v->ops->flush      = 0;
    726:   v->iformat         = 0;
    727:   vbinary->fdes_info = 0;
    728:   vbinary->fdes      = 0;
    729:   vbinary->skipinfo        = PETSC_FALSE;
    730:   vbinary->skipoptions     = PETSC_TRUE;
    731:   v->ops->getsingleton     = PetscViewerGetSingleton_Binary;
    732:   v->ops->restoresingleton = PetscViewerRestoreSingleton_Binary;
    733:   vbinary->btype           = (PetscViewerFileType) -1;
    734:   vbinary->storecompressed = PETSC_FALSE;
    735:   vbinary->filename        = 0;

    737:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFilename_C",
    738:                                     "PetscViewerSetFilename_Binary",
    739:                                      PetscViewerSetFilename_Binary);
    740:   PetscObjectComposeFunctionDynamic((PetscObject)v,"PetscViewerSetFileType_C",
    741:                                     "PetscViewerSetFileType_Binary",
    742:                                      PetscViewerSetFileType_Binary);
    743:   return(0);
    744: }

    748: /* ---------------------------------------------------------------------*/
    749: /*
    750:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
    751:   is attached to a communicator, in this case the attribute is a PetscViewer.
    752: */
    753: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

    757: /*@C
    758:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
    759:                      in a communicator.

    761:      Collective on MPI_Comm

    763:      Input Parameter:
    764: .    comm - the MPI communicator to share the binary PetscViewer
    765:
    766:      Level: intermediate

    768:    Options Database Keys:
    769: $    -viewer_binary_filename <name>

    771:    Environmental variables:
    772: -   PETSC_VIEWER_BINARY_FILENAME

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

    779: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
    780:           PetscViewerDestroy()
    781: @*/
    782: PetscViewer PETSC_DLLEXPORT PETSC_VIEWER_BINARY_(MPI_Comm comm)
    783: {
    785:   PetscTruth     flg;
    786:   PetscViewer    viewer;
    787:   char           fname[PETSC_MAX_PATH_LEN];

    790:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
    791:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
    792:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
    793:   }
    794:   MPI_Attr_get(comm,Petsc_Viewer_Binary_keyval,(void **)&viewer,(int*)&flg);
    795:   if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
    796:   if (!flg) { /* PetscViewer not yet created */
    797:     PetscOptionsGetenv(comm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
    798:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
    799:     if (!flg) {
    800:       PetscStrcpy(fname,"binaryoutput");
    801:       if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
    802:     }
    803:     PetscViewerBinaryOpen(comm,fname,PETSC_FILE_CREATE,&viewer);
    804:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
    805:     PetscObjectRegisterDestroy((PetscObject)viewer);
    806:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
    807:     MPI_Attr_put(comm,Petsc_Viewer_Binary_keyval,(void*)viewer);
    808:     if (ierr) {PetscError(__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,__SDIR__,1,1," "); viewer = 0;}
    809:   }
    810:   PetscFunctionReturn(viewer);
    811: }