Actual source code: binv.c

petsc-3.8.4 2018-03-24
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_Offset    moff;
 17: #endif
 18:   PetscFileMode btype;                /* read or write? */
 19:   FILE          *fdes_info;           /* optional file containing info on binary file*/
 20:   PetscBool     storecompressed;      /* gzip the write binary file when closing it*/
 21:   char          *filename;
 22:   char          *ogzfilename;         /* gzip can be run after the filename has been updated */
 23:   PetscBool     skipinfo;             /* Don't create info file for writing; don't use for reading */
 24:   PetscBool     skipoptions;          /* don't use PETSc options database when loading */
 25:   PetscInt      flowcontrol;          /* allow only <flowcontrol> messages outstanding at a time while doing IO */
 26:   PetscBool     skipheader;           /* don't write header, only raw data */
 27:   PetscBool     matlabheaderwritten;  /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
 28:   PetscBool     setfromoptionscalled;
 29: } PetscViewer_Binary;

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

 38:   PetscViewerSetUp(viewer);
 39:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
 40:   if (!rank) {
 41:     PetscViewerCreate(PETSC_COMM_SELF,outviewer);
 42:     PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);
 43:     obinary = (PetscViewer_Binary*)(*outviewer)->data;
 44:     PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));
 45:   } SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Cannot get subcomm viewer for binary files or sockets unless SubViewer contains the rank 0 process");
 46:   return(0);
 47: }

 49: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
 50: {
 52:   PetscErrorCode rank;

 55:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
 56:   if (!rank) {
 57:     PetscFree((*outviewer)->data);
 58:     PetscHeaderDestroy(outviewer);
 59:   }
 60:   return(0);
 61: }

 63: #if defined(PETSC_HAVE_MPIIO)
 64: /*@C
 65:     PetscViewerBinaryGetMPIIOOffset - Gets the current offset that should be passed to MPI_File_set_view()

 67:     Not Collective

 69:     Input Parameter:
 70: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

 72:     Output Parameter:
 73: .    off - the current offset

 75:     Level: advanced

 77:     Fortran Note:
 78:     This routine is not supported in Fortran.

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

 82:   Concepts: file descriptor^getting
 83:   Concepts: PetscViewerBinary^accessing file descriptor

 85: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryAddMPIIOOffset()
 86: @*/
 87: PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off)
 88: {
 89:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

 92:   *off = vbinary->moff;
 93:   return(0);
 94: }

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

 99:     Not Collective

101:     Input Parameters:
102: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
103: -    off - the addition to the offset

105:     Level: advanced

107:     Fortran Note:
108:     This routine is not supported in Fortran.

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

112:   Concepts: file descriptor^getting
113:   Concepts: PetscViewerBinary^accessing file descriptor

115: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
116: @*/
117: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)
118: {
119:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

122:   vbinary->moff += off;
123:   return(0);
124: }

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

129:     Not Collective

131:     Input Parameter:
132: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

134:     Output Parameter:
135: .   fdes - file descriptor

137:     Level: advanced

139:     Fortran Note:
140:     This routine is not supported in Fortran.

142:   Concepts: file descriptor^getting
143:   Concepts: PetscViewerBinary^accessing file descriptor

145: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
146: @*/
147: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
148: {
149:   PetscErrorCode     ierr;
150:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

153:   PetscViewerSetUp(viewer);
154:   *fdes = vbinary->mfdes;
155:   return(0);
156: }

158: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *flg)
159: {
160:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
161: 
163:   *flg = vbinary->usempiio;
164:   return(0);
165: }
166: #endif


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

172:     Not Collective

174:     Input Parameter:
175: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

177:     Output Parameter:
178: -   flg - PETSC_TRUE if MPI-IO is being used

180:     Options Database:
181:     -viewer_binary_mpiio : Flag for using MPI-IO

183:     Level: advanced

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

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(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
195: @*/
196: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *flg)
197: {

201:   *flg = PETSC_FALSE;
202:   PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,flg));
203:   return(0);
204: }

206: static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
207: {
208:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

211:   *fc = vbinary->flowcontrol;
212:   return(0);
213: }

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

218:     Not Collective

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

223:     Output Parameter:
224: .   fc - the number of messages

226:     Level: advanced

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

230: @*/
231: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
232: {

236:   PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));
237:   return(0);
238: }

240: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
241: {
242:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

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

253:     Not Collective

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

259:     Level: advanced

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

263: @*/
264: PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
265: {

269:   PetscUseMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));
270:   return(0);
271: }

273: /*@C
274:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

276:     Collective On PetscViewer

278:     Input Parameter:
279: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

281:     Output Parameter:
282: .   fdes - file descriptor

284:     Level: advanced

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

292:     Fortran Note:
293:     This routine is not supported in Fortran.

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


299:   Concepts: file descriptor^getting
300:   Concepts: PetscViewerBinary^accessing file descriptor

302: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
303: @*/
304: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
305: {
306:   PetscErrorCode     ierr;
307:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

310:   PetscViewerSetUp(viewer);
311:   *fdes = vbinary->fdes;
312:   return(0);
313: }

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

318:     Not Collective

320:     Input Paramter:
321: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

323:     Options Database Key:
324: .   -viewer_binary_skip_info

326:     Level: advanced

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

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

335:    Concepts: PetscViewerBinary^accessing info file

337: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
338:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
339: @*/
340: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
341: {
342:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

345:   vbinary->skipinfo = PETSC_TRUE;
346:   return(0);
347: }

349: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
350: {
351:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

354:   vbinary->skipinfo = skip;
355:   return(0);
356: }

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

361:     Not Collective

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

366:     Options Database Key:
367: .   -viewer_binary_skip_info

369:     Level: advanced

371:     Concepts: PetscViewerBinary^accessing info file

373: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
374:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
375: @*/
376: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
377: {

381:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));
382:   return(0);
383: }

385: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
386: {
387:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

390:   *skip  = vbinary->skipinfo;
391:   return(0);
392: }

394: /*@
395:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

397:     Not Collective

399:     Input Parameter:
400: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

402:     Output Parameter:
403: .   skip - PETSC_TRUE implies the .info file was not generated

405:     Level: advanced

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

409:     Concepts: PetscViewerBinary^accessing info file

411: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
412:           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
413: @*/
414: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
415: {

419:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));
420:   return(0);
421: }

423: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
424: {
425:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

428:   vbinary->skipoptions = skip;
429:   return(0);
430: }

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

435:     Not Collective

437:     Input Parameters:
438: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
439: -   skip - PETSC_TRUE means do not use

441:     Options Database Key:
442: .   -viewer_binary_skip_options

444:     Level: advanced

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

448:    Concepts: PetscViewerBinary^accessing info file

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

458:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));
459:   return(0);
460: }

462: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
463: {
464:   PetscViewer_Binary *vbinary;

468:   vbinary = (PetscViewer_Binary*)viewer->data;
469:   *skip   = vbinary->skipoptions;
470:   return(0);
471: }

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

476:     Not Collective

478:     Input Parameter:
479: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

481:     Output Parameter:
482: .   skip - PETSC_TRUE means do not use

484:     Level: advanced

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

488:    Concepts: PetscViewerBinary^accessing info file

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

498:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));
499:   return(0);
500: }

502: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
503: {
504:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

507:   vbinary->skipheader = skip;
508:   return(0);
509: }

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

514:     Not Collective

516:     Input Parameters:
517: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
518: -   skip - PETSC_TRUE means do not write header

520:     Options Database Key:
521: .   -viewer_binary_skip_header

523:     Level: advanced

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

527:            Can ONLY be called on a binary viewer

529: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
530:           PetscViewerBinaryGetSkipHeader()
531: @*/
532: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
533: {

537:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));
538:   return(0);
539: }

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

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

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

553:     Not Collective

555:     Input Parameter:
556: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

558:     Output Parameter:
559: .   skip - PETSC_TRUE means do not write header

561:     Level: advanced

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

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

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

575:   *skip = PETSC_FALSE;
576:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));
577:   return(0);
578: }

580: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
581: {
582:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
583:   PetscErrorCode     ierr;
584:   MPI_Comm           comm;

587:   PetscViewerSetUp(viewer);
588:   *file = vbinary->fdes_info;
589:   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
590:     vbinary->matlabheaderwritten = PETSC_TRUE;
591:     PetscObjectGetComm((PetscObject)viewer,&comm);
592:     PetscFPrintf(comm,*file,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
593:     PetscFPrintf(comm,*file,"#$$ Set.filename = '%s';\n",vbinary->filename);
594:     PetscFPrintf(comm,*file,"#$$ fd = PetscOpenFile(Set.filename);\n");
595:     PetscFPrintf(comm,*file,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
596:   }
597:   return(0);
598: }

600: /*@C
601:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
602:           info file associated with a binary file.

604:     Not Collective

606:     Input Parameter:
607: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

609:     Output Parameter:
610: .   file - file pointer  Always returns NULL if not a binary viewer

612:     Level: advanced

614:     Notes:
615:       For writable binary PetscViewers, the descriptor will only be valid for the
616:     first processor in the communicator that shares the PetscViewer.

618:     Fortran Note:
619:     This routine is not supported in Fortran.

621:   Concepts: PetscViewerBinary^accessing info file

623: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
624: @*/
625: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
626: {

630:   *file = NULL;
631:   PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));
632:   return(0);
633: }

635: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
636: {
637:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
638:   PetscErrorCode     ierr;
639:   PetscMPIInt        rank;
640:   int                err;

643:   MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);
644:   if ((!rank || vbinary->btype == FILE_MODE_READ) && vbinary->fdes) {
645:     close(vbinary->fdes);
646:     if (!rank && vbinary->storecompressed) {
647:       char par[PETSC_MAX_PATH_LEN],buf[PETSC_MAX_PATH_LEN];
648:       FILE *fp;
649:       /* compress the file */
650:       PetscStrcpy(par,"gzip -f ");
651:       PetscStrcat(par,vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename);
652:       PetscFree(vbinary->ogzfilename);
653: #if defined(PETSC_HAVE_POPEN)
654:       PetscPOpen(PETSC_COMM_SELF,NULL,par,"r",&fp);
655:       if (fgets(buf,1024,fp)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error from command %s\n%s",par,buf);
656:       PetscPClose(PETSC_COMM_SELF,fp,NULL);
657: #else
658:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Cannot run external programs on this machine");
659: #endif
660:     }
661:   }
662:   if (vbinary->fdes_info) {
663:     err = fclose(vbinary->fdes_info);
664:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
665:   }
666:   return(0);
667: }

669: #if defined(PETSC_HAVE_MPIIO)
670: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
671: {
672:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
673:   int                err;
674:   PetscErrorCode     ierr;

677:   if (vbinary->mfdes) {
678:     MPI_File_close(&vbinary->mfdes);
679:   }
680:   if (vbinary->fdes_info) {
681:     err = fclose(vbinary->fdes_info);
682:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
683:   }
684:   return(0);
685: }
686: #endif

688: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
689: {
690:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
691:   PetscErrorCode     ierr;

694:   if (v->format == PETSC_VIEWER_BINARY_MATLAB) {
695:     MPI_Comm comm;
696:     FILE     *info;

698:     PetscObjectGetComm((PetscObject)v,&comm);
699:     PetscViewerBinaryGetInfoPointer(v,&info);
700:     PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
701:     PetscFPrintf(comm,info,"#$$ close(fd);\n");
702:     PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
703:   }
704: #if defined(PETSC_HAVE_MPIIO)
705:   if (vbinary->usempiio) {
706:     PetscViewerFileClose_BinaryMPIIO(v);
707:   } else {
708: #endif
709:     PetscViewerFileClose_Binary(v);
710: #if defined(PETSC_HAVE_MPIIO)
711:   }
712: #endif
713:   PetscFree(vbinary->filename);
714:   PetscFree(vbinary->ogzfilename);
715:   PetscFree(vbinary);
716:   return(0);
717: }

719: /*@C
720:    PetscViewerBinaryOpen - Opens a file for binary input/output.

722:    Collective on MPI_Comm

724:    Input Parameters:
725: +  comm - MPI communicator
726: .  name - name of file
727: -  type - type of file
728: $    FILE_MODE_WRITE - create new file for binary output
729: $    FILE_MODE_READ - open existing file for binary input
730: $    FILE_MODE_APPEND - open existing file for binary output

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

735:     Options Database Keys:
736: +    -viewer_binary_filename <name>
737: .    -viewer_binary_skip_info
738: .    -viewer_binary_skip_options
739: .    -viewer_binary_skip_header
740: -    -viewer_binary_mpiio

742:    Level: beginner

744:    Note:
745:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

753:     For writing files it only opens the file on processor 0 in the communicator.
754:     For readable files it opens the file on all nodes that have the file. If
755:     node 0 does not have the file it generates an error even if other nodes
756:     do have the file.

758:    Concepts: binary files
759:    Concepts: PetscViewerBinary^creating
760:    Concepts: gzip
761:    Concepts: accessing remote file
762:    Concepts: remote file

764: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
765:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
766:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
767:           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
768: @*/
769: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
770: {

774:   PetscViewerCreate(comm,binv);
775:   PetscViewerSetType(*binv,PETSCVIEWERBINARY);
776:   PetscViewerFileSetMode(*binv,type);
777:   PetscViewerFileSetName(*binv,name);
778:   PetscViewerSetFromOptions(*binv);
779:   return(0);
780: }

782: #if defined(PETSC_HAVE_MPIIO)
783: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype,PetscBool write)
784: {
785:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
786:   PetscErrorCode     ierr;
787:   MPI_Datatype       mdtype;
788:   PetscMPIInt        cnt;
789:   MPI_Status         status;
790:   MPI_Aint           ul,dsize;

793:   PetscMPIIntCast(num,&cnt);
794:   PetscDataTypeToMPIDataType(dtype,&mdtype);
795:   MPI_File_set_view(vbinary->mfdes,vbinary->moff,mdtype,mdtype,(char*)"native",MPI_INFO_NULL);
796:   if (write) {
797:     MPIU_File_write_all(vbinary->mfdes,data,cnt,mdtype,&status);
798:   } else {
799:     MPIU_File_read_all(vbinary->mfdes,data,cnt,mdtype,&status);
800:   }
801:   MPI_Type_get_extent(mdtype,&ul,&dsize);

803:   vbinary->moff += dsize*cnt;
804:   if (count) *count = num;
805:   return(0);
806: }
807: #endif

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

812:    Collective on MPI_Comm

814:    Input Parameters:
815: +  viewer - the binary viewer
816: .  data - location of the data to be written
817: .  num - number of items of data to read
818: -  dtype - type of data to read

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

823:    Level: beginner

825:    Concepts: binary files

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

829: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
830:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
831:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
832: @*/
833: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer,void *data,PetscInt num,PetscInt *count,PetscDataType dtype)
834: {
835:   PetscErrorCode     ierr;
836:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

838:   PetscViewerSetUp(viewer);
839: #if defined(PETSC_HAVE_MPIIO)
840:   if (vbinary->usempiio) {
841:     PetscViewerBinaryWriteReadMPIIO(viewer,data,num,count,dtype,PETSC_FALSE);
842:   } else {
843: #endif
844:     PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,num,dtype);
845:     if (count) *count = num;
846: #if defined(PETSC_HAVE_MPIIO)
847:   }
848: #endif
849:   return(0);
850: }

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

855:    Collective on MPI_Comm

857:    Input Parameters:
858: +  viewer - the binary viewer
859: .  data - location of data
860: .  count - number of items of data to write
861: .  dtype - type of data to write
862: -  istemp - data may be overwritten

864:    Level: beginner

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

868:    Concepts: binary files

870: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
871:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(), PetscDataType
872:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
873: @*/
874: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer,void *data,PetscInt count,PetscDataType dtype,PetscBool istemp)
875: {
876:   PetscErrorCode     ierr;
877:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

880:   PetscViewerSetUp(viewer);
881: #if defined(PETSC_HAVE_MPIIO)
882:   if (vbinary->usempiio) {
883:     PetscViewerBinaryWriteReadMPIIO(viewer,data,count,NULL,dtype,PETSC_TRUE);
884:   } else {
885: #endif
886:     PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype,istemp);
887: #if defined(PETSC_HAVE_MPIIO)
888:   }
889: #endif
890:   return(0);
891: }

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

896:    Collective on MPI_Comm

898:    Input Parameters:
899: +  viewer - the binary viewer
900: -  data - location of the array of strings


903:    Level: intermediate

905:    Concepts: binary files

907:     Notes: array of strings is null terminated

909: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
910:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
911:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
912: @*/
913: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data)
914: {
916:   PetscInt       i,n = 0,*sizes;

918:   PetscViewerSetUp(viewer);
919:   /* count number of strings */
920:   while (data[n++]) ;
921:   n--;
922:   PetscMalloc1(n+1,&sizes);
923:   sizes[0] = n;
924:   for (i=0; i<n; i++) {
925:     size_t tmp;
926:     PetscStrlen(data[i],&tmp);
927:     sizes[i+1] = tmp + 1;   /* size includes space for the null terminator */
928:   }
929:   PetscViewerBinaryWrite(viewer,sizes,n+1,PETSC_INT,PETSC_FALSE);
930:   for (i=0; i<n; i++) {
931:     PetscViewerBinaryWrite(viewer,(void*)data[i],sizes[i+1],PETSC_CHAR,PETSC_FALSE);
932:   }
933:   PetscFree(sizes);
934:   return(0);
935: }

937: /*@C
938:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

940:    Collective on MPI_Comm

942:    Input Parameter:
943: .  viewer - the binary viewer

945:    Output Parameter:
946: .  data - location of the array of strings

948:    Level: intermediate

950:    Concepts: binary files

952:     Notes: array of strings is null terminated

954: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
955:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
956:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
957: @*/
958: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
959: {
961:   PetscInt       i,n,*sizes,N = 0;

963:   PetscViewerSetUp(viewer);
964:   /* count number of strings */
965:   PetscViewerBinaryRead(viewer,&n,1,NULL,PETSC_INT);
966:   PetscMalloc1(n,&sizes);
967:   PetscViewerBinaryRead(viewer,sizes,n,NULL,PETSC_INT);
968:   for (i=0; i<n; i++) N += sizes[i];
969:   PetscMalloc((n+1)*sizeof(char*) + N*sizeof(char),data);
970:   (*data)[0] = (char*)((*data) + n + 1);
971:   for (i=1; i<n; i++) (*data)[i] = (*data)[i-1] + sizes[i-1];
972:   PetscViewerBinaryRead(viewer,(*data)[0],N,NULL,PETSC_CHAR);

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

976:   PetscFree(sizes);
977:   return(0);
978: }

980: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
981: {
982:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

985:   *name = vbinary->filename;
986:   return(0);
987: }

989: /*@C
990:      PetscViewerFileGetMode - Gets the type of file to be open

992:     Not Collective

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

997:   Output Parameter:
998: .  type - type of file
999: $    FILE_MODE_WRITE - create new file for binary output
1000: $    FILE_MODE_READ - open existing file for binary input
1001: $    FILE_MODE_APPEND - open existing file for binary output

1003:   Level: advanced

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

1007: @*/
1008: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
1009: {

1015:   PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));
1016:   return(0);
1017: }

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

1023:     Logically Collective on PetscViewer

1025:     Input Parameters:
1026: +   viewer - the PetscViewer; must be a binary
1027: -   flg - PETSC_TRUE means MPI-IO will be used

1029:     Options Database:
1030:     -viewer_binary_mpiio : Flag for using MPI-IO

1032:     Level: advanced

1034: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
1035:           PetscViewerBinaryGetUseMPIIO()

1037: @*/
1038: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool flg)
1039: {

1044:   PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,flg));
1045:   return(0);
1046: }

1048: /*@C
1049:      PetscViewerFileSetMode - Sets the type of file to be open

1051:     Logically Collective on PetscViewer

1053:   Input Parameters:
1054: +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1055: -  type - type of file
1056: $    FILE_MODE_WRITE - create new file for binary output
1057: $    FILE_MODE_READ - open existing file for binary input
1058: $    FILE_MODE_APPEND - open existing file for binary output

1060:   Level: advanced

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

1064: @*/
1065: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
1066: {

1072:   PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));
1073:   return(0);
1074: }

1076: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
1077: {
1078:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1081:   *type = vbinary->btype;
1082:   return(0);
1083: }

1085: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
1086: {
1087:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1090:   vbinary->btype = type;
1091:   return(0);
1092: }

1094: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1095: {
1096:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1097:   PetscErrorCode     ierr;

1100:   if (vbinary->filename) {
1101:     /* gzip can be run after the file with the previous filename has been closed */
1102:     PetscFree(vbinary->ogzfilename);
1103:     PetscStrallocpy(vbinary->filename,&vbinary->ogzfilename);
1104:     PetscFree(vbinary->filename);
1105:     viewer->setupcalled = PETSC_FALSE;
1106:   }
1107:   PetscStrallocpy(name,&vbinary->filename);
1108:   return(0);
1109: }
1110: /*
1111:         Actually opens the file
1112: */
1113: static PetscErrorCode PetscViewerFileSetUp_Binary(PetscViewer viewer)
1114: {
1115:   PetscMPIInt        rank;
1116:   PetscErrorCode     ierr;
1117:   size_t             len;
1118:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1119:   const char         *fname;
1120:   char               bname[PETSC_MAX_PATH_LEN],*gz;
1121:   PetscBool          found;
1122:   PetscFileMode      type = vbinary->btype;

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

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

1131:   /* if ends in .gz strip that off and note user wants file compressed */
1132:   vbinary->storecompressed = PETSC_FALSE;
1133:   if (!rank && type == FILE_MODE_WRITE) {
1134:     /* remove .gz if it ends library name */
1135:     PetscStrstr(vbinary->filename,".gz",&gz);
1136:     if (gz) {
1137:       PetscStrlen(gz,&len);
1138:       if (len == 3) {
1139:         *gz = 0;
1140:         vbinary->storecompressed = PETSC_TRUE;
1141:       }
1142:     }
1143:   }

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

1148:     if (type == FILE_MODE_READ) {
1149:       /* possibly get the file from remote site or compressed file */
1150:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
1151:       fname = bname;
1152:       if (!rank && !found) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
1153:       else if (!found) {
1154:         PetscInfo(viewer,"Nonzero processor did not locate readonly file\n");
1155:         fname = 0;
1156:       }
1157:     } else fname = vbinary->filename;

1159: #if defined(PETSC_HAVE_O_BINARY)
1160:     if (type == FILE_MODE_WRITE) {
1161:       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);
1162:     } else if (type == FILE_MODE_READ && fname) {
1163:       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);
1164:     } else if (type == FILE_MODE_APPEND) {
1165:       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);
1166:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1167: #else
1168:     if (type == FILE_MODE_WRITE) {
1169:       if ((vbinary->fdes = creat(fname,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
1170:     } else if (type == FILE_MODE_READ && fname) {
1171:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
1172:     } else if (type == FILE_MODE_APPEND) {
1173:       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);
1174:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1175: #endif
1176:   } else vbinary->fdes = -1;

1178:   /*
1179:       try to open info file: all processors open this file if read only
1180:   */
1181:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1182:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

1184:     PetscStrcpy(infoname,vbinary->filename);
1185:     /* remove .gz if it ends library name */
1186:     PetscStrstr(infoname,".gz",&gz);
1187:     if (gz) {
1188:       PetscStrlen(gz,&len);
1189:       if (len == 3) *gz = 0;
1190:     }

1192:     PetscStrcat(infoname,".info");
1193:     PetscFixFilename(infoname,iname);
1194:     if (type == FILE_MODE_READ) {
1195:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
1196:       PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
1197:     } else {
1198:       vbinary->fdes_info = fopen(infoname,"w");
1199:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1200:     }
1201:   }
1202: #if defined(PETSC_USE_LOG)
1203:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1204: #endif
1205:   return(0);
1206: }

1208: #if defined(PETSC_HAVE_MPIIO)
1209: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1210: {
1211:   PetscMPIInt        rank;
1212:   PetscErrorCode     ierr;
1213:   size_t             len;
1214:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1215:   char               *gz;
1216:   PetscBool          found;
1217:   PetscFileMode      type = vbinary->btype;

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

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

1226:   vbinary->storecompressed = PETSC_FALSE;

1228:   /* only first processor opens file if writeable */
1229:   if (type == FILE_MODE_READ) {
1230:     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_RDONLY,MPI_INFO_NULL,&vbinary->mfdes);
1231:   } else if (type == FILE_MODE_WRITE) {
1232:     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_WRONLY | MPI_MODE_CREATE,MPI_INFO_NULL,&vbinary->mfdes);
1233:   }

1235:   /*
1236:       try to open info file: all processors open this file if read only

1238:       Below is identical code to the code for Binary above, should be put in separate routine
1239:   */
1240:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1241:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

1243:     PetscStrcpy(infoname,vbinary->filename);
1244:     /* remove .gz if it ends library name */
1245:     PetscStrstr(infoname,".gz",&gz);
1246:     if (gz) {
1247:       PetscStrlen(gz,&len);
1248:       if (len == 3) *gz = 0;
1249:     }

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

1267: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
1268: {
1269:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1271:   vbinary->usempiio = flg;
1272:   return(0);
1273: }
1274: #endif

1276: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1277: {
1278:   PetscErrorCode     ierr;
1279:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1282:   if (binary->filename) {
1283:     PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);
1284:   }
1285:   return(0);
1286: }

1288: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
1289: {
1290:   PetscErrorCode     ierr;
1291:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1294:   if (!binary->setfromoptionscalled) { PetscViewerSetFromOptions(v); }
1295: 
1296: #if defined(PETSC_HAVE_MPIIO)
1297:   if (binary->usempiio) {
1298:     PetscViewerFileSetUp_BinaryMPIIO(v);
1299:   } else {
1300: #endif
1301:     PetscViewerFileSetUp_Binary(v);
1302: #if defined(PETSC_HAVE_MPIIO)
1303:   }
1304: #endif
1305:   return(0);
1306: }

1308: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer v)
1309: {
1310:   PetscErrorCode     ierr;
1311:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1312:   char               defaultname[PETSC_MAX_PATH_LEN];
1313:   PetscBool          flg;

1316:   PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");
1317:   PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");
1318:   PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);
1319:   if (flg) { PetscViewerFileSetName_Binary(v,defaultname); }
1320:   PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",PETSC_FALSE,&binary->skipinfo,NULL);
1321:   PetscOptionsBool("-viewer_binary_skip_options","Skip parsing vec load options","PetscViewerBinarySetSkipOptions",PETSC_TRUE,&binary->skipoptions,NULL);
1322:   PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",PETSC_FALSE,&binary->skipheader,NULL);
1323: #if defined(PETSC_HAVE_MPIIO)
1324:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,&binary->usempiio,NULL);
1325: #elif defined(PETSC_HAVE_MPIUNI)
1326:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);
1327: #endif
1328:   PetscOptionsTail();
1329:   binary->setfromoptionscalled = PETSC_TRUE;
1330:   return(0);
1331: }

1333: /*MC
1334:    PETSCVIEWERBINARY - A viewer that saves to binary files


1337: .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
1338:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
1339:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
1340:            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()

1342:   Level: beginner

1344: M*/

1346: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1347: {
1348:   PetscErrorCode     ierr;
1349:   PetscViewer_Binary *vbinary;

1352:   PetscNewLog(v,&vbinary);
1353:   v->data                  = (void*)vbinary;
1354:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1355:   v->ops->destroy          = PetscViewerDestroy_Binary;
1356:   v->ops->view             = PetscViewerView_Binary;
1357:   v->ops->setup            = PetscViewerSetUp_Binary;
1358:   v->ops->flush            = NULL;
1359:   vbinary->fdes_info       = 0;
1360:   vbinary->fdes            = 0;
1361:   vbinary->skipinfo        = PETSC_FALSE;
1362:   vbinary->skipoptions     = PETSC_TRUE;
1363:   vbinary->skipheader      = PETSC_FALSE;
1364:   vbinary->setfromoptionscalled = PETSC_FALSE;
1365:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1366:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1367:   v->ops->read             = PetscViewerBinaryRead;
1368:   vbinary->btype           = (PetscFileMode) -1;
1369:   vbinary->storecompressed = PETSC_FALSE;
1370:   vbinary->filename        = NULL;
1371:   vbinary->ogzfilename     = NULL;
1372:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

1374:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Binary);
1375:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetFlowControl_C",PetscViewerBinarySetFlowControl_Binary);
1376:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Binary);
1377:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Binary);
1378:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipOptions_C",PetscViewerBinaryGetSkipOptions_Binary);
1379:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipOptions_C",PetscViewerBinarySetSkipOptions_Binary);
1380:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipInfo_C",PetscViewerBinaryGetSkipInfo_Binary);
1381:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipInfo_C",PetscViewerBinarySetSkipInfo_Binary);
1382:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetInfoPointer_C",PetscViewerBinaryGetInfoPointer_Binary);
1383:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_Binary);
1384:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_Binary);
1385:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_Binary);
1386:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_Binary);
1387: #if defined(PETSC_HAVE_MPIIO)
1388:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetUseMPIIO_C",PetscViewerBinaryGetUseMPIIO_Binary);
1389:   PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetUseMPIIO_C",PetscViewerBinarySetUseMPIIO_Binary);
1390: #endif
1391:   return(0);
1392: }

1394: /* ---------------------------------------------------------------------*/
1395: /*
1396:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1397:   is attached to a communicator, in this case the attribute is a PetscViewer.
1398: */
1399: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

1401: /*@C
1402:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1403:                      in a communicator.

1405:      Collective on MPI_Comm

1407:      Input Parameter:
1408: .    comm - the MPI communicator to share the binary PetscViewer

1410:      Level: intermediate

1412:    Options Database Keys:
1413: +    -viewer_binary_filename <name>
1414: .    -viewer_binary_skip_info
1415: .    -viewer_binary_skip_options
1416: .    -viewer_binary_skip_header
1417: -    -viewer_binary_mpiio

1419:    Environmental variables:
1420: -   PETSC_VIEWER_BINARY_FILENAME

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

1427: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1428:           PetscViewerDestroy()
1429: @*/
1430: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1431: {
1433:   PetscBool      flg;
1434:   PetscViewer    viewer;
1435:   char           fname[PETSC_MAX_PATH_LEN];
1436:   MPI_Comm       ncomm;

1439:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1440:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1441:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
1442:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1443:   }
1444:   MPI_Attr_get(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
1445:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1446:   if (!flg) { /* PetscViewer not yet created */
1447:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1448:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1449:     if (!flg) {
1450:       PetscStrcpy(fname,"binaryoutput");
1451:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1452:     }
1453:     PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
1454:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1455:     PetscObjectRegisterDestroy((PetscObject)viewer);
1456:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1457:     MPI_Attr_put(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1458:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1459:   }
1460:   PetscCommDestroy(&ncomm);
1461:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1462:   PetscFunctionReturn(viewer);
1463: }