Actual source code: binv.c

petsc-3.9.4 2018-09-11
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: This must be called on all processes because Dave May changed
345:     the source code that this may be trigger a PetscViewerSetUp() call if it was not previously triggered.


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

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

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

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

367:     Not Collective

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

372:     Options Database Key:
373: .   -viewer_binary_skip_info

375:     Level: advanced

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

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

384:    Concepts: PetscViewerBinary^accessing info file

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

394:   vbinary->skipinfo = PETSC_TRUE;
395:   return(0);
396: }

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

403:   vbinary->skipinfo = skip;
404:   return(0);
405: }

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

410:     Not Collective

412:     Input Paramter:
413: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

415:     Options Database Key:
416: .   -viewer_binary_skip_info

418:     Level: advanced

420:     Concepts: PetscViewerBinary^accessing info file

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

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

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

439:   *skip  = vbinary->skipinfo;
440:   return(0);
441: }

443: /*@
444:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

446:     Not Collective

448:     Input Parameter:
449: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

451:     Output Parameter:
452: .   skip - PETSC_TRUE implies the .info file was not generated

454:     Level: advanced

456:     Notes: This must be called after PetscViewerSetType()

458:     Concepts: PetscViewerBinary^accessing info file

460: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
461:           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
462: @*/
463: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
464: {

468:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));
469:   return(0);
470: }

472: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
473: {
474:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

477:   vbinary->skipoptions = skip;
478:   return(0);
479: }

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

484:     Not Collective

486:     Input Parameters:
487: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
488: -   skip - PETSC_TRUE means do not use

490:     Options Database Key:
491: .   -viewer_binary_skip_options

493:     Level: advanced

495:     Notes: This must be called after PetscViewerSetType()

497:    Concepts: PetscViewerBinary^accessing info file

499: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
500:           PetscViewerBinaryGetSkipOptions()
501: @*/
502: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)
503: {

507:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));
508:   return(0);
509: }

511: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
512: {
513:   PetscViewer_Binary *vbinary;

517:   vbinary = (PetscViewer_Binary*)viewer->data;
518:   *skip   = vbinary->skipoptions;
519:   return(0);
520: }

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

525:     Not Collective

527:     Input Parameter:
528: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

530:     Output Parameter:
531: .   skip - PETSC_TRUE means do not use

533:     Level: advanced

535:     Notes: This must be called after PetscViewerSetType()

537:    Concepts: PetscViewerBinary^accessing info file

539: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
540:           PetscViewerBinarySetSkipOptions()
541: @*/
542: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
543: {

547:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));
548:   return(0);
549: }

551: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
552: {
553:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

556:   vbinary->skipheader = skip;
557:   return(0);
558: }

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

563:     Not Collective

565:     Input Parameters:
566: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
567: -   skip - PETSC_TRUE means do not write header

569:     Options Database Key:
570: .   -viewer_binary_skip_header

572:     Level: advanced

574:     Notes: This must be called after PetscViewerSetType()

576:            Can ONLY be called on a binary viewer

578: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
579:           PetscViewerBinaryGetSkipHeader()
580: @*/
581: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
582: {

586:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));
587:   return(0);
588: }

590: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer,PetscBool  *skip)
591: {
592:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

595:   *skip = vbinary->skipheader;
596:   return(0);
597: }

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

602:     Not Collective

604:     Input Parameter:
605: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

607:     Output Parameter:
608: .   skip - PETSC_TRUE means do not write header

610:     Level: advanced

612:     Notes: This must be called after PetscViewerSetType()

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

616: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
617:           PetscViewerBinarySetSkipHeader()
618: @*/
619: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer,PetscBool  *skip)
620: {

624:   *skip = PETSC_FALSE;
625:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));
626:   return(0);
627: }

629: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
630: {
631:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
632:   PetscErrorCode     ierr;
633:   MPI_Comm           comm;

636:   PetscViewerSetUp(viewer);
637:   *file = vbinary->fdes_info;
638:   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
639:     vbinary->matlabheaderwritten = PETSC_TRUE;
640:     PetscObjectGetComm((PetscObject)viewer,&comm);
641:     PetscFPrintf(comm,*file,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
642:     PetscFPrintf(comm,*file,"#$$ Set.filename = '%s';\n",vbinary->filename);
643:     PetscFPrintf(comm,*file,"#$$ fd = PetscOpenFile(Set.filename);\n");
644:     PetscFPrintf(comm,*file,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
645:   }
646:   return(0);
647: }

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

653:     Not Collective

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

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

661:     Level: advanced

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

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

670:   Concepts: PetscViewerBinary^accessing info file

672: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
673: @*/
674: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
675: {

679:   *file = NULL;
680:   PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));
681:   return(0);
682: }

684: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
685: {
686:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
687:   PetscErrorCode     ierr;
688:   PetscMPIInt        rank;
689:   int                err;

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

718: #if defined(PETSC_HAVE_MPIIO)
719: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
720: {
721:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
722:   int                err;
723:   PetscErrorCode     ierr;

726:   if (vbinary->mfdes != MPI_FILE_NULL) {
727:     MPI_File_close(&vbinary->mfdes);
728:   }
729:   if (vbinary->mfsub != MPI_FILE_NULL) {
730:     MPI_File_close(&vbinary->mfsub);
731:   }
732:   if (vbinary->fdes_info) {
733:     err = fclose(vbinary->fdes_info);
734:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
735:   }
736:   return(0);
737: }
738: #endif

740: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
741: {
742:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
743:   PetscErrorCode     ierr;

746:   if (v->format == PETSC_VIEWER_BINARY_MATLAB) {
747:     MPI_Comm comm;
748:     FILE     *info;

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

771: /*@C
772:    PetscViewerBinaryOpen - Opens a file for binary input/output.

774:    Collective on MPI_Comm

776:    Input Parameters:
777: +  comm - MPI communicator
778: .  name - name of file
779: -  type - type of file
780: $    FILE_MODE_WRITE - create new file for binary output
781: $    FILE_MODE_READ - open existing file for binary input
782: $    FILE_MODE_APPEND - open existing file for binary output

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

787:     Options Database Keys:
788: +    -viewer_binary_filename <name>
789: .    -viewer_binary_skip_info
790: .    -viewer_binary_skip_options
791: .    -viewer_binary_skip_header
792: -    -viewer_binary_mpiio

794:    Level: beginner

796:    Note:
797:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

805:     For writing files it only opens the file on processor 0 in the communicator.
806:     For readable files it opens the file on all nodes that have the file. If
807:     node 0 does not have the file it generates an error even if other nodes
808:     do have the file.

810:    Concepts: binary files
811:    Concepts: PetscViewerBinary^creating
812:    Concepts: gzip
813:    Concepts: accessing remote file
814:    Concepts: remote file

816: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
817:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
818:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
819:           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
820: @*/
821: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
822: {

826:   PetscViewerCreate(comm,binv);
827:   PetscViewerSetType(*binv,PETSCVIEWERBINARY);
828:   PetscViewerFileSetMode(*binv,type);
829:   PetscViewerFileSetName(*binv,name);
830:   PetscViewerSetFromOptions(*binv);
831:   return(0);
832: }

834: #if defined(PETSC_HAVE_MPIIO)
835: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write)
836: {
837:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
838:   PetscErrorCode     ierr;
839:   MPI_File           mfdes;
840:   MPI_Datatype       mdtype;
841:   PetscMPIInt        cnt;
842:   MPI_Status         status;
843:   MPI_Aint           ul,dsize;

846:   mfdes = vbinary->mfdes;
847:   PetscMPIIntCast(num,&cnt);
848:   PetscDataTypeToMPIDataType(dtype,&mdtype);
849:   MPI_File_set_view(mfdes,vbinary->moff,mdtype,mdtype,(char*)"native",MPI_INFO_NULL);
850:   if (write) {
851:     MPIU_File_write_all(mfdes,data,cnt,mdtype,&status);
852:   } else {
853:     MPIU_File_read_all(mfdes,data,cnt,mdtype,&status);
854:   }
855:   MPI_Type_get_extent(mdtype,&ul,&dsize);

857:   vbinary->moff += dsize*cnt;
858:   if (count) *count = num;
859:   return(0);
860: }
861: #endif

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

866:    Collective on MPI_Comm

868:    Input Parameters:
869: +  viewer - the binary viewer
870: .  data - location of the data to be written
871: .  num - number of items of data to read
872: -  dtype - type of data to read

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

877:    Level: beginner

879:    Concepts: binary files

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

883: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
884:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
885:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
886: @*/
887: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
888: {
889:   PetscErrorCode     ierr;
890:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

892:   PetscViewerSetUp(viewer);
893: #if defined(PETSC_HAVE_MPIIO)
894:   if (vbinary->usempiio) {
895:     PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE);
896:   } else {
897: #endif
898:     PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,dtype);
899:     if (count) *count = num;
900: #if defined(PETSC_HAVE_MPIIO)
901:   }
902: #endif
903:   return(0);
904: }

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

909:    Collective on MPI_Comm

911:    Input Parameters:
912: +  viewer - the binary viewer
913: .  data - location of data
914: .  count - number of items of data to write
915: .  dtype - type of data to write
916: -  istemp - data may be overwritten

918:    Level: beginner

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

922:    Concepts: binary files

924: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
925:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
926:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
927: @*/
928: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscBool istemp)
929: {
930:   PetscErrorCode     ierr;
931:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

934:   PetscViewerSetUp(viewer);
935: #if defined(PETSC_HAVE_MPIIO)
936:   if (vbinary->usempiio) {
937:     PetscViewerBinaryWriteReadMPIIO(viewer,data,count,NULL,dtype,PETSC_TRUE);
938:   } else {
939: #endif
940:     PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype,istemp);
941: #if defined(PETSC_HAVE_MPIIO)
942:   }
943: #endif
944:   return(0);
945: }

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

950:    Collective on MPI_Comm

952:    Input Parameters:
953: +  viewer - the binary viewer
954: -  data - location of the array of strings


957:    Level: intermediate

959:    Concepts: binary files

961:     Notes: array of strings is null terminated

963: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
964:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
965:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
966: @*/
967: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data)
968: {
970:   PetscInt       i,n = 0,*sizes;

972:   PetscViewerSetUp(viewer);
973:   /* count number of strings */
974:   while (data[n++]) ;
975:   n--;
976:   PetscMalloc1(n+1,&sizes);
977:   sizes[0] = n;
978:   for (i=0; i<n; i++) {
979:     size_t tmp;
980:     PetscStrlen(data[i],&tmp);
981:     sizes[i+1] = tmp + 1;   /* size includes space for the null terminator */
982:   }
983:   PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT,PETSC_FALSE);
984:   for (i=0; i<n; i++) {
985:     PetscViewerBinaryWrite(viewer,(void*)data[i],sizes[i+1],PETSC_CHAR,PETSC_FALSE);
986:   }
987:   PetscFree(sizes);
988:   return(0);
989: }

991: /*@C
992:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

994:    Collective on MPI_Comm

996:    Input Parameter:
997: .  viewer - the binary viewer

999:    Output Parameter:
1000: .  data - location of the array of strings

1002:    Level: intermediate

1004:    Concepts: binary files

1006:     Notes: array of strings is null terminated

1008: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
1009:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
1010:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
1011: @*/
1012: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
1013: {
1015:   PetscInt       i,n,*sizes,N = 0;

1017:   PetscViewerSetUp(viewer);
1018:   /* count number of strings */
1019:   PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);
1020:   PetscMalloc1(n,&sizes);
1021:   PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);
1022:   for (i=0; i<n; i++) N += sizes[i];
1023:   PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);
1024:   (*data)[0] = (char*)((*data) + n + 1);
1025:   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
1026:   PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);

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

1030:   PetscFree(sizes);
1031:   return(0);
1032: }

1034: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
1035: {
1036:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1039:   *name = vbinary->filename;
1040:   return(0);
1041: }

1043: /*@C
1044:      PetscViewerFileGetMode - Gets the type of file to be open

1046:     Not Collective

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

1051:   Output Parameter:
1052: .  type - type of file
1053: $    FILE_MODE_WRITE - create new file for binary output
1054: $    FILE_MODE_READ - open existing file for binary input
1055: $    FILE_MODE_APPEND - open existing file for binary output

1057:   Level: advanced

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

1061: @*/
1062: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
1063: {

1069:   PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));
1070:   return(0);
1071: }

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

1077:     Logically Collective on PetscViewer

1079:     Input Parameters:
1080: +   viewer - the PetscViewer; must be a binary
1081: -   flg - PETSC_TRUE means MPI-IO will be used

1083:     Options Database:
1084:     -viewer_binary_mpiio : Flag for using MPI-IO

1086:     Level: advanced

1088: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
1089:           PetscViewerBinaryGetUseMPIIO()

1091: @*/
1092: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool flg)
1093: {

1098:   PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,flg));
1099:   return(0);
1100: }

1102: /*@C
1103:      PetscViewerFileSetMode - Sets the type of file to be open

1105:     Logically Collective on PetscViewer

1107:   Input Parameters:
1108: +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1109: -  type - type of file
1110: $    FILE_MODE_WRITE - create new file for binary output
1111: $    FILE_MODE_READ - open existing file for binary input
1112: $    FILE_MODE_APPEND - open existing file for binary output

1114:   Level: advanced

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

1118: @*/
1119: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
1120: {

1126:   PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));
1127:   return(0);
1128: }

1130: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
1131: {
1132:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1135:   *type = vbinary->btype;
1136:   return(0);
1137: }

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

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

1148: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1149: {
1150:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1151:   PetscErrorCode     ierr;

1154:   if (vbinary->filename) {
1155:     /* gzip can be run after the file with the previous filename has been closed */
1156:     PetscFree(vbinary->ogzfilename);
1157:     PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename);
1158:     PetscFree(vbinary->filename);
1159:     viewer->setupcalled = PETSC_FALSE;
1160:   }
1161:   PetscStrallocpy(name,&vbinary->filename);
1162:   return(0);
1163: }
1164: /*
1165:         Actually opens the file
1166: */
1167: static PetscErrorCode PetscViewerFileSetUp_Binary(PetscViewer viewer)
1168: {
1169:   PetscMPIInt        rank;
1170:   PetscErrorCode     ierr;
1171:   size_t             len;
1172:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1173:   const char         *fname;
1174:   char               bname[PETSC_MAX_PATH_LEN],*gz;
1175:   PetscBool          found;
1176:   PetscFileMode      type = vbinary->btype;

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

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

1185:   /* if ends in .gz strip that off and note user wants file compressed */
1186:   vbinary->storecompressed = PETSC_FALSE;
1187:   if (!rank && type == FILE_MODE_WRITE) {
1188:     /* remove .gz if it ends library name */
1189:     PetscStrstr(vbinary->filename,".gz",&gz);
1190:     if (gz) {
1191:       PetscStrlen(gz,&len);
1192:       if (len == 3) {
1193:         *gz = 0;
1194:         vbinary->storecompressed = PETSC_TRUE;
1195:       }
1196:     }
1197:   }

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

1202:     if (type == FILE_MODE_READ) {
1203:       /* possibly get the file from remote site or compressed file */
1204:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
1205:       fname = bname;
1206:       /* comm below may be global as all ranks go here for FILE_MODE_READ and output 'found' of PetscFileRetrieve() is valid on all processes */
1207:       if (!found) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
1208:     } else fname = vbinary->filename;

1210: #if defined(PETSC_HAVE_O_BINARY)
1211:     if (type == FILE_MODE_WRITE) {
1212:       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);
1213:     } else if (type == FILE_MODE_READ && fname) {
1214:       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);
1215:     } else if (type == FILE_MODE_APPEND) {
1216:       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);
1217:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1218: #else
1219:     if (type == FILE_MODE_WRITE) {
1220:       if ((vbinary->fdes = creat(fname,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
1221:     } else if (type == FILE_MODE_READ && fname) {
1222:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
1223:     } else if (type == FILE_MODE_APPEND) {
1224:       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);
1225:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1226: #endif
1227:   } else vbinary->fdes = -1;

1229:   /*
1230:       try to open info file: all processors open this file if read only
1231:   */
1232:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1233:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

1235:     PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));
1236:     /* remove .gz if it ends library name */
1237:     PetscStrstr(infoname,".gz",&gz);
1238:     if (gz) {
1239:       PetscStrlen(gz,&len);
1240:       if (len == 3) *gz = 0;
1241:     }

1243:     PetscStrlcat(infoname,".info",sizeof(infoname));
1244:     PetscFixFilename(infoname,iname);
1245:     if (type == FILE_MODE_READ) {
1246:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
1247:       if (found) {
1248:         PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
1249:       }
1250:     } else {
1251:       vbinary->fdes_info = fopen(infoname,"w");
1252:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1253:     }
1254:   }
1255: #if defined(PETSC_USE_LOG)
1256:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1257: #endif
1258:   return(0);
1259: }

1261: #if defined(PETSC_HAVE_MPIIO)
1262: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1263: {
1264:   PetscMPIInt        rank;
1265:   PetscErrorCode     ierr;
1266:   size_t             len;
1267:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1268:   char               *gz;
1269:   PetscBool          found;
1270:   PetscFileMode      type = vbinary->btype;
1271:   int                amode;

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

1278:   vbinary->storecompressed = PETSC_FALSE;

1280:   switch (type) {
1281:   case FILE_MODE_READ:  amode = MPI_MODE_RDONLY; break;
1282:   case FILE_MODE_WRITE: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE; break;
1283:   default: SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unsupported file mode %s",PetscFileModes[type]);
1284:   }
1285:   MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,amode,MPI_INFO_NULL,&vbinary->mfdes);

1287:   /*
1288:       try to open info file: all processors open this file if read only

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

1296:     PetscStrncpy(infoname,vbinary->filename,sizeof(infoname));
1297:     /* remove .gz if it ends library name */
1298:     PetscStrstr(infoname,".gz",&gz);
1299:     if (gz) {
1300:       PetscStrlen(gz,&len);
1301:       if (len == 3) *gz = 0;
1302:     }

1304:     PetscStrlcat(infoname,".info",sizeof(infoname));
1305:     PetscFixFilename(infoname,iname);
1306:     if (type == FILE_MODE_READ) {
1307:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
1308:       PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
1309:     } else {
1310:       vbinary->fdes_info = fopen(infoname,"w");
1311:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1312:     }
1313:   }
1314: #if defined(PETSC_USE_LOG)
1315:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1316: #endif
1317:   return(0);
1318: }

1320: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
1321: {
1322:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1324:   vbinary->usempiio = flg;
1325:   return(0);
1326: }
1327: #endif

1329: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1330: {
1331:   PetscErrorCode     ierr;
1332:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1335:   if (binary->filename) {
1336:     PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);
1337:   }
1338:   return(0);
1339: }

1341: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
1342: {
1343:   PetscErrorCode     ierr;
1344:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1347:   if (!binary->setfromoptionscalled) { PetscViewerSetFromOptions(v); }
1348: 
1349: #if defined(PETSC_HAVE_MPIIO)
1350:   if (binary->usempiio) {
1351:     PetscViewerFileSetUp_BinaryMPIIO(v);
1352:   } else {
1353: #endif
1354:     PetscViewerFileSetUp_Binary(v);
1355: #if defined(PETSC_HAVE_MPIIO)
1356:   }
1357: #endif
1358:   return(0);
1359: }

1361: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer v)
1362: {
1363:   PetscErrorCode     ierr;
1364:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1365:   char               defaultname[PETSC_MAX_PATH_LEN];
1366:   PetscBool          flg;

1369:   PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");
1370:   PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");
1371:   PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);
1372:   if (flg) { PetscViewerFileSetName_Binary(v,defaultname); }
1373:   PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",PETSC_FALSE,&binary->skipinfo,NULL);
1374:   PetscOptionsBool("-viewer_binary_skip_options","Skip parsing vec load options","PetscViewerBinarySetSkipOptions",PETSC_TRUE,&binary->skipoptions,NULL);
1375:   PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",PETSC_FALSE,&binary->skipheader,NULL);
1376: #if defined(PETSC_HAVE_MPIIO)
1377:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,&binary->usempiio,NULL);
1378: #elif defined(PETSC_HAVE_MPIUNI)
1379:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);
1380: #endif
1381:   PetscOptionsTail();
1382:   binary->setfromoptionscalled = PETSC_TRUE;
1383:   return(0);
1384: }

1386: /*MC
1387:    PETSCVIEWERBINARY - A viewer that saves to binary files


1390: .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
1391:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
1392:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
1393:            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()

1395:   Level: beginner

1397: M*/

1399: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1400: {
1401:   PetscErrorCode     ierr;
1402:   PetscViewer_Binary *vbinary;

1405:   PetscNewLog(v,&vbinary);
1406:   v->data                  = (void*)vbinary;
1407:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1408:   v->ops->destroy          = PetscViewerDestroy_Binary;
1409:   v->ops->view             = PetscViewerView_Binary;
1410:   v->ops->setup            = PetscViewerSetUp_Binary;
1411:   v->ops->flush            = NULL;
1412:   vbinary->fdes            = 0;
1413: #if defined(PETSC_HAVE_MPIIO)
1414:   vbinary->mfdes           = MPI_FILE_NULL;
1415:   vbinary->mfsub           = MPI_FILE_NULL;
1416: #endif
1417:   vbinary->fdes_info       = 0;
1418:   vbinary->skipinfo        = PETSC_FALSE;
1419:   vbinary->skipoptions     = PETSC_TRUE;
1420:   vbinary->skipheader      = PETSC_FALSE;
1421:   vbinary->setfromoptionscalled = PETSC_FALSE;
1422:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1423:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1424:   v->ops->read             = PetscViewerBinaryRead;
1425:   vbinary->btype           = (PetscFileMode) -1;
1426:   vbinary->storecompressed = PETSC_FALSE;
1427:   vbinary->filename        = NULL;
1428:   vbinary->ogzfilename     = NULL;
1429:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

1431:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);
1432:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);
1433:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);
1434:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);
1435:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);
1436:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);
1437:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);
1438:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);
1439:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);
1440:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);
1441:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);
1442:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);
1443:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);
1444: #if defined(PETSC_HAVE_MPIIO)
1445:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);
1446:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);
1447: #endif
1448:   return(0);
1449: }

1451: /* ---------------------------------------------------------------------*/
1452: /*
1453:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1454:   is attached to a communicator, in this case the attribute is a PetscViewer.
1455: */
1456: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

1458: /*@C
1459:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1460:                      in a communicator.

1462:      Collective on MPI_Comm

1464:      Input Parameter:
1465: .    comm - the MPI communicator to share the binary PetscViewer

1467:      Level: intermediate

1469:    Options Database Keys:
1470: +    -viewer_binary_filename <name>
1471: .    -viewer_binary_skip_info
1472: .    -viewer_binary_skip_options
1473: .    -viewer_binary_skip_header
1474: -    -viewer_binary_mpiio

1476:    Environmental variables:
1477: -   PETSC_VIEWER_BINARY_FILENAME

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

1484: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1485:           PetscViewerDestroy()
1486: @*/
1487: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1488: {
1490:   PetscBool      flg;
1491:   PetscViewer    viewer;
1492:   char           fname[PETSC_MAX_PATH_LEN];
1493:   MPI_Comm       ncomm;

1496:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1497:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1498:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
1499:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1500:   }
1501:   MPI_Comm_get_attr(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
1502:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1503:   if (!flg) { /* PetscViewer not yet created */
1504:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1505:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1506:     if (!flg) {
1507:       PetscStrcpy(fname,"binaryoutput");
1508:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1509:     }
1510:     PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
1511:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1512:     PetscObjectRegisterDestroy((PetscObject)viewer);
1513:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1514:     MPI_Comm_set_attr(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1515:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1516:   }
1517:   PetscCommDestroy(&ncomm);
1518:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1519:   PetscFunctionReturn(viewer);
1520: }