Actual source code: binv.c

petsc-master 2017-12-14
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: #if defined(PETSC_HAVE_MPIIO)
 40:   if (vbinary->usempiio) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Not yet implemented for binary viewers using MPI I/O");
 41: #endif
 42:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);
 43:   if (!rank) {
 44:     PetscViewerCreate(PETSC_COMM_SELF,outviewer);
 45:     PetscViewerSetType(*outviewer,PETSCVIEWERBINARY);
 46:     obinary = (PetscViewer_Binary*)(*outviewer)->data;
 47:     PetscMemcpy(obinary,vbinary,sizeof(PetscViewer_Binary));
 48:   } else {
 49:     *outviewer = NULL;
 50:   }
 51:   return(0);
 52: }

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

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

 68: #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(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryAddMPIIOOffset()
 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: }

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

104:     Not Collective

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

110:     Level: advanced

112:     Fortran Note:
113:     This routine is not supported in Fortran.

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

117:   Concepts: file descriptor^getting
118:   Concepts: PetscViewerBinary^accessing file descriptor

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

127:   vbinary->moff += off;
128:   return(0);
129: }

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

134:     Not Collective

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

139:     Output Parameter:
140: .   fdes - file descriptor

142:     Level: advanced

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

147:   Concepts: file descriptor^getting
148:   Concepts: PetscViewerBinary^accessing file descriptor

150: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer(), PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
151: @*/
152: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer,MPI_File *fdes)
153: {
154:   PetscErrorCode     ierr;
155:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

158:   PetscViewerSetUp(viewer);
159:   *fdes = vbinary->mfdes;
160:   return(0);
161: }

163: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer,PetscBool  *flg)
164: {
165:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
166: 
168:   *flg = vbinary->usempiio;
169:   return(0);
170: }
171: #endif


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

177:     Not Collective

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

182:     Output Parameter:
183: -   flg - PETSC_TRUE if MPI-IO is being used

185:     Options Database:
186:     -viewer_binary_mpiio : Flag for using MPI-IO

188:     Level: advanced

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

193:     Fortran Note:
194:     This routine is not supported in Fortran.

196:   Concepts: file descriptor^getting
197:   Concepts: PetscViewerBinary^accessing file descriptor

199: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetInfoPointer(), PetscViewerBinarySetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
200: @*/
201: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer,PetscBool *flg)
202: {

206:   *flg = PETSC_FALSE;
207:   PetscTryMethod(viewer,"PetscViewerBinaryGetUseMPIIO_C",(PetscViewer,PetscBool*),(viewer,flg));
208:   return(0);
209: }

211: static PetscErrorCode  PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer,PetscInt *fc)
212: {
213:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

216:   *fc = vbinary->flowcontrol;
217:   return(0);
218: }

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

223:     Not Collective

225:     Input Parameter:
226: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

228:     Output Parameter:
229: .   fc - the number of messages

231:     Level: advanced

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

235: @*/
236: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer,PetscInt *fc)
237: {

241:   PetscUseMethod(viewer,"PetscViewerBinaryGetFlowControl_C",(PetscViewer,PetscInt*),(viewer,fc));
242:   return(0);
243: }

245: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer,PetscInt fc)
246: {
247:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

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

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

258:     Not Collective

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

264:     Level: advanced

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

268: @*/
269: PetscErrorCode  PetscViewerBinarySetFlowControl(PetscViewer viewer,PetscInt fc)
270: {

274:   PetscUseMethod(viewer,"PetscViewerBinarySetFlowControl_C",(PetscViewer,PetscInt),(viewer,fc));
275:   return(0);
276: }

278: /*@C
279:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a PetscViewer.

281:     Collective On PetscViewer

283:     Input Parameter:
284: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

286:     Output Parameter:
287: .   fdes - file descriptor

289:     Level: advanced

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

297:     Fortran Note:
298:     This routine is not supported in Fortran.

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


304:   Concepts: file descriptor^getting
305:   Concepts: PetscViewerBinary^accessing file descriptor

307: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetInfoPointer()
308: @*/
309: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer,int *fdes)
310: {
311:   PetscErrorCode     ierr;
312:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

315:   PetscViewerSetUp(viewer);
316:   *fdes = vbinary->fdes;
317:   return(0);
318: }

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

323:     Not Collective

325:     Input Paramter:
326: .   viewer - PetscViewer context, obtained from PetscViewerCreate()

328:     Options Database Key:
329: .   -viewer_binary_skip_info

331:     Level: advanced

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

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

340:    Concepts: PetscViewerBinary^accessing info file

342: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
343:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
344: @*/
345: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
346: {
347:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

350:   vbinary->skipinfo = PETSC_TRUE;
351:   return(0);
352: }

354: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer,PetscBool skip)
355: {
356:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

359:   vbinary->skipinfo = skip;
360:   return(0);
361: }

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

366:     Not Collective

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

371:     Options Database Key:
372: .   -viewer_binary_skip_info

374:     Level: advanced

376:     Concepts: PetscViewerBinary^accessing info file

378: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySetSkipOptions(),
379:           PetscViewerBinaryGetSkipOptions(), PetscViewerBinaryGetSkipInfo()
380: @*/
381: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer,PetscBool skip)
382: {

386:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipInfo_C",(PetscViewer,PetscBool),(viewer,skip));
387:   return(0);
388: }

390: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer,PetscBool *skip)
391: {
392:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

395:   *skip  = vbinary->skipinfo;
396:   return(0);
397: }

399: /*@
400:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

402:     Not Collective

404:     Input Parameter:
405: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

407:     Output Parameter:
408: .   skip - PETSC_TRUE implies the .info file was not generated

410:     Level: advanced

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

414:     Concepts: PetscViewerBinary^accessing info file

416: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
417:           PetscViewerBinarySetSkipOptions(), PetscViewerBinarySetSkipInfo()
418: @*/
419: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer,PetscBool *skip)
420: {

424:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipInfo_C",(PetscViewer,PetscBool*),(viewer,skip));
425:   return(0);
426: }

428: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer,PetscBool skip)
429: {
430:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

433:   vbinary->skipoptions = skip;
434:   return(0);
435: }

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

440:     Not Collective

442:     Input Parameters:
443: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
444: -   skip - PETSC_TRUE means do not use

446:     Options Database Key:
447: .   -viewer_binary_skip_options

449:     Level: advanced

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

453:    Concepts: PetscViewerBinary^accessing info file

455: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
456:           PetscViewerBinaryGetSkipOptions()
457: @*/
458: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer,PetscBool skip)
459: {

463:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipOptions_C",(PetscViewer,PetscBool),(viewer,skip));
464:   return(0);
465: }

467: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer,PetscBool *skip)
468: {
469:   PetscViewer_Binary *vbinary;

473:   vbinary = (PetscViewer_Binary*)viewer->data;
474:   *skip   = vbinary->skipoptions;
475:   return(0);
476: }

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

481:     Not Collective

483:     Input Parameter:
484: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

486:     Output Parameter:
487: .   skip - PETSC_TRUE means do not use

489:     Level: advanced

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

493:    Concepts: PetscViewerBinary^accessing info file

495: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
496:           PetscViewerBinarySetSkipOptions()
497: @*/
498: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer,PetscBool *skip)
499: {

503:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipOptions_C",(PetscViewer,PetscBool*),(viewer,skip));
504:   return(0);
505: }

507: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer,PetscBool skip)
508: {
509:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

512:   vbinary->skipheader = skip;
513:   return(0);
514: }

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

519:     Not Collective

521:     Input Parameters:
522: +   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()
523: -   skip - PETSC_TRUE means do not write header

525:     Options Database Key:
526: .   -viewer_binary_skip_header

528:     Level: advanced

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

532:            Can ONLY be called on a binary viewer

534: .seealso: PetscViewerBinaryOpen(), PetscViewerBinaryGetDescriptor(), PetscViewerBinarySkipInfo(),
535:           PetscViewerBinaryGetSkipHeader()
536: @*/
537: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer,PetscBool skip)
538: {

542:   PetscUseMethod(viewer,"PetscViewerBinarySetSkipHeader_C",(PetscViewer,PetscBool),(viewer,skip));
543:   return(0);
544: }

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

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

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

558:     Not Collective

560:     Input Parameter:
561: .   viewer - PetscViewer context, obtained from PetscViewerBinaryOpen()

563:     Output Parameter:
564: .   skip - PETSC_TRUE means do not write header

566:     Level: advanced

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

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

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

580:   *skip = PETSC_FALSE;
581:   PetscUseMethod(viewer,"PetscViewerBinaryGetSkipHeader_C",(PetscViewer,PetscBool*),(viewer,skip));
582:   return(0);
583: }

585: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer,FILE **file)
586: {
587:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
588:   PetscErrorCode     ierr;
589:   MPI_Comm           comm;

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

605: /*@C
606:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
607:           info file associated with a binary file.

609:     Not Collective

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

614:     Output Parameter:
615: .   file - file pointer  Always returns NULL if not a binary viewer

617:     Level: advanced

619:     Notes:
620:       For writable binary PetscViewers, the descriptor will only be valid for the
621:     first processor in the communicator that shares the PetscViewer.

623:     Fortran Note:
624:     This routine is not supported in Fortran.

626:   Concepts: PetscViewerBinary^accessing info file

628: .seealso: PetscViewerBinaryOpen(),PetscViewerBinaryGetDescriptor()
629: @*/
630: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer,FILE **file)
631: {

635:   *file = NULL;
636:   PetscTryMethod(viewer,"PetscViewerBinaryGetInfoPointer_C",(PetscViewer,FILE **),(viewer,file));
637:   return(0);
638: }

640: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
641: {
642:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
643:   PetscErrorCode     ierr;
644:   PetscMPIInt        rank;
645:   int                err;

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

674: #if defined(PETSC_HAVE_MPIIO)
675: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
676: {
677:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
678:   int                err;
679:   PetscErrorCode     ierr;

682:   if (vbinary->mfdes) {
683:     MPI_File_close(&vbinary->mfdes);
684:   }
685:   if (vbinary->fdes_info) {
686:     err = fclose(vbinary->fdes_info);
687:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
688:   }
689:   return(0);
690: }
691: #endif

693: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
694: {
695:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)v->data;
696:   PetscErrorCode     ierr;

699:   if (v->format == PETSC_VIEWER_BINARY_MATLAB) {
700:     MPI_Comm comm;
701:     FILE     *info;

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

724: /*@C
725:    PetscViewerBinaryOpen - Opens a file for binary input/output.

727:    Collective on MPI_Comm

729:    Input Parameters:
730: +  comm - MPI communicator
731: .  name - name of file
732: -  type - type of file
733: $    FILE_MODE_WRITE - create new file for binary output
734: $    FILE_MODE_READ - open existing file for binary input
735: $    FILE_MODE_APPEND - open existing file for binary output

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

740:     Options Database Keys:
741: +    -viewer_binary_filename <name>
742: .    -viewer_binary_skip_info
743: .    -viewer_binary_skip_options
744: .    -viewer_binary_skip_header
745: -    -viewer_binary_mpiio

747:    Level: beginner

749:    Note:
750:    This PetscViewer should be destroyed with PetscViewerDestroy().

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

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

758:     For writing files it only opens the file on processor 0 in the communicator.
759:     For readable files it opens the file on all nodes that have the file. If
760:     node 0 does not have the file it generates an error even if other nodes
761:     do have the file.

763:    Concepts: binary files
764:    Concepts: PetscViewerBinary^creating
765:    Concepts: gzip
766:    Concepts: accessing remote file
767:    Concepts: remote file

769: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
770:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
771:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscViewerBinaryRead(), PetscViewerBinarySetUseMPIIO(),
772:           PetscViewerBinaryGetUseMPIIO(), PetscViewerBinaryGetMPIIOOffset()
773: @*/
774: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm,const char name[],PetscFileMode type,PetscViewer *binv)
775: {

779:   PetscViewerCreate(comm,binv);
780:   PetscViewerSetType(*binv,PETSCVIEWERBINARY);
781:   PetscViewerFileSetMode(*binv,type);
782:   PetscViewerFileSetName(*binv,name);
783:   PetscViewerSetFromOptions(*binv);
784:   return(0);
785: }

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

798:   PetscMPIIntCast(num,&cnt);
799:   PetscDataTypeToMPIDataType(dtype,&mdtype);
800:   MPI_File_set_view(vbinary->mfdes,vbinary->moff,mdtype,mdtype,(char*)"native",MPI_INFO_NULL);
801:   if (write) {
802:     MPIU_File_write_all(vbinary->mfdes,data,cnt,mdtype,&status);
803:   } else {
804:     MPIU_File_read_all(vbinary->mfdes,data,cnt,mdtype,&status);
805:   }
806:   MPI_Type_get_extent(mdtype,&ul,&dsize);

808:   vbinary->moff += dsize*cnt;
809:   if (count) *count = num;
810:   return(0);
811: }
812: #endif

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

817:    Collective on MPI_Comm

819:    Input Parameters:
820: +  viewer - the binary viewer
821: .  data - location of the data to be written
822: .  num - number of items of data to read
823: -  dtype - type of data to read

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

828:    Level: beginner

830:    Concepts: binary files

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

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

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

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

860:    Collective on MPI_Comm

862:    Input Parameters:
863: +  viewer - the binary viewer
864: .  data - location of data
865: .  count - number of items of data to write
866: .  dtype - type of data to write
867: -  istemp - data may be overwritten

869:    Level: beginner

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

873:    Concepts: binary files

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

885:   PetscViewerSetUp(viewer);
886: #if defined(PETSC_HAVE_MPIIO)
887:   if (vbinary->usempiio) {
888:     PetscViewerBinaryWriteReadMPIIO(viewer,data,count,NULL,dtype,PETSC_TRUE);
889:   } else {
890: #endif
891:     PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer),vbinary->fdes,data,count,dtype,istemp);
892: #if defined(PETSC_HAVE_MPIIO)
893:   }
894: #endif
895:   return(0);
896: }

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

901:    Collective on MPI_Comm

903:    Input Parameters:
904: +  viewer - the binary viewer
905: -  data - location of the array of strings


908:    Level: intermediate

910:    Concepts: binary files

912:     Notes: array of strings is null terminated

914: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
915:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
916:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
917: @*/
918: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer,const char * const *data)
919: {
921:   PetscInt       i,n = 0,*sizes;

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

942: /*@C
943:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings

945:    Collective on MPI_Comm

947:    Input Parameter:
948: .  viewer - the binary viewer

950:    Output Parameter:
951: .  data - location of the array of strings

953:    Level: intermediate

955:    Concepts: binary files

957:     Notes: array of strings is null terminated

959: .seealso: PetscViewerASCIIOpen(), PetscViewerPushFormat(), PetscViewerDestroy(),
960:           VecView(), MatView(), VecLoad(), MatLoad(), PetscViewerBinaryGetDescriptor(),
961:           PetscViewerBinaryGetInfoPointer(), PetscFileMode, PetscViewer, PetscBinaryViewerRead()
962: @*/
963: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer,char ***data)
964: {
966:   PetscInt       i,n,*sizes,N = 0;

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

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

981:   PetscFree(sizes);
982:   return(0);
983: }

985: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer,const char **name)
986: {
987:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

990:   *name = vbinary->filename;
991:   return(0);
992: }

994: /*@C
995:      PetscViewerFileGetMode - Gets the type of file to be open

997:     Not Collective

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

1002:   Output Parameter:
1003: .  type - type of file
1004: $    FILE_MODE_WRITE - create new file for binary output
1005: $    FILE_MODE_READ - open existing file for binary input
1006: $    FILE_MODE_APPEND - open existing file for binary output

1008:   Level: advanced

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

1012: @*/
1013: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer,PetscFileMode *type)
1014: {

1020:   PetscUseMethod(viewer,"PetscViewerFileGetMode_C",(PetscViewer,PetscFileMode*),(viewer,type));
1021:   return(0);
1022: }

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

1028:     Logically Collective on PetscViewer

1030:     Input Parameters:
1031: +   viewer - the PetscViewer; must be a binary
1032: -   flg - PETSC_TRUE means MPI-IO will be used

1034:     Options Database:
1035:     -viewer_binary_mpiio : Flag for using MPI-IO

1037:     Level: advanced

1039: .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen(),
1040:           PetscViewerBinaryGetUseMPIIO()

1042: @*/
1043: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer,PetscBool flg)
1044: {

1049:   PetscTryMethod(viewer,"PetscViewerBinarySetUseMPIIO_C",(PetscViewer,PetscBool),(viewer,flg));
1050:   return(0);
1051: }

1053: /*@C
1054:      PetscViewerFileSetMode - Sets the type of file to be open

1056:     Logically Collective on PetscViewer

1058:   Input Parameters:
1059: +  viewer - the PetscViewer; must be a a PETSCVIEWERBINARY, PETSCVIEWERMATLAB, PETSCVIEWERHDF5, or PETSCVIEWERASCII  PetscViewer
1060: -  type - type of file
1061: $    FILE_MODE_WRITE - create new file for binary output
1062: $    FILE_MODE_READ - open existing file for binary input
1063: $    FILE_MODE_APPEND - open existing file for binary output

1065:   Level: advanced

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

1069: @*/
1070: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer,PetscFileMode type)
1071: {

1077:   PetscTryMethod(viewer,"PetscViewerFileSetMode_C",(PetscViewer,PetscFileMode),(viewer,type));
1078:   return(0);
1079: }

1081: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer,PetscFileMode *type)
1082: {
1083:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1086:   *type = vbinary->btype;
1087:   return(0);
1088: }

1090: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer,PetscFileMode type)
1091: {
1092:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;

1095:   vbinary->btype = type;
1096:   return(0);
1097: }

1099: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer,const char name[])
1100: {
1101:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1102:   PetscErrorCode     ierr;

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

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

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

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

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

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

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

1183:   /*
1184:       try to open info file: all processors open this file if read only
1185:   */
1186:   if (!vbinary->skipinfo && (!rank || type == FILE_MODE_READ)) {
1187:     char infoname[PETSC_MAX_PATH_LEN],iname[PETSC_MAX_PATH_LEN];

1189:     PetscStrcpy(infoname,vbinary->filename);
1190:     /* remove .gz if it ends library name */
1191:     PetscStrstr(infoname,".gz",&gz);
1192:     if (gz) {
1193:       PetscStrlen(gz,&len);
1194:       if (len == 3) *gz = 0;
1195:     }

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

1213: #if defined(PETSC_HAVE_MPIIO)
1214: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1215: {
1216:   PetscMPIInt        rank;
1217:   PetscErrorCode     ierr;
1218:   size_t             len;
1219:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1220:   char               *gz;
1221:   PetscBool          found;
1222:   PetscFileMode      type = vbinary->btype;

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

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

1231:   vbinary->storecompressed = PETSC_FALSE;

1233:   /* only first processor opens file if writeable */
1234:   if (type == FILE_MODE_READ) {
1235:     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_RDONLY,MPI_INFO_NULL,&vbinary->mfdes);
1236:   } else if (type == FILE_MODE_WRITE) {
1237:     MPI_File_open(PetscObjectComm((PetscObject)viewer),vbinary->filename,MPI_MODE_WRONLY | MPI_MODE_CREATE,MPI_INFO_NULL,&vbinary->mfdes);
1238:   }

1240:   /*
1241:       try to open info file: all processors open this file if read only

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

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

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

1272: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer,PetscBool flg)
1273: {
1274:   PetscViewer_Binary *vbinary = (PetscViewer_Binary*)viewer->data;
1276:   vbinary->usempiio = flg;
1277:   return(0);
1278: }
1279: #endif

1281: static PetscErrorCode PetscViewerView_Binary(PetscViewer v,PetscViewer viewer)
1282: {
1283:   PetscErrorCode     ierr;
1284:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1287:   if (binary->filename) {
1288:     PetscViewerASCIIPrintf(viewer,"Filename: %s\n",binary->filename);
1289:   }
1290:   return(0);
1291: }

1293: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer v)
1294: {
1295:   PetscErrorCode     ierr;
1296:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;

1299:   if (!binary->setfromoptionscalled) { PetscViewerSetFromOptions(v); }
1300: 
1301: #if defined(PETSC_HAVE_MPIIO)
1302:   if (binary->usempiio) {
1303:     PetscViewerFileSetUp_BinaryMPIIO(v);
1304:   } else {
1305: #endif
1306:     PetscViewerFileSetUp_Binary(v);
1307: #if defined(PETSC_HAVE_MPIIO)
1308:   }
1309: #endif
1310:   return(0);
1311: }

1313: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscOptionItems *PetscOptionsObject,PetscViewer v)
1314: {
1315:   PetscErrorCode     ierr;
1316:   PetscViewer_Binary *binary = (PetscViewer_Binary*)v->data;
1317:   char               defaultname[PETSC_MAX_PATH_LEN];
1318:   PetscBool          flg;

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

1338: /*MC
1339:    PETSCVIEWERBINARY - A viewer that saves to binary files


1342: .seealso:  PetscViewerBinaryOpen(), PETSC_VIEWER_STDOUT_(),PETSC_VIEWER_STDOUT_SELF, PETSC_VIEWER_STDOUT_WORLD, PetscViewerCreate(), PetscViewerASCIIOpen(),
1343:            PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, PETSCVIEWERDRAW,
1344:            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType(),
1345:            PetscViewerBinaryGetUseMPIIO(), PetscViewerBinarySetUseMPIIO()

1347:   Level: beginner

1349: M*/

1351: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1352: {
1353:   PetscErrorCode     ierr;
1354:   PetscViewer_Binary *vbinary;

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

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

1399: /* ---------------------------------------------------------------------*/
1400: /*
1401:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1402:   is attached to a communicator, in this case the attribute is a PetscViewer.
1403: */
1404: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

1406: /*@C
1407:      PETSC_VIEWER_BINARY_ - Creates a binary PetscViewer shared by all processors
1408:                      in a communicator.

1410:      Collective on MPI_Comm

1412:      Input Parameter:
1413: .    comm - the MPI communicator to share the binary PetscViewer

1415:      Level: intermediate

1417:    Options Database Keys:
1418: +    -viewer_binary_filename <name>
1419: .    -viewer_binary_skip_info
1420: .    -viewer_binary_skip_options
1421: .    -viewer_binary_skip_header
1422: -    -viewer_binary_mpiio

1424:    Environmental variables:
1425: -   PETSC_VIEWER_BINARY_FILENAME

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

1432: .seealso: PETSC_VIEWER_BINARY_WORLD, PETSC_VIEWER_BINARY_SELF, PetscViewerBinaryOpen(), PetscViewerCreate(),
1433:           PetscViewerDestroy()
1434: @*/
1435: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1436: {
1438:   PetscBool      flg;
1439:   PetscViewer    viewer;
1440:   char           fname[PETSC_MAX_PATH_LEN];
1441:   MPI_Comm       ncomm;

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