Actual source code: binv.c
petsc-3.10.5 2019-03-28
Report Typos and Errors

      2:  #include <petsc/private/viewerimpl.h>
      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_File      mfsub;                /* subviewer support */
     17:   MPI_Offset    moff;
     18: #endif
     19:   PetscFileMode btype;                /* read or write? */
     20:   FILE          *fdes_info;           /* optional file containing info on binary file*/
     21:   PetscBool     storecompressed;      /* gzip the write binary file when closing it*/
     22:   char          *filename;
     23:   char          *ogzfilename;         /* gzip can be run after the filename has been updated */
     24:   PetscBool     skipinfo;             /* Don't create info file for writing; don't use for reading */
     25:   PetscBool     skipoptions;          /* don't use PETSc options database when loading */
     26:   PetscInt      flowcontrol;          /* allow only <flowcontrol> messages outstanding at a time while doing IO */
     27:   PetscBool     skipheader;           /* don't write header, only raw data */
     28:   PetscBool     matlabheaderwritten;  /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
     29:   PetscBool     setfromoptionscalled;
     30: } 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;

     39:   PetscViewerSetUp(viewer);

     41:   /* Return subviewer in process zero */
     42:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
     43:   if (!rank) {
     44:     PetscViewerCreate(PETSC_COMM_SELF,outviewer);
     45:     PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);
     46:     PetscMemcpy((*outviewer)->data,vbinary,sizeof(PetscViewer_Binary));
     47:     (*outviewer)->setupcalled = PETSC_TRUE;
     48:   } else {
     49:     *outviewer = NULL;
     50:   }

     52: #if defined(PETSC_HAVE_MPIIO)
     53:   if (vbinary->usempiio && *outviewer) {
     54:     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
     55:     /* Parent viewer opens a new MPI file handle on PETSC_COMM_SELF and keeps track of it for future reuse */
     56:     if (vbinary->mfsub == MPI_FILE_NULL) {
     57:       int amode;
     58:       switch (vbinary->btype) {
     59:       case FILE_MODE_READ:  amode = MPI_MODE_RDONLY; break;
     60:       case FILE_MODE_WRITE: amode = MPI_MODE_WRONLY; break;
     61:       default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->btype]);
     62:       }
     63:       MPI_File_open(PETSC_COMM_SELF,vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfsub);
     64:     }
     65:     /* Subviewer gets the MPI file handle on PETSC_COMM_SELF */
     66:     obinary->mfdes = vbinary->mfsub;
     67:     obinary->mfsub = MPI_FILE_NULL;
     68:     obinary->moff  = vbinary->moff;
     69:   }
     70: #endif
     71:   return(0);
     72: }

     74: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
     75: {
     76:   PetscErrorCode     rank;
     77:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
     78:   PetscErrorCode     ierr;
     79: #if defined(PETSC_HAVE_MPIIO)
     80:   MPI_Offset         moff = 0;
     81: #endif

     84:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
     85:   if (rank && *outviewer) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");

     87: #if defined(PETSC_HAVE_MPIIO)
     88:   if (vbinary->usempiio && *outviewer) {
     89:     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
     90:     if (obinary->mfdes != vbinary->mfsub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
     91:     moff = obinary->moff;
     92:   }
     93: #endif

     95:   if (*outviewer) {
     96:     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
     97:     if (obinary->fdes != vbinary->fdes) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
     98:     PetscFree((*outviewer)->data);
     99:     PetscHeaderDestroy(outviewer);
    100:   }

    102: #if defined(PETSC_HAVE_MPIIO)
    103:   if (vbinary->usempiio) {
    104:     PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */
    105:     MPI_Bcast(&ioff,1,MPIU_INT64,0,PetscObjectComm((PetscObject)viewer));
    106:     vbinary->moff = (MPI_Offset)ioff;
    107:   }
    108: #endif
    109:   return(0);
    110: }

    112: #if defined(PETSC_HAVE_MPIIO)
    113: /*@C
    114:     PetscViewerBinaryGetMPIIOOffset - Gets the current offset that should be passed to MPI_File_set_view()

    116:     Not Collective

    118:     Input Parameter:
    119: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    121:     Output Parameter:
    122: .    off - the current offset

    124:     Level: advanced

    126:     Fortran Note:
    127:     This routine is not supported in Fortran.

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

    131:   Concepts: file descriptor^getting
    132:   Concepts: PetscViewerBinary^accessing file descriptor

    134: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryAddMPIIOOffset()
    135: @*/
    136: PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off)
    137: {
    138:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    141:   *off = vbinary->moff;
    142:   return(0);
    143: }

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

    148:     Not Collective

    150:     Input Parameters:
    151: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    152: -    off - the addition to the offset

    154:     Level: advanced

    156:     Fortran Note:
    157:     This routine is not supported in Fortran.

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

    161:   Concepts: file descriptor^getting
    162:   Concepts: PetscViewerBinary^accessing file descriptor

    164: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    165: @*/
    166: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)
    167: {
    168:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    171:   vbinary->moff += off;
    172:   return(0);
    173: }

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

    178:     Not Collective

    180:     Input Parameter:
    181: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    183:     Output Parameter:
    184: .   fdes - file descriptor

    186:     Level: advanced

    188:     Fortran Note:
    189:     This routine is not supported in Fortran.

    191:   Concepts: file descriptor^getting
    192:   Concepts: PetscViewerBinary^accessing file descriptor

    194: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    195: @*/
    196: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
    197: {
    198:   PetscErrorCode     ierr;
    199:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    202:   PetscViewerSetUp(viewer);
    203:   *fdes = vbinary->mfdes;
    204:   return(0);
    205: }

    207: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *flg)
    208: {
    209:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    212:   *flg = vbinary->usempiio;
    213:   return(0);
    214: }
    215: #endif

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

    221:     Not Collective

    223:     Input Parameter:
    224: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    226:     Output Parameter:
    227: -   flg - PETSC_TRUE if MPI-IO is being used

    229:     Options Database:
    230:     -viewer_binary_mpiio : Flag for using MPI-IO

    232:     Level: advanced

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

    237:     Fortran Note:
    238:     This routine is not supported in Fortran.

    240:   Concepts: file descriptor^getting
    241:   Concepts: PetscViewerBinary^accessing file descriptor

    243: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    244: @*/
    245: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *flg)
    246: {

    250:   *flg = PETSC_FALSE;
    251:   PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,flg));
    252:   return(0);
    253: }

    255: static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
    256: {
    257:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    260:   *fc = vbinary->flowcontrol;
    261:   return(0);
    262: }

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

    267:     Not Collective

    269:     Input Parameter:
    270: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    272:     Output Parameter:
    273: .   fc - the number of messages

    275:     Level: advanced

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

    279: @*/
    280: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
    281: {

    285:   PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));
    286:   return(0);
    287: }

    289: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
    290: {
    291:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

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

    302:     Not Collective

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

    308:     Level: advanced

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

    312: @*/
    313: PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
    314: {

    318:   PetscUseMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));
    319:   return(0);
    320: }

    322: /*@C
    323:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

    325:     Collective On PetscViewer

    327:     Input Parameter:
    328: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    330:     Output Parameter:
    331: .   fdes - file descriptor

    333:     Level: advanced

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

    341:     Fortran Note:
    342:     This routine is not supported in Fortran.

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

    349:   Concepts: file descriptor^getting
    350:   Concepts: PetscViewerBinary^accessing file descriptor

    352: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
    353: @*/
    354: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
    355: {
    356:   PetscErrorCode     ierr;
    357:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    360:   PetscViewerSetUp(viewer);
    361:   *fdes = vbinary->fdes;
    362:   return(0);
    363: }

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

    368:     Not Collective

    370:     Input Paramter:
    371: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

    373:     Options Database Key:
    374: .   -viewer_binary_skip_info

    376:     Level: advanced

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

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

    386:    Concepts: PetscViewerBinary^accessing info file

    388: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
    389:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
    390: @*/
    391: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
    392: {
    393:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    396:   vbinary->skipinfo = PETSC_TRUE;
    397:   return(0);
    398: }

    400: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
    401: {
    402:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    405:   vbinary->skipinfo = skip;
    406:   return(0);
    407: }

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

    412:     Not Collective

    414:     Input Paramter:
    415: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

    417:     Options Database Key:
    418: .   -viewer_binary_skip_info

    420:     Level: advanced

    422:     Concepts: PetscViewerBinary^accessing info file

    424: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
    425:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
    426: @*/
    427: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
    428: {

    432:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));
    433:   return(0);
    434: }

    436: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
    437: {
    438:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    441:   *skip  = vbinary->skipinfo;
    442:   return(0);
    443: }

    445: /*@
    446:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

    448:     Not Collective

    450:     Input Parameter:
    451: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    453:     Output Parameter:
    454: .   skip - PETSC_TRUE implies the .info file was not generated

    456:     Level: advanced

    458:     Notes:
    459:     This must be called after PetscViewerSetType()

    461:     Concepts: PetscViewerBinary^accessing info file

    463: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    464:           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
    465: @*/
    466: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
    467: {

    471:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));
    472:   return(0);
    473: }

    475: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
    476: {
    477:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    480:   vbinary->skipoptions = skip;
    481:   return(0);
    482: }

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

    487:     Not Collective

    489:     Input Parameters:
    490: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    491: -   skip - PETSC_TRUE means do not use

    493:     Options Database Key:
    494: .   -viewer_binary_skip_options

    496:     Level: advanced

    498:     Notes:
    499:     This must be called after PetscViewerSetType()

    501:    Concepts: PetscViewerBinary^accessing info file

    503: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    504:           PetscViewerBinaryGetSkipOptions()
    505: @*/
    506: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)
    507: {

    511:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));
    512:   return(0);
    513: }

    515: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
    516: {
    517:   PetscViewer_Binary *vbinary;

    521:   vbinary = (PetscViewer_Binary*)viewer->data;
    522:   *skip   = vbinary->skipoptions;
    523:   return(0);
    524: }

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

    529:     Not Collective

    531:     Input Parameter:
    532: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    534:     Output Parameter:
    535: .   skip - PETSC_TRUE means do not use

    537:     Level: advanced

    539:     Notes:
    540:     This must be called after PetscViewerSetType()

    542:    Concepts: PetscViewerBinary^accessing info file

    544: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    545:           PetscViewerBinarySetSkipOptions()
    546: @*/
    547: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
    548: {

    552:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));
    553:   return(0);
    554: }

    556: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
    557: {
    558:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    561:   vbinary->skipheader = skip;
    562:   return(0);
    563: }

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

    568:     Not Collective

    570:     Input Parameters:
    571: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    572: -   skip - PETSC_TRUE means do not write header

    574:     Options Database Key:
    575: .   -viewer_binary_skip_header

    577:     Level: advanced

    579:     Notes:
    580:     This must be called after PetscViewerSetType()

    582:            Can ONLY be called on a binary viewer

    584: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    585:           PetscViewerBinaryGetSkipHeader()
    586: @*/
    587: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
    588: {

    592:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));
    593:   return(0);
    594: }

    596: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool  *skip)
    597: {
    598:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    601:   *skip = vbinary->skipheader;
    602:   return(0);
    603: }

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

    608:     Not Collective

    610:     Input Parameter:
    611: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    613:     Output Parameter:
    614: .   skip - PETSC_TRUE means do not write header

    616:     Level: advanced

    618:     Notes:
    619:     This must be called after PetscViewerSetType()

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

    623: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    624:           PetscViewerBinarySetSkipHeader()
    625: @*/
    626: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool  *skip)
    627: {

    631:   *skip = PETSC_FALSE;
    632:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));
    633:   return(0);
    634: }

    636: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
    637: {
    638:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    639:   PetscErrorCode     ierr;
    640:   MPI_Comm           comm;

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

    656: /*@C
    657:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
    658:           info file associated with a binary file.

    660:     Not Collective

    662:     Input Parameter:
    663: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    665:     Output Parameter:
    666: .   file - file pointer  Always returns NULL if not a binary viewer

    668:     Level: advanced

    670:     Notes:
    671:       For writable binary PetscViewers, the descriptor will only be valid for the
    672:     first processor in the communicator that shares the PetscViewer.

    674:     Fortran Note:
    675:     This routine is not supported in Fortran.

    677:   Concepts: PetscViewerBinary^accessing info file

    679: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
    680: @*/
    681: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
    682: {

    686:   *file = NULL;
    687:   PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));
    688:   return(0);
    689: }

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

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

    725: #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 != MPI_FILE_NULL) {
    734:     MPI_File_close(&vbinary->mfdes);
    735:   }
    736:   if (vbinary->mfsub != MPI_FILE_NULL) {
    737:     MPI_File_close(&vbinary->mfsub);
    738:   }
    739:   if (vbinary->fdes_info) {
    740:     err = fclose(vbinary->fdes_info);
    741:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
    742:   }
    743:   return(0);
    744: }
    745: #endif

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

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

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

    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(), PetscViewerBinarySetUseMPIIO(),
    826:           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    827: @*/
    828: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
    829: {

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

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

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

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

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

    873:    Collective on MPI_Comm

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

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

    884:    Level: beginner

    886:    Concepts: binary files

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

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

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

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

    916:    Collective on MPI_Comm

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

    925:    Level: beginner

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

    930:    Concepts: binary files

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

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

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

    958:    Collective on MPI_Comm

    960:    Input Parameters:
    961: +  viewer - the binary viewer
    962: -  data - location of the array of strings

    965:    Level: intermediate

    967:    Concepts: binary files

    969:     Notes:
    970:     array of strings is null terminated

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

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

    1000: /*@C
    1001:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

    1003:    Collective on MPI_Comm

    1005:    Input Parameter:
    1006: .  viewer - the binary viewer

    1008:    Output Parameter:
    1009: .  data - location of the array of strings

    1011:    Level: intermediate

    1013:    Concepts: binary files

    1015:     Notes:
    1016:     array of strings is null terminated

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

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

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

    1040:   PetscFree(sizes);
    1041:   return(0);
    1042: }

    1044: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
    1045: {
    1046:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1049:   *name = vbinary->filename;
    1050:   return(0);
    1051: }

    1053: /*@C
    1054:      PetscViewerFileGetMode - Gets the type of file to be open

    1056:     Not Collective

    1058:   Input Parameter:
    1059: .  viewer - the PetscViewer; must be a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer

    1061:   Output Parameter:
    1062: .  type - type of file
    1063: $    FILE_MODE_WRITE - create new file for binary output
    1064: $    FILE_MODE_READ - open existing file for binary input
    1065: $    FILE_MODE_APPEND - open existing file for binary output

    1067:   Level: advanced

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

    1071: @*/
    1072: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
    1073: {

    1079:   PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));
    1080:   return(0);
    1081: }

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

    1087:     Logically Collective on PetscViewer

    1089:     Input Parameters:
    1090: +   viewer - the PetscViewer; must be a binary
    1091: -   flg - PETSC_TRUE means MPI-IO will be used

    1093:     Options Database:
    1094:     -viewer_binary_mpiio : Flag for using MPI-IO

    1096:     Level: advanced

    1098: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
    1099:           PetscViewerBinaryGetUseMPIIO()

    1101: @*/
    1102: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool flg)
    1103: {

    1108:   PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,flg));
    1109:   return(0);
    1110: }

    1112: /*@C
    1113:      PetscViewerFileSetMode - Sets the type of file to be open

    1115:     Logically Collective on PetscViewer

    1117:   Input Parameters:
    1118: +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
    1119: -  type - type of file
    1120: $    FILE_MODE_WRITE - create new file for binary output
    1121: $    FILE_MODE_READ - open existing file for binary input
    1122: $    FILE_MODE_APPEND - open existing file for binary output

    1124:   Level: advanced

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

    1128: @*/
    1129: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
    1130: {

    1136:   PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));
    1137:   return(0);
    1138: }

    1140: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
    1141: {
    1142:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1145:   *type = vbinary->btype;
    1146:   return(0);
    1147: }

    1149: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
    1150: {
    1151:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1154:   vbinary->btype = type;
    1155:   return(0);
    1156: }

    1158: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
    1159: {
    1160:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1161:   PetscErrorCode     ierr;

    1164:   if (vbinary->filename) {
    1165:     /* gzip can be run after the file with the previous filename has been closed */
    1166:     PetscFree(vbinary->ogzfilename);
    1167:     PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename);
    1168:     PetscFree(vbinary->filename);
    1169:     viewer->setupcalled = PETSC_FALSE;
    1170:   }
    1171:   PetscStrallocpy(name,&vbinary->filename);
    1172:   return(0);
    1173: }
    1174: /*
    1175:         Actually opens the file
    1176: */
    1177: static PetscErrorCode PetscViewerFileSetUp_Binary(PetscViewer viewer)
    1178: {
    1179:   PetscMPIInt        rank;
    1180:   PetscErrorCode     ierr;
    1181:   size_t             len;
    1182:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1183:   const char         *fname;
    1184:   char               bname[PETSC_MAX_PATH_LEN],*gz;
    1185:   PetscBool          found;
    1186:   PetscFileMode      type = vbinary->btype;

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

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

    1195:   /* if ends in .gz strip that off and note user wants file compressed */
    1196:   vbinary->storecompressed = PETSC_FALSE;
    1197:   if (!rank && type == FILE_MODE_WRITE) {
    1198:     /* remove .gz if it ends library name */
    1199:     PetscStrstr(vbinary->filename,".gz",&gz);
    1200:     if (gz) {
    1201:       PetscStrlen(gz,&len);
    1202:       if (len == 3) {
    1203:         *gz = 0;
    1204:         vbinary->storecompressed = PETSC_TRUE;
    1205:       }
    1206:     }
    1207:   }

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

    1212:     if (type == FILE_MODE_READ) {
    1213:       /* possibly get the file from remote site or compressed file */
    1214:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
    1215:       fname = bname;
    1216:       /* comm below may be global as all ranks go here for FILE_MODE_READ and output 'found' of PetscFileRetrieve() is valid on all processes */
    1217:       if (!found) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
    1218:     } else fname = vbinary->filename;

    1220: #if defined(PETSC_HAVE_O_BINARY)
    1221:     if (type == FILE_MODE_WRITE) {
    1222:       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);
    1223:     } else if (type == FILE_MODE_READ && fname) {
    1224:       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);
    1225:     } else if (type == FILE_MODE_APPEND) {
    1226:       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);
    1227:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
    1228: #else
    1229:     if (type == FILE_MODE_WRITE) {
    1230:       if ((vbinary->fdes = creat(fname,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
    1231:     } else if (type == FILE_MODE_READ && fname) {
    1232:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
    1233:     } else if (type == FILE_MODE_APPEND) {
    1234:       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);
    1235:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
    1236: #endif
    1237:   } else vbinary->fdes = -1;

    1239:   /*
    1240:       try to open info file: all processors open this file if read only
    1241:   */
    1242:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
    1243:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

    1245:     PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));
    1246:     /* remove .gz if it ends library name */
    1247:     PetscStrstr(infoname,".gz",&gz);
    1248:     if (gz) {
    1249:       PetscStrlen(gz,&len);
    1250:       if (len == 3) *gz = 0;
    1251:     }

    1253:     PetscStrlcat(infoname,".info",sizeof(infoname));
    1254:     PetscFixFilename(infoname,iname);
    1255:     if (type == FILE_MODE_READ) {
    1256:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
    1257:       if (found) {
    1258:         PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
    1259:       }
    1260:     } else {
    1261:       vbinary->fdes_info = fopen(infoname,"w");
    1262:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
    1263:     }
    1264:   }
    1265: #if defined(PETSC_USE_LOG)
    1266:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
    1267: #endif
    1268:   return(0);
    1269: }

    1271: #if defined(PETSC_HAVE_MPIIO)
    1272: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
    1273: {
    1274:   PetscMPIInt        rank;
    1275:   PetscErrorCode     ierr;
    1276:   size_t             len;
    1277:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1278:   char               *gz;
    1279:   PetscBool          found;
    1280:   PetscFileMode      type = vbinary->btype;
    1281:   int                amode;

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

    1288:   vbinary->storecompressed = PETSC_FALSE;

    1290:   switch (type) {
    1291:   case FILE_MODE_READ:  amode = MPI_MODE_RDONLY; break;
    1292:   case FILE_MODE_WRITE: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE; break;
    1293:   default: SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[type]);
    1294:   }
    1295:   MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfdes);

    1297:   /*
    1298:       try to open info file: all processors open this file if read only

    1300:       Below is identical code to the code for Binary above, should be put in separate routine
    1301:   */
    1302:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
    1303:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
    1304:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

    1306:     PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));
    1307:     /* remove .gz if it ends library name */
    1308:     PetscStrstr(infoname,".gz",&gz);
    1309:     if (gz) {
    1310:       PetscStrlen(gz,&len);
    1311:       if (len == 3) *gz = 0;
    1312:     }

    1314:     PetscStrlcat(infoname,".info",sizeof(infoname));
    1315:     PetscFixFilename(infoname,iname);
    1316:     if (type == FILE_MODE_READ) {
    1317:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
    1318:       PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
    1319:     } else {
    1320:       vbinary->fdes_info = fopen(infoname,"w");
    1321:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
    1322:     }
    1323:   }
    1324: #if defined(PETSC_USE_LOG)
    1325:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
    1326: #endif
    1327:   return(0);
    1328: }

    1330: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
    1331: {
    1332:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1334:   vbinary->usempiio = flg;
    1335:   return(0);
    1336: }
    1337: #endif

    1339: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
    1340: {
    1341:   PetscErrorCode     ierr;
    1342:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

    1345:   if (binary->filename) {
    1346:     PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);
    1347:   }
    1348:   return(0);
    1349: }

    1351: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
    1352: {
    1353:   PetscErrorCode     ierr;
    1354:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

    1357:   if (!binary->setfromoptionscalled) { PetscViewerSetFromOptions(v); }
    1358:
    1359: #if defined(PETSC_HAVE_MPIIO)
    1360:   if (binary->usempiio) {
    1361:     PetscViewerFileSetUp_BinaryMPIIO(v);
    1362:   } else {
    1363: #endif
    1364:     PetscViewerFileSetUp_Binary(v);
    1365: #if defined(PETSC_HAVE_MPIIO)
    1366:   }
    1367: #endif
    1368:   return(0);
    1369: }

    1371: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer v)
    1372: {
    1373:   PetscErrorCode     ierr;
    1374:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
    1375:   char               defaultname[PETSC_MAX_PATH_LEN];
    1376:   PetscBool          flg;

    1379:   PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");
    1380:   PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");
    1381:   PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);
    1382:   if (flg) { PetscViewerFileSetName_Binary(v,defaultname); }
    1383:   PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",PETSC_FALSE,&binary->skipinfo,NULL);
    1384:   PetscOptionsBool("-viewer_binary_skip_options","Skip parsing vec load options","PetscViewerBinarySetSkipOptions",PETSC_TRUE,&binary->skipoptions,NULL);
    1385:   PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",PETSC_FALSE,&binary->skipheader,NULL);
    1386: #if defined(PETSC_HAVE_MPIIO)
    1387:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,&binary->usempiio,NULL);
    1388: #elif defined(PETSC_HAVE_MPIUNI)
    1389:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);
    1390: #endif
    1391:   PetscOptionsTail();
    1392:   binary->setfromoptionscalled = PETSC_TRUE;
    1393:   return(0);
    1394: }

    1396: /*MC
    1397:    PETSCVIEWERBINARY - A viewer that saves to binary files

    1400: .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
    1401:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
    1402:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
    1403:            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()

    1405:   Level: beginner

    1407: M*/

    1409: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
    1410: {
    1411:   PetscErrorCode     ierr;
    1412:   PetscViewer_Binary *vbinary;

    1415:   PetscNewLog(v,&vbinary);
    1416:   v->data                  = (void*)vbinary;
    1417:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
    1418:   v->ops->destroy          = PetscViewerDestroy_Binary;
    1419:   v->ops->view             = PetscViewerView_Binary;
    1420:   v->ops->setup            = PetscViewerSetUp_Binary;
    1421:   v->ops->flush            = NULL;
    1422:   vbinary->fdes            = 0;
    1423: #if defined(PETSC_HAVE_MPIIO)
    1424:   vbinary->mfdes           = MPI_FILE_NULL;
    1425:   vbinary->mfsub           = MPI_FILE_NULL;
    1426: #endif
    1427:   vbinary->fdes_info       = 0;
    1428:   vbinary->skipinfo        = PETSC_FALSE;
    1429:   vbinary->skipoptions     = PETSC_TRUE;
    1430:   vbinary->skipheader      = PETSC_FALSE;
    1431:   vbinary->setfromoptionscalled = PETSC_FALSE;
    1432:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
    1433:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
    1434:   v->ops->read             = PetscViewerBinaryRead;
    1435:   vbinary->btype           = (PetscFileMode) -1;
    1436:   vbinary->storecompressed = PETSC_FALSE;
    1437:   vbinary->filename        = NULL;
    1438:   vbinary->ogzfilename     = NULL;
    1439:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

    1441:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);
    1442:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);
    1443:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);
    1444:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);
    1445:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);
    1446:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);
    1447:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);
    1448:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);
    1449:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);
    1450:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);
    1451:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);
    1452:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);
    1453:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);
    1454: #if defined(PETSC_HAVE_MPIIO)
    1455:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);
    1456:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);
    1457: #endif
    1458:   return(0);
    1459: }

    1461: /* ---------------------------------------------------------------------*/
    1462: /*
    1463:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
    1464:   is attached to a communicator, in this case the attribute is a PetscViewer.
    1465: */
    1466: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

    1468: /*@C
    1469:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
    1470:                      in a communicator.

    1472:      Collective on MPI_Comm

    1474:      Input Parameter:
    1475: .    comm - the MPI communicator to share the binary PetscViewer

    1477:      Level: intermediate

    1479:    Options Database Keys:
    1480: +    -viewer_binary_filename <name>
    1481: .    -viewer_binary_skip_info
    1482: .    -viewer_binary_skip_options
    1483: .    -viewer_binary_skip_header
    1484: -    -viewer_binary_mpiio

    1486:    Environmental variables:
    1487: -   PETSC_VIEWER_BINARY_FILENAME

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

    1494: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
    1495:           PetscViewerDestroy()
    1496: @*/
    1497: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
    1498: {
    1500:   PetscBool      flg;
    1501:   PetscViewer    viewer;
    1502:   char           fname[PETSC_MAX_PATH_LEN];
    1503:   MPI_Comm       ncomm;

    1506:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1507:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
    1508:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
    1509:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1510:   }
    1511:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
    1512:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1513:   if (!flg) { /* PetscViewer not yet created */
    1514:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
    1515:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1516:     if (!flg) {
    1517:       PetscStrcpy(fname,"binaryoutput");
    1518:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1519:     }
    1520:     PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
    1521:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1522:     PetscObjectRegisterDestroy((PetscObject)viewer);
    1523:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1524:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
    1525:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1526:   }
    1527:   PetscCommDestroy(&ncomm);
    1528:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
    1529:   PetscFunctionReturn(viewer);
    1530: }