Actual source code: binv.c

petsc-3.7.7 2017-09-25
Report Typos and Errors
  2: #include <petsc/private/viewerimpl.h>    /*I   "petscviewer.h"   I*/
  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:   PetscBool     skipinfo;             /* Don't create info file for writing; don't use for reading */
 23:   PetscBool     skipoptions;          /* don't use PETSc options database when loading */
 24:   PetscInt      flowcontrol;          /* allow only <flowcontrol> messages outstanding at a time while doing IO */
 25:   PetscBool     skipheader;           /* don't write header, only raw data */
 26:   PetscBool     matlabheaderwritten;  /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
 27:   PetscBool     setfromoptionscalled;
 28: } PetscViewer_Binary;

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

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

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

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

 66: #if defined(PETSC_HAVE_MPIIO)
 69: /*@C
 70:     PetscViewerBinaryGetMPIIOOffset - Gets the current offset that should be passed to MPI_File_set_view()

 72:     Not Collective

 74:     Input Parameter:
 75: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

 77:     Output Parameter:
 78: .    off - the current offset

 80:     Level: advanced

 82:     Fortran Note:
 83:     This routine is not supported in Fortran.

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

 87:   Concepts: file descriptor^getting
 88:   Concepts: PetscViewerBinary^accessing file descriptor

 90: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
 91: @*/
 92: PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer,MPI_Offset *off)
 93: {
 94:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

 97:   *off = vbinary->moff;
 98:   return(0);
 99: }

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

106:     Not Collective

108:     Input Parameters:
109: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
110: -    off - the addition to the offset

112:     Level: advanced

114:     Fortran Note:
115:     This routine is not supported in Fortran.

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

119:   Concepts: file descriptor^getting
120:   Concepts: PetscViewerBinary^accessing file descriptor

122: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
123: @*/
124: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer,MPI_Offset off)
125: {
126:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

129:   vbinary->moff += off;
130:   return(0);
131: }

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

138:     Not Collective

140:     Input Parameter:
141: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

143:     Output Parameter:
144: .   fdes - file descriptor

146:     Level: advanced

148:     Fortran Note:
149:     This routine is not supported in Fortran.

151:   Concepts: file descriptor^getting
152:   Concepts: PetscViewerBinary^accessing file descriptor

154: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
155: @*/
156: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
157: {
158:   PetscErrorCode     ierr;
159:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

162:   PetscViewerSetUp(viewer);
163:   *fdes = vbinary->mfdes;
164:   return(0);
165: }

169: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *flg)
170: {
171:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
172: 
174:   *flg = vbinary->usempiio;
175:   return(0);
176: }
177: #endif


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

185:     Not Collective

187:     Input Parameter:
188: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

190:     Output Parameter:
191: -   flg - PETSC_TRUE if MPI-IO is being used

193:     Options Database:
194:     -viewer_binary_mpiio : Flag for using MPI-IO

196:     Level: advanced

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

201:     Fortran Note:
202:     This routine is not supported in Fortran.

204:   Concepts: file descriptor^getting
205:   Concepts: PetscViewerBinary^accessing file descriptor

207: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer()
208: @*/
209: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *flg)
210: {

214:   *flg = PETSC_FALSE;
215:   PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,flg));
216:   return(0);
217: }

221: static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
222: {
223:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

226:   *fc = vbinary->flowcontrol;
227:   return(0);
228: }

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

235:     Not Collective

237:     Input Parameter:
238: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

240:     Output Parameter:
241: .   fc - the number of messages

243:     Level: advanced

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

247: @*/
248: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
249: {

253:   PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));
254:   return(0);
255: }

259: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
260: {
261:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

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

274:     Not Collective

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

280:     Level: advanced

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

284: @*/
285: PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
286: {

290:   PetscUseMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));
291:   return(0);
292: }

296: /*@C
297:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

299:     Collective On PetscViewer

301:     Input Parameter:
302: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

304:     Output Parameter:
305: .   fdes - file descriptor

307:     Level: advanced

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

315:     Fortran Note:
316:     This routine is not supported in Fortran.

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


322:   Concepts: file descriptor^getting
323:   Concepts: PetscViewerBinary^accessing file descriptor

325: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
326: @*/
327: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
328: {
329:   PetscErrorCode     ierr;
330:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

333:   PetscViewerSetUp(viewer);
334:   *fdes = vbinary->fdes;
335:   return(0);
336: }

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

343:     Not Collective

345:     Input Paramter:
346: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

348:     Options Database Key:
349: .   -viewer_binary_skip_info

351:     Level: advanced

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

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

360:    Concepts: PetscViewerBinary^accessing info file

362: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
363:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
364: @*/
365: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
366: {
367:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

370:   vbinary->skipinfo = PETSC_TRUE;
371:   return(0);
372: }

376: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
377: {
378:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

381:   vbinary->skipinfo = skip;
382:   return(0);
383: }

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

390:     Not Collective

392:     Input Paramter:
393: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

395:     Options Database Key:
396: .   -viewer_binary_skip_info

398:     Level: advanced

400:     Concepts: PetscViewerBinary^accessing info file

402: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
403:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
404: @*/
405: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
406: {

410:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));
411:   return(0);
412: }

416: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
417: {
418:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

421:   *skip  = vbinary->skipinfo;
422:   return(0);
423: }

427: /*@
428:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

430:     Not Collective

432:     Input Parameter:
433: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

435:     Output Parameter:
436: .   skip - PETSC_TRUE implies the .info file was not generated

438:     Level: advanced

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

442:     Concepts: PetscViewerBinary^accessing info file

444: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
445:           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
446: @*/
447: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
448: {

452:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));
453:   return(0);
454: }

458: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
459: {
460:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

463:   vbinary->skipoptions = skip;
464:   return(0);
465: }

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

472:     Not Collective

474:     Input Parameters:
475: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
476: -   skip - PETSC_TRUE means do not use

478:     Options Database Key:
479: .   -viewer_binary_skip_options

481:     Level: advanced

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

485:    Concepts: PetscViewerBinary^accessing info file

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

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

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

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

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

517:     Not Collective

519:     Input Parameter:
520: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

522:     Output Parameter:
523: .   skip - PETSC_TRUE means do not use

525:     Level: advanced

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

529:    Concepts: PetscViewerBinary^accessing info file

531: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
532:           PetscViewerBinarySetSkipOptions()
533: @*/
534: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
535: {

539:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));
540:   return(0);
541: }

545: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
546: {
547:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

550:   vbinary->skipheader = skip;
551:   return(0);
552: }

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

559:     Not Collective

561:     Input Parameters:
562: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
563: -   skip - PETSC_TRUE means do not write header

565:     Options Database Key:
566: .   -viewer_binary_skip_header

568:     Level: advanced

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

572:            Can ONLY be called on a binary viewer

574: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
575:           PetscViewerBinaryGetSkipHeader()
576: @*/
577: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
578: {

582:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));
583:   return(0);
584: }

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

593:   *skip = vbinary->skipheader;
594:   return(0);
595: }

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

602:     Not Collective

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

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

610:     Level: advanced

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

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

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

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

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

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

653: /*@C
654:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
655:           info file associated with a binary file.

657:     Not Collective

659:     Input Parameter:
660: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

662:     Output Parameter:
663: .   file - file pointer  Always returns NULL if not a binary viewer

665:     Level: advanced

667:     Notes:
668:       For writable binary PetscViewers, the descriptor will only be valid for the
669:     first processor in the communicator that shares the PetscViewer.

671:     Fortran Note:
672:     This routine is not supported in Fortran.

674:   Concepts: PetscViewerBinary^accessing info file

676: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
677: @*/
678: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
679: {

683:   *file = NULL;
684:   PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));
685:   return(0);
686: }

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

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

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

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

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

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

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

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

781:    Collective on MPI_Comm

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

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

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

801:    Level: beginner

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

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

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

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

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

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

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

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

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

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

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

874:    Collective on MPI_Comm

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

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

885:    Level: beginner

887:    Concepts: binary files

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

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

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

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

919:    Collective on MPI_Comm

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

928:    Level: beginner

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

932:    Concepts: binary files

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

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

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

962:    Collective on MPI_Comm

964:    Input Parameters:
965: +  viewer - the binary viewer
966: -  data - location of the array of strings


969:    Level: intermediate

971:    Concepts: binary files

973:     Notes: array of strings is null terminated

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

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

1005: /*@C
1006:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

1008:    Collective on MPI_Comm

1010:    Input Parameter:
1011: .  viewer - the binary viewer

1013:    Output Parameter:
1014: .  data - location of the array of strings

1016:    Level: intermediate

1018:    Concepts: binary files

1020:     Notes: array of strings is null terminated

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

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

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

1044:   PetscFree(sizes);
1045:   return(0);
1046: }

1050: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
1051: {
1052:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1055:   *name = vbinary->filename;
1056:   return(0);
1057: }

1061: /*@C
1062:      PetscViewerFileGetMode - Gets the type of file to be open

1064:     Not Collective

1066:   Input Parameter:
1067: .  viewer - the PetscViewer; must be a binary, MATLAB, hdf, or netcdf PetscViewer

1069:   Output Parameter:
1070: .  type - type of file
1071: $    FILE_MODE_WRITE - create new file for binary output
1072: $    FILE_MODE_READ - open existing file for binary input
1073: $    FILE_MODE_APPEND - open existing file for binary output

1075:   Level: advanced

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

1079: @*/
1080: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
1081: {

1087:   PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));
1088:   return(0);
1089: }

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

1097:     Logically Collective on PetscViewer

1099:     Input Parameters:
1100: +   viewer - the PetscViewer; must be a binary
1101: -   flg - PETSC_TRUE means MPI-IO will be used

1103:     Options Database:
1104:     -viewer_binary_mpiio : Flag for using MPI-IO

1106:     Level: advanced

1108: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
1109:           PetscViewerBinaryGetUseMPIIO()

1111: @*/
1112: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool flg)
1113: {

1118:   PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,flg));
1119:   return(0);
1120: }

1124: /*@C
1125:      PetscViewerFileSetMode - Sets the type of file to be open

1127:     Logically Collective on PetscViewer

1129:   Input Parameters:
1130: +  viewer - the PetscViewer; must be a binary, Matlab, hdf, or netcdf PetscViewer
1131: -  type - type of file
1132: $    FILE_MODE_WRITE - create new file for binary output
1133: $    FILE_MODE_READ - open existing file for binary input
1134: $    FILE_MODE_APPEND - open existing file for binary output

1136:   Level: advanced

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

1140: @*/
1141: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
1142: {

1148:   PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));
1149:   return(0);
1150: }

1154: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
1155: {
1156:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1159:   *type = vbinary->btype;
1160:   return(0);
1161: }

1165: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
1166: {
1167:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1170:   vbinary->btype = type;
1171:   return(0);
1172: }

1176: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1177: {
1178:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1179:   PetscErrorCode     ierr;
1180: 
1182:   if (vbinary->filename) { PetscFree(vbinary->filename); }
1183:   PetscStrallocpy(name,&vbinary->filename);
1184:   return(0);
1185: }
1186: /*
1187:         Actually opens the file
1188: */
1191: static PetscErrorCode PetscViewerFileSetUp_Binary(PetscViewer viewer)
1192: {
1193:   PetscMPIInt        rank;
1194:   PetscErrorCode     ierr;
1195:   size_t             len;
1196:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1197:   const char         *fname;
1198:   char               bname[PETSC_MAX_PATH_LEN],*gz;
1199:   PetscBool          found;
1200:   PetscFileMode      type = vbinary->btype;

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

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

1209:   /* if ends in .gz strip that off and note user wants file compressed */
1210:   vbinary->storecompressed = PETSC_FALSE;
1211:   if (!rank && type == FILE_MODE_WRITE) {
1212:     /* remove .gz if it ends library name */
1213:     PetscStrstr(vbinary->filename,".gz",&gz);
1214:     if (gz) {
1215:       PetscStrlen(gz,&len);
1216:       if (len == 3) {
1217:         *gz = 0;
1218:         vbinary->storecompressed = PETSC_TRUE;
1219:       }
1220:     }
1221:   }

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

1226:     if (type == FILE_MODE_READ) {
1227:       /* possibly get the file from remote site or compressed file */
1228:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),vbinary->filename,bname,PETSC_MAX_PATH_LEN,&found);
1229:       fname = bname;
1230:       if (!rank && !found) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot locate file: %s on node zero",vbinary->filename);
1231:       else if (!found) {
1232:         PetscInfo(viewer,"Nonzero processor did not locate readonly file\n");
1233:         fname = 0;
1234:       }
1235:     } else fname = vbinary->filename;

1237: #if defined(PETSC_HAVE_O_BINARY)
1238:     if (type == FILE_MODE_WRITE) {
1239:       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);
1240:     } else if (type == FILE_MODE_READ && fname) {
1241:       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);
1242:     } else if (type == FILE_MODE_APPEND) {
1243:       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);
1244:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1245: #else
1246:     if (type == FILE_MODE_WRITE) {
1247:       if ((vbinary->fdes = creat(fname,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file %s for writing",fname);
1248:     } else if (type == FILE_MODE_READ && fname) {
1249:       if ((vbinary->fdes = open(fname,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file %s for reading",fname);
1250:     } else if (type == FILE_MODE_APPEND) {
1251:       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);
1252:     } else if (fname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
1253: #endif
1254:   } else vbinary->fdes = -1;

1256:   /*
1257:       try to open info file: all processors open this file if read only
1258:   */
1259:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1260:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

1262:     PetscStrcpy(infoname,vbinary->filename);
1263:     /* remove .gz if it ends library name */
1264:     PetscStrstr(infoname,".gz",&gz);
1265:     if (gz) {
1266:       PetscStrlen(gz,&len);
1267:       if (len == 3) *gz = 0;
1268:     }

1270:     PetscStrcat(infoname,".info");
1271:     PetscFixFilename(infoname,iname);
1272:     if (type == FILE_MODE_READ) {
1273:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
1274:       PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
1275:     } else {
1276:       vbinary->fdes_info = fopen(infoname,"w");
1277:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1278:     }
1279:   }
1280: #if defined(PETSC_USE_LOG)
1281:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1282: #endif
1283:   return(0);
1284: }

1286: #if defined(PETSC_HAVE_MPIIO)
1289: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1290: {
1291:   PetscMPIInt        rank;
1292:   PetscErrorCode     ierr;
1293:   size_t             len;
1294:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1295:   char               *gz;
1296:   PetscBool          found;
1297:   PetscFileMode      type = vbinary->btype;

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

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

1306:   vbinary->storecompressed = PETSC_FALSE;

1308:   /* only first processor opens file if writeable */
1309:   if (type == FILE_MODE_READ) {
1310:     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_RDONLY,MPI_INFO_NULL,&vbinary->mfdes);
1311:   } else if (type == FILE_MODE_WRITE) {
1312:     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_WRONLY | MPI_MODE_CREATE,MPI_INFO_NULL,&vbinary->mfdes);
1313:   }

1315:   /*
1316:       try to open info file: all processors open this file if read only

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

1323:     PetscStrcpy(infoname,vbinary->filename);
1324:     /* remove .gz if it ends library name */
1325:     PetscStrstr(infoname,".gz",&gz);
1326:     if (gz) {
1327:       PetscStrlen(gz,&len);
1328:       if (len == 3) *gz = 0;
1329:     }

1331:     PetscStrcat(infoname,".info");
1332:     PetscFixFilename(infoname,iname);
1333:     if (type == FILE_MODE_READ) {
1334:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer),iname,infoname,PETSC_MAX_PATH_LEN,&found);
1335:       PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer),((PetscObject)viewer)->options,infoname,PETSC_FALSE);
1336:     } else {
1337:       vbinary->fdes_info = fopen(infoname,"w");
1338:       if (!vbinary->fdes_info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open .info file %s for writing",infoname);
1339:     }
1340:   }
1341: #if defined(PETSC_USE_LOG)
1342:   PetscLogObjectState((PetscObject)viewer,"File: %s",vbinary->filename);
1343: #endif
1344:   return(0);
1345: }

1349: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
1350: {
1351:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1353:   vbinary->usempiio = flg;
1354:   return(0);
1355: }
1356: #endif

1360: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1361: {
1362:   PetscErrorCode     ierr;
1363:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1366:   if (binary->filename) {
1367:     PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);
1368:   }
1369:   return(0);
1370: }

1374: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
1375: {
1376:   PetscErrorCode     ierr;
1377:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1380:   if (!binary->setfromoptionscalled) { PetscViewerSetFromOptions(v); }
1381: 
1382: #if defined(PETSC_HAVE_MPIIO)
1383:   if (binary->usempiio) {
1384:     PetscViewerFileSetUp_BinaryMPIIO(v);
1385:   } else {
1386: #endif
1387:     PetscViewerFileSetUp_Binary(v);
1388: #if defined(PETSC_HAVE_MPIIO)
1389:   }
1390: #endif
1391:   return(0);
1392: }

1396: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer v)
1397: {
1398:   PetscErrorCode     ierr;
1399:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1400:   char               defaultname[PETSC_MAX_PATH_LEN];
1401:   PetscBool          flg;

1404:   PetscOptionsHead(PetscOptionsObject,"Binary PetscViewer Options");
1405:   PetscSNPrintf(defaultname,PETSC_MAX_PATH_LEN-1,"binaryoutput");
1406:   PetscOptionsString("-viewer_binary_filename","Specify filename","PetscViewerFileSetName",defaultname,defaultname,PETSC_MAX_PATH_LEN-1,&flg);
1407:   if (flg) { PetscViewerFileSetName_Binary(v,defaultname); }
1408:   PetscOptionsBool("-viewer_binary_skip_info","Skip writing/reading .info file","PetscViewerBinarySetSkipInfo",PETSC_FALSE,&binary->skipinfo,NULL);
1409:   PetscOptionsBool("-viewer_binary_skip_options","Skip parsing vec load options","PetscViewerBinarySetSkipOptions",PETSC_TRUE,&binary->skipoptions,NULL);
1410:   PetscOptionsBool("-viewer_binary_skip_header","Skip writing/reading header information","PetscViewerBinarySetSkipHeader",PETSC_FALSE,&binary->skipheader,NULL);
1411: #if defined(PETSC_HAVE_MPIIO)
1412:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,&binary->usempiio,NULL);
1413: #elif defined(PETSC_HAVE_MPIUNI)
1414:   PetscOptionsBool("-viewer_binary_mpiio","Use MPI-IO functionality to write/read binary file","PetscViewerBinarySetUseMPIIO",PETSC_FALSE,NULL,NULL);
1415: #endif
1416:   PetscOptionsTail();
1417:   binary->setfromoptionscalled = PETSC_TRUE;
1418:   return(0);
1419: }

1423: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1424: {
1425:   PetscErrorCode     ierr;
1426:   PetscViewer_Binary *vbinary;

1429:   PetscNewLog(v,&vbinary);
1430:   v->data                  = (void*)vbinary;
1431:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1432:   v->ops->destroy          = PetscViewerDestroy_Binary;
1433:   v->ops->view             = PetscViewerView_Binary;
1434:   v->ops->setup            = PetscViewerSetUp_Binary;
1435:   v->ops->flush            = NULL;
1436:   vbinary->fdes_info       = 0;
1437:   vbinary->fdes            = 0;
1438:   vbinary->skipinfo        = PETSC_FALSE;
1439:   vbinary->skipoptions     = PETSC_TRUE;
1440:   vbinary->skipheader      = PETSC_FALSE;
1441:   vbinary->setfromoptionscalled = PETSC_FALSE;
1442:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1443:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1444:   v->ops->read             = PetscViewerBinaryRead;
1445:   vbinary->btype           = (PetscFileMode) -1;
1446:   vbinary->storecompressed = PETSC_FALSE;
1447:   vbinary->filename        = 0;
1448:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

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

1470: /* ---------------------------------------------------------------------*/
1471: /*
1472:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1473:   is attached to a communicator, in this case the attribute is a PetscViewer.
1474: */
1475: static int Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

1479: /*@C
1480:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1481:                      in a communicator.

1483:      Collective on MPI_Comm

1485:      Input Parameter:
1486: .    comm - the MPI communicator to share the binary PetscViewer

1488:      Level: intermediate

1490:    Options Database Keys:
1491: +    -viewer_binary_filename <name>
1492: .    -viewer_binary_skip_info
1493: .    -viewer_binary_skip_options
1494: .    -viewer_binary_skip_header
1495: -    -viewer_binary_mpiio

1497:    Environmental variables:
1498: -   PETSC_VIEWER_BINARY_FILENAME

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

1505: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1506:           PetscViewerDestroy()
1507: @*/
1508: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1509: {
1511:   PetscBool      flg;
1512:   PetscViewer    viewer;
1513:   char           fname[PETSC_MAX_PATH_LEN];
1514:   MPI_Comm       ncomm;

1517:   PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1518:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1519:     MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Binary_keyval,0);
1520:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1521:   }
1522:   MPI_Attr_get(ncomm,Petsc_Viewer_Binary_keyval,(void**)&viewer,(int*)&flg);
1523:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1524:   if (!flg) { /* PetscViewer not yet created */
1525:     PetscOptionsGetenv(ncomm,"PETSC_VIEWER_BINARY_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
1526:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1527:     if (!flg) {
1528:       PetscStrcpy(fname,"binaryoutput");
1529:       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1530:     }
1531:     PetscViewerBinaryOpen(ncomm,fname,FILE_MODE_WRITE,&viewer);
1532:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1533:     PetscObjectRegisterDestroy((PetscObject)viewer);
1534:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1535:     MPI_Attr_put(ncomm,Petsc_Viewer_Binary_keyval,(void*)viewer);
1536:     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1537:   }
1538:   PetscCommDestroy(&ncomm);
1539:   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_BINARY_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");return(0);}
1540:   PetscFunctionReturn(viewer);
1541: }