Actual source code: binv.c

petsc-3.11.4 2019-09-28
Report Typos and Errors

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

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

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

 39:   PetscViewerSetUp(viewer);

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

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

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

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

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

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

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

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

116:     Not Collective

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

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

124:     Level: advanced

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

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

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

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

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

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

148:     Not Collective

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

154:     Level: advanced

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

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

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

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

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

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

178:     Not Collective

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

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

186:     Level: advanced

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

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

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

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

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

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


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

221:     Not Collective

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

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

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

232:     Level: advanced

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

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

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

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

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

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

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

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

267:     Not Collective

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

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

275:     Level: advanced

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

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

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

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

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

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

302:     Not Collective

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

308:     Level: advanced

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

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

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

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

325:     Collective On PetscViewer

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

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

333:     Level: advanced

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

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

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


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

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

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

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

368:     Not Collective

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

373:     Options Database Key:
374: .   -viewer_binary_skip_info

376:     Level: advanced

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

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

386:    Concepts: PetscViewerBinary^accessing info file

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

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

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

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

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

412:     Not Collective

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

417:     Options Database Key:
418: .   -viewer_binary_skip_info

420:     Level: advanced

422:     Concepts: PetscViewerBinary^accessing info file

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

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

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

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

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

448:     Not Collective

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

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

456:     Level: advanced

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

461:     Concepts: PetscViewerBinary^accessing info file

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

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

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

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

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

487:     Not Collective

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

493:     Options Database Key:
494: .   -viewer_binary_skip_options

496:     Level: advanced

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

501:    Concepts: PetscViewerBinary^accessing info file

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

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

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

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

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

529:     Not Collective

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

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

537:     Level: advanced

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

542:    Concepts: PetscViewerBinary^accessing info file

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

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

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

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

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

568:     Not Collective

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

574:     Options Database Key:
575: .   -viewer_binary_skip_header

577:     Level: advanced

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

582:            Can ONLY be called on a binary viewer

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

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

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

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

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

608:     Not Collective

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

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

616:     Level: advanced

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

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

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

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

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

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

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

660:     Not Collective

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

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

668:     Level: advanced

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

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

677:   Concepts: PetscViewerBinary^accessing info file

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

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

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

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

725: #if defined(PETSC_HAVE_MPIIO)
726: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
727: {
728:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
729:   int                err;
730:   PetscErrorCode     ierr;

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

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

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

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

778: /*@C
779:    PetscViewerBinaryOpen - Opens a file for binary input/output.

781:    Collective on MPI_Comm

783:    Input Parameters:
784: +  comm - MPI communicator
785: .  name - name of file
786: -  type - type of file
787: $    FILE_MODE_WRITE - create new file for binary output
788: $    FILE_MODE_READ - open existing file for binary input
789: $    FILE_MODE_APPEND - open existing file for binary output

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

794:     Options Database Keys:
795: +    -viewer_binary_filename <name>
796: .    -viewer_binary_skip_info
797: .    -viewer_binary_skip_options
798: .    -viewer_binary_skip_header
799: -    -viewer_binary_mpiio

801:    Level: beginner

803:    Note:
804:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

812:     For writing files it only opens the file on processor 0 in the communicator.
813:     For readable files it opens the file on all nodes that have the file. If
814:     node 0 does not have the file it generates an error even if other nodes
815:     do have the file.

817:    Concepts: binary files
818:    Concepts: PetscViewerBinary^creating
819:    Concepts: gzip
820:    Concepts: accessing remote file
821:    Concepts: remote file

823: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
824:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
825:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
826:           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
827: @*/
828: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
829: {

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

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

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

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

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

873:    Collective on MPI_Comm

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

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

884:    Level: beginner

886:    Concepts: binary files

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

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

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

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

916:    Collective on MPI_Comm

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

925:    Level: beginner

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

930:    Concepts: binary files

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

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

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

958:    Collective on MPI_Comm

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


965:    Level: intermediate

967:    Concepts: binary files

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

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

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

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

1003:    Collective on MPI_Comm

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

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

1011:    Level: intermediate

1013:    Concepts: binary files

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

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

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

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

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

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

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

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

1056:     Not Collective

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

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

1067:   Level: advanced

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

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

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

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

1087:     Logically Collective on PetscViewer

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

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

1096:     Level: advanced

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

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

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

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

1115:     Logically Collective on PetscViewer

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

1124:   Level: advanced

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1291:   vbinary->storecompressed = PETSC_FALSE;

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

1300:   /*
1301:       try to open info file: all processors open this file if read only

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

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

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

1333: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
1334: {
1335:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1337:   vbinary->usempiio = flg;
1338:   return(0);
1339: }
1340: #endif

1342: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1343: {
1344:   PetscErrorCode     ierr;
1345:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

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

1354: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
1355: {
1356:   PetscErrorCode     ierr;
1357:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

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

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

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

1399: /*MC
1400:    PETSCVIEWERBINARY - A viewer that saves to binary files


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

1408:   Level: beginner

1410: M*/

1412: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1413: {
1414:   PetscErrorCode     ierr;
1415:   PetscViewer_Binary *vbinary;

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

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

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

1471: /*@C
1472:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1473:                      in a communicator.

1475:      Collective on MPI_Comm

1477:      Input Parameter:
1478: .    comm - the MPI communicator to share the binary PetscViewer

1480:      Level: intermediate

1482:    Options Database Keys:
1483: +    -viewer_binary_filename <name>
1484: .    -viewer_binary_skip_info
1485: .    -viewer_binary_skip_options
1486: .    -viewer_binary_skip_header
1487: -    -viewer_binary_mpiio

1489:    Environmental variables:
1490: -   PETSC_VIEWER_BINARY_FILENAME

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

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

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