Actual source code: binv.c

  1: #include <petsc/private/viewerimpl.h>

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

 24: #if defined(PETSC_HAVE_MPIIO)
 25: static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer)
 26: {
 27:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

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

 46:   PetscViewerSetUp(viewer);

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

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

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

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

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

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

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

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

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

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

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

135:     Not Collective

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

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

143:     Level: advanced

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

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

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

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

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

166:     Logically Collective

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

172:     Level: advanced

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

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

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

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

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

195:     Not Collective

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

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

203:     Level: advanced

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

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

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

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

227:     Logically Collective on PetscViewer

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

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

236:     Level: advanced

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

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

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

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

263:     Not Collective

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

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

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

274:     Level: advanced

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

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

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

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

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

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

306:     Not Collective

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

312:     Level: advanced

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

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

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

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

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

337:     Not Collective

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

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

345:     Level: advanced

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

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

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

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

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

369:     Collective On PetscViewer

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

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

377:     Level: advanced

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

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

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

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

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

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

409:     Not Collective

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

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

417:     Level: advanced

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

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

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

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

439:     Not Collective

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

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

448:     Level: advanced

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

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

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

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

472:     Not Collective

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

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

480:     Level: advanced

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

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

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

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

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

507:     Not Collective

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

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

516:     Level: advanced

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

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

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

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

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

543:     Not Collective

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

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

551:     Level: advanced

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

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

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

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

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

578:     Not Collective

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

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

587:     Level: advanced

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

592:       Is ignored on anything but a binary viewer

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

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

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

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

616:     Not Collective

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

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

624:     Level: advanced

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

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

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

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

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

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

654:     Not Collective

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

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

662:     Level: advanced

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

805:    Collective

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

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

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

825:    Level: beginner

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

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

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

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

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

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

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

887:    Collective

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

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

898:    Level: beginner

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

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

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

927:    Collective

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

935:    Level: beginner

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

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

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

974:   PetscViewerSetUp(viewer);

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

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

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

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

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

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

1062:    Collective

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

1072:    Level: advanced

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

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

1085:    Collective

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

1095:    Level: advanced

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

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

1108:    Collective

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

1114:    Level: intermediate

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

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

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

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

1149:    Collective

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

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

1157:    Level: intermediate

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

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

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

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

1188:     Logically Collective on PetscViewer

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

1197:   Level: advanced

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

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

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

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

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

1224:     Not Collective

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

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

1235:   Level: advanced

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

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

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

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

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

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

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

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

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

1285:   vbinary->storecompressed = PETSC_FALSE;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1450:   Level: beginner

1452: M*/

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

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

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

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

1486:   vbinary->setfromoptionscalled = PETSC_FALSE;

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

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

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

1519:      Collective

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

1524:      Level: intermediate

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

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

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

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

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