Actual source code: binv.c

petsc-master 2019-10-23
Report Typos and Errors

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

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

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

 39:   PetscViewerSetUp(viewer);

 41:   /* Return subviewer in process zero */
 42:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
 43:   if (!rank) {
 44:     PetscMPIInt flg;

 46:     MPI_Comm_compare(PETSC_COMM_SELF,comm,&flg);
 47:     if (flg != MPI_IDENT && flg != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"PetscViewerGetSubViewer() for PETSCVIEWERBINARY requires a singleton MPI_Comm");
 48:     PetscViewerCreate(comm,outviewer);
 49:     PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);
 50:     PetscMemcpy((*outviewer)->data,vbinary,sizeof(PetscViewer_Binary));
 51:     (*outviewer)->setupcalled = PETSC_TRUE;
 52:   } else {
 53:     *outviewer = NULL;
 54:   }

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

 78: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
 79: {
 80:   PetscMPIInt        rank;
 81:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
 82:   PetscErrorCode     ierr;
 83: #if defined(PETSC_HAVE_MPIIO)
 84:   MPI_Offset         moff = 0;
 85: #endif

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

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

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

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

116: #if defined(PETSC_HAVE_MPIIO)
117: /*@C
118:     PetscViewerBinaryGetMPIIOOffset - Gets the current offset that should be passed to MPI_File_set_view()

120:     Not Collective

122:     Input Parameter:
123: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

125:     Output Parameter:
126: .    off - the current offset

128:     Level: advanced

130:     Fortran Note:
131:     This routine is not supported in Fortran.

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


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

143:   *off = vbinary->moff;
144:   return(0);
145: }

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

150:     Not Collective

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

156:     Level: advanced

158:     Fortran Note:
159:     This routine is not supported in Fortran.

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


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

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

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

178:     Not Collective

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

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

186:     Level: advanced

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


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

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

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

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


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

219:     Not Collective

221:     Input Parameter:
222: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

224:     Output Parameter:
225: -   flg - PETSC_TRUE if MPI-IO is being used

227:     Options Database:
228:     -viewer_binary_mpiio : Flag for using MPI-IO

230:     Level: advanced

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

235:     Fortran Note:
236:     This routine is not supported in Fortran.


239: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
240: @*/
241: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *flg)
242: {

246:   *flg = PETSC_FALSE;
247:   PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,flg));
248:   return(0);
249: }

251: static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
252: {
253:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

256:   *fc = vbinary->flowcontrol;
257:   return(0);
258: }

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

263:     Not Collective

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

268:     Output Parameter:
269: .   fc - the number of messages

271:     Level: advanced

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

275: @*/
276: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
277: {

281:   PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));
282:   return(0);
283: }

285: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
286: {
287:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

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

298:     Not Collective

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

304:     Level: advanced

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

308: @*/
309: PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
310: {

314:   PetscUseMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));
315:   return(0);
316: }

318: /*@C
319:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

321:     Collective On PetscViewer

323:     Input Parameter:
324: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

326:     Output Parameter:
327: .   fdes - file descriptor

329:     Level: advanced

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

337:     Fortran Note:
338:     This routine is not supported in Fortran.

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



346: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
347: @*/
348: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
349: {
350:   PetscErrorCode     ierr;
351:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

354:   PetscViewerSetUp(viewer);
355:   *fdes = vbinary->fdes;
356:   return(0);
357: }

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

362:     Not Collective

364:     Input Paramter:
365: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

367:     Options Database Key:
368: .   -viewer_binary_skip_info

370:     Level: advanced

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

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

380: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
381:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
382: @*/
383: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
384: {
385:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

388:   vbinary->skipinfo = PETSC_TRUE;
389:   return(0);
390: }

392: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
393: {
394:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

397:   vbinary->skipinfo = skip;
398:   return(0);
399: }

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

404:     Not Collective

406:     Input Paramter:
407: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

409:     Options Database Key:
410: .   -viewer_binary_skip_info

412:     Level: advanced

414: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
415:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
416: @*/
417: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
418: {

422:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));
423:   return(0);
424: }

426: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
427: {
428:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

431:   *skip  = vbinary->skipinfo;
432:   return(0);
433: }

435: /*@
436:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

438:     Not Collective

440:     Input Parameter:
441: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

443:     Output Parameter:
444: .   skip - PETSC_TRUE implies the .info file was not generated

446:     Level: advanced

448:     Notes:
449:     This must be called after PetscViewerSetType()

451: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
452:           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
453: @*/
454: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
455: {

459:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));
460:   return(0);
461: }

463: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
464: {
465:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

468:   vbinary->skipoptions = skip;
469:   return(0);
470: }

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

475:     Not Collective

477:     Input Parameters:
478: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
479: -   skip - PETSC_TRUE means do not use

481:     Options Database Key:
482: .   -viewer_binary_skip_options

484:     Level: advanced

486:     Notes:
487:     This must be called after PetscViewerSetType()

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

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

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

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

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

515:     Not Collective

517:     Input Parameter:
518: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

520:     Output Parameter:
521: .   skip - PETSC_TRUE means do not use

523:     Level: advanced

525:     Notes:
526:     This must be called after PetscViewerSetType()

528: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
529:           PetscViewerBinarySetSkipOptions()
530: @*/
531: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
532: {

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

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

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

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

552:     Not Collective

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

558:     Options Database Key:
559: .   -viewer_binary_skip_header

561:     Level: advanced

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

566:            Can ONLY be called on a binary viewer

568: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
569:           PetscViewerBinaryGetSkipHeader()
570: @*/
571: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
572: {

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

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

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

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

592:     Not Collective

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

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

600:     Level: advanced

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

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

607: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
608:           PetscViewerBinarySetSkipHeader()
609: @*/
610: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool  *skip)
611: {

615:   *skip = PETSC_FALSE;
616:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));
617:   return(0);
618: }

620: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
621: {
622:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
623:   PetscErrorCode     ierr;
624:   MPI_Comm           comm;

627:   PetscViewerSetUp(viewer);
628:   *file = vbinary->fdes_info;
629:   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
630:     vbinary->matlabheaderwritten = PETSC_TRUE;
631:     PetscObjectGetComm((PetscObject)viewer,&comm);
632:     PetscFPrintf(comm,*file,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
633:     PetscFPrintf(comm,*file,"#$$ Set.filename = '%s';\n",vbinary->filename);
634:     PetscFPrintf(comm,*file,"#$$ fd = PetscOpenFile(Set.filename);\n");
635:     PetscFPrintf(comm,*file,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
636:   }
637:   return(0);
638: }

640: /*@C
641:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
642:           info file associated with a binary file.

644:     Not Collective

646:     Input Parameter:
647: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

649:     Output Parameter:
650: .   file - file pointer  Always returns NULL if not a binary viewer

652:     Level: advanced

654:     Notes:
655:       For writable binary PetscViewers, the descriptor will only be valid for the
656:     first processor in the communicator that shares the PetscViewer.

658:     Fortran Note:
659:     This routine is not supported in Fortran.

661: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
662: @*/
663: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
664: {

668:   *file = NULL;
669:   PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));
670:   return(0);
671: }

673: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
674: {
675:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
676:   PetscErrorCode     ierr;
677:   PetscMPIInt        rank;
678:   int                err;

681:   MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);
682:   if ((!rank || vbinary->btype == FILE_MODE_READ) && vbinary->fdes) {
683:     close(vbinary->fdes);
684:     if (!rank && vbinary->storecompressed) {
685:       char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
686:       FILE *fp;
687:       /* compress the file */
688:       PetscStrncpy(par,"gzip -f ",sizeof(par));
689:       PetscStrlcat(par,vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename,sizeof(par));
690:       PetscFree(vbinary->ogzfilename);
691: #if defined(PETSC_HAVE_POPEN)
692:       PetscPOpen(PETSC_COMM_SELF,NULL,par,"r",&fp);
693:       if (fgets(buf,1024,fp)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from command %s\n%s",par,buf);
694:       PetscPClose(PETSC_COMM_SELF,fp);
695: #else
696:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
697: #endif
698:     }
699:   }
700:   if (vbinary->fdes_info) {
701:     err = fclose(vbinary->fdes_info);
702:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
703:   }
704:   return(0);
705: }

707: #if defined(PETSC_HAVE_MPIIO)
708: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
709: {
710:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
711:   int                err;
712:   PetscErrorCode     ierr;

715:   if (vbinary->mfdes != MPI_FILE_NULL) {
716:     MPI_File_close(&vbinary->mfdes);
717:   }
718:   if (vbinary->mfsub != MPI_FILE_NULL) {
719:     MPI_File_close(&vbinary->mfsub);
720:   }
721:   if (vbinary->fdes_info) {
722:     err = fclose(vbinary->fdes_info);
723:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
724:   }
725:   return(0);
726: }
727: #endif

729: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
730: {
731:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
732:   PetscErrorCode     ierr;

735:   if (v->format == PETSC_VIEWER_BINARY_MATLAB) {
736:     MPI_Comm comm;
737:     FILE     *info;

739:     PetscObjectGetComm((PetscObject)v,&comm);
740:     PetscViewerBinaryGetInfoPointer(v,&info);
741:     PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
742:     PetscFPrintf(comm,info,"#$$ close(fd);\n");
743:     PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
744:   }
745: #if defined(PETSC_HAVE_MPIIO)
746:   if (vbinary->usempiio) {
747:     PetscViewerFileClose_BinaryMPIIO(v);
748:   } else {
749: #endif
750:     PetscViewerFileClose_Binary(v);
751: #if defined(PETSC_HAVE_MPIIO)
752:   }
753: #endif
754:   PetscFree(vbinary->filename);
755:   PetscFree(vbinary->ogzfilename);
756:   PetscFree(vbinary);
757:   return(0);
758: }

760: /*@C
761:    PetscViewerBinaryOpen - Opens a file for binary input/output.

763:    Collective

765:    Input Parameters:
766: +  comm - MPI communicator
767: .  name - name of file
768: -  type - type of file
769: $    FILE_MODE_WRITE - create new file for binary output
770: $    FILE_MODE_READ - open existing file for binary input
771: $    FILE_MODE_APPEND - open existing file for binary output

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

776:     Options Database Keys:
777: +    -viewer_binary_filename <name> -
778: .    -viewer_binary_skip_info -
779: .    -viewer_binary_skip_options -
780: .    -viewer_binary_skip_header -
781: -    -viewer_binary_mpiio -

783:    Level: beginner

785:    Note:
786:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

794:     For writing files it only opens the file on processor 0 in the communicator.
795:     For readable files it opens the file on all nodes that have the file. If
796:     node 0 does not have the file it generates an error even if other nodes
797:     do have the file.

799: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
800:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
801:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
802:           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
803: @*/
804: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
805: {

809:   PetscViewerCreate(comm,binv);
810:   PetscViewerSetType(*binv,PETSCVIEWERBINARY);
811:   PetscViewerFileSetMode(*binv,type);
812:   PetscViewerFileSetName(*binv,name);
813:   PetscViewerSetFromOptions(*binv);
814:   return(0);
815: }

817: #if defined(PETSC_HAVE_MPIIO)
818: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write)
819: {
820:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
821:   PetscErrorCode     ierr;
822:   MPI_File           mfdes;
823:   MPI_Datatype       mdtype;
824:   PetscMPIInt        cnt;
825:   MPI_Status         status;
826:   MPI_Aint           ul,dsize;

829:   mfdes = vbinary->mfdes;
830:   PetscMPIIntCast(num,&cnt);
831:   PetscDataTypeToMPIDataType(dtype,&mdtype);
832:   MPI_File_set_view(mfdes,vbinary->moff,mdtype,mdtype,(char*)"native",MPI_INFO_NULL);
833:   if (write) {
834:     MPIU_File_write_all(mfdes,data,cnt,mdtype,&status);
835:   } else {
836:     MPIU_File_read_all(mfdes,data,cnt,mdtype,&status);
837:     if (cnt > 0) {MPI_Get_count(&status,mdtype,&cnt);}
838:   }
839:   MPI_Type_get_extent(mdtype,&ul,&dsize);

841:   vbinary->moff += dsize*cnt;
842:   if (count) *count = cnt;
843:   return(0);
844: }
845: #endif

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

850:    Collective

852:    Input Parameters:
853: +  viewer - the binary viewer
854: .  data - location of the data to be written
855: .  num - number of items of data to read
856: -  dtype - type of data to read

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

861:    Level: beginner

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

865: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
866:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
867:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
868: @*/
869: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
870: {
871:   PetscErrorCode     ierr;
872:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

874:   PetscViewerSetUp(viewer);
875: #if defined(PETSC_HAVE_MPIIO)
876:   if (vbinary->usempiio) {
877:     PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE);
878:   } else {
879: #endif
880:     PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,count,dtype);
881: #if defined(PETSC_HAVE_MPIIO)
882:   }
883: #endif
884:   return(0);
885: }

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

890:    Collective

892:    Input Parameters:
893: +  viewer - the binary viewer
894: .  data - location of data
895: .  count - number of items of data to write
896: .  dtype - type of data to write
897: -  istemp - data may be overwritten

899:    Level: beginner

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

904: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
905:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
906:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
907: @*/
908: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscBool istemp)
909: {
910:   PetscErrorCode     ierr;
911:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

914:   PetscViewerSetUp(viewer);
915: #if defined(PETSC_HAVE_MPIIO)
916:   if (vbinary->usempiio) {
917:     PetscViewerBinaryWriteReadMPIIO(viewer,data,count,NULL,dtype,PETSC_TRUE);
918:   } else {
919: #endif
920:     PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype,istemp);
921: #if defined(PETSC_HAVE_MPIIO)
922:   }
923: #endif
924:   return(0);
925: }

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

930:    Collective

932:    Input Parameters:
933: +  viewer - the binary viewer
934: -  data - location of the array of strings


937:    Level: intermediate

939:     Notes:
940:     array of strings is null terminated

942: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
943:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
944:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
945: @*/
946: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data)
947: {
949:   PetscInt       i,n = 0,*sizes;

951:   PetscViewerSetUp(viewer);
952:   /* count number of strings */
953:   while (data[n++]) ;
954:   n--;
955:   PetscMalloc1(n+1,&sizes);
956:   sizes[0] = n;
957:   for (i=0; i<n; i++) {
958:     size_t tmp;
959:     PetscStrlen(data[i],&tmp);
960:     sizes[i+1] = tmp + 1;   /* size includes space for the null terminator */
961:   }
962:   PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT,PETSC_FALSE);
963:   for (i=0; i<n; i++) {
964:     PetscViewerBinaryWrite(viewer,(void*)data[i],sizes[i+1],PETSC_CHAR,PETSC_FALSE);
965:   }
966:   PetscFree(sizes);
967:   return(0);
968: }

970: /*@C
971:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

973:    Collective

975:    Input Parameter:
976: .  viewer - the binary viewer

978:    Output Parameter:
979: .  data - location of the array of strings

981:    Level: intermediate

983:     Notes:
984:     array of strings is null terminated

986: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
987:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
988:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
989: @*/
990: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
991: {
993:   PetscInt       i,n,*sizes,N = 0;

995:   PetscViewerSetUp(viewer);
996:   /* count number of strings */
997:   PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);
998:   PetscMalloc1(n,&sizes);
999:   PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);
1000:   for (i=0; i<n; i++) N += sizes[i];
1001:   PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);
1002:   (*data)[0] = (char*)((*data) + n + 1);
1003:   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
1004:   PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);

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

1008:   PetscFree(sizes);
1009:   return(0);
1010: }

1012: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
1013: {
1014:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1017:   *name = vbinary->filename;
1018:   return(0);
1019: }

1021: /*@C
1022:      PetscViewerFileGetMode - Gets the type of file to be open

1024:     Not Collective

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

1029:   Output Parameter:
1030: .  type - type of file
1031: $    FILE_MODE_WRITE - create new file for binary output
1032: $    FILE_MODE_READ - open existing file for binary input
1033: $    FILE_MODE_APPEND - open existing file for binary output

1035:   Level: advanced

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

1039: @*/
1040: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
1041: {

1047:   PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));
1048:   return(0);
1049: }

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

1055:     Logically Collective on PetscViewer

1057:     Input Parameters:
1058: +   viewer - the PetscViewer; must be a binary
1059: -   flg - PETSC_TRUE means MPI-IO will be used

1061:     Options Database:
1062:     -viewer_binary_mpiio : Flag for using MPI-IO

1064:     Level: advanced

1066: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
1067:           PetscViewerBinaryGetUseMPIIO()

1069: @*/
1070: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool flg)
1071: {

1076:   PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,flg));
1077:   return(0);
1078: }

1080: /*@C
1081:      PetscViewerFileSetMode - Sets the type of file to be open

1083:     Logically Collective on PetscViewer

1085:   Input Parameters:
1086: +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1087: -  type - type of file
1088: $    FILE_MODE_WRITE - create new file for output
1089: $    FILE_MODE_READ - open existing file for input
1090: $    FILE_MODE_APPEND - open existing file for output

1092:   Level: advanced

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

1096: @*/
1097: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
1098: {

1104:   PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));
1105:   return(0);
1106: }

1108: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
1109: {
1110:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1113:   *type = vbinary->btype;
1114:   return(0);
1115: }

1117: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
1118: {
1119:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1122:   vbinary->btype = type;
1123:   return(0);
1124: }

1126: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1127: {
1128:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1129:   PetscErrorCode     ierr;

1132:   if (vbinary->filename) {
1133:     /* gzip can be run after the file with the previous filename has been closed */
1134:     PetscFree(vbinary->ogzfilename);
1135:     PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename);
1136:     PetscFree(vbinary->filename);
1137:     viewer->setupcalled = PETSC_FALSE;
1138:   }
1139:   PetscStrallocpy(name,&vbinary->filename);
1140:   return(0);
1141: }
1142: /*
1143:         Actually opens the file
1144: */
1145: static PetscErrorCode PetscViewerFileSetUp_Binary(PetscViewer viewer)
1146: {
1147:   PetscMPIInt        rank;
1148:   PetscErrorCode     ierr;
1149:   size_t             len;
1150:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1151:   const char         *fname;
1152:   char               bname[PETSC_MAX_PATH_LEN],*gz;
1153:   PetscBool          found;
1154:   PetscFileMode      type = vbinary->btype;

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

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

1163:   /* if ends in .gz strip that off and note user wants file compressed */
1164:   vbinary->storecompressed = PETSC_FALSE;
1165:   if (!rank && type == FILE_MODE_WRITE) {
1166:     /* remove .gz if it ends library name */
1167:     PetscStrstr(vbinary->filename,".gz",&gz);
1168:     if (gz) {
1169:       PetscStrlen(gz,&len);
1170:       if (len == 3) {
1171:         *gz = 0;
1172:         vbinary->storecompressed = PETSC_TRUE;
1173:       }
1174:     }
1175:   }

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

1180:     if (type == FILE_MODE_READ) {
1181:       /* possibly get the file from remote site or compressed file */
1182:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
1183:       fname = bname;
1184:       /* comm below may be global as all ranks go here for FILE_MODE_READ and output 'found' of PetscFileRetrieve() is valid on all processes */
1185:       if (!found) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
1186:     } else fname = vbinary->filename;
1187:     if (type == FILE_MODE_APPEND) { /* check if asked to append to a non-existing file */
1188:       PetscTestFile(fname,'\0',&found);
1189:     }

1191: #if defined(PETSC_HAVE_O_BINARY)
1192:     if (type == FILE_MODE_WRITE || (type == FILE_MODE_APPEND && !found) ) {
1193:       if ((vbinary->fdes = open(fname,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
1194:     } else if (type == FILE_MODE_READ && fname) {
1195:       if ((vbinary->fdes = open(fname,O_RDONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
1196:     } else if (type == FILE_MODE_APPEND) {
1197:       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
1198:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1199: #else
1200:     if (type == FILE_MODE_WRITE || (type == FILE_MODE_APPEND && !found) ) {
1201:       if ((vbinary->fdes = creat(fname,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
1202:     } else if (type == FILE_MODE_READ && fname) {
1203:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
1204:     } else if (type == FILE_MODE_APPEND) {
1205:       if ((vbinary->fdes = open(fname,O_WRONLY|O_APPEND,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for writing",fname);
1206:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1207: #endif
1208:   } else vbinary->fdes = -1;

1210:   /*
1211:       try to open info file: all processors open this file if read only
1212:   */
1213:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1214:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

1216:     PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));
1217:     /* remove .gz if it ends library name */
1218:     PetscStrstr(infoname,".gz",&gz);
1219:     if (gz) {
1220:       PetscStrlen(gz,&len);
1221:       if (len == 3) *gz = 0;
1222:     }

1224:     PetscStrlcat(infoname,".info",sizeof(infoname));
1225:     PetscFixFilename(infoname,iname);
1226:     if (type == FILE_MODE_READ) {
1227:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
1228:       if (found) {
1229:         PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
1230:       }
1231:     } else {
1232:       vbinary->fdes_info = fopen(infoname,"w");
1233:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1234:     }
1235:   }
1236: #if defined(PETSC_USE_LOG)
1237:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1238: #endif
1239:   return(0);
1240: }

1242: #if defined(PETSC_HAVE_MPIIO)
1243: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1244: {
1245:   PetscMPIInt        rank;
1246:   PetscErrorCode     ierr;
1247:   size_t             len;
1248:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1249:   char               *gz;
1250:   PetscBool          found;
1251:   PetscFileMode      type = vbinary->btype;
1252:   int                amode;

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

1259:   vbinary->storecompressed = PETSC_FALSE;

1261:   switch (type) {
1262:   case FILE_MODE_READ:  amode = MPI_MODE_RDONLY; break;
1263:   case FILE_MODE_WRITE: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE; break;
1264:   default: SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[type]);
1265:   }
1266:   MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfdes);

1268:   /*
1269:       try to open info file: all processors open this file if read only

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

1277:     PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));
1278:     /* remove .gz if it ends library name */
1279:     PetscStrstr(infoname,".gz",&gz);
1280:     if (gz) {
1281:       PetscStrlen(gz,&len);
1282:       if (len == 3) *gz = 0;
1283:     }

1285:     PetscStrlcat(infoname,".info",sizeof(infoname));
1286:     PetscFixFilename(infoname,iname);
1287:     if (type == FILE_MODE_READ) {
1288:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
1289:       PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
1290:     } else {
1291:       vbinary->fdes_info = fopen(infoname,"w");
1292:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1293:     }
1294:   }
1295: #if defined(PETSC_USE_LOG)
1296:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1297: #endif
1298:   return(0);
1299: }

1301: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
1302: {
1303:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1305:   vbinary->usempiio = flg;
1306:   return(0);
1307: }
1308: #endif

1310: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1311: {
1312:   PetscErrorCode     ierr;
1313:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1316:   if (binary->filename) {
1317:     PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);
1318:   }
1319:   return(0);
1320: }

1322: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
1323: {
1324:   PetscErrorCode     ierr;
1325:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1328:   if (!binary->setfromoptionscalled) { PetscViewerSetFromOptions(v); }
1329: 
1330: #if defined(PETSC_HAVE_MPIIO)
1331:   if (binary->usempiio) {
1332:     PetscViewerFileSetUp_BinaryMPIIO(v);
1333:   } else {
1334: #endif
1335:     PetscViewerFileSetUp_Binary(v);
1336: #if defined(PETSC_HAVE_MPIIO)
1337:   }
1338: #endif
1339:   return(0);
1340: }

1342: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer v)
1343: {
1344:   PetscErrorCode     ierr;
1345:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1346:   char               defaultname[PETSC_MAX_PATH_LEN];
1347:   PetscBool          flg;

1350:   PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");
1351:   PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");
1352:   PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);
1353:   if (flg) { PetscViewerFileSetName_Binary(v,defaultname); }
1354:   PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",PETSC_FALSE,&binary->skipinfo,NULL);
1355:   PetscOptionsBool("-viewer_binary_skip_options","Skip parsing vec load options","PetscViewerBinarySetSkipOptions",PETSC_TRUE,&binary->skipoptions,NULL);
1356:   PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",PETSC_FALSE,&binary->skipheader,NULL);
1357: #if defined(PETSC_HAVE_MPIIO)
1358:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,&binary->usempiio,NULL);
1359: #elif defined(PETSC_HAVE_MPIUNI)
1360:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);
1361: #endif
1362:   PetscOptionsTail();
1363:   binary->setfromoptionscalled = PETSC_TRUE;
1364:   return(0);
1365: }

1367: /*MC
1368:    PETSCVIEWERBINARY - A viewer that saves to binary files


1371: .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
1372:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
1373:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
1374:            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()

1376:   Level: beginner

1378: M*/

1380: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1381: {
1382:   PetscErrorCode     ierr;
1383:   PetscViewer_Binary *vbinary;

1386:   PetscNewLog(v,&vbinary);
1387:   v->data                  = (void*)vbinary;
1388:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1389:   v->ops->destroy          = PetscViewerDestroy_Binary;
1390:   v->ops->view             = PetscViewerView_Binary;
1391:   v->ops->setup            = PetscViewerSetUp_Binary;
1392:   v->ops->flush            = NULL;
1393:   vbinary->fdes            = 0;
1394: #if defined(PETSC_HAVE_MPIIO)
1395:   vbinary->mfdes           = MPI_FILE_NULL;
1396:   vbinary->mfsub           = MPI_FILE_NULL;
1397: #endif
1398:   vbinary->fdes_info       = 0;
1399:   vbinary->skipinfo        = PETSC_FALSE;
1400:   vbinary->skipoptions     = PETSC_TRUE;
1401:   vbinary->skipheader      = PETSC_FALSE;
1402:   vbinary->setfromoptionscalled = PETSC_FALSE;
1403:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1404:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1405:   v->ops->read             = PetscViewerBinaryRead;
1406:   vbinary->btype           = (PetscFileMode) -1;
1407:   vbinary->storecompressed = PETSC_FALSE;
1408:   vbinary->filename        = NULL;
1409:   vbinary->ogzfilename     = NULL;
1410:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

1412:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);
1413:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);
1414:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);
1415:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);
1416:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);
1417:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);
1418:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);
1419:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);
1420:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);
1421:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);
1422:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);
1423:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);
1424:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);
1425: #if defined(PETSC_HAVE_MPIIO)
1426:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);
1427:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);
1428: #endif
1429:   return(0);
1430: }

1432: /* ---------------------------------------------------------------------*/
1433: /*
1434:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1435:   is attached to a communicator, in this case the attribute is a PetscViewer.
1436: */
1437: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

1439: /*@C
1440:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1441:                      in a communicator.

1443:      Collective

1445:      Input Parameter:
1446: .    comm - the MPI communicator to share the binary PetscViewer

1448:      Level: intermediate

1450:    Options Database Keys:
1451: +    -viewer_binary_filename <name>
1452: .    -viewer_binary_skip_info
1453: .    -viewer_binary_skip_options
1454: .    -viewer_binary_skip_header
1455: -    -viewer_binary_mpiio

1457:    Environmental variables:
1458: -   PETSC_VIEWER_BINARY_FILENAME

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

1465: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1466:           PetscViewerDestroy()
1467: @*/
1468: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1469: {
1471:   PetscBool      flg;
1472:   PetscViewer    viewer;
1473:   char           fname[PETSC_MAX_PATH_LEN];
1474:   MPI_Comm       ncomm;

1477:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1478:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1479:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
1480:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1481:   }
1482:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
1483:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1484:   if (!flg) { /* PetscViewer not yet created */
1485:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1486:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1487:     if (!flg) {
1488:       PetscStrcpy(fname,"binaryoutput");
1489:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1490:     }
1491:     PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
1492:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1493:     PetscObjectRegisterDestroy((PetscObject)viewer);
1494:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1495:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1496:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1497:   }
1498:   PetscCommDestroy(&ncomm);
1499:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1500:   PetscFunctionReturn(viewer);
1501: }