Date: 2016-07-24T16:46:08+00:00

Actual source code: binv.c
petsc-3.7.3 2016-07-24
Report Typos and Errors

      2: #include <petsc/private/viewerimpl.h>    /*I   "petscviewer.h"   I*/
      3: #include <fcntl.h>
      4: #if defined(PETSC_HAVE_UNISTD_H)
      5: #include <unistd.h>
      6: #endif
      7: #if defined(PETSC_HAVE_IO_H)
      8: #include <io.h>
      9: #endif

     11: typedef struct  {
     12:   int           fdes;                 /* file descriptor, ignored if using MPI IO */
     13: #if defined(PETSC_HAVE_MPIIO)
     14:   PetscBool     usempiio;
     15:   MPI_File      mfdes;                /* ignored unless using MPI IO */
     16:   MPI_Offset    moff;
     17: #endif
     18:   PetscFileMode btype;                /* read or write? */
     19:   FILE          *fdes_info;           /* optional file containing info on binary file*/
     20:   PetscBool     storecompressed;      /* gzip the write binary file when closing it*/
     21:   char          *filename;
     22:   PetscBool     skipinfo;             /* Don't create info file for writing; don't use for reading */
     23:   PetscBool     skipoptions;          /* don't use PETSc options database when loading */
     24:   PetscInt      flowcontrol;          /* allow only <flowcontrol> messages outstanding at a time while doing IO */
     25:   PetscBool     skipheader;           /* don't write header, only raw data */
     26:   PetscBool     matlabheaderwritten;  /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
     27:   PetscBool     setfromoptionscalled;
     28: } PetscViewer_Binary;

     32: static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
     33: {
     34:   int                rank;
     35:   PetscErrorCode     ierr;
     36:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data,*obinary;

     39:   PetscViewerSetUp(viewer);
     40:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
     41:   if (!rank) {
     42:     PetscViewerCreate(PETSC_COMM_SELF,outviewer);
     43:     PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);
     44:     obinary = (PetscViewer_Binary*)(*outviewer)->data;
     45:     PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));
     46:   } SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Cannot get subcomm viewer for binary files or sockets unless SubViewer contains the rank 0 process");
     47:   return(0);
     48: }

     52: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
     53: {
     55:   PetscErrorCode rank;

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

     66: #if defined(PETSC_HAVE_MPIIO)
     69: /*@C
     70:     PetscViewerBinaryGetMPIIOOffset - Gets the current offset that should be passed to MPI_File_set_view()

     72:     Not Collective

     74:     Input Parameter:
     75: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

     77:     Output Parameter:
     78: .    off - the current offset

     80:     Level: advanced

     82:     Fortran Note:
     83:     This routine is not supported in Fortran.

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

     87:   Concepts: file descriptor^getting
     88:   Concepts: PetscViewerBinary^accessing file descriptor

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

     97:   *off = vbinary->moff;
     98:   return(0);
     99: }

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

    106:     Not Collective

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

    112:     Level: advanced

    114:     Fortran Note:
    115:     This routine is not supported in Fortran.

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

    119:   Concepts: file descriptor^getting
    120:   Concepts: PetscViewerBinary^accessing file descriptor

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

    129:   vbinary->moff += off;
    130:   return(0);
    131: }

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

    138:     Not Collective

    140:     Input Parameter:
    141: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    143:     Output Parameter:
    144: .   fdes - file descriptor

    146:     Level: advanced

    148:     Fortran Note:
    149:     This routine is not supported in Fortran.

    151:   Concepts: file descriptor^getting
    152:   Concepts: PetscViewerBinary^accessing file descriptor

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

    162:   PetscViewerSetUp(viewer);
    163:   *fdes = vbinary->mfdes;
    164:   return(0);
    165: }

    169: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *flg)
    170: {
    171:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    172:
    174:   *flg = vbinary->usempiio;
    175:   return(0);
    176: }
    177: #endif

    182: /*@C
    183:     PetscViewerBinaryGetUseMPIIO - Returns PETSC_TRUE if the binary viewer uses MPI-IO.

    185:     Not Collective

    187:     Input Parameter:
    188: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    190:     Output Parameter:
    191: -   flg - PETSC_TRUE if MPI-IO is being used

    193:     Options Database:
    194:     -viewer_binary_mpiio : Flag for using MPI-IO

    196:     Level: advanced

    198:     Note:
    199:     If MPI-IO is not available, this function will always return PETSC_FALSE

    201:     Fortran Note:
    202:     This routine is not supported in Fortran.

    204:   Concepts: file descriptor^getting
    205:   Concepts: PetscViewerBinary^accessing file descriptor

    207: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer()
    208: @*/
    209: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *flg)
    210: {

    214:   *flg = PETSC_FALSE;
    215:   PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,flg));
    216:   return(0);
    217: }

    221: static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
    222: {
    223:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    226:   *fc = vbinary->flowcontrol;
    227:   return(0);
    228: }

    232: /*@C
    233:     PetscViewerBinaryGetFlowControl - Returns how many messages are allowed to outstanding at the same time during parallel IO reads/writes

    235:     Not Collective

    237:     Input Parameter:
    238: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    240:     Output Parameter:
    241: .   fc - the number of messages

    243:     Level: advanced

    245: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetFlowControl()

    247: @*/
    248: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
    249: {

    253:   PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));
    254:   return(0);
    255: }

    259: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
    260: {
    261:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    264:   if (fc <= 1) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ARG_OUTOFRANGE,"Flow control count must be greater than 1, %D was set",fc);
    265:   vbinary->flowcontrol = fc;
    266:   return(0);
    267: }

    271: /*@C
    272:     PetscViewerBinarySetFlowControl - Sets how many messages are allowed to outstanding at the same time during parallel IO reads/writes

    274:     Not Collective

    276:     Input Parameter:
    277: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    278: -   fc - the number of messages, defaults to 256 if this function was not called

    280:     Level: advanced

    282: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetFlowControl()

    284: @*/
    285: PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
    286: {

    290:   PetscUseMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));
    291:   return(0);
    292: }

    296: /*@C
    297:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

    299:     Collective On PetscViewer

    301:     Input Parameter:
    302: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    304:     Output Parameter:
    305: .   fdes - file descriptor

    307:     Level: advanced

    309:     Notes:
    310:       For writable binary PetscViewers, the descriptor will only be valid for the
    311:     first processor in the communicator that shares the PetscViewer. For readable
    312:     files it will only be valid on nodes that have the file. If node 0 does not
    313:     have the file it generates an error even if another node does have the file.

    315:     Fortran Note:
    316:     This routine is not supported in Fortran.

    318:     Developer Notes: This must be called on all processes because Dave May changed
    319:     the source code that this may be trigger a PetscViewerSetUp() call if it was not previously triggered.

    322:   Concepts: file descriptor^getting
    323:   Concepts: PetscViewerBinary^accessing file descriptor

    325: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
    326: @*/
    327: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
    328: {
    329:   PetscErrorCode     ierr;
    330:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    333:   PetscViewerSetUp(viewer);
    334:   *fdes = vbinary->fdes;
    335:   return(0);
    336: }

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

    343:     Not Collective

    345:     Input Paramter:
    346: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

    348:     Options Database Key:
    349: .   -viewer_binary_skip_info

    351:     Level: advanced

    353:     Notes: This must be called after PetscViewerSetType(). If you use PetscViewerBinaryOpen() then
    354:     you can only skip the info file with the -viewer_binary_skip_info flag. To use the function you must open the
    355:     viewer with PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinarySkipInfo().

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

    360:    Concepts: PetscViewerBinary^accessing info file

    362: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
    363:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
    364: @*/
    365: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
    366: {
    367:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    370:   vbinary->skipinfo = PETSC_TRUE;
    371:   return(0);
    372: }

    376: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
    377: {
    378:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    381:   vbinary->skipinfo = skip;
    382:   return(0);
    383: }

    387: /*@
    388:     PetscViewerBinarySetSkipInfo - Binary file will not have .info file created with it

    390:     Not Collective

    392:     Input Paramter:
    393: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

    395:     Options Database Key:
    396: .   -viewer_binary_skip_info

    398:     Level: advanced

    400:     Concepts: PetscViewerBinary^accessing info file

    402: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
    403:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
    404: @*/
    405: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
    406: {

    410:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));
    411:   return(0);
    412: }

    416: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
    417: {
    418:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    421:   *skip  = vbinary->skipinfo;
    422:   return(0);
    423: }

    427: /*@
    428:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

    430:     Not Collective

    432:     Input Parameter:
    433: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    435:     Output Parameter:
    436: .   skip - PETSC_TRUE implies the .info file was not generated

    438:     Level: advanced

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

    442:     Concepts: PetscViewerBinary^accessing info file

    444: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    445:           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
    446: @*/
    447: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
    448: {

    452:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));
    453:   return(0);
    454: }

    458: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
    459: {
    460:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    463:   vbinary->skipoptions = skip;
    464:   return(0);
    465: }

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

    472:     Not Collective

    474:     Input Parameters:
    475: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    476: -   skip - PETSC_TRUE means do not use

    478:     Options Database Key:
    479: .   -viewer_binary_skip_options

    481:     Level: advanced

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

    485:    Concepts: PetscViewerBinary^accessing info file

    487: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    488:           PetscViewerBinaryGetSkipOptions()
    489: @*/
    490: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)
    491: {

    495:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));
    496:   return(0);
    497: }

    501: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
    502: {
    503:   PetscViewer_Binary *vbinary;

    507:   vbinary = (PetscViewer_Binary*)viewer->data;
    508:   *skip   = vbinary->skipoptions;
    509:   return(0);
    510: }

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

    517:     Not Collective

    519:     Input Parameter:
    520: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    522:     Output Parameter:
    523: .   skip - PETSC_TRUE means do not use

    525:     Level: advanced

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

    529:    Concepts: PetscViewerBinary^accessing info file

    531: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    532:           PetscViewerBinarySetSkipOptions()
    533: @*/
    534: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
    535: {

    539:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));
    540:   return(0);
    541: }

    545: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
    546: {
    547:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    550:   vbinary->skipheader = skip;
    551:   return(0);
    552: }

    556: /*@
    557:     PetscViewerBinarySetSkipHeader - do not write a header with size information on output, just raw data

    559:     Not Collective

    561:     Input Parameters:
    562: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    563: -   skip - PETSC_TRUE means do not write header

    565:     Options Database Key:
    566: .   -viewer_binary_skip_header

    568:     Level: advanced

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

    572:            Can ONLY be called on a binary viewer

    574: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    575:           PetscViewerBinaryGetSkipHeader()
    576: @*/
    577: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
    578: {

    582:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));
    583:   return(0);
    584: }

    588: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool  *skip)
    589: {
    590:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    593:   *skip = vbinary->skipheader;
    594:   return(0);
    595: }

    599: /*@
    600:     PetscViewerBinaryGetSkipHeader - checks whether to write a header with size information on output, or just raw data

    602:     Not Collective

    604:     Input Parameter:
    605: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    607:     Output Parameter:
    608: .   skip - PETSC_TRUE means do not write header

    610:     Level: advanced

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

    614:             Returns false for PETSCSOCKETVIEWER, you cannot skip the header for it.

    616: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    617:           PetscViewerBinarySetSkipHeader()
    618: @*/
    619: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool  *skip)
    620: {

    624:   *skip = PETSC_FALSE;
    625:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));
    626:   return(0);
    627: }

    631: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
    632: {
    633:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    634:   PetscErrorCode     ierr;
    635:   MPI_Comm           comm;

    638:   PetscViewerSetUp(viewer);
    639:   *file = vbinary->fdes_info;
    640:   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
    641:     vbinary->matlabheaderwritten = PETSC_TRUE;
    642:     PetscObjectGetComm((PetscObject)viewer,&comm);
    643:     PetscFPrintf(comm,*file,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
    644:     PetscFPrintf(comm,*file,"#$$ Set.filename = '%s';\n",vbinary->filename);
    645:     PetscFPrintf(comm,*file,"#$$ fd = PetscOpenFile(Set.filename);\n");
    646:     PetscFPrintf(comm,*file,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
    647:   }
    648:   return(0);
    649: }

    653: /*@C
    654:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
    655:           info file associated with a binary file.

    657:     Not Collective

    659:     Input Parameter:
    660: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    662:     Output Parameter:
    663: .   file - file pointer  Always returns NULL if not a binary viewer

    665:     Level: advanced

    667:     Notes:
    668:       For writable binary PetscViewers, the descriptor will only be valid for the
    669:     first processor in the communicator that shares the PetscViewer.

    671:     Fortran Note:
    672:     This routine is not supported in Fortran.

    674:   Concepts: PetscViewerBinary^accessing info file

    676: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
    677: @*/
    678: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
    679: {

    683:   *file = NULL;
    684:   PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));
    685:   return(0);
    686: }

    690: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
    691: {
    692:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    693:   PetscErrorCode     ierr;
    694:   PetscMPIInt        rank;
    695:   int                err;

    698:   MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);
    699:   if ((!rank || vbinary->btype == FILE_MODE_READ) && vbinary->fdes) {
    700:     close(vbinary->fdes);
    701:     if (!rank && vbinary->storecompressed) {
    702:       char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
    703:       FILE *fp;
    704:       /* compress the file */
    705:       PetscStrcpy(par,"gzip -f ");
    706:       PetscStrcat(par,vbinary->filename);
    707: #if defined(PETSC_HAVE_POPEN)
    708:       PetscPOpen(PETSC_COMM_SELF,NULL,par,"r",&fp);
    709:       if (fgets(buf,1024,fp)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from command %s\n%s",par,buf);
    710:       PetscPClose(PETSC_COMM_SELF,fp,NULL);
    711: #else
    712:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
    713: #endif
    714:     }
    715:   }
    716:   if (vbinary->fdes_info) {
    717:     err = fclose(vbinary->fdes_info);
    718:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
    719:   }
    720:   return(0);
    721: }

    723: #if defined(PETSC_HAVE_MPIIO)
    726: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
    727: {
    728:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    729:   int                err;
    730:   PetscErrorCode     ierr;

    733:   if (vbinary->mfdes) {
    734:     MPI_File_close(&vbinary->mfdes);
    735:   }
    736:   if (vbinary->fdes_info) {
    737:     err = fclose(vbinary->fdes_info);
    738:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
    739:   }
    740:   return(0);
    741: }
    742: #endif

    746: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
    747: {
    748:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    749:   PetscErrorCode     ierr;

    752:   if (v->format == PETSC_VIEWER_BINARY_MATLAB) {
    753:     MPI_Comm comm;
    754:     FILE     *info;

    756:     PetscObjectGetComm((PetscObject)v,&comm);
    757:     PetscViewerBinaryGetInfoPointer(v,&info);
    758:     PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
    759:     PetscFPrintf(comm,info,"#$$ close(fd);\n");
    760:     PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
    761:   }
    762: #if defined(PETSC_HAVE_MPIIO)
    763:   if (vbinary->usempiio) {
    764:     PetscViewerFileClose_BinaryMPIIO(v);
    765:   } else {
    766: #endif
    767:     PetscViewerFileClose_Binary(v);
    768: #if defined(PETSC_HAVE_MPIIO)
    769:   }
    770: #endif
    771:   if (vbinary->filename) { PetscFree(vbinary->filename); }
    772:   PetscFree(vbinary);
    773:   return(0);
    774: }

    778: /*@C
    779:    PetscViewerBinaryOpen - Opens a file for binary input/output.

    781:    Collective on MPI_Comm

    783:    Input Parameters:
    784: +  comm - MPI communicator
    785: .  name - name of file
    786: -  type - type of file
    787: $    FILE_MODE_WRITE - create new file for binary output
    788: $    FILE_MODE_READ - open existing file for binary input
    789: $    FILE_MODE_APPEND - open existing file for binary output

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

    794:     Options Database Keys:
    795: +    -viewer_binary_filename <name>
    796: .    -viewer_binary_skip_info
    797: .    -viewer_binary_skip_options
    798: .    -viewer_binary_skip_header
    799: -    -viewer_binary_mpiio

    801:    Level: beginner

    803:    Note:
    804:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

    812:     For writing files it only opens the file on processor 0 in the communicator.
    813:     For readable files it opens the file on all nodes that have the file. If
    814:     node 0 does not have the file it generates an error even if other nodes
    815:     do have the file.

    817:    Concepts: binary files
    818:    Concepts: PetscViewerBinary^creating
    819:    Concepts: gzip
    820:    Concepts: accessing remote file
    821:    Concepts: remote file

    823: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    824:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    825:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    826: @*/
    827: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
    828: {

    832:   PetscViewerCreate(comm,binv);
    833:   PetscViewerSetType(*binv,PETSCVIEWERBINARY);
    834:   PetscViewerFileSetMode(*binv,type);
    835:   PetscViewerFileSetName(*binv,name);
    836:   PetscViewerSetFromOptions(*binv);
    837:   return(0);
    838: }

    840: #if defined(PETSC_HAVE_MPIIO)
    843: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write)
    844: {
    845:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    846:   PetscErrorCode     ierr;
    847:   MPI_Datatype       mdtype;
    848:   PetscMPIInt        cnt;
    849:   MPI_Status         status;
    850:   MPI_Aint           ul,dsize;

    853:   PetscMPIIntCast(num,&cnt);
    854:   PetscDataTypeToMPIDataType(dtype,&mdtype);
    855:   MPI_File_set_view(vbinary->mfdes,vbinary->moff,mdtype,mdtype,(char*)"native",MPI_INFO_NULL);
    856:   if (write) {
    857:     MPIU_File_write_all(vbinary->mfdes,data,cnt,mdtype,&status);
    858:   } else {
    859:     MPIU_File_read_all(vbinary->mfdes,data,cnt,mdtype,&status);
    860:   }
    861:   MPI_Type_get_extent(mdtype,&ul,&dsize);

    863:   vbinary->moff += dsize*cnt;
    864:   if (count) *count = num;
    865:   return(0);
    866: }
    867: #endif

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

    874:    Collective on MPI_Comm

    876:    Input Parameters:
    877: +  viewer - the binary viewer
    878: .  data - location of the data to be written
    879: .  num - number of items of data to read
    880: -  dtype - type of data to read

    882:    Output Parameters:
    883: .  count - number of items of data actually read, or NULL. Unless an error is generated this is always set to the input parameter num.

    885:    Level: beginner

    887:    Concepts: binary files

    889:    Developer Note: Since count is always set to num it is not clear what purpose the output argument count serves.

    891: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    892:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    893:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
    894: @*/
    895: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
    896: {
    897:   PetscErrorCode     ierr;
    898:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    900:   PetscViewerSetUp(viewer);
    901: #if defined(PETSC_HAVE_MPIIO)
    902:   if (vbinary->usempiio) {
    903:     PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE);
    904:   } else {
    905: #endif
    906:     PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,dtype);
    907:     if (count) *count = num;
    908: #if defined(PETSC_HAVE_MPIIO)
    909:   }
    910: #endif
    911:   return(0);
    912: }

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

    919:    Collective on MPI_Comm

    921:    Input Parameters:
    922: +  viewer - the binary viewer
    923: .  data - location of data
    924: .  count - number of items of data to write
    925: .  dtype - type of data to write
    926: -  istemp - data may be overwritten

    928:    Level: beginner

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

    932:    Concepts: binary files

    934: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    935:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
    936:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
    937: @*/
    938: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscBool istemp)
    939: {
    940:   PetscErrorCode     ierr;
    941:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    944:   PetscViewerSetUp(viewer);
    945: #if defined(PETSC_HAVE_MPIIO)
    946:   if (vbinary->usempiio) {
    947:     PetscViewerBinaryWriteReadMPIIO(viewer,data,count,NULL,dtype,PETSC_TRUE);
    948:   } else {
    949: #endif
    950:     PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype,istemp);
    951: #if defined(PETSC_HAVE_MPIIO)
    952:   }
    953: #endif
    954:   return(0);
    955: }

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

    962:    Collective on MPI_Comm

    964:    Input Parameters:
    965: +  viewer - the binary viewer
    966: -  data - location of the array of strings

    969:    Level: intermediate

    971:    Concepts: binary files

    973:     Notes: array of strings is null terminated

    975: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    976:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    977:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
    978: @*/
    979: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,char **data)
    980: {
    982:   PetscInt       i,n = 0,*sizes;

    984:   PetscViewerSetUp(viewer);
    985:   /* count number of strings */
    986:   while (data[n++]) ;
    987:   n--;
    988:   PetscMalloc1(n+1,&sizes);
    989:   sizes[0] = n;
    990:   for (i=0; i<n; i++) {
    991:     size_t tmp;
    992:     PetscStrlen(data[i],&tmp);
    993:     sizes[i+1] = tmp + 1;   /* size includes space for the null terminator */
    994:   }
    995:   PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT,PETSC_FALSE);
    996:   for (i=0; i<n; i++) {
    997:     PetscViewerBinaryWrite(viewer,data[i],sizes[i+1],PETSC_CHAR,PETSC_FALSE);
    998:   }
    999:   PetscFree(sizes);
    1000:   return(0);
    1001: }

    1005: /*@C
    1006:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

    1008:    Collective on MPI_Comm

    1010:    Input Parameter:
    1011: .  viewer - the binary viewer

    1013:    Output Parameter:
    1014: .  data - location of the array of strings

    1016:    Level: intermediate

    1018:    Concepts: binary files

    1020:     Notes: array of strings is null terminated

    1022: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    1023:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    1024:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
    1025: @*/
    1026: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
    1027: {
    1029:   PetscInt       i,n,*sizes,N = 0;

    1031:   PetscViewerSetUp(viewer);
    1032:   /* count number of strings */
    1033:   PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);
    1034:   PetscMalloc1(n,&sizes);
    1035:   PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);
    1036:   for (i=0; i<n; i++) N += sizes[i];
    1037:   PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);
    1038:   (*data)[0] = (char*)((*data) + n + 1);
    1039:   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
    1040:   PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);

    1042:   (*data)[n] = 0;

    1044:   PetscFree(sizes);
    1045:   return(0);
    1046: }

    1050: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
    1051: {
    1052:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1055:   *name = vbinary->filename;
    1056:   return(0);
    1057: }

    1061: /*@C
    1062:      PetscViewerFileGetMode - Gets the type of file to be open

    1064:     Not Collective

    1066:   Input Parameter:
    1067: .  viewer - the PetscViewer; must be a binary, MATLAB, hdf, or netcdf PetscViewer

    1069:   Output Parameter:
    1070: .  type - type of file
    1071: $    FILE_MODE_WRITE - create new file for binary output
    1072: $    FILE_MODE_READ - open existing file for binary input
    1073: $    FILE_MODE_APPEND - open existing file for binary output

    1075:   Level: advanced

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

    1079: @*/
    1080: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
    1081: {

    1087:   PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));
    1088:   return(0);
    1089: }

    1093: /*@
    1094:     PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
    1095:         before PetscViewerFileSetName()

    1097:     Logically Collective on PetscViewer

    1099:     Input Parameters:
    1100: +   viewer - the PetscViewer; must be a binary
    1101: -   flg - PETSC_TRUE means MPI-IO will be used

    1103:     Options Database:
    1104:     -viewer_binary_mpiio : Flag for using MPI-IO

    1106:     Level: advanced

    1108: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
    1109:           PetscViewerBinaryGetUseMPIIO()

    1111: @*/
    1112: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool flg)
    1113: {

    1118:   PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,flg));
    1119:   return(0);
    1120: }

    1124: /*@C
    1125:      PetscViewerFileSetMode - Sets the type of file to be open

    1127:     Logically Collective on PetscViewer

    1129:   Input Parameters:
    1130: +  viewer - the PetscViewer; must be a binary, Matlab, hdf, or netcdf PetscViewer
    1131: -  type - type of file
    1132: $    FILE_MODE_WRITE - create new file for binary output
    1133: $    FILE_MODE_READ - open existing file for binary input
    1134: $    FILE_MODE_APPEND - open existing file for binary output

    1136:   Level: advanced

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

    1140: @*/
    1141: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
    1142: {

    1148:   PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));
    1149:   return(0);
    1150: }

    1154: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
    1155: {
    1156:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1159:   *type = vbinary->btype;
    1160:   return(0);
    1161: }

    1165: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
    1166: {
    1167:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1170:   vbinary->btype = type;
    1171:   return(0);
    1172: }

    1176: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
    1177: {
    1178:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1179:   PetscErrorCode     ierr;
    1180:
    1182:   if (vbinary->filename) { PetscFree(vbinary->filename); }
    1183:   PetscStrallocpy(name,&vbinary->filename);
    1184:   return(0);
    1185: }
    1186: /*
    1187:         Actually opens the file
    1188: */
    1191: static PetscErrorCode PetscViewerFileSetUp_Binary(PetscViewer viewer)
    1192: {
    1193:   PetscMPIInt        rank;
    1194:   PetscErrorCode     ierr;
    1195:   size_t             len;
    1196:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1197:   const char         *fname;
    1198:   char               bname[PETSC_MAX_PATH_LEN],*gz;
    1199:   PetscBool          found;
    1200:   PetscFileMode      type = vbinary->btype;

    1203:   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
    1204:   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
    1205:   PetscViewerFileClose_Binary(viewer);

    1207:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);

    1209:   /* if ends in .gz strip that off and note user wants file compressed */
    1210:   vbinary->storecompressed = PETSC_FALSE;
    1211:   if (!rank && type == FILE_MODE_WRITE) {
    1212:     /* remove .gz if it ends library name */
    1213:     PetscStrstr(vbinary->filename,".gz",&gz);
    1214:     if (gz) {
    1215:       PetscStrlen(gz,&len);
    1216:       if (len == 3) {
    1217:         *gz = 0;
    1218:         vbinary->storecompressed = PETSC_TRUE;
    1219:       }
    1220:     }
    1221:   }

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

    1226:     if (type == FILE_MODE_READ) {
    1227:       /* possibly get the file from remote site or compressed file */
    1228:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
    1229:       fname = bname;
    1230:       if (!rank && !found) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
    1231:       else if (!found) {
    1232:         PetscInfo(viewer,"Nonzero processor did not locate readonly file\n");
    1233:         fname = 0;
    1234:       }
    1235:     } else fname = vbinary->filename;

    1237: #if defined(PETSC_HAVE_O_BINARY)
    1238:     if (type == FILE_MODE_WRITE) {
    1239:       if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
    1240:     } else if (type == FILE_MODE_READ && fname) {
    1241:       if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
    1242:     } else if (type == FILE_MODE_APPEND) {
    1243:       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
    1244:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
    1245: #else
    1246:     if (type == FILE_MODE_WRITE) {
    1247:       if ((vbinary->fdes = creat(fname,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
    1248:     } else if (type == FILE_MODE_READ && fname) {
    1249:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
    1250:     } else if (type == FILE_MODE_APPEND) {
    1251:       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
    1252:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
    1253: #endif
    1254:   } else vbinary->fdes = -1;

    1256:   /*
    1257:       try to open info file: all processors open this file if read only
    1258:   */
    1259:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
    1260:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

    1262:     PetscStrcpy(infoname,vbinary->filename);
    1263:     /* remove .gz if it ends library name */
    1264:     PetscStrstr(infoname,".gz",&gz);
    1265:     if (gz) {
    1266:       PetscStrlen(gz,&len);
    1267:       if (len == 3) *gz = 0;
    1268:     }

    1270:     PetscStrcat(infoname,".info");
    1271:     PetscFixFilename(infoname,iname);
    1272:     if (type == FILE_MODE_READ) {
    1273:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
    1274:       PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
    1275:     } else {
    1276:       vbinary->fdes_info = fopen(infoname,"w");
    1277:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
    1278:     }
    1279:   }
    1280: #if defined(PETSC_USE_LOG)
    1281:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
    1282: #endif
    1283:   return(0);
    1284: }

    1286: #if defined(PETSC_HAVE_MPIIO)
    1289: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
    1290: {
    1291:   PetscMPIInt        rank;
    1292:   PetscErrorCode     ierr;
    1293:   size_t             len;
    1294:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1295:   char               *gz;
    1296:   PetscBool          found;
    1297:   PetscFileMode      type = vbinary->btype;

    1300:   if (type == (PetscFileMode) -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
    1301:   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
    1302:   PetscViewerFileClose_BinaryMPIIO(viewer);

    1304:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);

    1306:   vbinary->storecompressed = PETSC_FALSE;

    1308:   /* only first processor opens file if writeable */
    1309:   if (type == FILE_MODE_READ) {
    1310:     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_RDONLY,MPI_INFO_NULL,&vbinary->mfdes);
    1311:   } else if (type == FILE_MODE_WRITE) {
    1312:     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_WRONLY | MPI_MODE_CREATE,MPI_INFO_NULL,&vbinary->mfdes);
    1313:   }

    1315:   /*
    1316:       try to open info file: all processors open this file if read only

    1318:       Below is identical code to the code for Binary above, should be put in separate routine
    1319:   */
    1320:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
    1321:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

    1323:     PetscStrcpy(infoname,vbinary->filename);
    1324:     /* remove .gz if it ends library name */
    1325:     PetscStrstr(infoname,".gz",&gz);
    1326:     if (gz) {
    1327:       PetscStrlen(gz,&len);
    1328:       if (len == 3) *gz = 0;
    1329:     }

    1331:     PetscStrcat(infoname,".info");
    1332:     PetscFixFilename(infoname,iname);
    1333:     if (type == FILE_MODE_READ) {
    1334:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
    1335:       PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
    1336:     } else {
    1337:       vbinary->fdes_info = fopen(infoname,"w");
    1338:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
    1339:     }
    1340:   }
    1341: #if defined(PETSC_USE_LOG)
    1342:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
    1343: #endif
    1344:   return(0);
    1345: }

    1349: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
    1350: {
    1351:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1353:   vbinary->usempiio = flg;
    1354:   return(0);
    1355: }
    1356: #endif

    1360: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
    1361: {
    1362:   PetscErrorCode     ierr;
    1363:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

    1366:   if (binary->filename) {
    1367:     PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);
    1368:   }
    1369:   return(0);
    1370: }

    1374: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
    1375: {
    1376:   PetscErrorCode     ierr;
    1377:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

    1380:   if (!binary->setfromoptionscalled) { PetscViewerSetFromOptions(v); }
    1381:
    1382: #if defined(PETSC_HAVE_MPIIO)
    1383:   if (binary->usempiio) {
    1384:     PetscViewerFileSetUp_BinaryMPIIO(v);
    1385:   } else {
    1386: #endif
    1387:     PetscViewerFileSetUp_Binary(v);
    1388: #if defined(PETSC_HAVE_MPIIO)
    1389:   }
    1390: #endif
    1391:   return(0);
    1392: }

    1396: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer v)
    1397: {
    1398:   PetscErrorCode     ierr;
    1399:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
    1400:   char               defaultname[PETSC_MAX_PATH_LEN];
    1401:   PetscBool          flg;

    1404:   PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");
    1405:   PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");
    1406:   PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);
    1407:   if (flg) { PetscViewerFileSetName_Binary(v,defaultname); }
    1408:   PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",PETSC_FALSE,&binary->skipinfo,NULL);
    1409:   PetscOptionsBool("-viewer_binary_skip_options","Skip parsing vec load options","PetscViewerBinarySetSkipOptions",PETSC_TRUE,&binary->skipoptions,NULL);
    1410:   PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",PETSC_FALSE,&binary->skipheader,NULL);
    1411: #if defined(PETSC_HAVE_MPIIO)
    1412:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,&binary->usempiio,NULL);
    1413: #elif defined(PETSC_HAVE_MPIUNI)
    1414:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);
    1415: #endif
    1416:   PetscOptionsTail();
    1417:   binary->setfromoptionscalled = PETSC_TRUE;
    1418:   return(0);
    1419: }

    1423: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
    1424: {
    1425:   PetscErrorCode     ierr;
    1426:   PetscViewer_Binary *vbinary;

    1429:   PetscNewLog(v,&vbinary);
    1430:   v->data                  = (void*)vbinary;
    1431:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
    1432:   v->ops->destroy          = PetscViewerDestroy_Binary;
    1433:   v->ops->view             = PetscViewerView_Binary;
    1434:   v->ops->setup            = PetscViewerSetUp_Binary;
    1435:   v->ops->flush            = NULL;
    1436:   vbinary->fdes_info       = 0;
    1437:   vbinary->fdes            = 0;
    1438:   vbinary->skipinfo        = PETSC_FALSE;
    1439:   vbinary->skipoptions     = PETSC_TRUE;
    1440:   vbinary->skipheader      = PETSC_FALSE;
    1441:   vbinary->setfromoptionscalled = PETSC_FALSE;
    1442:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
    1443:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
    1444:   v->ops->read             = PetscViewerBinaryRead;
    1445:   vbinary->btype           = (PetscFileMode) -1;
    1446:   vbinary->storecompressed = PETSC_FALSE;
    1447:   vbinary->filename        = 0;
    1448:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

    1450:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);
    1451:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);
    1452:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);
    1453:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);
    1454:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);
    1455:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);
    1456:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);
    1457:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);
    1458:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);
    1459:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);
    1460:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);
    1461:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);
    1462:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);
    1463: #if defined(PETSC_HAVE_MPIIO)
    1464:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);
    1465:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);
    1466: #endif
    1467:   return(0);
    1468: }

    1470: /* ---------------------------------------------------------------------*/
    1471: /*
    1472:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
    1473:   is attached to a communicator, in this case the attribute is a PetscViewer.
    1474: */
    1475: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

    1479: /*@C
    1480:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
    1481:                      in a communicator.

    1483:      Collective on MPI_Comm

    1485:      Input Parameter:
    1486: .    comm - the MPI communicator to share the binary PetscViewer

    1488:      Level: intermediate

    1490:    Options Database Keys:
    1491: +    -viewer_binary_filename <name>
    1492: .    -viewer_binary_skip_info
    1493: .    -viewer_binary_skip_options
    1494: .    -viewer_binary_skip_header
    1495: -    -viewer_binary_mpiio

    1497:    Environmental variables:
    1498: -   PETSC_VIEWER_BINARY_FILENAME

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

    1505: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
    1506:           PetscViewerDestroy()
    1507: @*/
    1508: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
    1509: {
    1511:   PetscBool      flg;
    1512:   PetscViewer    viewer;
    1513:   char           fname[PETSC_MAX_PATH_LEN];
    1514:   MPI_Comm       ncomm;

    1517:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1518:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
    1519:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
    1520:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1521:   }
    1522:   MPI_Attr_get(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
    1523:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1524:   if (!flg) { /* PetscViewer not yet created */
    1525:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
    1526:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1527:     if (!flg) {
    1528:       PetscStrcpy(fname,"binaryoutput");
    1529:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1530:     }
    1531:     PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
    1532:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1533:     PetscObjectRegisterDestroy((PetscObject)viewer);
    1534:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1535:     MPI_Attr_put(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
    1536:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1537:   }
    1538:   PetscCommDestroy(&ncomm);
    1539:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1540:   PetscFunctionReturn(viewer);
    1541: }