Actual source code: binv.c

      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;

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

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

     46:   PetscViewerSetUp(viewer);

     48:   /* Return subviewer in process zero */
     49:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
     50:   if (rank == 0) {
     51:     PetscMPIInt flg;

     53:     MPI_Comm_compare(PETSC_COMM_SELF,comm,&flg);
     55:     PetscViewerCreate(comm,outviewer);
     56:     PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);
     57:     PetscMemcpy((*outviewer)->data,vbinary,sizeof(PetscViewer_Binary));
     58:     (*outviewer)->setupcalled = PETSC_TRUE;
     59:   } else {
     60:     *outviewer = NULL;
     61:   }

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

     84: #if defined(PETSC_HAVE_MPIIO)
     85:   PetscViewerBinarySyncMPIIO(viewer);
     86: #endif
     87:   return 0;
     88: }

     90: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
     91: {
     92:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
     93:   PetscMPIInt        rank;
     94: #if defined(PETSC_HAVE_MPIIO)
     95:   MPI_Offset         moff = 0;
     96: #endif

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

    101: #if defined(PETSC_HAVE_MPIIO)
    102:   if (vbinary->usempiio && *outviewer) {
    103:     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
    105:     if (obinary->mfsub != MPI_FILE_NULL) MPI_File_close(&obinary->mfsub);
    106:     moff = obinary->moff;
    107:   }
    108: #endif

    110:   if (*outviewer) {
    111:     PetscViewer_Binary *obinary = (PetscViewer_Binary*)(*outviewer)->data;
    113:     PetscFree((*outviewer)->data);
    114:     PetscHeaderDestroy(outviewer);
    115:   }

    117: #if defined(PETSC_HAVE_MPIIO)
    118:   if (vbinary->usempiio) {
    119:     PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */
    120:     MPI_Bcast(&ioff,1,MPIU_INT64,0,PetscObjectComm((PetscObject)viewer));
    121:     vbinary->moff = (MPI_Offset)ioff;
    122:   }
    123: #endif

    125: #if defined(PETSC_HAVE_MPIIO)
    126:   PetscViewerBinarySyncMPIIO(viewer);
    127: #endif
    128:   return 0;
    129: }

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

    135:     Not Collective

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

    140:     Output Parameter:
    141: .   off - the current global offset

    143:     Level: advanced

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

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

    150: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryAddMPIIOOffset()
    151: @*/
    152: PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off)
    153: {
    154:   PetscViewer_Binary *vbinary;

    158:   vbinary = (PetscViewer_Binary*)viewer->data;
    159:   *off = vbinary->moff;
    160:   return 0;
    161: }

    163: /*@C
    164:     PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset

    166:     Logically Collective

    168:     Input Parameters:
    169: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    170: -   off - the addition to the global offset

    172:     Level: advanced

    174:     Fortran Note:
    175:     This routine is not supported in Fortran.

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

    179: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    180: @*/
    181: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)
    182: {
    183:   PetscViewer_Binary *vbinary;

    187:   vbinary = (PetscViewer_Binary*)viewer->data;
    188:   vbinary->moff += off;
    189:   return 0;
    190: }

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

    195:     Not Collective

    197:     Input Parameter:
    198: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    200:     Output Parameter:
    201: .   fdes - file descriptor

    203:     Level: advanced

    205:     Fortran Note:
    206:     This routine is not supported in Fortran.

    208: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    209: @*/
    210: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
    211: {
    212:   PetscViewer_Binary *vbinary;

    216:   PetscViewerSetUp(viewer);
    217:   vbinary = (PetscViewer_Binary*)viewer->data;
    218:   *fdes = vbinary->mfdes;
    219:   return 0;
    220: }
    221: #endif

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

    227:     Logically Collective on PetscViewer

    229:     Input Parameters:
    230: +   viewer - the PetscViewer; must be a binary
    231: -   use - PETSC_TRUE means MPI-IO will be used

    233:     Options Database:
    234:     -viewer_binary_mpiio : Flag for using MPI-IO

    236:     Level: advanced

    238: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
    239:           PetscViewerBinaryGetUseMPIIO()

    241: @*/
    242: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool use)
    243: {
    246:   PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,use));
    247:   return 0;
    248: }

    250: #if defined(PETSC_HAVE_MPIIO)
    251: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool use)
    252: {
    253:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    255:   vbinary->usempiio = use;
    256:   return 0;
    257: }
    258: #endif

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

    263:     Not Collective

    265:     Input Parameter:
    266: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    268:     Output Parameter:
    269: .   use - PETSC_TRUE if MPI-IO is being used

    271:     Options Database:
    272:     -viewer_binary_mpiio : Flag for using MPI-IO

    274:     Level: advanced

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

    279:     Fortran Note:
    280:     This routine is not supported in Fortran.

    282: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    283: @*/
    284: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *use)
    285: {
    288:   *use = PETSC_FALSE;
    289:   PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,use));
    290:   return 0;
    291: }

    293: #if defined(PETSC_HAVE_MPIIO)
    294: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *use)
    295: {
    296:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    298:   *use = vbinary->usempiio;
    299:   return 0;
    300: }
    301: #endif

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

    306:     Not Collective

    308:     Input Parameters:
    309: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    310: -   fc - the number of messages, defaults to 256 if this function was not called

    312:     Level: advanced

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

    316: @*/
    317: PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
    318: {
    321:   PetscTryMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));
    322:   return 0;
    323: }

    325: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
    326: {
    327:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    330:   vbinary->flowcontrol = fc;
    331:   return 0;
    332: }

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

    337:     Not Collective

    339:     Input Parameter:
    340: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    342:     Output Parameter:
    343: .   fc - the number of messages

    345:     Level: advanced

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

    349: @*/
    350: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
    351: {
    354:   PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));
    355:   return 0;
    356: }

    358: static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
    359: {
    360:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    362:   *fc = vbinary->flowcontrol;
    363:   return 0;
    364: }

    366: /*@C
    367:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

    369:     Collective On PetscViewer

    371:     Input Parameter:
    372: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    374:     Output Parameter:
    375: .   fdes - file descriptor

    377:     Level: advanced

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

    385:     Fortran Note:
    386:     This routine is not supported in Fortran.

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

    392: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
    393: @*/
    394: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
    395: {
    396:   PetscViewer_Binary *vbinary;

    400:   PetscViewerSetUp(viewer);
    401:   vbinary = (PetscViewer_Binary*)viewer->data;
    402:   *fdes = vbinary->fdes;
    403:   return 0;
    404: }

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

    409:     Not Collective

    411:     Input Parameter:
    412: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

    414:     Options Database Key:
    415: .   -viewer_binary_skip_info - true indicates do not generate .info file

    417:     Level: advanced

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

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

    427: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
    428:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
    429: @*/
    430: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
    431: {
    432:   PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE);
    433:   return 0;
    434: }

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

    439:     Not Collective

    441:     Input Parameters:
    442: +   viewer - PetscViewer context, obtained from PetscViewerCreate()
    443: -   skip - PETSC_TRUE implies the .info file will not be generated

    445:     Options Database Key:
    446: .   -viewer_binary_skip_info - true indicates do not generate .info file

    448:     Level: advanced

    450: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
    451:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
    452: @*/
    453: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
    454: {
    457:   PetscTryMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));
    458:   return 0;
    459: }

    461: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
    462: {
    463:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    465:   vbinary->skipinfo = skip;
    466:   return 0;
    467: }

    469: /*@
    470:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

    472:     Not Collective

    474:     Input Parameter:
    475: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    477:     Output Parameter:
    478: .   skip - PETSC_TRUE implies the .info file was not generated

    480:     Level: advanced

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

    485: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    486:           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
    487: @*/
    488: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
    489: {
    492:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));
    493:   return 0;
    494: }

    496: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
    497: {
    498:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    500:   *skip  = vbinary->skipinfo;
    501:   return 0;
    502: }

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

    507:     Not Collective

    509:     Input Parameters:
    510: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    511: -   skip - PETSC_TRUE means do not use the options from the options database

    513:     Options Database Key:
    514: .   -viewer_binary_skip_options - true means do not use the options from the options database

    516:     Level: advanced

    518:     Notes:
    519:     This must be called after PetscViewerSetType()

    521: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    522:           PetscViewerBinaryGetSkipOptions()
    523: @*/
    524: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)
    525: {
    528:   PetscTryMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));
    529:   return 0;
    530: }

    532: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
    533: {
    534:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    536:   vbinary->skipoptions = skip;
    537:   return 0;
    538: }

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

    543:     Not Collective

    545:     Input Parameter:
    546: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    548:     Output Parameter:
    549: .   skip - PETSC_TRUE means do not use

    551:     Level: advanced

    553:     Notes:
    554:     This must be called after PetscViewerSetType()

    556: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    557:           PetscViewerBinarySetSkipOptions()
    558: @*/
    559: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
    560: {
    563:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));
    564:   return 0;
    565: }

    567: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
    568: {
    569:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    571:   *skip = vbinary->skipoptions;
    572:   return 0;
    573: }

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

    578:     Not Collective

    580:     Input Parameters:
    581: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
    582: -   skip - PETSC_TRUE means do not write header

    584:     Options Database Key:
    585: .   -viewer_binary_skip_header - PETSC_TRUE means do not write header

    587:     Level: advanced

    589:     Notes:
    590:       This must be called after PetscViewerSetType()

    592:       Is ignored on anything but a binary viewer

    594: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    595:           PetscViewerBinaryGetSkipHeader()
    596: @*/
    597: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
    598: {
    601:   PetscTryMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));
    602:   return 0;
    603: }

    605: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
    606: {
    607:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    609:   vbinary->skipheader = skip;
    610:   return 0;
    611: }

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

    616:     Not Collective

    618:     Input Parameter:
    619: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    621:     Output Parameter:
    622: .   skip - PETSC_TRUE means do not write header

    624:     Level: advanced

    626:     Notes:
    627:     This must be called after PetscViewerSetType()

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

    631: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
    632:           PetscViewerBinarySetSkipHeader()
    633: @*/
    634: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool  *skip)
    635: {
    638:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));
    639:   return 0;
    640: }

    642: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool  *skip)
    643: {
    644:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    646:   *skip = vbinary->skipheader;
    647:   return 0;
    648: }

    650: /*@C
    651:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
    652:           info file associated with a binary file.

    654:     Not Collective

    656:     Input Parameter:
    657: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

    659:     Output Parameter:
    660: .   file - file pointer  Always returns NULL if not a binary viewer

    662:     Level: advanced

    664:     Notes:
    665:       For writable binary PetscViewers, the descriptor will only be valid for the
    666:     first processor in the communicator that shares the PetscViewer.

    668:     Fortran Note:
    669:     This routine is not supported in Fortran.

    671: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
    672: @*/
    673: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
    674: {
    677:   *file = NULL;
    678:   PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));
    679:   return 0;
    680: }

    682: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
    683: {
    684:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    686:   PetscViewerSetUp(viewer);
    687:   *file = vbinary->fdes_info;
    688:   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
    689:     if (vbinary->fdes_info) {
    690:       FILE *info = vbinary->fdes_info;
    691:       PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
    692:       PetscFPrintf(PETSC_COMM_SELF,info,"#$$ Set.filename = '%s';\n",vbinary->filename);
    693:       PetscFPrintf(PETSC_COMM_SELF,info,"#$$ fd = PetscOpenFile(Set.filename);\n");
    694:       PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
    695:     }
    696:     vbinary->matlabheaderwritten = PETSC_TRUE;
    697:   }
    698:   return 0;
    699: }

    701: #if defined(PETSC_HAVE_MPIIO)
    702: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
    703: {
    704:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;

    706:   if (vbinary->mfdes != MPI_FILE_NULL) {
    707:     MPI_File_close(&vbinary->mfdes);
    708:   }
    709:   if (vbinary->mfsub != MPI_FILE_NULL) {
    710:     MPI_File_close(&vbinary->mfsub);
    711:   }
    712:   vbinary->moff = 0;
    713:   return 0;
    714: }
    715: #endif

    717: static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
    718: {
    719:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;

    721:   if (vbinary->fdes != -1) {
    722:     PetscBinaryClose(vbinary->fdes);
    723:     vbinary->fdes = -1;
    724:     if (vbinary->storecompressed) {
    725:       char cmd[8+PETSC_MAX_PATH_LEN],out[64+PETSC_MAX_PATH_LEN] = "";
    726:       const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
    727:       /* compress the file */
    728:       PetscStrncpy(cmd,"gzip -f ",sizeof(cmd));
    729:       PetscStrlcat(cmd,gzfilename,sizeof(cmd));
    730: #if defined(PETSC_HAVE_POPEN)
    731:       {
    732:         FILE *fp;
    733:         PetscPOpen(PETSC_COMM_SELF,NULL,cmd,"r",&fp);
    735:         PetscPClose(PETSC_COMM_SELF,fp);
    736:       }
    737: #endif
    738:     }
    739:   }
    740:   PetscFree(vbinary->ogzfilename);
    741:   return 0;
    742: }

    744: static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
    745: {
    746:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;

    748:   if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
    749:     if (vbinary->fdes_info) {
    750:       FILE *info = vbinary->fdes_info;
    751:       PetscFPrintf(PETSC_COMM_SELF,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
    752:       PetscFPrintf(PETSC_COMM_SELF,info,"#$$ close(fd);\n");
    753:       PetscFPrintf(PETSC_COMM_SELF,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
    754:     }
    755:   }
    756:   if (vbinary->fdes_info) {
    757:     FILE *info = vbinary->fdes_info;
    758:     vbinary->fdes_info = NULL;
    760:   }
    761:   return 0;
    762: }

    764: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
    765: {
    766: #if defined(PETSC_HAVE_MPIIO)
    767:   PetscViewerFileClose_BinaryMPIIO(v);
    768: #endif
    769:   PetscViewerFileClose_BinarySTDIO(v);
    770:   PetscViewerFileClose_BinaryInfo(v);
    771:   return 0;
    772: }

    774: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
    775: {
    776:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;

    778:   PetscViewerFileClose_Binary(v);
    779:   PetscFree(vbinary->filename);
    780:   PetscFree(vbinary);

    782:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",NULL);
    783:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",NULL);
    784:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",NULL);
    785:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",NULL);
    786:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",NULL);
    787:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",NULL);
    788:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",NULL);
    789:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",NULL);
    790:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",NULL);
    791:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",NULL);
    792:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",NULL);
    793:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",NULL);
    794:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",NULL);
    795: #if defined(PETSC_HAVE_MPIIO)
    796:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",NULL);
    797:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",NULL);
    798: #endif
    799:   return 0;
    800: }

    802: /*@C
    803:    PetscViewerBinaryOpen - Opens a file for binary input/output.

    805:    Collective

    807:    Input Parameters:
    808: +  comm - MPI communicator
    809: .  name - name of file
    810: -  mode - open mode of file
    811: $    FILE_MODE_WRITE - create new file for binary output
    812: $    FILE_MODE_READ - open existing file for binary input
    813: $    FILE_MODE_APPEND - open existing file for binary output

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

    818:     Options Database Keys:
    819: +    -viewer_binary_filename <name> -
    820: .    -viewer_binary_skip_info -
    821: .    -viewer_binary_skip_options -
    822: .    -viewer_binary_skip_header -
    823: -    -viewer_binary_mpiio -

    825:    Level: beginner

    827:    Note:
    828:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

    836: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    837:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    838:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
    839:           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
    840: @*/
    841: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode mode,PetscViewer *viewer)
    842: {
    843:   PetscViewerCreate(comm,viewer);
    844:   PetscViewerSetType(*viewer,PETSCVIEWERBINARY);
    845:   PetscViewerFileSetMode(*viewer,mode);
    846:   PetscViewerFileSetName(*viewer,name);
    847:   PetscViewerSetFromOptions(*viewer);
    848:   return 0;
    849: }

    851: #if defined(PETSC_HAVE_MPIIO)
    852: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write)
    853: {
    854:   MPI_Comm           comm = PetscObjectComm((PetscObject)viewer);
    855:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    856:   MPI_File           mfdes = vbinary->mfdes;
    857:   MPI_Datatype       mdtype;
    858:   PetscMPIInt        rank,cnt;
    859:   MPI_Status         status;
    860:   MPI_Aint           ul,dsize;

    862:   MPI_Comm_rank(comm,&rank);
    863:   PetscMPIIntCast(num,&cnt);
    864:   PetscDataTypeToMPIDataType(dtype,&mdtype);
    865:   if (write) {
    866:     if (rank == 0) {
    867:       MPIU_File_write_at(mfdes,vbinary->moff,data,cnt,mdtype,&status);
    868:     }
    869:   } else {
    870:     if (rank == 0) {
    871:       MPIU_File_read_at(mfdes,vbinary->moff,data,cnt,mdtype,&status);
    872:       if (cnt > 0) MPI_Get_count(&status,mdtype,&cnt);
    873:     }
    874:     MPI_Bcast(&cnt,1,MPI_INT,0,comm);
    875:     MPI_Bcast(data,cnt,mdtype,0,comm);
    876:   }
    877:   MPI_Type_get_extent(mdtype,&ul,&dsize);
    878:   vbinary->moff += dsize*cnt;
    879:   if (count) *count = cnt;
    880:   return 0;
    881: }
    882: #endif

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

    887:    Collective

    889:    Input Parameters:
    890: +  viewer - the binary viewer
    891: .  data - location of the data to be written
    892: .  num - number of items of data to read
    893: -  dtype - type of data to read

    895:    Output Parameters:
    896: .  count - number of items of data actually read, or NULL.

    898:    Level: beginner

    900: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    901:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    902:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    903: @*/
    904: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
    905: {
    906:   PetscViewer_Binary *vbinary;

    910:   PetscViewerSetUp(viewer);
    911:   vbinary = (PetscViewer_Binary*)viewer->data;
    912: #if defined(PETSC_HAVE_MPIIO)
    913:   if (vbinary->usempiio) {
    914:     PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE);
    915:   } else {
    916: #endif
    917:     PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,count,dtype);
    918: #if defined(PETSC_HAVE_MPIIO)
    919:   }
    920: #endif
    921:   return 0;
    922: }

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

    927:    Collective

    929:    Input Parameters:
    930: +  viewer - the binary viewer
    931: .  data - location of data
    932: .  count - number of items of data to write
    933: -  dtype - type of data to write

    935:    Level: beginner

    937: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    938:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
    939:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    940: @*/
    941: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,const void *data,PetscInt count,PetscDataType dtype)
    942: {
    943:   PetscViewer_Binary *vbinary;

    947:   PetscViewerSetUp(viewer);
    948:   vbinary = (PetscViewer_Binary*)viewer->data;
    949: #if defined(PETSC_HAVE_MPIIO)
    950:   if (vbinary->usempiio) {
    951:     PetscViewerBinaryWriteReadMPIIO(viewer,(void*)data,count,NULL,dtype,PETSC_TRUE);
    952:   } else {
    953: #endif
    954:     PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype);
    955: #if defined(PETSC_HAVE_MPIIO)
    956:   }
    957: #endif
    958:   return 0;
    959: }

    961: static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer,PetscBool write,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
    962: {
    963:   MPI_Comm              comm = PetscObjectComm((PetscObject)viewer);
    964:   PetscMPIInt           size,rank;
    965:   MPI_Datatype          mdtype;
    966:   PETSC_UNUSED MPI_Aint lb;
    967:   MPI_Aint              dsize;
    968:   PetscBool             useMPIIO;

    974:   PetscViewerSetUp(viewer);

    976:   PetscDataTypeToMPIDataType(dtype,&mdtype);
    977:   MPI_Type_get_extent(mdtype,&lb,&dsize);
    978:   MPI_Comm_rank(comm,&rank);
    979:   MPI_Comm_size(comm,&size);

    981:   PetscViewerBinaryGetUseMPIIO(viewer,&useMPIIO);
    982: #if defined(PETSC_HAVE_MPIIO)
    983:   if (useMPIIO) {
    984:     MPI_File       mfdes;
    985:     MPI_Offset     off;
    986:     PetscMPIInt    cnt;

    988:     if (start == PETSC_DETERMINE) {
    989:       MPI_Scan(&count,&start,1,MPIU_INT,MPI_SUM,comm);
    990:       start -= count;
    991:     }
    992:     if (total == PETSC_DETERMINE) {
    993:       total = start + count;
    994:       MPI_Bcast(&total,1,MPIU_INT,size-1,comm);
    995:     }
    996:     PetscMPIIntCast(count,&cnt);
    997:     PetscViewerBinaryGetMPIIODescriptor(viewer,&mfdes);
    998:     PetscViewerBinaryGetMPIIOOffset(viewer,&off);
    999:     off += (MPI_Offset)(start*dsize);
    1000:     if (write) {
    1001:       MPIU_File_write_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE);
    1002:     } else {
    1003:       MPIU_File_read_at_all(mfdes,off,data,cnt,mdtype,MPI_STATUS_IGNORE);
    1004:     }
    1005:     off  = (MPI_Offset)(total*dsize);
    1006:     PetscViewerBinaryAddMPIIOOffset(viewer,off);
    1007:     return 0;
    1008:   }
    1009: #endif
    1010:   {
    1011:     int         fdes;
    1012:     char        *workbuf = NULL;
    1013:     PetscInt    tcount = rank == 0 ? 0 : count,maxcount=0,message_count,flowcontrolcount;
    1014:     PetscMPIInt tag,cnt,maxcnt,scnt=0,rcnt=0,j;
    1015:     MPI_Status  status;

    1017:     PetscCommGetNewTag(comm,&tag);
    1018:     MPI_Reduce(&tcount,&maxcount,1,MPIU_INT,MPI_MAX,0,comm);
    1019:     PetscMPIIntCast(maxcount,&maxcnt);
    1020:     PetscMPIIntCast(count,&cnt);

    1022:     PetscViewerBinaryGetDescriptor(viewer,&fdes);
    1023:     PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);
    1024:     if (rank == 0) {
    1025:       PetscMalloc(maxcnt*dsize,&workbuf);
    1026:       if (write) {
    1027:         PetscBinaryWrite(fdes,data,cnt,dtype);
    1028:       } else {
    1029:         PetscBinaryRead(fdes,data,cnt,NULL,dtype);
    1030:       }
    1031:       for (j=1; j<size; j++) {
    1032:         PetscViewerFlowControlStepMain(viewer,j,&message_count,flowcontrolcount);
    1033:         if (write) {
    1034:           MPI_Recv(workbuf,maxcnt,mdtype,j,tag,comm,&status);
    1035:           MPI_Get_count(&status,mdtype,&rcnt);
    1036:           PetscBinaryWrite(fdes,workbuf,rcnt,dtype);
    1037:         } else {
    1038:           MPI_Recv(&scnt,1,MPI_INT,j,tag,comm,MPI_STATUS_IGNORE);
    1039:           PetscBinaryRead(fdes,workbuf,scnt,NULL,dtype);
    1040:           MPI_Send(workbuf,scnt,mdtype,j,tag,comm);
    1041:         }
    1042:       }
    1043:       PetscFree(workbuf);
    1044:       PetscViewerFlowControlEndMain(viewer,&message_count);
    1045:     } else {
    1046:       PetscViewerFlowControlStepWorker(viewer,rank,&message_count);
    1047:       if (write) {
    1048:         MPI_Send(data,cnt,mdtype,0,tag,comm);
    1049:       } else {
    1050:         MPI_Send(&cnt,1,MPI_INT,0,tag,comm);
    1051:         MPI_Recv(data,cnt,mdtype,0,tag,comm,MPI_STATUS_IGNORE);
    1052:       }
    1053:       PetscViewerFlowControlEndWorker(viewer,&message_count);
    1054:     }
    1055:   }
    1056:   return 0;
    1057: }

    1059: /*@C
    1060:    PetscViewerBinaryReadAll - reads from a binary file from all processes

    1062:    Collective

    1064:    Input Parameters:
    1065: +  viewer - the binary viewer
    1066: .  data - location of data
    1067: .  count - local number of items of data to read
    1068: .  start - local start, can be PETSC_DETERMINE
    1069: .  total - global number of items of data to read, can be PETSC_DETERMINE
    1070: -  dtype - type of data to read

    1072:    Level: advanced

    1074: .seealso: PetscViewerBinaryOpen(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryRead(), PetscViewerBinaryWriteAll()
    1075: @*/
    1076: PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer,void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
    1077: {
    1078:   PetscViewerBinaryWriteReadAll(viewer,PETSC_FALSE,data,count,start,total,dtype);
    1079:   return 0;
    1080: }

    1082: /*@C
    1083:    PetscViewerBinaryWriteAll - writes to a binary file from all processes

    1085:    Collective

    1087:    Input Parameters:
    1088: +  viewer - the binary viewer
    1089: .  data - location of data
    1090: .  count - local number of items of data to write
    1091: .  start - local start, can be PETSC_DETERMINE
    1092: .  total - global number of items of data to write, can be PETSC_DETERMINE
    1093: -  dtype - type of data to write

    1095:    Level: advanced

    1097: .seealso: PetscViewerBinaryOpen(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryWriteAll(), PetscViewerBinaryReadAll()
    1098: @*/
    1099: PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer,const void *data,PetscInt count,PetscInt start,PetscInt total,PetscDataType dtype)
    1100: {
    1101:   PetscViewerBinaryWriteReadAll(viewer,PETSC_TRUE,(void*)data,count,start,total,dtype);
    1102:   return 0;
    1103: }

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

    1108:    Collective

    1110:    Input Parameters:
    1111: +  viewer - the binary viewer
    1112: -  data - location of the array of strings

    1114:    Level: intermediate

    1116:     Notes:
    1117:     array of strings is null terminated

    1119: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    1120:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    1121:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    1122: @*/
    1123: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data)
    1124: {
    1125:   PetscInt       i,n = 0,*sizes;
    1126:   size_t         len;

    1128:   PetscViewerSetUp(viewer);
    1129:   /* count number of strings */
    1130:   while (data[n++]);
    1131:   n--;
    1132:   PetscMalloc1(n+1,&sizes);
    1133:   sizes[0] = n;
    1134:   for (i=0; i<n; i++) {
    1135:     PetscStrlen(data[i],&len);
    1136:     sizes[i+1] = (PetscInt)len + 1; /* size includes space for the null terminator */
    1137:   }
    1138:   PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT);
    1139:   for (i=0; i<n; i++) {
    1140:     PetscViewerBinaryWrite(viewer,(void*)data[i],sizes[i+1],PETSC_CHAR);
    1141:   }
    1142:   PetscFree(sizes);
    1143:   return 0;
    1144: }

    1146: /*@C
    1147:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

    1149:    Collective

    1151:    Input Parameter:
    1152: .  viewer - the binary viewer

    1154:    Output Parameter:
    1155: .  data - location of the array of strings

    1157:    Level: intermediate

    1159:     Notes:
    1160:     array of strings is null terminated

    1162: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
    1163:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
    1164:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead()
    1165: @*/
    1166: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
    1167: {
    1168:   PetscInt       i,n,*sizes,N = 0;

    1170:   PetscViewerSetUp(viewer);
    1171:   /* count number of strings */
    1172:   PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);
    1173:   PetscMalloc1(n,&sizes);
    1174:   PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);
    1175:   for (i=0; i<n; i++) N += sizes[i];
    1176:   PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);
    1177:   (*data)[0] = (char*)((*data) + n + 1);
    1178:   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
    1179:   PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);
    1180:   (*data)[n] = NULL;
    1181:   PetscFree(sizes);
    1182:   return 0;
    1183: }

    1185: /*@C
    1186:      PetscViewerFileSetMode - Sets the open mode of file

    1188:     Logically Collective on PetscViewer

    1190:   Input Parameters:
    1191: +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
    1192: -  mode - open mode of file
    1193: $    FILE_MODE_WRITE - create new file for output
    1194: $    FILE_MODE_READ - open existing file for input
    1195: $    FILE_MODE_APPEND - open existing file for output

    1197:   Level: advanced

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

    1201: @*/
    1202: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode mode)
    1203: {
    1208:   PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,mode));
    1209:   return 0;
    1210: }

    1212: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode mode)
    1213: {
    1214:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1217:   vbinary->filemode = mode;
    1218:   return 0;
    1219: }

    1221: /*@C
    1222:      PetscViewerFileGetMode - Gets the open mode of file

    1224:     Not Collective

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

    1229:   Output Parameter:
    1230: .  mode - open mode of file
    1231: $    FILE_MODE_WRITE - create new file for binary output
    1232: $    FILE_MODE_READ - open existing file for binary input
    1233: $    FILE_MODE_APPEND - open existing file for binary output

    1235:   Level: advanced

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

    1239: @*/
    1240: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *mode)
    1241: {
    1244:   PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,mode));
    1245:   return 0;
    1246: }

    1248: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *mode)
    1249: {
    1250:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1252:   *mode = vbinary->filemode;
    1253:   return 0;
    1254: }

    1256: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
    1257: {
    1258:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1260:   if (viewer->setupcalled && vbinary->filename) {
    1261:     /* gzip can be run after the file with the previous filename has been closed */
    1262:     PetscFree(vbinary->ogzfilename);
    1263:     PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename);
    1264:   }
    1265:   PetscFree(vbinary->filename);
    1266:   PetscStrallocpy(name,&vbinary->filename);
    1267:   viewer->setupcalled = PETSC_FALSE;
    1268:   return 0;
    1269: }

    1271: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
    1272: {
    1273:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

    1275:   *name = vbinary->filename;
    1276:   return 0;
    1277: }

    1279: #if defined(PETSC_HAVE_MPIIO)
    1280: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
    1281: {
    1282:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1283:   int                amode;

    1285:   vbinary->storecompressed = PETSC_FALSE;

    1287:   vbinary->moff = 0;
    1288:   switch (vbinary->filemode) {
    1289:   case FILE_MODE_READ:   amode = MPI_MODE_RDONLY; break;
    1290:   case FILE_MODE_WRITE:  amode = MPI_MODE_WRONLY | MPI_MODE_CREATE; break;
    1291:   case FILE_MODE_APPEND: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND; break;
    1292:   case FILE_MODE_UNDEFINED: SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerSetUp()");
    1293:   default: SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[vbinary->filemode]);
    1294:   }
    1295:   MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfdes);
    1296:   /*
    1297:       The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
    1298:   */
    1299:   if (vbinary->filemode == FILE_MODE_WRITE) MPI_File_set_size(vbinary->mfdes,0);
    1300:   /*
    1301:       Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
    1302:       MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
    1303:       Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
    1304:       the offset in etype units to an absolute byte position.
    1305:    */
    1306:   if (vbinary->filemode == FILE_MODE_APPEND) MPI_File_get_position(vbinary->mfdes,&vbinary->moff);
    1307:   return 0;
    1308: }
    1309: #endif

    1311: static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
    1312: {
    1313:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1314:   const char         *fname;
    1315:   char               bname[PETSC_MAX_PATH_LEN],*gz;
    1316:   PetscBool          found;
    1317:   PetscMPIInt        rank;

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

    1321:   /* if file name ends in .gz strip that off and note user wants file compressed */
    1322:   vbinary->storecompressed = PETSC_FALSE;
    1323:   if (vbinary->filemode == FILE_MODE_WRITE) {
    1324:     PetscStrstr(vbinary->filename,".gz",&gz);
    1325:     if (gz && gz[3] == 0) {*gz = 0; vbinary->storecompressed = PETSC_TRUE;}
    1326:   }
    1327: #if !defined(PETSC_HAVE_POPEN)
    1329: #endif

    1331:   fname = vbinary->filename;
    1332:   if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
    1333:     PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),fname,bname,PETSC_MAX_PATH_LEN,&found);
    1335:     fname = bname;
    1336:   }

    1338:   vbinary->fdes = -1;
    1339:   if (rank == 0) { /* only first processor opens file*/
    1340:     PetscFileMode mode = vbinary->filemode;
    1341:     if (mode == FILE_MODE_APPEND) {
    1342:       /* check if asked to append to a non-existing file */
    1343:       PetscTestFile(fname,'\0',&found);
    1344:       if (!found) mode = FILE_MODE_WRITE;
    1345:     }
    1346:     PetscBinaryOpen(fname,mode,&vbinary->fdes);
    1347:   }
    1348:   return 0;
    1349: }

    1351: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
    1352: {
    1353:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1354:   PetscMPIInt        rank;
    1355:   PetscBool          found;

    1357:   vbinary->fdes_info = NULL;
    1358:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
    1359:   if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || rank == 0)) {
    1360:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN],*gz;

    1362:     PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));
    1363:     /* remove .gz if it ends file name */
    1364:     PetscStrstr(infoname,".gz",&gz);
    1365:     if (gz && gz[3] == 0) *gz = 0;

    1367:     PetscStrlcat(infoname,".info",sizeof(infoname));
    1368:     if (vbinary->filemode == FILE_MODE_READ) {
    1369:       PetscFixFilename(infoname,iname);
    1370:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
    1371:       if (found) PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
    1372:     } else if (rank == 0) { /* write or append */
    1373:       const char *omode = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
    1374:       vbinary->fdes_info = fopen(infoname,omode);
    1376:     }
    1377:   }
    1378:   return 0;
    1379: }

    1381: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
    1382: {
    1383:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
    1384:   PetscBool          usempiio;

    1386:   if (!vbinary->setfromoptionscalled) PetscViewerSetFromOptions(viewer);
    1389:   PetscViewerFileClose_Binary(viewer);

    1391:   PetscViewerBinaryGetUseMPIIO(viewer,&usempiio);
    1392:   if (usempiio) {
    1393: #if defined(PETSC_HAVE_MPIIO)
    1394:     PetscViewerFileSetUp_BinaryMPIIO(viewer);
    1395: #endif
    1396:   } else {
    1397:     PetscViewerFileSetUp_BinarySTDIO(viewer);
    1398:   }
    1399:   PetscViewerFileSetUp_BinaryInfo(viewer);

    1401:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
    1402:   return 0;
    1403: }

    1405: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
    1406: {
    1407:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
    1408:   const char         *fname = vbinary->filename ? vbinary->filename : "not yet set";
    1409:   const char         *fmode = vbinary->filemode != (PetscFileMode) -1 ? PetscFileModes[vbinary->filemode] : "not yet set";
    1410:   PetscBool          usempiio;

    1412:   PetscViewerBinaryGetUseMPIIO(v,&usempiio);
    1413:   PetscViewerASCIIPrintf(viewer,"Filename: %s\n",fname);
    1414:   PetscViewerASCIIPrintf(viewer,"Mode: %s (%s)\n",fmode,usempiio ? "mpiio" : "stdio");
    1415:   return 0;
    1416: }

    1418: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer viewer)
    1419: {
    1420:   PetscViewer_Binary *binary = (PetscViewer_Binary*)viewer->data;
    1421:   char               defaultname[PETSC_MAX_PATH_LEN];
    1422:   PetscBool          flg;

    1424:   if (viewer->setupcalled) return 0;
    1425:   PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");
    1426:   PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");
    1427:   PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,sizeof(defaultname),&flg);
    1428:   if (flg) PetscViewerFileSetName_Binary(viewer,defaultname);
    1429:   PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",binary->skipinfo,&binary->skipinfo,NULL);
    1430:   PetscOptionsBool("-viewer_binary_skip_options","Skip parsing Vec/Mat load options","PetscViewerBinarySetSkipOptions",binary->skipoptions,&binary->skipoptions,NULL);
    1431:   PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",binary->skipheader,&binary->skipheader,NULL);
    1432: #if defined(PETSC_HAVE_MPIIO)
    1433:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",binary->usempiio,&binary->usempiio,NULL);
    1434: #else
    1435:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);
    1436: #endif
    1437:   PetscOptionsTail();
    1438:   binary->setfromoptionscalled = PETSC_TRUE;
    1439:   return 0;
    1440: }

    1442: /*MC
    1443:    PETSCVIEWERBINARY - A viewer that saves to binary files

    1445: .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
    1446:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
    1447:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
    1448:            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()

    1450:   Level: beginner

    1452: M*/

    1454: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
    1455: {
    1456:   PetscViewer_Binary *vbinary;

    1458:   PetscNewLog(v,&vbinary);
    1459:   v->data = (void*)vbinary;

    1461:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
    1462:   v->ops->destroy          = PetscViewerDestroy_Binary;
    1463:   v->ops->view             = PetscViewerView_Binary;
    1464:   v->ops->setup            = PetscViewerSetUp_Binary;
    1465:   v->ops->flush            = NULL; /* Should we support Flush() ? */
    1466:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
    1467:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
    1468:   v->ops->read             = PetscViewerBinaryRead;

    1470:   vbinary->fdes            = -1;
    1471: #if defined(PETSC_HAVE_MPIIO)
    1472:   vbinary->usempiio        = PETSC_FALSE;
    1473:   vbinary->mfdes           = MPI_FILE_NULL;
    1474:   vbinary->mfsub           = MPI_FILE_NULL;
    1475: #endif
    1476:   vbinary->filename        = NULL;
    1477:   vbinary->filemode        = FILE_MODE_UNDEFINED;
    1478:   vbinary->fdes_info       = NULL;
    1479:   vbinary->skipinfo        = PETSC_FALSE;
    1480:   vbinary->skipoptions     = PETSC_TRUE;
    1481:   vbinary->skipheader      = PETSC_FALSE;
    1482:   vbinary->storecompressed = PETSC_FALSE;
    1483:   vbinary->ogzfilename     = NULL;
    1484:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

    1486:   vbinary->setfromoptionscalled = PETSC_FALSE;

    1488:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);
    1489:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);
    1490:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);
    1491:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);
    1492:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);
    1493:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);
    1494:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);
    1495:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);
    1496:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);
    1497:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);
    1498:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);
    1499:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);
    1500:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);
    1501: #if defined(PETSC_HAVE_MPIIO)
    1502:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);
    1503:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);
    1504: #endif
    1505:   return 0;
    1506: }

    1508: /* ---------------------------------------------------------------------*/
    1509: /*
    1510:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
    1511:   is attached to a communicator, in this case the attribute is a PetscViewer.
    1512: */
    1513: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

    1515: /*@C
    1516:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
    1517:                      in a communicator.

    1519:      Collective

    1521:      Input Parameter:
    1522: .    comm - the MPI communicator to share the binary PetscViewer

    1524:      Level: intermediate

    1526:    Options Database Keys:
    1527: +    -viewer_binary_filename <name> - filename in which to store the binary data, defaults to binaryoutput
    1528: .    -viewer_binary_skip_info - true means do not create .info file for this viewer
    1529: .    -viewer_binary_skip_options - true means do not use the options database for this viewer
    1530: .    -viewer_binary_skip_header - true means do not store the usual header information in the binary file
    1531: -    -viewer_binary_mpiio - true means use the file via MPI-IO, maybe faster for large files and many MPI ranks

    1533:    Environmental variables:
    1534: -   PETSC_VIEWER_BINARY_FILENAME - filename in which to store the binary data, defaults to binaryoutput

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

    1541: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
    1542:           PetscViewerDestroy()
    1543: @*/
    1544: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
    1545: {
    1547:   PetscBool      flg;
    1548:   PetscViewer    viewer;
    1549:   char           fname[PETSC_MAX_PATH_LEN];
    1550:   MPI_Comm       ncomm;

    1552:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
    1553:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
    1554:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,NULL);
    1555:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
    1556:   }
    1557:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
    1558:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
    1559:   if (!flg) { /* PetscViewer not yet created */
    1560:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
    1561:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
    1562:     if (!flg) {
    1563:       PetscStrcpy(fname,"binaryoutput");
    1564:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
    1565:     }
    1566:     PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
    1567:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
    1568:     PetscObjectRegisterDestroy((PetscObject)viewer);
    1569:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
    1570:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
    1571:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return NULL;}
    1572:   }
    1573:   PetscCommDestroy(&ncomm);
    1574:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_REPEAT," ");return NULL;}
    1575:   return viewer;
    1576: }