Actual source code: binv.c
petsc-3.13.6 2020-09-29
Report Typos and Errors

      1:  #include <petsc/private/viewerimpl.h>

      3: typedef struct  {
      4:   int           fdes;                 /* file descriptor, ignored if using MPI IO */
      5: #if defined(PETSC_HAVE_MPIIO)
      6:   PetscBool     usempiio;
      7:   MPI_File      mfdes;                /* ignored unless using MPI IO */
      8:   MPI_File      mfsub;                /* subviewer support */
      9:   MPI_Offset    moff;
     10: #endif
     11:   char          *filename;            /* file name */
     12:   PetscFileMode filemode;             /* read/write/append mode */
     13:   FILE          *fdes_info;           /* optional file containing info on binary file*/
     14:   PetscBool     storecompressed;      /* gzip the write binary file when closing it*/
     15:   char          *ogzfilename;         /* gzip can be run after the filename has been updated */
     16:   PetscBool     skipinfo;             /* Don't create info file for writing; don't use for reading */
     17:   PetscBool     skipoptions;          /* don't use PETSc options database when loading */
     18:   PetscInt      flowcontrol;          /* allow only <flowcontrol> messages outstanding at a time while doing IO */
     19:   PetscBool     skipheader;           /* don't write header, only raw data */
     20:   PetscBool     matlabheaderwritten;  /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
     21:   PetscBool     setfromoptionscalled;
     22: } PetscViewer_Binary;

     24: #if defined(PETSC_HAVE_MPIIO)
     25: static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer)
     26: {
     27:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
     28:   PetscErrorCode     ierr;

     31:   if (vbinary->filemode == FILE_MODE_READ) return(0);
     32:   if (vbinary->mfsub != MPI_FILE_NULL) {
     33:     MPI_File_sync(vbinary->mfsub);
     34:   }
     35:   if (vbinary->mfdes != MPI_FILE_NULL) {
     36:     MPI_Barrier(PetscObjectComm((PetscObject)viewer));
     37:     MPI_File_sync(vbinary->mfdes);
     38:   }
     39:   return(0);
     40: }
     41: #endif

     43: static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
     44: {
     45:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
     46:   PetscMPIInt        rank;
     47:   PetscErrorCode     ierr;

     50:   PetscViewerSetUp(viewer);

     52:   /* Return subviewer in process zero */
     53:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
     54:   if (!rank) {
     55:     PetscMPIInt flg;

     57:     MPI_Comm_compare(PETSC_COMM_SELF,comm,&flg);
     58:     if (flg != MPI_IDENT && flg != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscViewerGetSubViewer() for PETSCVIEWERBINARY requires a singleton MPI_Comm");
     59:     PetscViewerCreate(comm,outviewer);
     60:     PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);
     61:     PetscMemcpy((*outviewer)->data,vbinary,sizeof(PetscViewer_Binary));
     62:     (*outviewer)->setupcalled = PETSC_TRUE;
     63:   } else {
     64:     *outviewer = NULL;
     65:   }

     67: #if defined(PETSC_HAVE_MPIIO)
     68:   if (vbinary->usempiio && *outviewer) {
     69:     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
     70:     /* Parent viewer opens a new MPI file handle on PETSC_COMM_SELF and keeps track of it for future reuse */
     71:     if (vbinary->mfsub == MPI_FILE_NULL) {
     72:       int amode;
     73:       switch (vbinary->filemode) {
     74:       case FILE_MODE_READ:   amode = MPI_MODE_RDONLY; break;
     75:       case FILE_MODE_WRITE:  amode = MPI_MODE_WRONLY; break;
     76:       case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY; break;
     77:       default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->filemode]);
     78:       }
     79:       MPI_File_open(PETSC_COMM_SELF,vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfsub);
     80:     }
     81:     /* Subviewer gets the MPI file handle on PETSC_COMM_SELF */
     82:     obinary->mfdes = vbinary->mfsub;
     83:     obinary->mfsub = MPI_FILE_NULL;
     84:     obinary->moff  = vbinary->moff;
     85:   }
     86: #endif

     88: #if defined(PETSC_HAVE_MPIIO)
     89:   PetscViewerBinarySyncMPIIO(viewer);
     90: #endif
     91:   return(0);
     92: }

     94: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
     95: {
     96:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
     97:   PetscMPIInt        rank;
     98:   PetscErrorCode     ierr;
     99: #if defined(PETSC_HAVE_MPIIO)
    100:   MPI_Offset         moff = 0;
    101: #endif

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

    107: #if defined(PETSC_HAVE_MPIIO)
    108:   if (vbinary->usempiio && *outviewer) {
    109:     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
    110:     if (obinary->mfdes != vbinary->mfsub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
    111:     if (obinary->mfsub != MPI_FILE_NULL) {MPI_File_close(&obinary->mfsub);}
    112:     moff = obinary->moff;
    113:   }
    114: #endif

    116:   if (*outviewer) {
    117:     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
    118:     if (obinary->fdes != vbinary->fdes) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Subviewer not obtained from viewer");
    119:     PetscFree((*outviewer)->data);
    120:     PetscHeaderDestroy(outviewer);
    121:   }

    123: #if defined(PETSC_HAVE_MPIIO)
    124:   if (vbinary->usempiio) {
    125:     PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */
    126:     MPI_Bcast(&ioff,1,MPIU_INT64,0,PetscObjectComm((PetscObject)viewer));
    127:     vbinary->moff = (MPI_Offset)ioff;
    128:   }
    129: #endif

    131: #if defined(PETSC_HAVE_MPIIO)
    132:   PetscViewerBinarySyncMPIIO(viewer);
    133: #endif
    134:   return(0);
    135: }

    137: #if defined(PETSC_HAVE_MPIIO)
    138: /*@C
    139:     PetscViewerBinaryGetMPIIOOffset - Gets the current global offset that should be passed to MPI_File_set_view() or MPI_File_{write|read}_at[_all]()

    141:     Not Collective

    143:     Input Parameter:
    144: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    146:     Output Parameter:
    147: .   off - the current global offset

    149:     Level: advanced

    151:     Fortran Note:
    152:     This routine is not supported in Fortran.

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

    157: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryAddMPIIOOffset()
    158: @*/
    159: PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off)
    160: {
    161:   PetscViewer_Binary *vbinary;

    166:   vbinary = (PetscViewer_Binary*)viewer->data;
    167:   *off = vbinary->moff;
    168:   return(0);
    169: }

    171: /*@C
    172:     PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset

    174:     Logically Collective

    176:     Input Parameters:
    177: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    178: -   off - the addition to the global offset

    180:     Level: advanced

    182:     Fortran Note:
    183:     This routine is not supported in Fortran.

    185:     Use PetscViewerBinaryGetMPIIOOffset() to get the value that you should pass to MPI_File_set_view() or MPI_File_{write|read}_at[_all]()

    188: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    189: @*/
    190: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)
    191: {
    192:   PetscViewer_Binary *vbinary;

    197:   vbinary = (PetscViewer_Binary*)viewer->data;
    198:   vbinary->moff += off;
    199:   return(0);
    200: }

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

    205:     Not Collective

    207:     Input Parameter:
    208: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    210:     Output Parameter:
    211: .   fdes - file descriptor

    213:     Level: advanced

    215:     Fortran Note:
    216:     This routine is not supported in Fortran.

    219: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    220: @*/
    221: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
    222: {
    223:   PetscErrorCode     ierr;
    224:   PetscViewer_Binary *vbinary;

    229:   PetscViewerSetUp(viewer);
    230:   vbinary = (PetscViewer_Binary*)viewer->data;
    231:   *fdes = vbinary->mfdes;
    232:   return(0);
    233: }
    234: #endif

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

    240:     Logically Collective on PetscViewer

    242:     Input Parameters:
    243: +   viewer - the PetscViewer; must be a binary
    244: -   use - PETSC_TRUE means MPI-IO will be used

    246:     Options Database:
    247:     -viewer_binary_mpiio : Flag for using MPI-IO

    249:     Level: advanced

    251: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
    252:           PetscViewerBinaryGetUseMPIIO()

    254: @*/
    255: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool use)
    256: {

    262:   PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,use));
    263:   return(0);
    264: }

    266: #if defined(PETSC_HAVE_MPIIO)
    267: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool use)
    268: {
    269:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    271:   if (viewer->setupcalled && vbinary->usempiio != use) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change MPIIO to %s after setup",PetscBools[use]);
    272:   vbinary->usempiio = use;
    273:   return(0);
    274: }
    275: #endif

    277: /*@
    278:     PetscViewerBinaryGetUseMPIIO - Returns PETSC_TRUE if the binary viewer uses MPI-IO.

    280:     Not Collective

    282:     Input Parameter:
    283: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    285:     Output Parameter:
    286: -   use - PETSC_TRUE if MPI-IO is being used

    288:     Options Database:
    289:     -viewer_binary_mpiio : Flag for using MPI-IO

    291:     Level: advanced

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

    296:     Fortran Note:
    297:     This routine is not supported in Fortran.

    300: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    301: @*/
    302: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *use)
    303: {

    309:   *use = PETSC_FALSE;
    310:   PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,use));
    311:   return(0);
    312: }

    314: #if defined(PETSC_HAVE_MPIIO)
    315: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *use)
    316: {
    317:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    320:   *use = vbinary->usempiio;
    321:   return(0);
    322: }
    323: #endif

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

    328:     Not Collective

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

    334:     Level: advanced

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

    338: @*/
    339: PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
    340: {

    346:   PetscTryMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));
    347:   return(0);
    348: }

    350: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
    351: {
    352:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

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

    363:     Not Collective

    365:     Input Parameter:
    366: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    368:     Output Parameter:
    369: .   fc - the number of messages

    371:     Level: advanced

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

    375: @*/
    376: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
    377: {

    383:   PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));
    384:   return(0);
    385: }

    387: static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
    388: {
    389:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    392:   *fc = vbinary->flowcontrol;
    393:   return(0);
    394: }

    396: /*@C
    397:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

    399:     Collective On PetscViewer

    401:     Input Parameter:
    402: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    404:     Output Parameter:
    405: .   fdes - file descriptor

    407:     Level: advanced

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

    415:     Fortran Note:
    416:     This routine is not supported in Fortran.

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

    424: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
    425: @*/
    426: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
    427: {
    428:   PetscErrorCode     ierr;
    429:   PetscViewer_Binary *vbinary;

    434:   PetscViewerSetUp(viewer);
    435:   vbinary = (PetscViewer_Binary*)viewer->data;
    436:   *fdes = vbinary->fdes;
    437:   return(0);
    438: }

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

    443:     Not Collective

    445:     Input Parameter:
    446: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

    448:     Options Database Key:
    449: .   -viewer_binary_skip_info

    451:     Level: advanced

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

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

    461: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
    462:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
    463: @*/
    464: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
    465: {

    469:   PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE);
    470:   return(0);
    471: }

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

    476:     Not Collective

    478:     Input Parameter:
    479: +   viewer - PetscViewer context, obtained from PetscViewerCreate()
    480: -   skip - PETSC_TRUE implies the .info file will not be generated

    482:     Options Database Key:
    483: .   -viewer_binary_skip_info

    485:     Level: advanced

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

    497:   PetscTryMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));
    498:   return(0);
    499: }

    501: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
    502: {
    503:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    506:   vbinary->skipinfo = skip;
    507:   return(0);
    508: }

    510: /*@
    511:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

    513:     Not Collective

    515:     Input Parameter:
    516: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    518:     Output Parameter:
    519: .   skip - PETSC_TRUE implies the .info file was not generated

    521:     Level: advanced

    523:     Notes:
    524:     This must be called after PetscViewerSetType()

    526: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    527:           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
    528: @*/
    529: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
    530: {

    536:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));
    537:   return(0);
    538: }

    540: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
    541: {
    542:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    545:   *skip  = vbinary->skipinfo;
    546:   return(0);
    547: }

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

    552:     Not Collective

    554:     Input Parameters:
    555: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    556: -   skip - PETSC_TRUE means do not use

    558:     Options Database Key:
    559: .   -viewer_binary_skip_options

    561:     Level: advanced

    563:     Notes:
    564:     This must be called after PetscViewerSetType()

    566: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    567:           PetscViewerBinaryGetSkipOptions()
    568: @*/
    569: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)
    570: {

    576:   PetscTryMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));
    577:   return(0);
    578: }

    580: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
    581: {
    582:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    585:   vbinary->skipoptions = skip;
    586:   return(0);
    587: }

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

    592:     Not Collective

    594:     Input Parameter:
    595: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    597:     Output Parameter:
    598: .   skip - PETSC_TRUE means do not use

    600:     Level: advanced

    602:     Notes:
    603:     This must be called after PetscViewerSetType()

    605: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    606:           PetscViewerBinarySetSkipOptions()
    607: @*/
    608: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
    609: {

    615:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));
    616:   return(0);
    617: }

    619: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
    620: {
    621:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    624:   *skip = vbinary->skipoptions;
    625:   return(0);
    626: }

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

    631:     Not Collective

    633:     Input Parameters:
    634: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    635: -   skip - PETSC_TRUE means do not write header

    637:     Options Database Key:
    638: .   -viewer_binary_skip_header

    640:     Level: advanced

    642:     Notes:
    643:     This must be called after PetscViewerSetType()

    645:            Can ONLY be called on a binary viewer

    647: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    648:           PetscViewerBinaryGetSkipHeader()
    649: @*/
    650: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
    651: {

    657:   PetscTryMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));
    658:   return(0);
    659: }

    661: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
    662: {
    663:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    666:   vbinary->skipheader = skip;
    667:   return(0);
    668: }

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

    673:     Not Collective

    675:     Input Parameter:
    676: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    678:     Output Parameter:
    679: .   skip - PETSC_TRUE means do not write header

    681:     Level: advanced

    683:     Notes:
    684:     This must be called after PetscViewerSetType()

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

    688: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    689:           PetscViewerBinarySetSkipHeader()
    690: @*/
    691: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool  *skip)
    692: {

    698:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));
    699:   return(0);
    700: }

    702: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool  *skip)
    703: {
    704:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    707:   *skip = vbinary->skipheader;
    708:   return(0);
    709: }

    711: /*@C
    712:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
    713:           info file associated with a binary file.

    715:     Not Collective

    717:     Input Parameter:
    718: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    720:     Output Parameter:
    721: .   file - file pointer  Always returns NULL if not a binary viewer

    723:     Level: advanced

    725:     Notes:
    726:       For writable binary PetscViewers, the descriptor will only be valid for the
    727:     first processor in the communicator that shares the PetscViewer.

    729:     Fortran Note:
    730:     This routine is not supported in Fortran.

    732: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
    733: @*/
    734: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
    735: {

    741:   *file = NULL;
    742:   PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));
    743:   return(0);
    744: }

    746: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
    747: {
    748:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    749:   PetscErrorCode     ierr;

    752:   PetscViewerSetUp(viewer);
    753:   *file = vbinary->fdes_info;
    754:   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
    755:     if (vbinary->fdes_info) {
    756:       FILE *info = vbinary->fdes_info;
    757:       PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
    758:       PetscFPrintf(PETSC_COMM_SELF,info,"#$$ Set.filename = '%s';\n",vbinary->filename);
    759:       PetscFPrintf(PETSC_COMM_SELF,info,"#$$ fd = PetscOpenFile(Set.filename);\n");
    760:       PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
    761:     }
    762:     vbinary->matlabheaderwritten = PETSC_TRUE;
    763:   }
    764:   return(0);
    765: }

    768: #if defined(PETSC_HAVE_MPIIO)
    769: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
    770: {
    771:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    772:   PetscErrorCode     ierr;

    775:   if (vbinary->mfdes != MPI_FILE_NULL) {
    776:     MPI_File_close(&vbinary->mfdes);
    777:   }
    778:   if (vbinary->mfsub != MPI_FILE_NULL) {
    779:     MPI_File_close(&vbinary->mfsub);
    780:   }
    781:   vbinary->moff = 0;
    782:   return(0);
    783: }
    784: #endif

    786: static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
    787: {
    788:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    789:   PetscErrorCode     ierr;

    792:   if (vbinary->fdes != -1) {
    793:     PetscBinaryClose(vbinary->fdes);
    794:     vbinary->fdes = -1;
    795:     if (vbinary->storecompressed) {
    796:       char cmd[8+PETSC_MAX_PATH_LEN],out[64+PETSC_MAX_PATH_LEN] = "";
    797:       const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
    798:       /* compress the file */
    799:       PetscStrncpy(cmd,"gzip -f ",sizeof(cmd));
    800:       PetscStrlcat(cmd,gzfilename,sizeof(cmd));
    801: #if defined(PETSC_HAVE_POPEN)
    802:       {
    803:         FILE *fp;
    804:         PetscPOpen(PETSC_COMM_SELF,NULL,cmd,"r",&fp);
    805:         if (fgets(out,(int)(sizeof(out)-1),fp)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from command %s\n%s",cmd,out);
    806:         PetscPClose(PETSC_COMM_SELF,fp);
    807:       }
    808: #endif
    809:     }
    810:   }
    811:   PetscFree(vbinary->ogzfilename);
    812:   return(0);
    813: }

    815: static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
    816: {
    817:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    818:   PetscErrorCode     ierr;

    821:   if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
    822:     if (vbinary->fdes_info) {
    823:       FILE *info = vbinary->fdes_info;
    824:       PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
    825:       PetscFPrintf(PETSC_COMM_SELF,info,"#$$ close(fd);\n");
    826:       PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
    827:     }
    828:   }
    829:   if (vbinary->fdes_info) {
    830:     FILE *info = vbinary->fdes_info;
    831:     vbinary->fdes_info = NULL;
    832:     if (fclose(info)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
    833:   }
    834:   return(0);
    835: }

    837: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
    838: {
    839:   PetscErrorCode     ierr;

    842: #if defined(PETSC_HAVE_MPIIO)
    843:   PetscViewerFileClose_BinaryMPIIO(v);
    844: #endif
    845:   PetscViewerFileClose_BinarySTDIO(v);
    846:   PetscViewerFileClose_BinaryInfo(v);
    847:   return(0);
    848: }

    850: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
    851: {
    852:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    853:   PetscErrorCode     ierr;

    856:   PetscViewerFileClose_Binary(v);
    857:   PetscFree(vbinary->filename);
    858:   PetscFree(vbinary);

    860:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",NULL);
    861:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",NULL);
    862:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",NULL);
    863:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",NULL);
    864:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",NULL);
    865:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",NULL);
    866:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",NULL);
    867:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",NULL);
    868:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",NULL);
    869:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",NULL);
    870:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",NULL);
    871:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",NULL);
    872:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",NULL);
    873: #if defined(PETSC_HAVE_MPIIO)
    874:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",NULL);
    875:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",NULL);
    876: #endif
    877:   return(0);
    878: }

    880: /*@C
    881:    PetscViewerBinaryOpen - Opens a file for binary input/output.

    883:    Collective

    885:    Input Parameters:
    886: +  comm - MPI communicator
    887: .  name - name of file
    888: -  mode - open mode of file
    889: $    FILE_MODE_WRITE - create new file for binary output
    890: $    FILE_MODE_READ - open existing file for binary input
    891: $    FILE_MODE_APPEND - open existing file for binary output

    893:    Output Parameter:
    894: .  viewer - PetscViewer for binary input/output to use with the specified file

    896:     Options Database Keys:
    897: +    -viewer_binary_filename <name> -
    898: .    -viewer_binary_skip_info -
    899: .    -viewer_binary_skip_options -
    900: .    -viewer_binary_skip_header -
    901: -    -viewer_binary_mpiio -

    903:    Level: beginner

    905:    Note:
    906:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

    914: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    915:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    916:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
    917:           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    918: @*/
    919: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode mode,PetscViewer *viewer)
    920: {

    924:   PetscViewerCreate(comm,viewer);
    925:   PetscViewerSetType(*viewer,PETSCVIEWERBINARY);
    926:   PetscViewerFileSetMode(*viewer,mode);
    927:   PetscViewerFileSetName(*viewer,name);
    928:   PetscViewerSetFromOptions(*viewer);
    929:   return(0);
    930: }

    932: #if defined(PETSC_HAVE_MPIIO)
    933: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write)
    934: {
    935:   MPI_Comm           comm = PetscObjectComm((PetscObject)viewer);
    936:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    937:   MPI_File           mfdes = vbinary->mfdes;
    938:   PetscErrorCode     ierr;
    939:   MPI_Datatype       mdtype;
    940:   PetscMPIInt        rank,cnt;
    941:   MPI_Status         status;
    942:   MPI_Aint           ul,dsize;

    945:   MPI_Comm_rank(comm,&rank);
    946:   PetscMPIIntCast(num,&cnt);
    947:   PetscDataTypeToMPIDataType(dtype,&mdtype);
    948:   if (write) {
    949:     if (!rank) {
    950:       MPIU_File_write_at(mfdes,vbinary->moff,data,cnt,mdtype,&status);
    951:     }
    952:   } else {
    953:     if (!rank) {
    954:       MPIU_File_read_at(mfdes,vbinary->moff,data,cnt,mdtype,&status);
    955:       if (cnt > 0) {MPI_Get_count(&status,mdtype,&cnt);}
    956:     }
    957:     MPI_Bcast(&cnt,1,MPI_INT,0,comm);
    958:     MPI_Bcast(data,cnt,mdtype,0,comm);
    959:   }
    960:   MPI_Type_get_extent(mdtype,&ul,&dsize);
    961:   vbinary->moff += dsize*cnt;
    962:   if (count) *count = cnt;
    963:   return(0);
    964: }
    965: #endif

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

    970:    Collective

    972:    Input Parameters:
    973: +  viewer - the binary viewer
    974: .  data - location of the data to be written
    975: .  num - number of items of data to read
    976: -  dtype - type of data to read

    978:    Output Parameters:
    979: .  count - number of items of data actually read, or NULL.

    981:    Level: beginner

    983: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    984:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    985:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    986: @*/
    987: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
    988: {
    989:   PetscErrorCode     ierr;
    990:   PetscViewer_Binary *vbinary;

    995:   PetscViewerSetUp(viewer);
    996:   vbinary = (PetscViewer_Binary*)viewer->data;
    997: #if defined(PETSC_HAVE_MPIIO)
    998:   if (vbinary->usempiio) {
    999:     PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE);
    1000:   } else {
    1001: #endif
    1002:     PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,count,dtype);
    1003: #if defined(PETSC_HAVE_MPIIO)
    1004:   }
    1005: #endif
    1006:   return(0);
    1007: }

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

    1012:    Collective

    1014:    Input Parameters:
    1015: +  viewer - the binary viewer
    1016: .  data - location of data
    1017: .  count - number of items of data to write
    1018: -  dtype - type of data to write

    1020:    Level: beginner

    1022: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    1023:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
    1024:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    1025: @*/
    1026: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,const void *data,PetscInt count,PetscDataType dtype)
    1027: {
    1028:   PetscErrorCode     ierr;
    1029:   PetscViewer_Binary *vbinary;

    1034:   PetscViewerSetUp(viewer);
    1035:   vbinary = (PetscViewer_Binary*)viewer->data;
    1036: #if defined(PETSC_HAVE_MPIIO)
    1037:   if (vbinary->usempiio) {
    1038:     PetscViewerBinaryWriteReadMPIIO(viewer,(void*)data,count,NULL,dtype,PETSC_TRUE);
    1039:   } else {
    1040: #endif
    1041:     PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype);
    1042: #if defined(PETSC_HAVE_MPIIO)
    1043:   }
    1044: #endif
    1045:   return(0);
    1046: }

    1048: static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer,PetscBool write,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
    1049: {
    1050:   MPI_Comm       comm = PetscObjectComm((PetscObject)viewer);
    1051:   PetscMPIInt    size,rank;
    1052:   MPI_Datatype   mdtype;
    1053:   MPI_Aint       lb,dsize;
    1054:   PetscBool      useMPIIO;

    1062:   PetscViewerSetUp(viewer);

    1064:   PetscDataTypeToMPIDataType(dtype,&mdtype);
    1065:   MPI_Type_get_extent(mdtype,&lb,&dsize);
    1066:   MPI_Comm_rank(comm,&rank);
    1067:   MPI_Comm_size(comm,&size);

    1069:   PetscViewerBinaryGetUseMPIIO(viewer,&useMPIIO);
    1070: #if defined(PETSC_HAVE_MPIIO)
    1071:   if (useMPIIO) {
    1072:     MPI_File       mfdes;
    1073:     MPI_Offset     off;
    1074:     PetscMPIInt    cnt;

    1076:     if (start == PETSC_DETERMINE) {
    1077:       MPI_Scan(&count,&start,1,MPIU_INT,MPI_SUM,comm);
    1078:       start -= count;
    1079:     }
    1080:     if (total == PETSC_DETERMINE) {
    1081:       total = start + count;
    1082:       MPI_Bcast(&total,1,MPIU_INT,size-1,comm);
    1083:     }
    1084:     PetscMPIIntCast(count,&cnt);
    1085:     PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);
    1086:     PetscViewerBinaryGetMPIIOOffset(viewer,&off);
    1087:     off += (MPI_Offset)(start*dsize);
    1088:     if (write) {
    1089:       MPIU_File_write_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE);
    1090:     } else {
    1091:       MPIU_File_read_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE);
    1092:     }
    1093:     off  = (MPI_Offset)(total*dsize);
    1094:     PetscViewerBinaryAddMPIIOOffset(viewer,off);
    1095:     return(0);
    1096:   }
    1097: #endif
    1098:   {
    1099:     int         fdes;
    1100:     char        *workbuf = NULL;
    1101:     PetscInt    maxcount=0,message_count,flowcontrolcount;
    1102:     PetscMPIInt tag,cnt,maxcnt,scnt=0,rcnt=0,j;
    1103:     MPI_Status  status;

    1105:     PetscCommGetNewTag(comm,&tag);
    1106:     MPI_Reduce(&count,&maxcount,1,MPIU_INT,MPI_MAX,0,comm);
    1107:     PetscMPIIntCast(maxcount,&maxcnt);
    1108:     PetscMPIIntCast(count,&cnt);

    1110:     PetscViewerBinaryGetDescriptor(viewer,&fdes);
    1111:     PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);
    1112:     if (!rank) {
    1113:       PetscMalloc(maxcnt*dsize,&workbuf);
    1114:       if (write) {
    1115:         PetscBinaryWrite(fdes,data,cnt,dtype);
    1116:       } else {
    1117:         PetscBinaryRead(fdes,data,cnt,NULL,dtype);
    1118:       }
    1119:       for (j=1; j<size; j++) {
    1120:         PetscViewerFlowControlStepMaster(viewer,j,&message_count,flowcontrolcount);
    1121:         if (write) {
    1122:           MPI_Recv(workbuf,maxcnt,mdtype,j,tag,comm,&status);
    1123:           MPI_Get_count(&status,mdtype,&rcnt);
    1124:           PetscBinaryWrite(fdes,workbuf,rcnt,dtype);
    1125:         } else {
    1126:           MPI_Recv(&scnt,1,MPI_INT,j,tag,comm,MPI_STATUS_IGNORE);
    1127:           PetscBinaryRead(fdes,workbuf,scnt,NULL,dtype);
    1128:           MPI_Send(workbuf,scnt,mdtype,j,tag,comm);
    1129:         }
    1130:       }
    1131:       PetscFree(workbuf);
    1132:       PetscViewerFlowControlEndMaster(viewer,&message_count);
    1133:     } else {
    1134:       PetscViewerFlowControlStepWorker(viewer,rank,&message_count);
    1135:       if (write) {
    1136:         MPI_Send(data,cnt,mdtype,0,tag,comm);
    1137:       } else {
    1138:         MPI_Send(&cnt,1,MPI_INT,0,tag,comm);
    1139:         MPI_Recv(data,cnt,mdtype,0,tag,comm,MPI_STATUS_IGNORE);
    1140:       }
    1141:       PetscViewerFlowControlEndWorker(viewer,&message_count);
    1142:     }
    1143:   }
    1144:   return(0);
    1145: }

    1147: /*@C
    1148:    PetscViewerBinaryReadAll - reads from a binary file from all processes

    1150:    Collective

    1152:    Input Parameters:
    1153: +  viewer - the binary viewer
    1154: .  data - location of data
    1155: .  count - local number of items of data to read
    1156: .  start - local start, can be PETSC_DETERMINE
    1157: .  total - global number of items of data to read, can be PETSC_DETERMINE
    1158: -  dtype - type of data to read

    1160:    Level: advanced

    1162: .seealso: PetscViewerBinaryOpen(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryRead(), PetscViewerBinaryWriteAll()
    1163: @*/
    1164: PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
    1165: {
    1168:   PetscViewerBinaryWriteReadAll(viewer,PETSC_FALSE,data,count,start,total,dtype);
    1169:   return(0);
    1170: }

    1172: /*@C
    1173:    PetscViewerBinaryWriteAll - writes to a binary file from all processes

    1175:    Collective

    1177:    Input Parameters:
    1178: +  viewer - the binary viewer
    1179: .  data - location of data
    1180: .  count - local number of items of data to write
    1181: .  start - local start, can be PETSC_DETERMINE
    1182: .  total - global number of items of data to write, can be PETSC_DETERMINE
    1183: -  dtype - type of data to write

    1185:    Level: advanced

    1187: .seealso: PetscViewerBinaryOpen(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryWriteAll(), PetscViewerBinaryReadAll()
    1188: @*/
    1189: PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer,const void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
    1190: {
    1193:   PetscViewerBinaryWriteReadAll(viewer,PETSC_TRUE,(void*)data,count,start,total,dtype);
    1194:   return(0);
    1195: }

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

    1200:    Collective

    1202:    Input Parameters:
    1203: +  viewer - the binary viewer
    1204: -  data - location of the array of strings

    1207:    Level: intermediate

    1209:     Notes:
    1210:     array of strings is null terminated

    1212: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    1213:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    1214:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    1215: @*/
    1216: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data)
    1217: {
    1219:   PetscInt       i,n = 0,*sizes;
    1220:   size_t         len;

    1223:   PetscViewerSetUp(viewer);
    1224:   /* count number of strings */
    1225:   while (data[n++]);
    1226:   n--;
    1227:   PetscMalloc1(n+1,&sizes);
    1228:   sizes[0] = n;
    1229:   for (i=0; i<n; i++) {
    1230:     PetscStrlen(data[i],&len);
    1231:     sizes[i+1] = (PetscInt)len + 1; /* size includes space for the null terminator */
    1232:   }
    1233:   PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT);
    1234:   for (i=0; i<n; i++) {
    1235:     PetscViewerBinaryWrite(viewer,(void*)data[i],sizes[i+1],PETSC_CHAR);
    1236:   }
    1237:   PetscFree(sizes);
    1238:   return(0);
    1239: }

    1241: /*@C
    1242:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

    1244:    Collective

    1246:    Input Parameter:
    1247: .  viewer - the binary viewer

    1249:    Output Parameter:
    1250: .  data - location of the array of strings

    1252:    Level: intermediate

    1254:     Notes:
    1255:     array of strings is null terminated

    1257: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    1258:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    1259:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    1260: @*/
    1261: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
    1262: {
    1264:   PetscInt       i,n,*sizes,N = 0;

    1267:   PetscViewerSetUp(viewer);
    1268:   /* count number of strings */
    1269:   PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);
    1270:   PetscMalloc1(n,&sizes);
    1271:   PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);
    1272:   for (i=0; i<n; i++) N += sizes[i];
    1273:   PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);
    1274:   (*data)[0] = (char*)((*data) + n + 1);
    1275:   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
    1276:   PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);
    1277:   (*data)[n] = NULL;
    1278:   PetscFree(sizes);
    1279:   return(0);
    1280: }

    1282: /*@C
    1283:      PetscViewerFileSetMode - Sets the open mode of file

    1285:     Logically Collective on PetscViewer

    1287:   Input Parameters:
    1288: +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
    1289: -  mode - open mode of file
    1290: $    FILE_MODE_WRITE - create new file for output
    1291: $    FILE_MODE_READ - open existing file for input
    1292: $    FILE_MODE_APPEND - open existing file for output

    1294:   Level: advanced

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

    1298: @*/
    1299: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode mode)
    1300: {

    1306:   PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,mode));
    1307:   return(0);
    1308: }

    1310: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode mode)
    1311: {
    1312:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1315:   if (viewer->setupcalled && vbinary->filemode != mode) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER,"Cannot change mode to %s after setup",PetscFileModes[mode]);
    1316:   vbinary->filemode = mode;
    1317:   return(0);
    1318: }

    1320: /*@C
    1321:      PetscViewerFileGetMode - Gets the open mode of file

    1323:     Not Collective

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

    1328:   Output Parameter:
    1329: .  mode - open mode of file
    1330: $    FILE_MODE_WRITE - create new file for binary output
    1331: $    FILE_MODE_READ - open existing file for binary input
    1332: $    FILE_MODE_APPEND - open existing file for binary output

    1334:   Level: advanced

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

    1338: @*/
    1339: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *mode)
    1340: {

    1346:   PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,mode));
    1347:   return(0);
    1348: }

    1350: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *mode)
    1351: {
    1352:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1355:   *mode = vbinary->filemode;
    1356:   return(0);
    1357: }

    1359: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
    1360: {
    1361:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1362:   PetscErrorCode     ierr;

    1365:   if (viewer->setupcalled && vbinary->filename) {
    1366:     /* gzip can be run after the file with the previous filename has been closed */
    1367:     PetscFree(vbinary->ogzfilename);
    1368:     PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename);
    1369:   }
    1370:   PetscFree(vbinary->filename);
    1371:   PetscStrallocpy(name,&vbinary->filename);
    1372:   viewer->setupcalled = PETSC_FALSE;
    1373:   return(0);
    1374: }

    1376: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
    1377: {
    1378:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1381:   *name = vbinary->filename;
    1382:   return(0);
    1383: }

    1385: #if defined(PETSC_HAVE_MPIIO)
    1386: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
    1387: {
    1388:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1389:   int                amode;
    1390:   PetscErrorCode     ierr;

    1393:   vbinary->storecompressed = PETSC_FALSE;

    1395:   vbinary->moff = 0;
    1396:   switch (vbinary->filemode) {
    1397:   case FILE_MODE_READ:   amode = MPI_MODE_RDONLY; break;
    1398:   case FILE_MODE_WRITE:  amode = MPI_MODE_WRONLY | MPI_MODE_CREATE; break;
    1399:   case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND; break;
    1400:   default: SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->filemode]);
    1401:   }
    1402:   MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfdes);
    1403:   /*
    1404:       The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
    1405:   */
    1406:   if (vbinary->filemode == FILE_MODE_WRITE) {MPI_File_set_size(vbinary->mfdes,0);}
    1407:   /*
    1408:       Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
    1409:       MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
    1410:       Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
    1411:       the offset in etype units to an absolute byte position.
    1412:    */
    1413:   if (vbinary->filemode == FILE_MODE_APPEND) {MPI_File_get_position(vbinary->mfdes,&vbinary->moff);}
    1414:   return(0);
    1415: }
    1416: #endif

    1418: static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
    1419: {
    1420:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1421:   const char         *fname;
    1422:   char               bname[PETSC_MAX_PATH_LEN],*gz;
    1423:   PetscBool          found;
    1424:   PetscMPIInt        rank;
    1425:   PetscErrorCode     ierr;

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

    1430:   /* if file name ends in .gz strip that off and note user wants file compressed */
    1431:   vbinary->storecompressed = PETSC_FALSE;
    1432:   if (vbinary->filemode == FILE_MODE_WRITE) {
    1433:     PetscStrstr(vbinary->filename,".gz",&gz);
    1434:     if (gz && gz[3] == 0) {*gz = 0; vbinary->storecompressed = PETSC_TRUE;}
    1435:   }
    1436: #if !defined(PETSC_HAVE_POPEN)
    1437:   if (vbinary->storecompressed) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP_SYS,"Cannot run gzip on this machine");
    1438: #endif

    1441:   fname = vbinary->filename;
    1442:   if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
    1443:     PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),fname,bname,PETSC_MAX_PATH_LEN,&found);
    1444:     if (!found) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_OPEN,"Cannot locate file: %s",fname);
    1445:     fname = bname;
    1446:   }

    1448:   vbinary->fdes = -1;
    1449:   if (!rank) { /* only first processor opens file*/
    1450:     PetscFileMode mode = vbinary->filemode;
    1451:     if (mode == FILE_MODE_APPEND) {
    1452:       /* check if asked to append to a non-existing file */
    1453:       PetscTestFile(fname,'\0',&found);
    1454:       if (!found) mode = FILE_MODE_WRITE;
    1455:     }
    1456:     PetscBinaryOpen(fname,mode,&vbinary->fdes);
    1457:   }
    1458:   return(0);
    1459: }

    1461: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
    1462: {
    1463:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1464:   PetscMPIInt        rank;
    1465:   PetscBool          found;
    1466:   PetscErrorCode     ierr;

    1469:   vbinary->fdes_info = NULL;
    1470:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
    1471:   if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || !rank)) {
    1472:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN],*gz;

    1474:     PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));
    1475:     /* remove .gz if it ends file name */
    1476:     PetscStrstr(infoname,".gz",&gz);
    1477:     if (gz && gz[3] == 0) *gz = 0;

    1479:     PetscStrlcat(infoname,".info",sizeof(infoname));
    1480:     if (vbinary->filemode == FILE_MODE_READ) {
    1481:       PetscFixFilename(infoname,iname);
    1482:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
    1483:       if (found) {PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);}
    1484:     } else if (!rank) { /* write or append */
    1485:       const char *omode = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
    1486:       vbinary->fdes_info = fopen(infoname,omode);
    1487:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
    1488:     }
    1489:   }
    1490:   return(0);
    1491: }

    1493: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
    1494: {
    1495:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1496:   PetscBool          usempiio;
    1497:   PetscErrorCode     ierr;

    1500:   if (!vbinary->setfromoptionscalled) {PetscViewerSetFromOptions(viewer);}
    1501:   if (!vbinary->filename) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetName()");
    1502:   if (vbinary->filemode == (PetscFileMode)-1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call PetscViewerFileSetMode()");
    1503:   PetscViewerFileClose_Binary(viewer);

    1505:   PetscViewerBinaryGetUseMPIIO(viewer,&usempiio);
    1506:   if (usempiio) {
    1507: #if defined(PETSC_HAVE_MPIIO)
    1508:     PetscViewerFileSetUp_BinaryMPIIO(viewer);
    1509: #endif
    1510:   } else {
    1511:     PetscViewerFileSetUp_BinarySTDIO(viewer);
    1512:   }
    1513:   PetscViewerFileSetUp_BinaryInfo(viewer);

    1515:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
    1516:   return(0);
    1517: }

    1519: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
    1520: {
    1521:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    1522:   const char         *fname = vbinary->filename ? vbinary->filename : "not yet set";
    1523:   const char         *fmode = vbinary->filemode != (PetscFileMode) -1 ? PetscFileModes[vbinary->filemode] : "not yet set";
    1524:   PetscBool          usempiio;
    1525:   PetscErrorCode     ierr;

    1528:   PetscViewerBinaryGetUseMPIIO(v,&usempiio);
    1529:   PetscViewerASCIIPrintf(viewer,"Filename: %s\n",fname);
    1530:   PetscViewerASCIIPrintf(viewer,"Mode: %s (%s)\n",fmode,usempiio ? "mpiio" : "stdio");
    1531:   return(0);
    1532: }

    1534: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer viewer)
    1535: {
    1536:   PetscViewer_Binary *binary = (PetscViewer_Binary*)viewer->data;
    1537:   char               defaultname[PETSC_MAX_PATH_LEN];
    1538:   PetscBool          flg;
    1539:   PetscErrorCode     ierr;

    1542:   if (viewer->setupcalled) return(0);
    1543:   PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");
    1544:   PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");
    1545:   PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);
    1546:   if (flg) { PetscViewerFileSetName_Binary(viewer,defaultname); }
    1547:   PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",binary->skipinfo,&binary->skipinfo,NULL);
    1548:   PetscOptionsBool("-viewer_binary_skip_options","Skip parsing Vec/Mat load options","PetscViewerBinarySetSkipOptions",binary->skipoptions,&binary->skipoptions,NULL);
    1549:   PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",binary->skipheader,&binary->skipheader,NULL);
    1550: #if defined(PETSC_HAVE_MPIIO)
    1551:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",binary->usempiio,&binary->usempiio,NULL);
    1552: #else
    1553:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);
    1554: #endif
    1555:   PetscOptionsTail();
    1556:   binary->setfromoptionscalled = PETSC_TRUE;
    1557:   return(0);
    1558: }

    1560: /*MC
    1561:    PETSCVIEWERBINARY - A viewer that saves to binary files

    1564: .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
    1565:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
    1566:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
    1567:            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()

    1569:   Level: beginner

    1571: M*/

    1573: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
    1574: {
    1575:   PetscErrorCode     ierr;
    1576:   PetscViewer_Binary *vbinary;

    1579:   PetscNewLog(v,&vbinary);
    1580:   v->data = (void*)vbinary;

    1582:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
    1583:   v->ops->destroy          = PetscViewerDestroy_Binary;
    1584:   v->ops->view             = PetscViewerView_Binary;
    1585:   v->ops->setup            = PetscViewerSetUp_Binary;
    1586:   v->ops->flush            = NULL; /* Should we support Flush() ? */
    1587:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
    1588:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
    1589:   v->ops->read             = PetscViewerBinaryRead;

    1591:   vbinary->fdes            = -1;
    1592: #if defined(PETSC_HAVE_MPIIO)
    1593:   vbinary->usempiio        = PETSC_FALSE;
    1594:   vbinary->mfdes           = MPI_FILE_NULL;
    1595:   vbinary->mfsub           = MPI_FILE_NULL;
    1596: #endif
    1597:   vbinary->filename        = NULL;
    1598:   vbinary->filemode        = (PetscFileMode)-1;
    1599:   vbinary->fdes_info       = NULL;
    1600:   vbinary->skipinfo        = PETSC_FALSE;
    1601:   vbinary->skipoptions     = PETSC_TRUE;
    1602:   vbinary->skipheader      = PETSC_FALSE;
    1603:   vbinary->storecompressed = PETSC_FALSE;
    1604:   vbinary->ogzfilename     = NULL;
    1605:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

    1607:   vbinary->setfromoptionscalled = PETSC_FALSE;

    1609:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);
    1610:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);
    1611:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);
    1612:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);
    1613:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);
    1614:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);
    1615:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);
    1616:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);
    1617:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);
    1618:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);
    1619:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);
    1620:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);
    1621:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);
    1622: #if defined(PETSC_HAVE_MPIIO)
    1623:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);
    1624:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);
    1625: #endif
    1626:   return(0);
    1627: }

    1629: /* ---------------------------------------------------------------------*/
    1630: /*
    1631:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
    1632:   is attached to a communicator, in this case the attribute is a PetscViewer.
    1633: */
    1634: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

    1636: /*@C
    1637:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
    1638:                      in a communicator.

    1640:      Collective

    1642:      Input Parameter:
    1643: .    comm - the MPI communicator to share the binary PetscViewer

    1645:      Level: intermediate

    1647:    Options Database Keys:
    1648: +    -viewer_binary_filename <name>
    1649: .    -viewer_binary_skip_info
    1650: .    -viewer_binary_skip_options
    1651: .    -viewer_binary_skip_header
    1652: -    -viewer_binary_mpiio

    1654:    Environmental variables:
    1655: -   PETSC_VIEWER_BINARY_FILENAME

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

    1662: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
    1663:           PetscViewerDestroy()
    1664: @*/
    1665: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
    1666: {
    1668:   PetscBool      flg;
    1669:   PetscViewer    viewer;
    1670:   char           fname[PETSC_MAX_PATH_LEN];
    1671:   MPI_Comm       ncomm;

    1674:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    1675:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
    1676:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,NULL);
    1677:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    1678:   }
    1679:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
    1680:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    1681:   if (!flg) { /* PetscViewer not yet created */
    1682:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
    1683:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    1684:     if (!flg) {
    1685:       PetscStrcpy(fname,"binaryoutput");
    1686:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    1687:     }
    1688:     PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
    1689:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    1690:     PetscObjectRegisterDestroy((PetscObject)viewer);
    1691:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    1692:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
    1693:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    1694:   }
    1695:   PetscCommDestroy(&ncomm);
    1696:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(NULL);}
    1697:   PetscFunctionReturn(viewer);
    1698: }