Actual source code: binv.c

petsc-master 2020-12-02
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:   PETSC_UNUSED MPI_Aint lb;
1054:   MPI_Aint              dsize;
1055:   PetscBool             useMPIIO;
1056:   PetscErrorCode        ierr;

1063:   PetscViewerSetUp(viewer);

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

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

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

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

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

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

1151:    Collective

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

1161:    Level: advanced

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

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

1176:    Collective

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

1186:    Level: advanced

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

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

1201:    Collective

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


1208:    Level: intermediate

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

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

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

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

1245:    Collective

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

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

1253:    Level: intermediate

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

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

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

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

1286:     Logically Collective on PetscViewer

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

1295:   Level: advanced

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

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

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

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

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

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

1324:     Not Collective

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

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

1335:   Level: advanced

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

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

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

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

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

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

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

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

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

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

1394:   vbinary->storecompressed = PETSC_FALSE;

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

1570:   Level: beginner

1572: M*/

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

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

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

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

1608:   vbinary->setfromoptionscalled = PETSC_FALSE;

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

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

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

1641:      Collective

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

1646:      Level: intermediate

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

1655:    Environmental variables:
1656: -   PETSC_VIEWER_BINARY_FILENAME

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

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

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