Actual source code: binv.c

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

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

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

 49: #if defined(PETSC_HAVE_MPIIO)
 50: static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer)
 51: {
 52:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

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

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

 69:   PetscViewerSetUp(viewer);

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

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

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

114: #if defined(PETSC_HAVE_MPIIO)
115:   PetscViewerBinarySyncMPIIO(viewer);
116: #endif
117:   return 0;
118: }

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

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

131: #if defined(PETSC_HAVE_MPIIO)
132:   if (vbinary->usempiio && *outviewer) {
133:     PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
135:     if (obinary->mfsub != MPI_FILE_NULL) MPI_File_close(&obinary->mfsub);
136:     moff = obinary->moff;
137:   }
138: #endif

140:   if (*outviewer) {
141:     PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
143:     PetscFree((*outviewer)->data);
144:     PetscViewerBinaryClearFunctionList(*outviewer);
145:     PetscHeaderDestroy(outviewer);
146:   }

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

156: #if defined(PETSC_HAVE_MPIIO)
157:   PetscViewerBinarySyncMPIIO(viewer);
158: #endif
159:   return 0;
160: }

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

166:     Not Collective

168:     Input Parameter:
169: .   viewer - PetscViewer context, obtained from `PetscViewerBinaryOpen()`

171:     Output Parameter:
172: .   off - the current global offset

174:     Level: advanced

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

179:     Fortran Note:
180:     This routine is not supported in Fortran.

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

190:   vbinary = (PetscViewer_Binary *)viewer->data;
191:   *off    = vbinary->moff;
192:   return 0;
193: }

195: /*@C
196:     PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset

198:     Logically Collective

200:     Input Parameters:
201: +   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
202: -   off - the addition to the global offset

204:     Level: advanced

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

209:     Fortran Note:
210:     This routine is not supported in Fortran.

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

220:   vbinary = (PetscViewer_Binary *)viewer->data;
221:   vbinary->moff += off;
222:   return 0;
223: }

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

228:     Not Collective

230:     Input Parameter:
231: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

233:     Output Parameter:
234: .   fdes - file descriptor

236:     Level: advanced

238:     Fortran Note:
239:     This routine is not supported in Fortran.

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

249:   PetscViewerSetUp(viewer);
250:   vbinary = (PetscViewer_Binary *)viewer->data;
251:   *fdes   = vbinary->mfdes;
252:   return 0;
253: }
254: #endif

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

260:     Logically Collective on viewer

262:     Input Parameters:
263: +   viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`
264: -   use - `PETSC_TRUE` means MPI-IO will be used

266:     Options Database Key:
267:     -viewer_binary_mpiio : Flag for using MPI-IO

269:     Level: advanced

271: .seealso: `PETSCVIEWERBINARY`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
272:           `PetscViewerBinaryGetUseMPIIO()`
273: @*/
274: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer, PetscBool use)
275: {
278:   PetscTryMethod(viewer, "PetscViewerBinarySetUseMPIIO_C", (PetscViewer, PetscBool), (viewer, use));
279:   return 0;
280: }

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

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

295:     Not Collective

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

300:     Output Parameter:
301: .   use - `PETSC_TRUE` if MPI-IO is being used

303:     Level: advanced

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

308: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
309: @*/
310: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer, PetscBool *use)
311: {
314:   *use = PETSC_FALSE;
315:   PetscTryMethod(viewer, "PetscViewerBinaryGetUseMPIIO_C", (PetscViewer, PetscBool *), (viewer, use));
316:   return 0;
317: }

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

324:   *use = vbinary->usempiio;
325:   return 0;
326: }
327: #endif

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

332:     Not Collective

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

338:     Level: advanced

340: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetFlowControl()`
341: @*/
342: PetscErrorCode PetscViewerBinarySetFlowControl(PetscViewer viewer, PetscInt fc)
343: {
346:   PetscTryMethod(viewer, "PetscViewerBinarySetFlowControl_C", (PetscViewer, PetscInt), (viewer, fc));
347:   return 0;
348: }

350: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer, PetscInt fc)
351: {
352:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

355:   vbinary->flowcontrol = fc;
356:   return 0;
357: }

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

362:     Not Collective

364:     Input Parameter:
365: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

367:     Output Parameter:
368: .   fc - the number of messages

370:     Level: advanced

372: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetFlowControl()`
373: @*/
374: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer, PetscInt *fc)
375: {
378:   PetscUseMethod(viewer, "PetscViewerBinaryGetFlowControl_C", (PetscViewer, PetscInt *), (viewer, fc));
379:   return 0;
380: }

382: PETSC_INTERN PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer, PetscInt *fc)
383: {
384:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

386:   *fc = vbinary->flowcontrol;
387:   return 0;
388: }

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

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

395:     Input Parameter:
396: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

398:     Output Parameter:
399: .   fdes - file descriptor

401:     Level: advanced

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

409:     Fortran Note:
410:     This routine is not supported in Fortran.

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

420:   PetscViewerSetUp(viewer);
421:   vbinary = (PetscViewer_Binary *)viewer->data;
422:   *fdes   = vbinary->fdes;
423:   return 0;
424: }

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

429:     Not Collective

431:     Input Parameter:
432: .   viewer - `PetscViewer` context, obtained from `PetscViewerCreate()`

434:     Options Database Key:
435: .   -viewer_binary_skip_info - true indicates do not generate .info file

437:     Level: advanced

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

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

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

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

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

461:     Not Collective

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

467:     Options Database Key:
468: .   -viewer_binary_skip_info - true indicates do not generate .info file

470:     Level: advanced

472: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
473:           `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
474: @*/
475: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer, PetscBool skip)
476: {
479:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipInfo_C", (PetscViewer, PetscBool), (viewer, skip));
480:   return 0;
481: }

483: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer, PetscBool skip)
484: {
485:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

487:   vbinary->skipinfo = skip;
488:   return 0;
489: }

491: /*@
492:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

494:     Not Collective

496:     Input Parameter:
497: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

499:     Output Parameter:
500: .   skip - `PETSC_TRUE` implies the .info file was not generated

502:     Level: advanced

504:     Note:
505:     This must be called after `PetscViewerSetType()`

507: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`,
508:           `PetscViewerBinarySetSkipOptions()`, `PetscViewerBinarySetSkipInfo()`
509: @*/
510: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer, PetscBool *skip)
511: {
514:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipInfo_C", (PetscViewer, PetscBool *), (viewer, skip));
515:   return 0;
516: }

518: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer, PetscBool *skip)
519: {
520:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

522:   *skip = vbinary->skipinfo;
523:   return 0;
524: }

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

529:     Not Collective

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

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

538:     Level: advanced

540:     Note:
541:     This must be called after `PetscViewerSetType()`

543: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
544:           `PetscViewerBinaryGetSkipOptions()`
545: @*/
546: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer, PetscBool skip)
547: {
550:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipOptions_C", (PetscViewer, PetscBool), (viewer, skip));
551:   return 0;
552: }

554: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer, PetscBool skip)
555: {
556:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

558:   vbinary->skipoptions = skip;
559:   return 0;
560: }

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

565:     Not Collective

567:     Input Parameter:
568: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

570:     Output Parameter:
571: .   skip - `PETSC_TRUE` means do not use

573:     Level: advanced

575:     Note:
576:     This must be called after `PetscViewerSetType()`

578: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
579:           `PetscViewerBinarySetSkipOptions()`
580: @*/
581: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer, PetscBool *skip)
582: {
585:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipOptions_C", (PetscViewer, PetscBool *), (viewer, skip));
586:   return 0;
587: }

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

593:   *skip = vbinary->skipoptions;
594:   return 0;
595: }

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

600:     Not Collective

602:     Input Parameters:
603: +   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
604: -   skip - `PETSC_TRUE `means do not write header

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

609:     Level: advanced

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

614:       Is ignored on anything but a binary viewer

616: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
617:           `PetscViewerBinaryGetSkipHeader()`
618: @*/
619: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer, PetscBool skip)
620: {
623:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipHeader_C", (PetscViewer, PetscBool), (viewer, skip));
624:   return 0;
625: }

627: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer, PetscBool skip)
628: {
629:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

631:   vbinary->skipheader = skip;
632:   return 0;
633: }

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

638:     Not Collective

640:     Input Parameter:
641: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

643:     Output Parameter:
644: .   skip - `PETSC_TRUE` means do not write header

646:     Level: advanced

648:     Notes:
649:     This must be called after PetscViewerSetType()

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

653: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
654:           `PetscViewerBinarySetSkipHeader()`
655: @*/
656: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer, PetscBool *skip)
657: {
660:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipHeader_C", (PetscViewer, PetscBool *), (viewer, skip));
661:   return 0;
662: }

664: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer, PetscBool *skip)
665: {
666:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

668:   *skip = vbinary->skipheader;
669:   return 0;
670: }

672: /*@C
673:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
674:           info file associated with a binary file.

676:     Not Collective

678:     Input Parameter:
679: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

681:     Output Parameter:
682: .   file - file pointer  Always returns NULL if not a binary viewer

684:     Level: advanced

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

690:     Fortran Note:
691:     This routine is not supported in Fortran.

693: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`
694: @*/
695: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer, FILE **file)
696: {
699:   *file = NULL;
700:   PetscTryMethod(viewer, "PetscViewerBinaryGetInfoPointer_C", (PetscViewer, FILE **), (viewer, file));
701:   return 0;
702: }

704: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer, FILE **file)
705: {
706:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

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

723: #if defined(PETSC_HAVE_MPIIO)
724: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
725: {
726:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

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

735: static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
736: {
737:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

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

762: static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
763: {
764:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

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

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

792: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
793: {
794:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

796:   PetscViewerFileClose_Binary(v);
797:   PetscFree(vbinary->filename);
798:   PetscFree(vbinary);
799:   PetscViewerBinaryClearFunctionList(v);
800:   return 0;
801: }

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

806:    Collective

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

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

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

826:    Level: beginner

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

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

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

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

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

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

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

886:    Collective

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

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

897:    Level: beginner

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

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

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

926:    Collective

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

934:    Level: beginner

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

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

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

973:   PetscViewerSetUp(viewer);

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

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

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

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

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

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

1061:    Collective

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

1071:    Level: advanced

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

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

1084:    Collective

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

1094:    Level: advanced

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

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

1107:    Collective

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

1113:    Level: intermediate

1115:     Note:
1116:     The array of strings must be null terminated

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

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

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

1147:    Collective

1149:    Input Parameter:
1150: .  viewer - the binary viewer

1152:    Output Parameter:
1153: .  data - location of the array of strings

1155:    Level: intermediate

1157:     Note:
1158:     The array of strings must null terminated

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

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

1183: /*@C
1184:      PetscViewerFileSetMode - Sets the open mode of file

1186:     Logically Collective on viewer

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

1195:   Level: advanced

1197: .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1198: @*/
1199: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer, PetscFileMode mode)
1200: {
1205:   PetscTryMethod(viewer, "PetscViewerFileSetMode_C", (PetscViewer, PetscFileMode), (viewer, mode));
1206:   return 0;
1207: }

1209: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer, PetscFileMode mode)
1210: {
1211:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1214:   vbinary->filemode = mode;
1215:   return 0;
1216: }

1218: /*@C
1219:      PetscViewerFileGetMode - Gets the open mode of file

1221:     Not Collective

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

1226:   Output Parameter:
1227: .  mode - open mode of file
1228: $    FILE_MODE_WRITE - create new file for binary output
1229: $    FILE_MODE_READ - open existing file for binary input
1230: $    FILE_MODE_APPEND - open existing file for binary output

1232:   Level: advanced

1234: .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1235: @*/
1236: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer, PetscFileMode *mode)
1237: {
1240:   PetscUseMethod(viewer, "PetscViewerFileGetMode_C", (PetscViewer, PetscFileMode *), (viewer, mode));
1241:   return 0;
1242: }

1244: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer, PetscFileMode *mode)
1245: {
1246:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1248:   *mode = vbinary->filemode;
1249:   return 0;
1250: }

1252: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer, const char name[])
1253: {
1254:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

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

1267: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer, const char **name)
1268: {
1269:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1271:   *name = vbinary->filename;
1272:   return 0;
1273: }

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

1281:   vbinary->storecompressed = PETSC_FALSE;

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

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

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

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

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

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

1358: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1359: {
1360:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1361:   PetscMPIInt         rank;
1362:   PetscBool           found;

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

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

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

1388: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1389: {
1390:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1391:   PetscBool           usempiio;

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

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

1408:   PetscLogObjectState((PetscObject)viewer, "File: %s", vbinary->filename);
1409:   return 0;
1410: }

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

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

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

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

1449: /*MC
1450:    PETSCVIEWERBINARY - A viewer that saves to binary files

1452:   Level: beginner

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

1460: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1461: {
1462:   PetscViewer_Binary *vbinary;

1464:   PetscNew(&vbinary);
1465:   v->data = (void *)vbinary;

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

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

1492:   vbinary->setfromoptionscalled = PETSC_FALSE;

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

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

1521: /*@C
1522:      PETSC_VIEWER_BINARY_ - Creates a `PETSCVIEWERBINARY` `PetscViewer` shared by all processors
1523:                      in a communicator.

1525:      Collective

1527:      Input Parameter:
1528: .    comm - the MPI communicator to share the `PETSCVIEWERBINARY`

1530:      Level: intermediate

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

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

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

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

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