Actual source code: binv.c

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

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

 24: static PetscErrorCode PetscViewerBinaryClearFunctionList(PetscViewer v)
 25: {
 26:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", NULL);
 27:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", NULL);
 28:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", NULL);
 29:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", NULL);
 30:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", NULL);
 31:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", NULL);
 32:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", NULL);
 33:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", NULL);
 34:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", NULL);
 35:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", NULL);
 36:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", NULL);
 37:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", NULL);
 38:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", NULL);
 39: #if defined(PETSC_HAVE_MPIIO)
 40:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", NULL);
 41:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", NULL);
 42: #endif
 43:   return 0;
 44: }

 46: #if defined(PETSC_HAVE_MPIIO)
 47: static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer)
 48: {
 49:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

 51:   if (vbinary->filemode == FILE_MODE_READ) return 0;
 52:   if (vbinary->mfsub != MPI_FILE_NULL) MPI_File_sync(vbinary->mfsub);
 53:   if (vbinary->mfdes != MPI_FILE_NULL) {
 54:     MPI_Barrier(PetscObjectComm((PetscObject)viewer));
 55:     MPI_File_sync(vbinary->mfdes);
 56:   }
 57:   return 0;
 58: }
 59: #endif

 61: static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
 62: {
 63:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
 64:   PetscMPIInt         rank;

 66:   PetscViewerSetUp(viewer);

 68:   /* Return subviewer in process zero */
 69:   MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
 70:   if (rank == 0) {
 71:     PetscMPIInt flg;

 73:     MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg);
 75:     PetscViewerCreate(comm, outviewer);
 76:     PetscViewerSetType(*outviewer, PETSCVIEWERBINARY);
 77:     PetscMemcpy((*outviewer)->data, vbinary, sizeof(PetscViewer_Binary));
 78:     (*outviewer)->setupcalled = PETSC_TRUE;
 79:   } else {
 80:     *outviewer = NULL;
 81:   }

 83: #if defined(PETSC_HAVE_MPIIO)
 84:   if (vbinary->usempiio && *outviewer) {
 85:     PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
 86:     /* Parent viewer opens a new MPI file handle on PETSC_COMM_SELF and keeps track of it for future reuse */
 87:     if (vbinary->mfsub == MPI_FILE_NULL) {
 88:       int amode;
 89:       switch (vbinary->filemode) {
 90:       case FILE_MODE_READ:
 91:         amode = MPI_MODE_RDONLY;
 92:         break;
 93:       case FILE_MODE_WRITE:
 94:         amode = MPI_MODE_WRONLY;
 95:         break;
 96:       case FILE_MODE_APPEND:
 97:         amode = MPI_MODE_WRONLY;
 98:         break;
 99:       default:
100:         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vbinary->filemode]);
101:       }
102:       MPI_File_open(PETSC_COMM_SELF, vbinary->filename, amode, MPI_INFO_NULL, &vbinary->mfsub);
103:     }
104:     /* Subviewer gets the MPI file handle on PETSC_COMM_SELF */
105:     obinary->mfdes = vbinary->mfsub;
106:     obinary->mfsub = MPI_FILE_NULL;
107:     obinary->moff  = vbinary->moff;
108:   }
109: #endif

111: #if defined(PETSC_HAVE_MPIIO)
112:   PetscViewerBinarySyncMPIIO(viewer);
113: #endif
114:   return 0;
115: }

117: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
118: {
119:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
120:   PetscMPIInt         rank;
121: #if defined(PETSC_HAVE_MPIIO)
122:   MPI_Offset moff = 0;
123: #endif

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

128: #if defined(PETSC_HAVE_MPIIO)
129:   if (vbinary->usempiio && *outviewer) {
130:     PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
132:     if (obinary->mfsub != MPI_FILE_NULL) MPI_File_close(&obinary->mfsub);
133:     moff = obinary->moff;
134:   }
135: #endif

137:   if (*outviewer) {
138:     PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
140:     PetscFree((*outviewer)->data);
141:     PetscViewerBinaryClearFunctionList(*outviewer);
142:     PetscHeaderDestroy(outviewer);
143:   }

145: #if defined(PETSC_HAVE_MPIIO)
146:   if (vbinary->usempiio) {
147:     PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */
148:     MPI_Bcast(&ioff, 1, MPIU_INT64, 0, PetscObjectComm((PetscObject)viewer));
149:     vbinary->moff = (MPI_Offset)ioff;
150:   }
151: #endif

153: #if defined(PETSC_HAVE_MPIIO)
154:   PetscViewerBinarySyncMPIIO(viewer);
155: #endif
156:   return 0;
157: }

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

163:     Not Collective

165:     Input Parameter:
166: .   viewer - PetscViewer context, obtained from `PetscViewerBinaryOpen()`

168:     Output Parameter:
169: .   off - the current global offset

171:     Level: advanced

173:     Note:
174:     Use `PetscViewerBinaryAddMPIIOOffset()` to increase this value after you have written a view.

176:     Fortran Note:
177:     This routine is not supported in Fortran.

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

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

192: /*@C
193:     PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset

195:     Logically Collective

197:     Input Parameters:
198: +   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
199: -   off - the addition to the global offset

201:     Level: advanced

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

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

209: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
210: @*/
211: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer, MPI_Offset off)
212: {
213:   PetscViewer_Binary *vbinary;

217:   vbinary = (PetscViewer_Binary *)viewer->data;
218:   vbinary->moff += off;
219:   return 0;
220: }

222: /*@C
223:     PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a `PetscViewer`.

225:     Not Collective

227:     Input Parameter:
228: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

230:     Output Parameter:
231: .   fdes - file descriptor

233:     Level: advanced

235:     Fortran Note:
236:     This routine is not supported in Fortran.

238: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
239: @*/
240: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer, MPI_File *fdes)
241: {
242:   PetscViewer_Binary *vbinary;

246:   PetscViewerSetUp(viewer);
247:   vbinary = (PetscViewer_Binary *)viewer->data;
248:   *fdes   = vbinary->mfdes;
249:   return 0;
250: }
251: #endif

253: /*@
254:     PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
255:         before `PetscViewerFileSetName()`

257:     Logically Collective on viewer

259:     Input Parameters:
260: +   viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`
261: -   use - `PETSC_TRUE` means MPI-IO will be used

263:     Options Database Key:
264:     -viewer_binary_mpiio : Flag for using MPI-IO

266:     Level: advanced

268: .seealso: `PETSCVIEWERBINARY`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
269:           `PetscViewerBinaryGetUseMPIIO()`
270: @*/
271: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer, PetscBool use)
272: {
275:   PetscTryMethod(viewer, "PetscViewerBinarySetUseMPIIO_C", (PetscViewer, PetscBool), (viewer, use));
276:   return 0;
277: }

279: #if defined(PETSC_HAVE_MPIIO)
280: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer, PetscBool use)
281: {
282:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
284:   vbinary->usempiio = use;
285:   return 0;
286: }
287: #endif

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

292:     Not Collective

294:     Input Parameter:
295: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`; must be a `PETSCVIEWERBINARY`

297:     Output Parameter:
298: .   use - `PETSC_TRUE` if MPI-IO is being used

300:     Level: advanced

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

305: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
306: @*/
307: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer, PetscBool *use)
308: {
311:   *use = PETSC_FALSE;
312:   PetscTryMethod(viewer, "PetscViewerBinaryGetUseMPIIO_C", (PetscViewer, PetscBool *), (viewer, use));
313:   return 0;
314: }

316: #if defined(PETSC_HAVE_MPIIO)
317: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer, PetscBool *use)
318: {
319:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

321:   *use = vbinary->usempiio;
322:   return 0;
323: }
324: #endif

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

329:     Not Collective

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

335:     Level: advanced

337: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetFlowControl()`
338: @*/
339: PetscErrorCode PetscViewerBinarySetFlowControl(PetscViewer viewer, PetscInt fc)
340: {
343:   PetscTryMethod(viewer, "PetscViewerBinarySetFlowControl_C", (PetscViewer, PetscInt), (viewer, fc));
344:   return 0;
345: }

347: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer, PetscInt fc)
348: {
349:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

352:   vbinary->flowcontrol = fc;
353:   return 0;
354: }

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

359:     Not Collective

361:     Input Parameter:
362: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

364:     Output Parameter:
365: .   fc - the number of messages

367:     Level: advanced

369: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetFlowControl()`
370: @*/
371: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer, PetscInt *fc)
372: {
375:   PetscUseMethod(viewer, "PetscViewerBinaryGetFlowControl_C", (PetscViewer, PetscInt *), (viewer, fc));
376:   return 0;
377: }

379: static PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer, PetscInt *fc)
380: {
381:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

383:   *fc = vbinary->flowcontrol;
384:   return 0;
385: }

387: /*@C
388:     PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a `PetscViewer` of `PetscViewerType` `PETSCVIEWERBINARY`.

390:     Collective on viewer because it may trigger a `PetscViewerSetUp()` call

392:     Input Parameter:
393: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

395:     Output Parameter:
396: .   fdes - file descriptor

398:     Level: advanced

400:     Note:
401:       For writable binary `PetscViewer`s, the descriptor will only be valid for the
402:     first processor in the communicator that shares the `PetscViewer`. For readable
403:     files it will only be valid on nodes that have the file. If node 0 does not
404:     have the file it generates an error even if another node does have the file.

406:     Fortran Note:
407:     This routine is not supported in Fortran.

409: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`
410: @*/
411: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer, int *fdes)
412: {
413:   PetscViewer_Binary *vbinary;

417:   PetscViewerSetUp(viewer);
418:   vbinary = (PetscViewer_Binary *)viewer->data;
419:   *fdes   = vbinary->fdes;
420:   return 0;
421: }

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

426:     Not Collective

428:     Input Parameter:
429: .   viewer - `PetscViewer` context, obtained from `PetscViewerCreate()`

431:     Options Database Key:
432: .   -viewer_binary_skip_info - true indicates do not generate .info file

434:     Level: advanced

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

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

444:     This routine is deprecated, use `PetscViewerBinarySetSkipInfo()`

446: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
447:           `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
448: @*/
449: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
450: {
451:   PetscViewerBinarySetSkipInfo(viewer, PETSC_TRUE);
452:   return 0;
453: }

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

458:     Not Collective

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

464:     Options Database Key:
465: .   -viewer_binary_skip_info - true indicates do not generate .info file

467:     Level: advanced

469: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
470:           `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
471: @*/
472: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer, PetscBool skip)
473: {
476:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipInfo_C", (PetscViewer, PetscBool), (viewer, skip));
477:   return 0;
478: }

480: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer, PetscBool skip)
481: {
482:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

484:   vbinary->skipinfo = skip;
485:   return 0;
486: }

488: /*@
489:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

491:     Not Collective

493:     Input Parameter:
494: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

496:     Output Parameter:
497: .   skip - `PETSC_TRUE` implies the .info file was not generated

499:     Level: advanced

501:     Note:
502:     This must be called after `PetscViewerSetType()`

504: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`,
505:           `PetscViewerBinarySetSkipOptions()`, `PetscViewerBinarySetSkipInfo()`
506: @*/
507: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer, PetscBool *skip)
508: {
511:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipInfo_C", (PetscViewer, PetscBool *), (viewer, skip));
512:   return 0;
513: }

515: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer, PetscBool *skip)
516: {
517:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

519:   *skip = vbinary->skipinfo;
520:   return 0;
521: }

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

526:     Not Collective

528:     Input Parameters:
529: +   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
530: -   skip - `PETSC_TRUE` means do not use the options from the options database

532:     Options Database Key:
533: .   -viewer_binary_skip_options <true or false> - true means do not use the options from the options database

535:     Level: advanced

537:     Note:
538:     This must be called after `PetscViewerSetType()`

540: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
541:           `PetscViewerBinaryGetSkipOptions()`
542: @*/
543: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer, PetscBool skip)
544: {
547:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipOptions_C", (PetscViewer, PetscBool), (viewer, skip));
548:   return 0;
549: }

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

555:   vbinary->skipoptions = skip;
556:   return 0;
557: }

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

562:     Not Collective

564:     Input Parameter:
565: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

567:     Output Parameter:
568: .   skip - `PETSC_TRUE` means do not use

570:     Level: advanced

572:     Note:
573:     This must be called after `PetscViewerSetType()`

575: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
576:           `PetscViewerBinarySetSkipOptions()`
577: @*/
578: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer, PetscBool *skip)
579: {
582:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipOptions_C", (PetscViewer, PetscBool *), (viewer, skip));
583:   return 0;
584: }

586: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer, PetscBool *skip)
587: {
588:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

590:   *skip = vbinary->skipoptions;
591:   return 0;
592: }

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

597:     Not Collective

599:     Input Parameters:
600: +   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
601: -   skip - `PETSC_TRUE `means do not write header

603:     Options Database Key:
604: .   -viewer_binary_skip_header <true or false> - true means do not write header

606:     Level: advanced

608:     Notes:
609:       This must be called after `PetscViewerSetType()`

611:       Is ignored on anything but a binary viewer

613: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
614:           `PetscViewerBinaryGetSkipHeader()`
615: @*/
616: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer, PetscBool skip)
617: {
620:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipHeader_C", (PetscViewer, PetscBool), (viewer, skip));
621:   return 0;
622: }

624: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer, PetscBool skip)
625: {
626:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

628:   vbinary->skipheader = skip;
629:   return 0;
630: }

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

635:     Not Collective

637:     Input Parameter:
638: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

640:     Output Parameter:
641: .   skip - `PETSC_TRUE` means do not write header

643:     Level: advanced

645:     Notes:
646:     This must be called after PetscViewerSetType()

648:     Returns `PETSC_FALSE` for `PETSCSOCKETVIEWER`, you cannot skip the header for it.

650: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
651:           `PetscViewerBinarySetSkipHeader()`
652: @*/
653: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer, PetscBool *skip)
654: {
657:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipHeader_C", (PetscViewer, PetscBool *), (viewer, skip));
658:   return 0;
659: }

661: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer, PetscBool *skip)
662: {
663:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

665:   *skip = vbinary->skipheader;
666:   return 0;
667: }

669: /*@C
670:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
671:           info file associated with a binary file.

673:     Not Collective

675:     Input Parameter:
676: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

678:     Output Parameter:
679: .   file - file pointer  Always returns NULL if not a binary viewer

681:     Level: advanced

683:     Note:
684:       For writable binary `PetscViewer`s, the file pointer will only be valid for the
685:     first processor in the communicator that shares the `PetscViewer`.

687:     Fortran Note:
688:     This routine is not supported in Fortran.

690: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`
691: @*/
692: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer, FILE **file)
693: {
696:   *file = NULL;
697:   PetscTryMethod(viewer, "PetscViewerBinaryGetInfoPointer_C", (PetscViewer, FILE **), (viewer, file));
698:   return 0;
699: }

701: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer, FILE **file)
702: {
703:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

705:   PetscViewerSetUp(viewer);
706:   *file = vbinary->fdes_info;
707:   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
708:     if (vbinary->fdes_info) {
709:       FILE *info = vbinary->fdes_info;
710:       PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
711:       PetscFPrintf(PETSC_COMM_SELF, info, "#$$ Set.filename = '%s';\n", vbinary->filename);
712:       PetscFPrintf(PETSC_COMM_SELF, info, "#$$ fd = PetscOpenFile(Set.filename);\n");
713:       PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
714:     }
715:     vbinary->matlabheaderwritten = PETSC_TRUE;
716:   }
717:   return 0;
718: }

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

725:   if (vbinary->mfdes != MPI_FILE_NULL) MPI_File_close(&vbinary->mfdes);
726:   if (vbinary->mfsub != MPI_FILE_NULL) MPI_File_close(&vbinary->mfsub);
727:   vbinary->moff = 0;
728:   return 0;
729: }
730: #endif

732: static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
733: {
734:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

736:   if (vbinary->fdes != -1) {
737:     PetscBinaryClose(vbinary->fdes);
738:     vbinary->fdes = -1;
739:     if (vbinary->storecompressed) {
740:       char        cmd[8 + PETSC_MAX_PATH_LEN], out[64 + PETSC_MAX_PATH_LEN] = "";
741:       const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
742:       /* compress the file */
743:       PetscStrncpy(cmd, "gzip -f ", sizeof(cmd));
744:       PetscStrlcat(cmd, gzfilename, sizeof(cmd));
745: #if defined(PETSC_HAVE_POPEN)
746:       {
747:         FILE *fp;
748:         PetscPOpen(PETSC_COMM_SELF, NULL, cmd, "r", &fp);
750:         PetscPClose(PETSC_COMM_SELF, fp);
751:       }
752: #endif
753:     }
754:   }
755:   PetscFree(vbinary->ogzfilename);
756:   return 0;
757: }

759: static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
760: {
761:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

763:   if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
764:     if (vbinary->fdes_info) {
765:       FILE *info = vbinary->fdes_info;
766:       PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
767:       PetscFPrintf(PETSC_COMM_SELF, info, "#$$ close(fd);\n");
768:       PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
769:     }
770:   }
771:   if (vbinary->fdes_info) {
772:     FILE *info         = vbinary->fdes_info;
773:     vbinary->fdes_info = NULL;
775:   }
776:   return 0;
777: }

779: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
780: {
781: #if defined(PETSC_HAVE_MPIIO)
782:   PetscViewerFileClose_BinaryMPIIO(v);
783: #endif
784:   PetscViewerFileClose_BinarySTDIO(v);
785:   PetscViewerFileClose_BinaryInfo(v);
786:   return 0;
787: }

789: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
790: {
791:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

793:   PetscViewerFileClose_Binary(v);
794:   PetscFree(vbinary->filename);
795:   PetscFree(vbinary);
796:   PetscViewerBinaryClearFunctionList(v);
797:   return 0;
798: }

800: /*@C
801:    PetscViewerBinaryOpen - Opens a file for binary input/output.

803:    Collective

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

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

816:     Options Database Keys:
817: +    -viewer_binary_filename <name> - name of file to use
818: .    -viewer_binary_skip_info - true to skip opening an info file
819: .    -viewer_binary_skip_options - true to not use options database while creating viewer
820: .    -viewer_binary_skip_header - true to skip output object headers to the file
821: -    -viewer_binary_mpiio - true to use MPI-IO for input and output to the file (more scalable for large problems)

823:    Level: beginner

825:    Note:
826:    This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.

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

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

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

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

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

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

883:    Collective

885:    Input Parameters:
886: +  viewer - the binary viewer
887: .  data - location of the data to be written
888: .  num - number of items of data to read
889: -  dtype - type of data to read

891:    Output Parameters:
892: .  count - number of items of data actually read, or NULL.

894:    Level: beginner

896: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
897:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
898:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
899: @*/
900: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
901: {
902:   PetscViewer_Binary *vbinary;

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

920: /*@C
921:    PetscViewerBinaryWrite - writes to a binary file, only from the first MPI rank

923:    Collective

925:    Input Parameters:
926: +  viewer - the binary viewer
927: .  data - location of data
928: .  count - number of items of data to write
929: -  dtype - type of data to write

931:    Level: beginner

933: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
934:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, `PetscDataType`
935:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
936: @*/
937: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer, const void *data, PetscInt count, PetscDataType dtype)
938: {
939:   PetscViewer_Binary *vbinary;

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

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

970:   PetscViewerSetUp(viewer);

972:   PetscDataTypeToMPIDataType(dtype, &mdtype);
973:   MPI_Type_get_extent(mdtype, &lb, &dsize);
974:   MPI_Comm_rank(comm, &rank);
975:   MPI_Comm_size(comm, &size);

977:   PetscViewerBinaryGetUseMPIIO(viewer, &useMPIIO);
978: #if defined(PETSC_HAVE_MPIIO)
979:   if (useMPIIO) {
980:     MPI_File    mfdes;
981:     MPI_Offset  off;
982:     PetscMPIInt cnt;

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

1013:     PetscCommGetNewTag(comm, &tag);
1014:     MPI_Reduce(&tcount, &maxcount, 1, MPIU_INT, MPI_MAX, 0, comm);
1015:     PetscMPIIntCast(maxcount, &maxcnt);
1016:     PetscMPIIntCast(count, &cnt);

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

1055: /*@C
1056:    PetscViewerBinaryReadAll - reads from a binary file from all MPI ranks, each rank receives its own portion of the data

1058:    Collective

1060:    Input Parameters:
1061: +  viewer - the binary viewer
1062: .  data - location of data
1063: .  count - local number of items of data to read
1064: .  start - local start, can be `PETSC_DETERMINE`
1065: .  total - global number of items of data to read, can be `PETSC_DETERMINE`
1066: -  dtype - type of data to read

1068:    Level: advanced

1070: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteAll()`
1071: @*/
1072: PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1073: {
1074:   PetscViewerBinaryWriteReadAll(viewer, PETSC_FALSE, data, count, start, total, dtype);
1075:   return 0;
1076: }

1078: /*@C
1079:    PetscViewerBinaryWriteAll - writes to a binary file from all MPI ranks, each rank writes its own portion of the data

1081:    Collective

1083:    Input Parameters:
1084: +  viewer - the binary viewer
1085: .  data - location of data
1086: .  count - local number of items of data to write
1087: .  start - local start, can be `PETSC_DETERMINE`
1088: .  total - global number of items of data to write, can be `PETSC_DETERMINE`
1089: -  dtype - type of data to write

1091:    Level: advanced

1093: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryWriteAll()`, `PetscViewerBinaryReadAll()`
1094: @*/
1095: PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer, const void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1096: {
1097:   PetscViewerBinaryWriteReadAll(viewer, PETSC_TRUE, (void *)data, count, start, total, dtype);
1098:   return 0;
1099: }

1101: /*@C
1102:    PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first MPI rank, an array of strings

1104:    Collective

1106:    Input Parameters:
1107: +  viewer - the binary viewer
1108: -  data - location of the array of strings

1110:    Level: intermediate

1112:     Note:
1113:     The array of strings must be null terminated

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

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

1141: /*@C
1142:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings to all MPI ranks

1144:    Collective

1146:    Input Parameter:
1147: .  viewer - the binary viewer

1149:    Output Parameter:
1150: .  data - location of the array of strings

1152:    Level: intermediate

1154:     Note:
1155:     The array of strings must null terminated

1157: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1158:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1159:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1160: @*/
1161: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer, char ***data)
1162: {
1163:   PetscInt i, n, *sizes, N = 0;

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

1180: /*@C
1181:      PetscViewerFileSetMode - Sets the open mode of file

1183:     Logically Collective on viewer

1185:   Input Parameters:
1186: +  viewer - the `PetscViewer`; must be a a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII`  `PetscViewer`
1187: -  mode - open mode of file
1188: $    FILE_MODE_WRITE - create new file for output
1189: $    FILE_MODE_READ - open existing file for input
1190: $    FILE_MODE_APPEND - open existing file for output

1192:   Level: advanced

1194: .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1195: @*/
1196: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer, PetscFileMode mode)
1197: {
1202:   PetscTryMethod(viewer, "PetscViewerFileSetMode_C", (PetscViewer, PetscFileMode), (viewer, mode));
1203:   return 0;
1204: }

1206: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer, PetscFileMode mode)
1207: {
1208:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1211:   vbinary->filemode = mode;
1212:   return 0;
1213: }

1215: /*@C
1216:      PetscViewerFileGetMode - Gets the open mode of file

1218:     Not Collective

1220:   Input Parameter:
1221: .  viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII`  `PetscViewer`

1223:   Output Parameter:
1224: .  mode - open mode of file
1225: $    FILE_MODE_WRITE - create new file for binary output
1226: $    FILE_MODE_READ - open existing file for binary input
1227: $    FILE_MODE_APPEND - open existing file for binary output

1229:   Level: advanced

1231: .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1232: @*/
1233: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer, PetscFileMode *mode)
1234: {
1237:   PetscUseMethod(viewer, "PetscViewerFileGetMode_C", (PetscViewer, PetscFileMode *), (viewer, mode));
1238:   return 0;
1239: }

1241: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer, PetscFileMode *mode)
1242: {
1243:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1245:   *mode = vbinary->filemode;
1246:   return 0;
1247: }

1249: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer, const char name[])
1250: {
1251:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1253:   if (viewer->setupcalled && vbinary->filename) {
1254:     /* gzip can be run after the file with the previous filename has been closed */
1255:     PetscFree(vbinary->ogzfilename);
1256:     PetscStrallocpy(vbinary->filename, &vbinary->ogzfilename);
1257:   }
1258:   PetscFree(vbinary->filename);
1259:   PetscStrallocpy(name, &vbinary->filename);
1260:   viewer->setupcalled = PETSC_FALSE;
1261:   return 0;
1262: }

1264: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer, const char **name)
1265: {
1266:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1268:   *name = vbinary->filename;
1269:   return 0;
1270: }

1272: #if defined(PETSC_HAVE_MPIIO)
1273: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1274: {
1275:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1276:   int                 amode;

1278:   vbinary->storecompressed = PETSC_FALSE;

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

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

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

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

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

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

1355: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1356: {
1357:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1358:   PetscMPIInt         rank;
1359:   PetscBool           found;

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

1366:     PetscStrncpy(infoname, vbinary->filename, sizeof(infoname));
1367:     /* remove .gz if it ends file name */
1368:     PetscStrstr(infoname, ".gz", &gz);
1369:     if (gz && gz[3] == 0) *gz = 0;

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

1385: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1386: {
1387:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1388:   PetscBool           usempiio;

1390:   if (!vbinary->setfromoptionscalled) PetscViewerSetFromOptions(viewer);
1393:   PetscViewerFileClose_Binary(viewer);

1395:   PetscViewerBinaryGetUseMPIIO(viewer, &usempiio);
1396:   if (usempiio) {
1397: #if defined(PETSC_HAVE_MPIIO)
1398:     PetscViewerFileSetUp_BinaryMPIIO(viewer);
1399: #endif
1400:   } else {
1401:     PetscViewerFileSetUp_BinarySTDIO(viewer);
1402:   }
1403:   PetscViewerFileSetUp_BinaryInfo(viewer);

1405:   PetscLogObjectState((PetscObject)viewer, "File: %s", vbinary->filename);
1406:   return 0;
1407: }

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

1416:   PetscViewerBinaryGetUseMPIIO(v, &usempiio);
1417:   PetscViewerASCIIPrintf(viewer, "Filename: %s\n", fname);
1418:   PetscViewerASCIIPrintf(viewer, "Mode: %s (%s)\n", fmode, usempiio ? "mpiio" : "stdio");
1419:   return 0;
1420: }

1422: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscViewer viewer, PetscOptionItems *PetscOptionsObject)
1423: {
1424:   PetscViewer_Binary *binary = (PetscViewer_Binary *)viewer->data;
1425:   char                defaultname[PETSC_MAX_PATH_LEN];
1426:   PetscBool           flg;

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

1446: /*MC
1447:    PETSCVIEWERBINARY - A viewer that saves to binary files

1449:   Level: beginner

1451: .seealso: `PetscViewerBinaryOpen()`, `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1452:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, `PETSCVIEWERDRAW`, `PETSCVIEWERSOCKET`
1453:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`,
1454:           `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`
1455: M*/

1457: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1458: {
1459:   PetscViewer_Binary *vbinary;

1461:   PetscNew(&vbinary);
1462:   v->data = (void *)vbinary;

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

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

1489:   vbinary->setfromoptionscalled = PETSC_FALSE;

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

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

1518: /*@C
1519:      PETSC_VIEWER_BINARY_ - Creates a `PETSCVIEWERBINARY` `PetscViewer` shared by all processors
1520:                      in a communicator.

1522:      Collective

1524:      Input Parameter:
1525: .    comm - the MPI communicator to share the `PETSCVIEWERBINARY`

1527:      Level: intermediate

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

1536:    Environmental variable:
1537: -   PETSC_VIEWER_BINARY_FILENAME - filename in which to store the binary data, defaults to binaryoutput

1539:      Note:
1540:      Unlike almost all other PETSc routines, `PETSC_VIEWER_BINARY_` does not return
1541:      an error code.  The binary PetscViewer is usually used in the form
1542: $       XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));

1544: .seealso: `PETSCVIEWERBINARY`, `PETSC_VIEWER_BINARY_WORLD`, `PETSC_VIEWER_BINARY_SELF`, `PetscViewerBinaryOpen()`, `PetscViewerCreate()`,
1545:           `PetscViewerDestroy()`
1546: @*/
1547: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1548: {
1550:   PetscBool      flg;
1551:   PetscViewer    viewer;
1552:   char           fname[PETSC_MAX_PATH_LEN];
1553:   MPI_Comm       ncomm;

1555:   PetscCommDuplicate(comm, &ncomm, NULL);
1556:   if (ierr) {
1557:     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1558:     return NULL;
1559:   }
1560:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1561:     MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Binary_keyval, NULL);
1562:     if (ierr) {
1563:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1564:       return NULL;
1565:     }
1566:   }
1567:   MPI_Comm_get_attr(ncomm, Petsc_Viewer_Binary_keyval, (void **)&viewer, (int *)&flg);
1568:   if (ierr) {
1569:     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1570:     return NULL;
1571:   }
1572:   if (!flg) { /* PetscViewer not yet created */
1573:     PetscOptionsGetenv(ncomm, "PETSC_VIEWER_BINARY_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
1574:     if (ierr) {
1575:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1576:       return NULL;
1577:     }
1578:     if (!flg) {
1579:       PetscStrcpy(fname, "binaryoutput");
1580:       if (ierr) {
1581:         PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1582:         return NULL;
1583:       }
1584:     }
1585:     PetscViewerBinaryOpen(ncomm, fname, FILE_MODE_WRITE, &viewer);
1586:     if (ierr) {
1587:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1588:       return NULL;
1589:     }
1590:     PetscObjectRegisterDestroy((PetscObject)viewer);
1591:     if (ierr) {
1592:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1593:       return NULL;
1594:     }
1595:     MPI_Comm_set_attr(ncomm, Petsc_Viewer_Binary_keyval, (void *)viewer);
1596:     if (ierr) {
1597:       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1598:       return NULL;
1599:     }
1600:   }
1601:   PetscCommDestroy(&ncomm);
1602:   if (ierr) {
1603:     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1604:     return NULL;
1605:   }
1606:   return viewer;
1607: }