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; No Fortran Support

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: .seealso: [](sec_viewers), `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; No Fortran Support

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: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
207: @*/
208: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer, MPI_Offset off)
209: {
210:   PetscViewer_Binary *vbinary;

214:   vbinary = (PetscViewer_Binary *)viewer->data;
215:   vbinary->moff += off;
216:   return 0;
217: }

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

222:     Not Collective; No Fortran Support

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

227:     Output Parameter:
228: .   fdes - file descriptor

230:     Level: advanced

232: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
233: @*/
234: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer, MPI_File *fdes)
235: {
236:   PetscViewer_Binary *vbinary;

240:   PetscViewerSetUp(viewer);
241:   vbinary = (PetscViewer_Binary *)viewer->data;
242:   *fdes   = vbinary->mfdes;
243:   return 0;
244: }
245: #endif

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

251:     Logically Collective

253:     Input Parameters:
254: +   viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`
255: -   use - `PETSC_TRUE` means MPI-IO will be used

257:     Options Database Key:
258:     -viewer_binary_mpiio : Flag for using MPI-IO

260:     Level: advanced

262: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
263:           `PetscViewerBinaryGetUseMPIIO()`
264: @*/
265: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer, PetscBool use)
266: {
269:   PetscTryMethod(viewer, "PetscViewerBinarySetUseMPIIO_C", (PetscViewer, PetscBool), (viewer, use));
270:   return 0;
271: }

273: #if defined(PETSC_HAVE_MPIIO)
274: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer, PetscBool use)
275: {
276:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
278:   vbinary->usempiio = use;
279:   return 0;
280: }
281: #endif

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

286:     Not Collective

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

291:     Output Parameter:
292: .   use - `PETSC_TRUE` if MPI-IO is being used

294:     Level: advanced

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

299: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
300: @*/
301: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer, PetscBool *use)
302: {
305:   *use = PETSC_FALSE;
306:   PetscTryMethod(viewer, "PetscViewerBinaryGetUseMPIIO_C", (PetscViewer, PetscBool *), (viewer, use));
307:   return 0;
308: }

310: #if defined(PETSC_HAVE_MPIIO)
311: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer, PetscBool *use)
312: {
313:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

315:   *use = vbinary->usempiio;
316:   return 0;
317: }
318: #endif

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

323:     Not Collective

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

329:     Level: advanced

331: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetFlowControl()`
332: @*/
333: PetscErrorCode PetscViewerBinarySetFlowControl(PetscViewer viewer, PetscInt fc)
334: {
337:   PetscTryMethod(viewer, "PetscViewerBinarySetFlowControl_C", (PetscViewer, PetscInt), (viewer, fc));
338:   return 0;
339: }

341: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer, PetscInt fc)
342: {
343:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

346:   vbinary->flowcontrol = fc;
347:   return 0;
348: }

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

353:     Not Collective

355:     Input Parameter:
356: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

358:     Output Parameter:
359: .   fc - the number of messages

361:     Level: advanced

363: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetFlowControl()`
364: @*/
365: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer, PetscInt *fc)
366: {
369:   PetscUseMethod(viewer, "PetscViewerBinaryGetFlowControl_C", (PetscViewer, PetscInt *), (viewer, fc));
370:   return 0;
371: }

373: PETSC_INTERN PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer, PetscInt *fc)
374: {
375:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

377:   *fc = vbinary->flowcontrol;
378:   return 0;
379: }

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

384:     Collective because it may trigger a `PetscViewerSetUp()` call; No Fortran Support

386:     Input Parameter:
387: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

389:     Output Parameter:
390: .   fdes - file descriptor

392:     Level: advanced

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

400: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`
401: @*/
402: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer, int *fdes)
403: {
404:   PetscViewer_Binary *vbinary;

408:   PetscViewerSetUp(viewer);
409:   vbinary = (PetscViewer_Binary *)viewer->data;
410:   *fdes   = vbinary->fdes;
411:   return 0;
412: }

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

417:     Not Collective

419:     Input Parameter:
420: .   viewer - `PetscViewer` context, obtained from `PetscViewerCreate()`

422:     Options Database Key:
423: .   -viewer_binary_skip_info - true indicates do not generate .info file

425:     Level: advanced

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

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

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

437: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
438:           `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
439: @*/
440: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
441: {
442:   PetscViewerBinarySetSkipInfo(viewer, PETSC_TRUE);
443:   return 0;
444: }

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

449:     Not Collective

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

455:     Options Database Key:
456: .   -viewer_binary_skip_info - true indicates do not generate .info file

458:     Level: advanced

460: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
461:           `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
462: @*/
463: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer, PetscBool skip)
464: {
467:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipInfo_C", (PetscViewer, PetscBool), (viewer, skip));
468:   return 0;
469: }

471: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer, PetscBool skip)
472: {
473:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

475:   vbinary->skipinfo = skip;
476:   return 0;
477: }

479: /*@
480:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file

482:     Not Collective

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

487:     Output Parameter:
488: .   skip - `PETSC_TRUE` implies the .info file was not generated

490:     Level: advanced

492:     Note:
493:     This must be called after `PetscViewerSetType()`

495: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`,
496:           `PetscViewerBinarySetSkipOptions()`, `PetscViewerBinarySetSkipInfo()`
497: @*/
498: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer, PetscBool *skip)
499: {
502:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipInfo_C", (PetscViewer, PetscBool *), (viewer, skip));
503:   return 0;
504: }

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

510:   *skip = vbinary->skipinfo;
511:   return 0;
512: }

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

517:     Not Collective

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

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

526:     Level: advanced

528:     Note:
529:     This must be called after `PetscViewerSetType()`

531: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
532:           `PetscViewerBinaryGetSkipOptions()`
533: @*/
534: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer, PetscBool skip)
535: {
538:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipOptions_C", (PetscViewer, PetscBool), (viewer, skip));
539:   return 0;
540: }

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

546:   vbinary->skipoptions = skip;
547:   return 0;
548: }

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

553:     Not Collective

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

558:     Output Parameter:
559: .   skip - `PETSC_TRUE` means do not use

561:     Level: advanced

563:     Note:
564:     This must be called after `PetscViewerSetType()`

566: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
567:           `PetscViewerBinarySetSkipOptions()`
568: @*/
569: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer, PetscBool *skip)
570: {
573:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipOptions_C", (PetscViewer, PetscBool *), (viewer, skip));
574:   return 0;
575: }

577: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer, PetscBool *skip)
578: {
579:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

581:   *skip = vbinary->skipoptions;
582:   return 0;
583: }

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

588:     Not Collective

590:     Input Parameters:
591: +   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
592: -   skip - `PETSC_TRUE `means do not write header

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

597:     Level: advanced

599:     Notes:
600:       This must be called after `PetscViewerSetType()`

602:       Is ignored on anything but a binary viewer

604: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
605:           `PetscViewerBinaryGetSkipHeader()`
606: @*/
607: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer, PetscBool skip)
608: {
611:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipHeader_C", (PetscViewer, PetscBool), (viewer, skip));
612:   return 0;
613: }

615: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer, PetscBool skip)
616: {
617:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

619:   vbinary->skipheader = skip;
620:   return 0;
621: }

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

626:     Not Collective

628:     Input Parameter:
629: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

631:     Output Parameter:
632: .   skip - `PETSC_TRUE` means do not write header

634:     Level: advanced

636:     Notes:
637:     This must be called after PetscViewerSetType()

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

641: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
642:           `PetscViewerBinarySetSkipHeader()`
643: @*/
644: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer, PetscBool *skip)
645: {
648:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipHeader_C", (PetscViewer, PetscBool *), (viewer, skip));
649:   return 0;
650: }

652: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer, PetscBool *skip)
653: {
654:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

656:   *skip = vbinary->skipheader;
657:   return 0;
658: }

660: /*@C
661:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
662:           info file associated with a binary file.

664:     Not Collective; No Fortran Support

666:     Input Parameter:
667: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

669:     Output Parameter:
670: .   file - file pointer  Always returns NULL if not a binary viewer

672:     Level: advanced

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

678: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`
679: @*/
680: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer, FILE **file)
681: {
684:   *file = NULL;
685:   PetscTryMethod(viewer, "PetscViewerBinaryGetInfoPointer_C", (PetscViewer, FILE **), (viewer, file));
686:   return 0;
687: }

689: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer, FILE **file)
690: {
691:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

693:   PetscViewerSetUp(viewer);
694:   *file = vbinary->fdes_info;
695:   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
696:     if (vbinary->fdes_info) {
697:       FILE *info = vbinary->fdes_info;
698:       PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
699:       PetscFPrintf(PETSC_COMM_SELF, info, "#$$ Set.filename = '%s';\n", vbinary->filename);
700:       PetscFPrintf(PETSC_COMM_SELF, info, "#$$ fd = PetscOpenFile(Set.filename);\n");
701:       PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
702:     }
703:     vbinary->matlabheaderwritten = PETSC_TRUE;
704:   }
705:   return 0;
706: }

708: #if defined(PETSC_HAVE_MPIIO)
709: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
710: {
711:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

713:   if (vbinary->mfdes != MPI_FILE_NULL) MPI_File_close(&vbinary->mfdes);
714:   if (vbinary->mfsub != MPI_FILE_NULL) MPI_File_close(&vbinary->mfsub);
715:   vbinary->moff = 0;
716:   return 0;
717: }
718: #endif

720: static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
721: {
722:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

724:   if (vbinary->fdes != -1) {
725:     PetscBinaryClose(vbinary->fdes);
726:     vbinary->fdes = -1;
727:     if (vbinary->storecompressed) {
728:       char        cmd[8 + PETSC_MAX_PATH_LEN], out[64 + PETSC_MAX_PATH_LEN] = "";
729:       const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
730:       /* compress the file */
731:       PetscStrncpy(cmd, "gzip -f ", sizeof(cmd));
732:       PetscStrlcat(cmd, gzfilename, sizeof(cmd));
733: #if defined(PETSC_HAVE_POPEN)
734:       {
735:         FILE *fp;
736:         PetscPOpen(PETSC_COMM_SELF, NULL, cmd, "r", &fp);
738:         PetscPClose(PETSC_COMM_SELF, fp);
739:       }
740: #endif
741:     }
742:   }
743:   PetscFree(vbinary->ogzfilename);
744:   return 0;
745: }

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

751:   if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
752:     if (vbinary->fdes_info) {
753:       FILE *info = vbinary->fdes_info;
754:       PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
755:       PetscFPrintf(PETSC_COMM_SELF, info, "#$$ close(fd);\n");
756:       PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
757:     }
758:   }
759:   if (vbinary->fdes_info) {
760:     FILE *info         = vbinary->fdes_info;
761:     vbinary->fdes_info = NULL;
763:   }
764:   return 0;
765: }

767: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
768: {
769: #if defined(PETSC_HAVE_MPIIO)
770:   PetscViewerFileClose_BinaryMPIIO(v);
771: #endif
772:   PetscViewerFileClose_BinarySTDIO(v);
773:   PetscViewerFileClose_BinaryInfo(v);
774:   return 0;
775: }

777: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
778: {
779:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

781:   PetscViewerFileClose_Binary(v);
782:   PetscFree(vbinary->filename);
783:   PetscFree(vbinary);
784:   PetscViewerBinaryClearFunctionList(v);
785:   return 0;
786: }

788: /*@C
789:    PetscViewerBinaryOpen - Opens a file for binary input/output.

791:    Collective

793:    Input Parameters:
794: +  comm - MPI communicator
795: .  name - name of file
796: -  mode - open mode of file
797: $    FILE_MODE_WRITE - create new file for binary output
798: $    FILE_MODE_READ - open existing file for binary input
799: $    FILE_MODE_APPEND - open existing file for binary output

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

804:     Options Database Keys:
805: +    -viewer_binary_filename <name> - name of file to use
806: .    -viewer_binary_skip_info - true to skip opening an info file
807: .    -viewer_binary_skip_options - true to not use options database while creating viewer
808: .    -viewer_binary_skip_header - true to skip output object headers to the file
809: -    -viewer_binary_mpiio - true to use MPI-IO for input and output to the file (more scalable for large problems)

811:    Level: beginner

813:    Note:
814:    This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.

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

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

822: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
823:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
824:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`, `PetscViewerBinarySetUseMPIIO()`,
825:           `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
826: @*/
827: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm, const char name[], PetscFileMode mode, PetscViewer *viewer)
828: {
829:   PetscViewerCreate(comm, viewer);
830:   PetscViewerSetType(*viewer, PETSCVIEWERBINARY);
831:   PetscViewerFileSetMode(*viewer, mode);
832:   PetscViewerFileSetName(*viewer, name);
833:   PetscViewerSetFromOptions(*viewer);
834:   return 0;
835: }

837: #if defined(PETSC_HAVE_MPIIO)
838: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype, PetscBool write)
839: {
840:   MPI_Comm            comm    = PetscObjectComm((PetscObject)viewer);
841:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
842:   MPI_File            mfdes   = vbinary->mfdes;
843:   MPI_Datatype        mdtype;
844:   PetscMPIInt         rank, cnt;
845:   MPI_Status          status;
846:   MPI_Aint            ul, dsize;

848:   MPI_Comm_rank(comm, &rank);
849:   PetscMPIIntCast(num, &cnt);
850:   PetscDataTypeToMPIDataType(dtype, &mdtype);
851:   if (write) {
852:     if (rank == 0) MPIU_File_write_at(mfdes, vbinary->moff, data, cnt, mdtype, &status);
853:   } else {
854:     if (rank == 0) {
855:       MPIU_File_read_at(mfdes, vbinary->moff, data, cnt, mdtype, &status);
856:       if (cnt > 0) MPI_Get_count(&status, mdtype, &cnt);
857:     }
858:     MPI_Bcast(&cnt, 1, MPI_INT, 0, comm);
859:     MPI_Bcast(data, cnt, mdtype, 0, comm);
860:   }
861:   MPI_Type_get_extent(mdtype, &ul, &dsize);
862:   vbinary->moff += dsize * cnt;
863:   if (count) *count = cnt;
864:   return 0;
865: }
866: #endif

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

871:    Collective

873:    Input Parameters:
874: +  viewer - the binary viewer
875: .  data - location of the data to be written
876: .  num - number of items of data to read
877: -  dtype - type of data to read

879:    Output Parameters:
880: .  count - number of items of data actually read, or NULL.

882:    Level: beginner

884: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
885:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
886:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
887: @*/
888: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
889: {
890:   PetscViewer_Binary *vbinary;

894:   PetscViewerSetUp(viewer);
895:   vbinary = (PetscViewer_Binary *)viewer->data;
896: #if defined(PETSC_HAVE_MPIIO)
897:   if (vbinary->usempiio) {
898:     PetscViewerBinaryWriteReadMPIIO(viewer, data, num, count, dtype, PETSC_FALSE);
899:   } else {
900: #endif
901:     PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, num, count, dtype);
902: #if defined(PETSC_HAVE_MPIIO)
903:   }
904: #endif
905:   return 0;
906: }

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

911:    Collective

913:    Input Parameters:
914: +  viewer - the binary viewer
915: .  data - location of data
916: .  count - number of items of data to write
917: -  dtype - type of data to write

919:    Level: beginner

921: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
922:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, `PetscDataType`
923:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
924: @*/
925: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer, const void *data, PetscInt count, PetscDataType dtype)
926: {
927:   PetscViewer_Binary *vbinary;

931:   PetscViewerSetUp(viewer);
932:   vbinary = (PetscViewer_Binary *)viewer->data;
933: #if defined(PETSC_HAVE_MPIIO)
934:   if (vbinary->usempiio) {
935:     PetscViewerBinaryWriteReadMPIIO(viewer, (void *)data, count, NULL, dtype, PETSC_TRUE);
936:   } else {
937: #endif
938:     PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, count, dtype);
939: #if defined(PETSC_HAVE_MPIIO)
940:   }
941: #endif
942:   return 0;
943: }

945: static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer, PetscBool write, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
946: {
947:   MPI_Comm              comm = PetscObjectComm((PetscObject)viewer);
948:   PetscMPIInt           size, rank;
949:   MPI_Datatype          mdtype;
950:   PETSC_UNUSED MPI_Aint lb;
951:   MPI_Aint              dsize;
952:   PetscBool             useMPIIO;

958:   PetscViewerSetUp(viewer);

960:   PetscDataTypeToMPIDataType(dtype, &mdtype);
961:   MPI_Type_get_extent(mdtype, &lb, &dsize);
962:   MPI_Comm_rank(comm, &rank);
963:   MPI_Comm_size(comm, &size);

965:   PetscViewerBinaryGetUseMPIIO(viewer, &useMPIIO);
966: #if defined(PETSC_HAVE_MPIIO)
967:   if (useMPIIO) {
968:     MPI_File    mfdes;
969:     MPI_Offset  off;
970:     PetscMPIInt cnt;

972:     if (start == PETSC_DETERMINE) {
973:       MPI_Scan(&count, &start, 1, MPIU_INT, MPI_SUM, comm);
974:       start -= count;
975:     }
976:     if (total == PETSC_DETERMINE) {
977:       total = start + count;
978:       MPI_Bcast(&total, 1, MPIU_INT, size - 1, comm);
979:     }
980:     PetscMPIIntCast(count, &cnt);
981:     PetscViewerBinaryGetMPIIODescriptor(viewer, &mfdes);
982:     PetscViewerBinaryGetMPIIOOffset(viewer, &off);
983:     off += (MPI_Offset)(start * dsize);
984:     if (write) {
985:       MPIU_File_write_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE);
986:     } else {
987:       MPIU_File_read_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE);
988:     }
989:     off = (MPI_Offset)(total * dsize);
990:     PetscViewerBinaryAddMPIIOOffset(viewer, off);
991:     return 0;
992:   }
993: #endif
994:   {
995:     int         fdes;
996:     char       *workbuf = NULL;
997:     PetscInt    tcount = rank == 0 ? 0 : count, maxcount = 0, message_count, flowcontrolcount;
998:     PetscMPIInt tag, cnt, maxcnt, scnt = 0, rcnt = 0, j;
999:     MPI_Status  status;

1001:     PetscCommGetNewTag(comm, &tag);
1002:     MPI_Reduce(&tcount, &maxcount, 1, MPIU_INT, MPI_MAX, 0, comm);
1003:     PetscMPIIntCast(maxcount, &maxcnt);
1004:     PetscMPIIntCast(count, &cnt);

1006:     PetscViewerBinaryGetDescriptor(viewer, &fdes);
1007:     PetscViewerFlowControlStart(viewer, &message_count, &flowcontrolcount);
1008:     if (rank == 0) {
1009:       PetscMalloc(maxcnt * dsize, &workbuf);
1010:       if (write) {
1011:         PetscBinaryWrite(fdes, data, cnt, dtype);
1012:       } else {
1013:         PetscBinaryRead(fdes, data, cnt, NULL, dtype);
1014:       }
1015:       for (j = 1; j < size; j++) {
1016:         PetscViewerFlowControlStepMain(viewer, j, &message_count, flowcontrolcount);
1017:         if (write) {
1018:           MPI_Recv(workbuf, maxcnt, mdtype, j, tag, comm, &status);
1019:           MPI_Get_count(&status, mdtype, &rcnt);
1020:           PetscBinaryWrite(fdes, workbuf, rcnt, dtype);
1021:         } else {
1022:           MPI_Recv(&scnt, 1, MPI_INT, j, tag, comm, MPI_STATUS_IGNORE);
1023:           PetscBinaryRead(fdes, workbuf, scnt, NULL, dtype);
1024:           MPI_Send(workbuf, scnt, mdtype, j, tag, comm);
1025:         }
1026:       }
1027:       PetscFree(workbuf);
1028:       PetscViewerFlowControlEndMain(viewer, &message_count);
1029:     } else {
1030:       PetscViewerFlowControlStepWorker(viewer, rank, &message_count);
1031:       if (write) {
1032:         MPI_Send(data, cnt, mdtype, 0, tag, comm);
1033:       } else {
1034:         MPI_Send(&cnt, 1, MPI_INT, 0, tag, comm);
1035:         MPI_Recv(data, cnt, mdtype, 0, tag, comm, MPI_STATUS_IGNORE);
1036:       }
1037:       PetscViewerFlowControlEndWorker(viewer, &message_count);
1038:     }
1039:   }
1040:   return 0;
1041: }

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

1046:    Collective

1048:    Input Parameters:
1049: +  viewer - the binary viewer
1050: .  data - location of data
1051: .  count - local number of items of data to read
1052: .  start - local start, can be `PETSC_DETERMINE`
1053: .  total - global number of items of data to read, can be `PETSC_DETERMINE`
1054: -  dtype - type of data to read

1056:    Level: advanced

1058: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteAll()`
1059: @*/
1060: PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1061: {
1062:   PetscViewerBinaryWriteReadAll(viewer, PETSC_FALSE, data, count, start, total, dtype);
1063:   return 0;
1064: }

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

1069:    Collective

1071:    Input Parameters:
1072: +  viewer - the binary viewer
1073: .  data - location of data
1074: .  count - local number of items of data to write
1075: .  start - local start, can be `PETSC_DETERMINE`
1076: .  total - global number of items of data to write, can be `PETSC_DETERMINE`
1077: -  dtype - type of data to write

1079:    Level: advanced

1081: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryWriteAll()`, `PetscViewerBinaryReadAll()`
1082: @*/
1083: PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer, const void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1084: {
1085:   PetscViewerBinaryWriteReadAll(viewer, PETSC_TRUE, (void *)data, count, start, total, dtype);
1086:   return 0;
1087: }

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

1092:    Collective

1094:    Input Parameters:
1095: +  viewer - the binary viewer
1096: -  data - location of the array of strings

1098:    Level: intermediate

1100:     Note:
1101:     The array of strings must be null terminated

1103: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1104:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1105:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1106: @*/
1107: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer, const char *const *data)
1108: {
1109:   PetscInt i, n = 0, *sizes;
1110:   size_t   len;

1112:   PetscViewerSetUp(viewer);
1113:   /* count number of strings */
1114:   while (data[n++])
1115:     ;
1116:   n--;
1117:   PetscMalloc1(n + 1, &sizes);
1118:   sizes[0] = n;
1119:   for (i = 0; i < n; i++) {
1120:     PetscStrlen(data[i], &len);
1121:     sizes[i + 1] = (PetscInt)len + 1; /* size includes space for the null terminator */
1122:   }
1123:   PetscViewerBinaryWrite(viewer, sizes, n + 1, PETSC_INT);
1124:   for (i = 0; i < n; i++) PetscViewerBinaryWrite(viewer, (void *)data[i], sizes[i + 1], PETSC_CHAR);
1125:   PetscFree(sizes);
1126:   return 0;
1127: }

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

1132:    Collective

1134:    Input Parameter:
1135: .  viewer - the binary viewer

1137:    Output Parameter:
1138: .  data - location of the array of strings

1140:    Level: intermediate

1142:     Note:
1143:     The array of strings must null terminated

1145: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1146:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1147:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1148: @*/
1149: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer, char ***data)
1150: {
1151:   PetscInt i, n, *sizes, N = 0;

1153:   PetscViewerSetUp(viewer);
1154:   /* count number of strings */
1155:   PetscViewerBinaryRead(viewer, &n, 1, NULL, PETSC_INT);
1156:   PetscMalloc1(n, &sizes);
1157:   PetscViewerBinaryRead(viewer, sizes, n, NULL, PETSC_INT);
1158:   for (i = 0; i < n; i++) N += sizes[i];
1159:   PetscMalloc((n + 1) * sizeof(char *) + N * sizeof(char), data);
1160:   (*data)[0] = (char *)((*data) + n + 1);
1161:   for (i = 1; i < n; i++) (*data)[i] = (*data)[i - 1] + sizes[i - 1];
1162:   PetscViewerBinaryRead(viewer, (*data)[0], N, NULL, PETSC_CHAR);
1163:   (*data)[n] = NULL;
1164:   PetscFree(sizes);
1165:   return 0;
1166: }

1168: /*@C
1169:      PetscViewerFileSetMode - Sets the open mode of file

1171:     Logically Collective

1173:   Input Parameters:
1174: +  viewer - the `PetscViewer`; must be a a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII`  `PetscViewer`
1175: -  mode - open mode of file
1176: .vb
1177:     FILE_MODE_WRITE - create new file for output
1178:     FILE_MODE_READ - open existing file for input
1179:     FILE_MODE_APPEND - open existing file for output
1180: .ve

1182:   Level: advanced

1184: .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1185: @*/
1186: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer, PetscFileMode mode)
1187: {
1192:   PetscTryMethod(viewer, "PetscViewerFileSetMode_C", (PetscViewer, PetscFileMode), (viewer, mode));
1193:   return 0;
1194: }

1196: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer, PetscFileMode mode)
1197: {
1198:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1201:   vbinary->filemode = mode;
1202:   return 0;
1203: }

1205: /*@C
1206:      PetscViewerFileGetMode - Gets the open mode of file

1208:     Not Collective

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

1213:   Output Parameter:
1214: .  mode - open mode of file
1215: .vb
1216:     FILE_MODE_WRITE - create new file for binary output
1217:     FILE_MODE_READ - open existing file for binary input
1218:     FILE_MODE_APPEND - open existing file for binary output
1219: .ve

1221:   Level: advanced

1223: .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1224: @*/
1225: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer, PetscFileMode *mode)
1226: {
1229:   PetscUseMethod(viewer, "PetscViewerFileGetMode_C", (PetscViewer, PetscFileMode *), (viewer, mode));
1230:   return 0;
1231: }

1233: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer, PetscFileMode *mode)
1234: {
1235:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1237:   *mode = vbinary->filemode;
1238:   return 0;
1239: }

1241: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer, const char name[])
1242: {
1243:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1245:   if (viewer->setupcalled && vbinary->filename) {
1246:     /* gzip can be run after the file with the previous filename has been closed */
1247:     PetscFree(vbinary->ogzfilename);
1248:     PetscStrallocpy(vbinary->filename, &vbinary->ogzfilename);
1249:   }
1250:   PetscFree(vbinary->filename);
1251:   PetscStrallocpy(name, &vbinary->filename);
1252:   viewer->setupcalled = PETSC_FALSE;
1253:   return 0;
1254: }

1256: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer, const char **name)
1257: {
1258:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1260:   *name = vbinary->filename;
1261:   return 0;
1262: }

1264: #if defined(PETSC_HAVE_MPIIO)
1265: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1266: {
1267:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1268:   int                 amode;

1270:   vbinary->storecompressed = PETSC_FALSE;

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

1304: static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
1305: {
1306:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1307:   const char         *fname;
1308:   char                bname[PETSC_MAX_PATH_LEN], *gz;
1309:   PetscBool           found;
1310:   PetscMPIInt         rank;

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

1314:   /* if file name ends in .gz strip that off and note user wants file compressed */
1315:   vbinary->storecompressed = PETSC_FALSE;
1316:   if (vbinary->filemode == FILE_MODE_WRITE) {
1317:     PetscStrstr(vbinary->filename, ".gz", &gz);
1318:     if (gz && gz[3] == 0) {
1319:       *gz                      = 0;
1320:       vbinary->storecompressed = PETSC_TRUE;
1321:     }
1322:   }
1323: #if !defined(PETSC_HAVE_POPEN)
1325: #endif

1327:   fname = vbinary->filename;
1328:   if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
1329:     PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), fname, bname, PETSC_MAX_PATH_LEN, &found);
1331:     fname = bname;
1332:   }

1334:   vbinary->fdes = -1;
1335:   if (rank == 0) { /* only first processor opens file*/
1336:     PetscFileMode mode = vbinary->filemode;
1337:     if (mode == FILE_MODE_APPEND) {
1338:       /* check if asked to append to a non-existing file */
1339:       PetscTestFile(fname, '\0', &found);
1340:       if (!found) mode = FILE_MODE_WRITE;
1341:     }
1342:     PetscBinaryOpen(fname, mode, &vbinary->fdes);
1343:   }
1344:   return 0;
1345: }

1347: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1348: {
1349:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1350:   PetscMPIInt         rank;
1351:   PetscBool           found;

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

1358:     PetscStrncpy(infoname, vbinary->filename, sizeof(infoname));
1359:     /* remove .gz if it ends file name */
1360:     PetscStrstr(infoname, ".gz", &gz);
1361:     if (gz && gz[3] == 0) *gz = 0;

1363:     PetscStrlcat(infoname, ".info", sizeof(infoname));
1364:     if (vbinary->filemode == FILE_MODE_READ) {
1365:       PetscFixFilename(infoname, iname);
1366:       PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), iname, infoname, PETSC_MAX_PATH_LEN, &found);
1367:       if (found) PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer), ((PetscObject)viewer)->options, infoname, PETSC_FALSE);
1368:     } else if (rank == 0) { /* write or append */
1369:       const char *omode  = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
1370:       vbinary->fdes_info = fopen(infoname, omode);
1372:     }
1373:   }
1374:   return 0;
1375: }

1377: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1378: {
1379:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1380:   PetscBool           usempiio;

1382:   if (!vbinary->setfromoptionscalled) PetscViewerSetFromOptions(viewer);
1385:   PetscViewerFileClose_Binary(viewer);

1387:   PetscViewerBinaryGetUseMPIIO(viewer, &usempiio);
1388:   if (usempiio) {
1389: #if defined(PETSC_HAVE_MPIIO)
1390:     PetscViewerFileSetUp_BinaryMPIIO(viewer);
1391: #endif
1392:   } else {
1393:     PetscViewerFileSetUp_BinarySTDIO(viewer);
1394:   }
1395:   PetscViewerFileSetUp_BinaryInfo(viewer);

1397:   PetscLogObjectState((PetscObject)viewer, "File: %s", vbinary->filename);
1398:   return 0;
1399: }

1401: static PetscErrorCode PetscViewerView_Binary(PetscViewer v, PetscViewer viewer)
1402: {
1403:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
1404:   const char         *fname   = vbinary->filename ? vbinary->filename : "not yet set";
1405:   const char         *fmode   = vbinary->filemode != (PetscFileMode)-1 ? PetscFileModes[vbinary->filemode] : "not yet set";
1406:   PetscBool           usempiio;

1408:   PetscViewerBinaryGetUseMPIIO(v, &usempiio);
1409:   PetscViewerASCIIPrintf(viewer, "Filename: %s\n", fname);
1410:   PetscViewerASCIIPrintf(viewer, "Mode: %s (%s)\n", fmode, usempiio ? "mpiio" : "stdio");
1411:   return 0;
1412: }

1414: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscViewer viewer, PetscOptionItems *PetscOptionsObject)
1415: {
1416:   PetscViewer_Binary *binary = (PetscViewer_Binary *)viewer->data;
1417:   char                defaultname[PETSC_MAX_PATH_LEN];
1418:   PetscBool           flg;

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

1438: /*MC
1439:    PETSCVIEWERBINARY - A viewer that saves to binary files

1441:   Level: beginner

1443: .seealso: [](sec_viewers), `PetscViewerBinaryOpen()`, `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1444:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, `PETSCVIEWERDRAW`, `PETSCVIEWERSOCKET`
1445:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`,
1446:           `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`
1447: M*/

1449: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1450: {
1451:   PetscViewer_Binary *vbinary;

1453:   PetscNew(&vbinary);
1454:   v->data = (void *)vbinary;

1456:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1457:   v->ops->destroy          = PetscViewerDestroy_Binary;
1458:   v->ops->view             = PetscViewerView_Binary;
1459:   v->ops->setup            = PetscViewerSetUp_Binary;
1460:   v->ops->flush            = NULL; /* Should we support Flush() ? */
1461:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1462:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1463:   v->ops->read             = PetscViewerBinaryRead;

1465:   vbinary->fdes = -1;
1466: #if defined(PETSC_HAVE_MPIIO)
1467:   vbinary->usempiio = PETSC_FALSE;
1468:   vbinary->mfdes    = MPI_FILE_NULL;
1469:   vbinary->mfsub    = MPI_FILE_NULL;
1470: #endif
1471:   vbinary->filename        = NULL;
1472:   vbinary->filemode        = FILE_MODE_UNDEFINED;
1473:   vbinary->fdes_info       = NULL;
1474:   vbinary->skipinfo        = PETSC_FALSE;
1475:   vbinary->skipoptions     = PETSC_TRUE;
1476:   vbinary->skipheader      = PETSC_FALSE;
1477:   vbinary->storecompressed = PETSC_FALSE;
1478:   vbinary->ogzfilename     = NULL;
1479:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

1481:   vbinary->setfromoptionscalled = PETSC_FALSE;

1483:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Binary);
1484:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", PetscViewerBinarySetFlowControl_Binary);
1485:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Binary);
1486:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Binary);
1487:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", PetscViewerBinaryGetSkipOptions_Binary);
1488:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", PetscViewerBinarySetSkipOptions_Binary);
1489:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", PetscViewerBinaryGetSkipInfo_Binary);
1490:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", PetscViewerBinarySetSkipInfo_Binary);
1491:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", PetscViewerBinaryGetInfoPointer_Binary);
1492:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_Binary);
1493:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_Binary);
1494:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_Binary);
1495:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Binary);
1496: #if defined(PETSC_HAVE_MPIIO)
1497:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", PetscViewerBinaryGetUseMPIIO_Binary);
1498:   PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", PetscViewerBinarySetUseMPIIO_Binary);
1499: #endif
1500:   return 0;
1501: }

1503: /* ---------------------------------------------------------------------*/
1504: /*
1505:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1506:   is attached to a communicator, in this case the attribute is a PetscViewer.
1507: */
1508: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

1510: /*@C
1511:      PETSC_VIEWER_BINARY_ - Creates a `PETSCVIEWERBINARY` `PetscViewer` shared by all processors
1512:                      in a communicator.

1514:      Collective

1516:      Input Parameter:
1517: .    comm - the MPI communicator to share the `PETSCVIEWERBINARY`

1519:      Level: intermediate

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

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

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

1536: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PETSC_VIEWER_BINARY_WORLD`, `PETSC_VIEWER_BINARY_SELF`, `PetscViewerBinaryOpen()`, `PetscViewerCreate()`,
1537:           `PetscViewerDestroy()`
1538: @*/
1539: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1540: {
1542:   PetscBool      flg;
1543:   PetscViewer    viewer;
1544:   char           fname[PETSC_MAX_PATH_LEN];
1545:   MPI_Comm       ncomm;

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