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:   PetscFunctionBegin;
 30:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", NULL));
 31:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", NULL));
 32:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", NULL));
 33:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", NULL));
 34:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", NULL));
 35:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", NULL));
 36:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", NULL));
 37:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", NULL));
 38:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", NULL));
 39:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", NULL));
 40:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", NULL));
 41:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", NULL));
 42:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", NULL));
 43: #if defined(PETSC_HAVE_MPIIO)
 44:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", NULL));
 45:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", NULL));
 46: #endif
 47:   PetscFunctionReturn(PETSC_SUCCESS);
 48: }

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

 55:   PetscFunctionBegin;
 56:   if (vbinary->filemode == FILE_MODE_READ) PetscFunctionReturn(PETSC_SUCCESS);
 57:   if (vbinary->mfsub != MPI_FILE_NULL) PetscCallMPI(MPI_File_sync(vbinary->mfsub));
 58:   if (vbinary->mfdes != MPI_FILE_NULL) {
 59:     PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)viewer)));
 60:     PetscCallMPI(MPI_File_sync(vbinary->mfdes));
 61:   }
 62:   PetscFunctionReturn(PETSC_SUCCESS);
 63: }
 64: #endif

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

 71:   PetscFunctionBegin;
 72:   PetscCall(PetscViewerSetUp(viewer));

 74:   /* Return subviewer in process zero */
 75:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
 76:   if (rank == 0) {
 77:     PetscMPIInt flg;

 79:     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
 80:     PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERBINARY requires a singleton MPI_Comm");
 81:     PetscCall(PetscViewerCreate(comm, outviewer));
 82:     PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERBINARY));
 83:     PetscCall(PetscMemcpy((*outviewer)->data, vbinary, sizeof(PetscViewer_Binary)));
 84:     (*outviewer)->setupcalled = PETSC_TRUE;
 85:   } else {
 86:     *outviewer = NULL;
 87:   }

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

117: #if defined(PETSC_HAVE_MPIIO)
118:   PetscCall(PetscViewerBinarySyncMPIIO(viewer));
119: #endif
120:   PetscFunctionReturn(PETSC_SUCCESS);
121: }

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

131:   PetscFunctionBegin;
132:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
133:   PetscCheck(rank == 0 || !*outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Subviewer not obtained from viewer");

135: #if defined(PETSC_HAVE_MPIIO)
136:   if (vbinary->usempiio && *outviewer) {
137:     PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
138:     PetscCheck(obinary->mfdes == vbinary->mfsub, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Subviewer not obtained from viewer");
139:     if (obinary->mfsub != MPI_FILE_NULL) PetscCallMPI(MPI_File_close(&obinary->mfsub));
140:     moff = obinary->moff;
141:   }
142: #endif

144:   if (*outviewer) {
145:     PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
146:     PetscCheck(obinary->fdes == vbinary->fdes, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Subviewer not obtained from viewer");
147:     PetscCall(PetscFree((*outviewer)->data));
148:     PetscCall(PetscViewerBinaryClearFunctionList(*outviewer));
149:     PetscCall(PetscHeaderDestroy(outviewer));
150:   }

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

160: #if defined(PETSC_HAVE_MPIIO)
161:   PetscCall(PetscViewerBinarySyncMPIIO(viewer));
162: #endif
163:   PetscFunctionReturn(PETSC_SUCCESS);
164: }

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

170:     Not Collective; No Fortran Support

172:     Input Parameter:
173: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

175:     Output Parameter:
176: .   off - the current global offset

178:     Level: advanced

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

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

189:   PetscFunctionBegin;
192:   vbinary = (PetscViewer_Binary *)viewer->data;
193:   *off    = vbinary->moff;
194:   PetscFunctionReturn(PETSC_SUCCESS);
195: }

197: /*@C
198:     PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset

200:     Logically Collective; No Fortran Support

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

206:     Level: advanced

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

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

217:   PetscFunctionBegin;
220:   vbinary = (PetscViewer_Binary *)viewer->data;
221:   vbinary->moff += off;
222:   PetscFunctionReturn(PETSC_SUCCESS);
223: }

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

228:     Not Collective; No Fortran Support

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

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

236:     Level: advanced

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

244:   PetscFunctionBegin;
247:   PetscCall(PetscViewerSetUp(viewer));
248:   vbinary = (PetscViewer_Binary *)viewer->data;
249:   *fdes   = vbinary->mfdes;
250:   PetscFunctionReturn(PETSC_SUCCESS);
251: }
252: #endif

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

258:     Logically Collective

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

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

267:     Level: advanced

269: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
270:           `PetscViewerBinaryGetUseMPIIO()`
271: @*/
272: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer, PetscBool use)
273: {
274:   PetscFunctionBegin;
277:   PetscTryMethod(viewer, "PetscViewerBinarySetUseMPIIO_C", (PetscViewer, PetscBool), (viewer, use));
278:   PetscFunctionReturn(PETSC_SUCCESS);
279: }

281: #if defined(PETSC_HAVE_MPIIO)
282: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer, PetscBool use)
283: {
284:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
285:   PetscFunctionBegin;
286:   PetscCheck(!viewer->setupcalled || vbinary->usempiio == use, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Cannot change MPIIO to %s after setup", PetscBools[use]);
287:   vbinary->usempiio = use;
288:   PetscFunctionReturn(PETSC_SUCCESS);
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: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
309: @*/
310: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer, PetscBool *use)
311: {
312:   PetscFunctionBegin;
315:   *use = PETSC_FALSE;
316:   PetscTryMethod(viewer, "PetscViewerBinaryGetUseMPIIO_C", (PetscViewer, PetscBool *), (viewer, use));
317:   PetscFunctionReturn(PETSC_SUCCESS);
318: }

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

325:   PetscFunctionBegin;
326:   *use = vbinary->usempiio;
327:   PetscFunctionReturn(PETSC_SUCCESS);
328: }
329: #endif

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

334:     Not Collective

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

340:     Level: advanced

342: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetFlowControl()`
343: @*/
344: PetscErrorCode PetscViewerBinarySetFlowControl(PetscViewer viewer, PetscInt fc)
345: {
346:   PetscFunctionBegin;
349:   PetscTryMethod(viewer, "PetscViewerBinarySetFlowControl_C", (PetscViewer, PetscInt), (viewer, fc));
350:   PetscFunctionReturn(PETSC_SUCCESS);
351: }

353: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer, PetscInt fc)
354: {
355:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

357:   PetscFunctionBegin;
358:   PetscCheck(fc > 1, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_OUTOFRANGE, "Flow control count must be greater than 1, %" PetscInt_FMT " was set", fc);
359:   vbinary->flowcontrol = fc;
360:   PetscFunctionReturn(PETSC_SUCCESS);
361: }

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

366:     Not Collective

368:     Input Parameter:
369: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

371:     Output Parameter:
372: .   fc - the number of messages

374:     Level: advanced

376: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetFlowControl()`
377: @*/
378: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer, PetscInt *fc)
379: {
380:   PetscFunctionBegin;
383:   PetscUseMethod(viewer, "PetscViewerBinaryGetFlowControl_C", (PetscViewer, PetscInt *), (viewer, fc));
384:   PetscFunctionReturn(PETSC_SUCCESS);
385: }

387: PETSC_INTERN PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer, PetscInt *fc)
388: {
389:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

391:   PetscFunctionBegin;
392:   *fc = vbinary->flowcontrol;
393:   PetscFunctionReturn(PETSC_SUCCESS);
394: }

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

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

401:     Input Parameter:
402: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

404:     Output Parameter:
405: .   fdes - file descriptor

407:     Level: advanced

409:     Note:
410:       For writable binary `PetscViewer`s, the descriptor will only be valid for the
411:     first processor in the communicator that shares the `PetscViewer`. For readable
412:     files it will only be valid on processes that have the file. If MPI rank 0 does not
413:     have the file it generates an error even if another MPI process does have the file.

415: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`
416: @*/
417: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer, int *fdes)
418: {
419:   PetscViewer_Binary *vbinary;

421:   PetscFunctionBegin;
424:   PetscCall(PetscViewerSetUp(viewer));
425:   vbinary = (PetscViewer_Binary *)viewer->data;
426:   *fdes   = vbinary->fdes;
427:   PetscFunctionReturn(PETSC_SUCCESS);
428: }

430: /*@
431:     PetscViewerBinarySkipInfo - Binary file will not have `.info` file created with it

433:     Not Collective

435:     Input Parameter:
436: .   viewer - `PetscViewer` context, obtained from `PetscViewerCreate()`

438:     Options Database Key:
439: .   -viewer_binary_skip_info - true indicates do not generate `.info` file

441:     Level: advanced

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

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

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

453: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
454:           `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
455: @*/
456: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
457: {
458:   PetscFunctionBegin;
459:   PetscCall(PetscViewerBinarySetSkipInfo(viewer, PETSC_TRUE));
460:   PetscFunctionReturn(PETSC_SUCCESS);
461: }

463: /*@
464:     PetscViewerBinarySetSkipInfo - Binary file will not have `.info` file created with it

466:     Not Collective

468:     Input Parameters:
469: +   viewer - PetscViewer context, obtained from `PetscViewerCreate()`
470: -   skip - `PETSC_TRUE` implies the `.info` file will not be generated

472:     Options Database Key:
473: .   -viewer_binary_skip_info - true indicates do not generate `.info` file

475:     Level: advanced

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

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

485: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
486:           `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`, `PetscViewerBinaryGetInfoPointer()`
487: @*/
488: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer, PetscBool skip)
489: {
490:   PetscFunctionBegin;
493:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipInfo_C", (PetscViewer, PetscBool), (viewer, skip));
494:   PetscFunctionReturn(PETSC_SUCCESS);
495: }

497: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer, PetscBool skip)
498: {
499:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

501:   PetscFunctionBegin;
502:   vbinary->skipinfo = skip;
503:   PetscFunctionReturn(PETSC_SUCCESS);
504: }

506: /*@
507:     PetscViewerBinaryGetSkipInfo - check if viewer wrote a `.info` file

509:     Not Collective

511:     Input Parameter:
512: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

514:     Output Parameter:
515: .   skip - `PETSC_TRUE` implies the `.info` file was not generated

517:     Level: advanced

519:     Note:
520:     This must be called after `PetscViewerSetType()`

522: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`,
523:           `PetscViewerBinarySetSkipOptions()`, `PetscViewerBinarySetSkipInfo()`, `PetscViewerBinaryGetInfoPointer()`
524: @*/
525: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer, PetscBool *skip)
526: {
527:   PetscFunctionBegin;
530:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipInfo_C", (PetscViewer, PetscBool *), (viewer, skip));
531:   PetscFunctionReturn(PETSC_SUCCESS);
532: }

534: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer, PetscBool *skip)
535: {
536:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

538:   PetscFunctionBegin;
539:   *skip = vbinary->skipinfo;
540:   PetscFunctionReturn(PETSC_SUCCESS);
541: }

543: /*@
544:     PetscViewerBinarySetSkipOptions - do not use values in the PETSc options database when loading objects

546:     Not Collective

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

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

555:     Level: advanced

557:     Note:
558:     This must be called after `PetscViewerSetType()`

560: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
561:           `PetscViewerBinaryGetSkipOptions()`
562: @*/
563: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer, PetscBool skip)
564: {
565:   PetscFunctionBegin;
568:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipOptions_C", (PetscViewer, PetscBool), (viewer, skip));
569:   PetscFunctionReturn(PETSC_SUCCESS);
570: }

572: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer, PetscBool skip)
573: {
574:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

576:   PetscFunctionBegin;
577:   vbinary->skipoptions = skip;
578:   PetscFunctionReturn(PETSC_SUCCESS);
579: }

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

584:     Not Collective

586:     Input Parameter:
587: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

589:     Output Parameter:
590: .   skip - `PETSC_TRUE` means do not use

592:     Level: advanced

594:     Note:
595:     This must be called after `PetscViewerSetType()`

597: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
598:           `PetscViewerBinarySetSkipOptions()`
599: @*/
600: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer, PetscBool *skip)
601: {
602:   PetscFunctionBegin;
605:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipOptions_C", (PetscViewer, PetscBool *), (viewer, skip));
606:   PetscFunctionReturn(PETSC_SUCCESS);
607: }

609: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer, PetscBool *skip)
610: {
611:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

613:   PetscFunctionBegin;
614:   *skip = vbinary->skipoptions;
615:   PetscFunctionReturn(PETSC_SUCCESS);
616: }

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

621:     Not Collective

623:     Input Parameters:
624: +   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
625: -   skip - `PETSC_TRUE` means do not write header

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

630:     Level: advanced

632:     Notes:
633:       This must be called after `PetscViewerSetType()`

635:     If this option is selected, the output file cannot be read with the `XXXLoad()` such as `VecLoad()`

637: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
638:           `PetscViewerBinaryGetSkipHeader()`
639: @*/
640: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer, PetscBool skip)
641: {
642:   PetscFunctionBegin;
645:   PetscTryMethod(viewer, "PetscViewerBinarySetSkipHeader_C", (PetscViewer, PetscBool), (viewer, skip));
646:   PetscFunctionReturn(PETSC_SUCCESS);
647: }

649: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer, PetscBool skip)
650: {
651:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

653:   PetscFunctionBegin;
654:   vbinary->skipheader = skip;
655:   PetscFunctionReturn(PETSC_SUCCESS);
656: }

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

661:     Not Collective

663:     Input Parameter:
664: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

666:     Output Parameter:
667: .   skip - `PETSC_TRUE` means do not write header

669:     Level: advanced

671:     Notes:
672:     This must be called after PetscViewerSetType()

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

676: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
677:           `PetscViewerBinarySetSkipHeader()`
678: @*/
679: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer, PetscBool *skip)
680: {
681:   PetscFunctionBegin;
684:   PetscUseMethod(viewer, "PetscViewerBinaryGetSkipHeader_C", (PetscViewer, PetscBool *), (viewer, skip));
685:   PetscFunctionReturn(PETSC_SUCCESS);
686: }

688: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer, PetscBool *skip)
689: {
690:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

692:   PetscFunctionBegin;
693:   *skip = vbinary->skipheader;
694:   PetscFunctionReturn(PETSC_SUCCESS);
695: }

697: /*@C
698:     PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
699:           `.info` file associated with a binary file.

701:     Not Collective; No Fortran Support

703:     Input Parameter:
704: .   viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`

706:     Output Parameter:
707: .   file - file pointer  Always returns `NULL` if not a binary viewer

709:     Level: advanced

711:     Note:
712:       For writable binary `PetscViewer`s, the file pointer will only be valid for the
713:     first processor in the MPI communicator that shares the `PetscViewer`.

715: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinaryGetSkipInfo()`,
716:           `PetscViewerBinarySetSkipInfo()`
717: @*/
718: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer, FILE **file)
719: {
720:   PetscFunctionBegin;
723:   *file = NULL;
724:   PetscTryMethod(viewer, "PetscViewerBinaryGetInfoPointer_C", (PetscViewer, FILE **), (viewer, file));
725:   PetscFunctionReturn(PETSC_SUCCESS);
726: }

728: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer, FILE **file)
729: {
730:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

732:   PetscFunctionBegin;
733:   PetscCall(PetscViewerSetUp(viewer));
734:   *file = vbinary->fdes_info;
735:   if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
736:     if (vbinary->fdes_info) {
737:       FILE *info = vbinary->fdes_info;
738:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n"));
739:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#$$ Set.filename = '%s';\n", vbinary->filename));
740:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#$$ fd = PetscOpenFile(Set.filename);\n"));
741:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n"));
742:     }
743:     vbinary->matlabheaderwritten = PETSC_TRUE;
744:   }
745:   PetscFunctionReturn(PETSC_SUCCESS);
746: }

748: #if defined(PETSC_HAVE_MPIIO)
749: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
750: {
751:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

753:   PetscFunctionBegin;
754:   if (vbinary->mfdes != MPI_FILE_NULL) PetscCallMPI(MPI_File_close(&vbinary->mfdes));
755:   if (vbinary->mfsub != MPI_FILE_NULL) PetscCallMPI(MPI_File_close(&vbinary->mfsub));
756:   vbinary->moff = 0;
757:   PetscFunctionReturn(PETSC_SUCCESS);
758: }
759: #endif

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

765:   PetscFunctionBegin;
766:   if (vbinary->fdes != -1) {
767:     PetscCall(PetscBinaryClose(vbinary->fdes));
768:     vbinary->fdes = -1;
769:     if (vbinary->storecompressed) {
770:       char        cmd[8 + PETSC_MAX_PATH_LEN], out[64 + PETSC_MAX_PATH_LEN] = "";
771:       const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
772:       /* compress the file */
773:       PetscCall(PetscStrncpy(cmd, "gzip -f ", sizeof(cmd)));
774:       PetscCall(PetscStrlcat(cmd, gzfilename, sizeof(cmd)));
775: #if defined(PETSC_HAVE_POPEN)
776:       {
777:         FILE *fp;
778:         PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, cmd, "r", &fp));
779:         PetscCheck(!fgets(out, (int)(sizeof(out) - 1), fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from command %s\n%s", cmd, out);
780:         PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
781:       }
782: #endif
783:     }
784:   }
785:   PetscCall(PetscFree(vbinary->ogzfilename));
786:   PetscFunctionReturn(PETSC_SUCCESS);
787: }

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

793:   PetscFunctionBegin;
794:   if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
795:     if (vbinary->fdes_info) {
796:       FILE *info = vbinary->fdes_info;
797:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n"));
798:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#$$ close(fd);\n"));
799:       PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n"));
800:     }
801:   }
802:   if (vbinary->fdes_info) {
803:     FILE *info         = vbinary->fdes_info;
804:     vbinary->fdes_info = NULL;
805:     PetscCheck(!fclose(info), PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
806:   }
807:   PetscFunctionReturn(PETSC_SUCCESS);
808: }

810: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
811: {
812:   PetscFunctionBegin;
813: #if defined(PETSC_HAVE_MPIIO)
814:   PetscCall(PetscViewerFileClose_BinaryMPIIO(v));
815: #endif
816:   PetscCall(PetscViewerFileClose_BinarySTDIO(v));
817:   PetscCall(PetscViewerFileClose_BinaryInfo(v));
818:   PetscFunctionReturn(PETSC_SUCCESS);
819: }

821: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
822: {
823:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;

825:   PetscFunctionBegin;
826:   PetscCall(PetscViewerFileClose_Binary(v));
827:   PetscCall(PetscFree(vbinary->filename));
828:   PetscCall(PetscFree(vbinary));
829:   PetscCall(PetscViewerBinaryClearFunctionList(v));
830:   PetscFunctionReturn(PETSC_SUCCESS);
831: }

833: /*@C
834:    PetscViewerBinaryOpen - Opens a file for binary input/output.

836:    Collective

838:    Input Parameters:
839: +  comm - MPI communicator
840: .  name - name of file
841: -  mode - open mode of file
842: .vb
843:     FILE_MODE_WRITE - create new file for binary output
844:     FILE_MODE_READ - open existing file for binary input
845:     FILE_MODE_APPEND - open existing file for binary output
846: .ve

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

851:     Options Database Keys:
852: +    -viewer_binary_filename <name> - name of file to use
853: .    -viewer_binary_skip_info - true to skip opening an info file
854: .    -viewer_binary_skip_options - true to not use options database while creating viewer
855: .    -viewer_binary_skip_header - true to skip output object headers to the file
856: -    -viewer_binary_mpiio - true to use MPI-IO for input and output to the file (more scalable for large problems)

858:    Level: beginner

860:    Note:
861:    This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.

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

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

869: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
870:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
871:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`, `PetscViewerBinarySetUseMPIIO()`,
872:           `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
873: @*/
874: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm, const char name[], PetscFileMode mode, PetscViewer *viewer)
875: {
876:   PetscFunctionBegin;
877:   PetscCall(PetscViewerCreate(comm, viewer));
878:   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERBINARY));
879:   PetscCall(PetscViewerFileSetMode(*viewer, mode));
880:   PetscCall(PetscViewerFileSetName(*viewer, name));
881:   PetscCall(PetscViewerSetFromOptions(*viewer));
882:   PetscFunctionReturn(PETSC_SUCCESS);
883: }

885: #if defined(PETSC_HAVE_MPIIO)
886: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype, PetscBool write)
887: {
888:   MPI_Comm            comm    = PetscObjectComm((PetscObject)viewer);
889:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
890:   MPI_File            mfdes   = vbinary->mfdes;
891:   MPI_Datatype        mdtype;
892:   PetscMPIInt         rank, cnt;
893:   MPI_Status          status;
894:   MPI_Aint            ul, dsize;

896:   PetscFunctionBegin;
897:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
898:   PetscCall(PetscMPIIntCast(num, &cnt));
899:   PetscCall(PetscDataTypeToMPIDataType(dtype, &mdtype));
900:   if (write) {
901:     if (rank == 0) PetscCall(MPIU_File_write_at(mfdes, vbinary->moff, data, cnt, mdtype, &status));
902:   } else {
903:     if (rank == 0) {
904:       PetscCall(MPIU_File_read_at(mfdes, vbinary->moff, data, cnt, mdtype, &status));
905:       if (cnt > 0) PetscCallMPI(MPI_Get_count(&status, mdtype, &cnt));
906:     }
907:     PetscCallMPI(MPI_Bcast(&cnt, 1, MPI_INT, 0, comm));
908:     PetscCallMPI(MPI_Bcast(data, cnt, mdtype, 0, comm));
909:   }
910:   PetscCallMPI(MPI_Type_get_extent(mdtype, &ul, &dsize));
911:   vbinary->moff += dsize * cnt;
912:   if (count) *count = cnt;
913:   PetscFunctionReturn(PETSC_SUCCESS);
914: }
915: #endif

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

920:    Collective

922:    Input Parameters:
923: +  viewer - the `PETSCVIEWERBINARY` viewer
924: .  num - number of items of data to read
925: -  dtype - type of data to read

927:    Output Parameters:
928: +  data - location of the read data, treated as an array of the type indicated by `dtype`
929: -  count - number of items of data actually read, or `NULL`.

931:    Level: beginner

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

941:   PetscFunctionBegin;
944:   PetscCall(PetscViewerSetUp(viewer));
945:   vbinary = (PetscViewer_Binary *)viewer->data;
946: #if defined(PETSC_HAVE_MPIIO)
947:   if (vbinary->usempiio) {
948:     PetscCall(PetscViewerBinaryWriteReadMPIIO(viewer, data, num, count, dtype, PETSC_FALSE));
949:   } else {
950: #endif
951:     PetscCall(PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, num, count, dtype));
952: #if defined(PETSC_HAVE_MPIIO)
953:   }
954: #endif
955:   PetscFunctionReturn(PETSC_SUCCESS);
956: }

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

961:    Collective

963:    Input Parameters:
964: +  viewer - the `PETSCVIEWERBINARY` viewer
965: .  data - location of data, treated as an array of the type indicated by `dtype`
966: .  count - number of items of data to write
967: -  dtype - type of data to write

969:    Level: beginner

971: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
972:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, `PetscDataType`
973:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
974: @*/
975: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer, const void *data, PetscInt count, PetscDataType dtype)
976: {
977:   PetscViewer_Binary *vbinary;

979:   PetscFunctionBegin;
982:   PetscCall(PetscViewerSetUp(viewer));
983:   vbinary = (PetscViewer_Binary *)viewer->data;
984: #if defined(PETSC_HAVE_MPIIO)
985:   if (vbinary->usempiio) {
986:     PetscCall(PetscViewerBinaryWriteReadMPIIO(viewer, (void *)data, count, NULL, dtype, PETSC_TRUE));
987:   } else {
988: #endif
989:     PetscCall(PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, count, dtype));
990: #if defined(PETSC_HAVE_MPIIO)
991:   }
992: #endif
993:   PetscFunctionReturn(PETSC_SUCCESS);
994: }

996: static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer, PetscBool write, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
997: {
998:   MPI_Comm              comm = PetscObjectComm((PetscObject)viewer);
999:   PetscMPIInt           size, rank;
1000:   MPI_Datatype          mdtype;
1001:   PETSC_UNUSED MPI_Aint lb;
1002:   MPI_Aint              dsize;
1003:   PetscBool             useMPIIO;

1005:   PetscFunctionBegin;
1010:   PetscCall(PetscViewerSetUp(viewer));

1012:   PetscCall(PetscDataTypeToMPIDataType(dtype, &mdtype));
1013:   PetscCallMPI(MPI_Type_get_extent(mdtype, &lb, &dsize));
1014:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1015:   PetscCallMPI(MPI_Comm_size(comm, &size));

1017:   PetscCall(PetscViewerBinaryGetUseMPIIO(viewer, &useMPIIO));
1018: #if defined(PETSC_HAVE_MPIIO)
1019:   if (useMPIIO) {
1020:     MPI_File    mfdes;
1021:     MPI_Offset  off;
1022:     PetscMPIInt cnt;

1024:     if (start == PETSC_DETERMINE) {
1025:       PetscCallMPI(MPI_Scan(&count, &start, 1, MPIU_INT, MPI_SUM, comm));
1026:       start -= count;
1027:     }
1028:     if (total == PETSC_DETERMINE) {
1029:       total = start + count;
1030:       PetscCallMPI(MPI_Bcast(&total, 1, MPIU_INT, size - 1, comm));
1031:     }
1032:     PetscCall(PetscMPIIntCast(count, &cnt));
1033:     PetscCall(PetscViewerBinaryGetMPIIODescriptor(viewer, &mfdes));
1034:     PetscCall(PetscViewerBinaryGetMPIIOOffset(viewer, &off));
1035:     off += (MPI_Offset)(start * dsize);
1036:     if (write) {
1037:       PetscCall(MPIU_File_write_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE));
1038:     } else {
1039:       PetscCall(MPIU_File_read_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE));
1040:     }
1041:     off = (MPI_Offset)(total * dsize);
1042:     PetscCall(PetscViewerBinaryAddMPIIOOffset(viewer, off));
1043:     PetscFunctionReturn(PETSC_SUCCESS);
1044:   }
1045: #endif
1046:   {
1047:     int         fdes;
1048:     char       *workbuf = NULL;
1049:     PetscInt    tcount = rank == 0 ? 0 : count, maxcount = 0, message_count, flowcontrolcount;
1050:     PetscMPIInt tag, cnt, maxcnt, scnt = 0, rcnt = 0, j;
1051:     MPI_Status  status;

1053:     PetscCall(PetscCommGetNewTag(comm, &tag));
1054:     PetscCallMPI(MPI_Reduce(&tcount, &maxcount, 1, MPIU_INT, MPI_MAX, 0, comm));
1055:     PetscCall(PetscMPIIntCast(maxcount, &maxcnt));
1056:     PetscCall(PetscMPIIntCast(count, &cnt));

1058:     PetscCall(PetscViewerBinaryGetDescriptor(viewer, &fdes));
1059:     PetscCall(PetscViewerFlowControlStart(viewer, &message_count, &flowcontrolcount));
1060:     if (rank == 0) {
1061:       PetscCall(PetscMalloc(maxcnt * dsize, &workbuf));
1062:       if (write) {
1063:         PetscCall(PetscBinaryWrite(fdes, data, cnt, dtype));
1064:       } else {
1065:         PetscCall(PetscBinaryRead(fdes, data, cnt, NULL, dtype));
1066:       }
1067:       for (j = 1; j < size; j++) {
1068:         PetscCall(PetscViewerFlowControlStepMain(viewer, j, &message_count, flowcontrolcount));
1069:         if (write) {
1070:           PetscCallMPI(MPI_Recv(workbuf, maxcnt, mdtype, j, tag, comm, &status));
1071:           PetscCallMPI(MPI_Get_count(&status, mdtype, &rcnt));
1072:           PetscCall(PetscBinaryWrite(fdes, workbuf, rcnt, dtype));
1073:         } else {
1074:           PetscCallMPI(MPI_Recv(&scnt, 1, MPI_INT, j, tag, comm, MPI_STATUS_IGNORE));
1075:           PetscCall(PetscBinaryRead(fdes, workbuf, scnt, NULL, dtype));
1076:           PetscCallMPI(MPI_Send(workbuf, scnt, mdtype, j, tag, comm));
1077:         }
1078:       }
1079:       PetscCall(PetscFree(workbuf));
1080:       PetscCall(PetscViewerFlowControlEndMain(viewer, &message_count));
1081:     } else {
1082:       PetscCall(PetscViewerFlowControlStepWorker(viewer, rank, &message_count));
1083:       if (write) {
1084:         PetscCallMPI(MPI_Send(data, cnt, mdtype, 0, tag, comm));
1085:       } else {
1086:         PetscCallMPI(MPI_Send(&cnt, 1, MPI_INT, 0, tag, comm));
1087:         PetscCallMPI(MPI_Recv(data, cnt, mdtype, 0, tag, comm, MPI_STATUS_IGNORE));
1088:       }
1089:       PetscCall(PetscViewerFlowControlEndWorker(viewer, &message_count));
1090:     }
1091:   }
1092:   PetscFunctionReturn(PETSC_SUCCESS);
1093: }

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

1098:    Collective

1100:    Input Parameters:
1101: +  viewer - the `PETSCVIEWERBINARY` viewer
1102: .  count - local number of items of data to read
1103: .  start - local start, can be `PETSC_DETERMINE`
1104: .  total - global number of items of data to read, can be `PETSC_DETERMINE`
1105: -  dtype - type of data to read

1107:    Output Parameter:
1108: .  data - location of data, treated as an array of type indicated by `dtype`

1110:    Level: advanced

1112: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteAll()`
1113: @*/
1114: PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1115: {
1116:   PetscFunctionBegin;
1117:   PetscCall(PetscViewerBinaryWriteReadAll(viewer, PETSC_FALSE, data, count, start, total, dtype));
1118:   PetscFunctionReturn(PETSC_SUCCESS);
1119: }

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

1124:    Collective

1126:    Input Parameters:
1127: +  viewer - the `PETSCVIEWERBINARY` viewer
1128: .  data - location of data
1129: .  count - local number of items of data to write, treated as an array of type indicated by `dtype`
1130: .  start - local start, can be `PETSC_DETERMINE`
1131: .  total - global number of items of data to write, can be `PETSC_DETERMINE`
1132: -  dtype - type of data to write

1134:    Level: advanced

1136: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryWriteAll()`, `PetscViewerBinaryReadAll()`
1137: @*/
1138: PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer, const void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1139: {
1140:   PetscFunctionBegin;
1141:   PetscCall(PetscViewerBinaryWriteReadAll(viewer, PETSC_TRUE, (void *)data, count, start, total, dtype));
1142:   PetscFunctionReturn(PETSC_SUCCESS);
1143: }

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

1148:    Collective

1150:    Input Parameters:
1151: +  viewer - the `PETSCVIEWERBINARY` viewer
1152: -  data - location of the array of strings

1154:    Level: intermediate

1156:     Note:
1157:     The array of strings must be `NULL` terminated

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

1168:   PetscFunctionBegin;
1169:   PetscCall(PetscViewerSetUp(viewer));
1170:   /* count number of strings */
1171:   while (data[n++])
1172:     ;
1173:   n--;
1174:   PetscCall(PetscMalloc1(n + 1, &sizes));
1175:   sizes[0] = n;
1176:   for (i = 0; i < n; i++) {
1177:     PetscCall(PetscStrlen(data[i], &len));
1178:     sizes[i + 1] = (PetscInt)len + 1; /* size includes space for the null terminator */
1179:   }
1180:   PetscCall(PetscViewerBinaryWrite(viewer, sizes, n + 1, PETSC_INT));
1181:   for (i = 0; i < n; i++) PetscCall(PetscViewerBinaryWrite(viewer, (void *)data[i], sizes[i + 1], PETSC_CHAR));
1182:   PetscCall(PetscFree(sizes));
1183:   PetscFunctionReturn(PETSC_SUCCESS);
1184: }

1186: /*@C
1187:    PetscViewerBinaryReadStringArray - reads a binary file an array of strings to all MPI processes

1189:    Collective

1191:    Input Parameter:
1192: .  viewer - the `PETSCVIEWERBINARY` viewer

1194:    Output Parameter:
1195: .  data - location of the array of strings

1197:    Level: intermediate

1199:     Note:
1200:     The array of strings must `NULL` terminated

1202: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1203:           `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1204:           `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1205: @*/
1206: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer, char ***data)
1207: {
1208:   PetscInt i, n, *sizes, N = 0;

1210:   PetscFunctionBegin;
1211:   PetscCall(PetscViewerSetUp(viewer));
1212:   /* count number of strings */
1213:   PetscCall(PetscViewerBinaryRead(viewer, &n, 1, NULL, PETSC_INT));
1214:   PetscCall(PetscMalloc1(n, &sizes));
1215:   PetscCall(PetscViewerBinaryRead(viewer, sizes, n, NULL, PETSC_INT));
1216:   for (i = 0; i < n; i++) N += sizes[i];
1217:   PetscCall(PetscMalloc((n + 1) * sizeof(char *) + N * sizeof(char), data));
1218:   (*data)[0] = (char *)((*data) + n + 1);
1219:   for (i = 1; i < n; i++) (*data)[i] = (*data)[i - 1] + sizes[i - 1];
1220:   PetscCall(PetscViewerBinaryRead(viewer, (*data)[0], N, NULL, PETSC_CHAR));
1221:   (*data)[n] = NULL;
1222:   PetscCall(PetscFree(sizes));
1223:   PetscFunctionReturn(PETSC_SUCCESS);
1224: }

1226: /*@C
1227:      PetscViewerFileSetMode - Sets the open mode of file

1229:     Logically Collective

1231:   Input Parameters:
1232: +  viewer - the `PetscViewer`; must be a a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII`  `PetscViewer`
1233: -  mode - open mode of file
1234: .vb
1235:     FILE_MODE_WRITE - create new file for output
1236:     FILE_MODE_READ - open existing file for input
1237:     FILE_MODE_APPEND - open existing file for output
1238: .ve

1240:   Level: advanced

1242: .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1243: @*/
1244: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer, PetscFileMode mode)
1245: {
1246:   PetscFunctionBegin;
1249:   PetscCheck(mode != FILE_MODE_UNDEFINED, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot set FILE_MODE_UNDEFINED");
1250:   PetscCheck(mode >= FILE_MODE_UNDEFINED && mode <= FILE_MODE_APPEND_UPDATE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_OUTOFRANGE, "Invalid file mode %d", (int)mode);
1251:   PetscTryMethod(viewer, "PetscViewerFileSetMode_C", (PetscViewer, PetscFileMode), (viewer, mode));
1252:   PetscFunctionReturn(PETSC_SUCCESS);
1253: }

1255: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer, PetscFileMode mode)
1256: {
1257:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1259:   PetscFunctionBegin;
1260:   PetscCheck(!viewer->setupcalled || vbinary->filemode == mode, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Cannot change mode to %s after setup", PetscFileModes[mode]);
1261:   vbinary->filemode = mode;
1262:   PetscFunctionReturn(PETSC_SUCCESS);
1263: }

1265: /*@C
1266:      PetscViewerFileGetMode - Gets the open mode of a file associated with a `PetscViewer`

1268:     Not Collective

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

1273:   Output Parameter:
1274: .  mode - open mode of file
1275: .vb
1276:     FILE_MODE_WRITE - create new file for binary output
1277:     FILE_MODE_READ - open existing file for binary input
1278:     FILE_MODE_APPEND - open existing file for binary output
1279: .ve

1281:   Level: advanced

1283: .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1284: @*/
1285: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer, PetscFileMode *mode)
1286: {
1287:   PetscFunctionBegin;
1290:   PetscUseMethod(viewer, "PetscViewerFileGetMode_C", (PetscViewer, PetscFileMode *), (viewer, mode));
1291:   PetscFunctionReturn(PETSC_SUCCESS);
1292: }

1294: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer, PetscFileMode *mode)
1295: {
1296:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1298:   PetscFunctionBegin;
1299:   *mode = vbinary->filemode;
1300:   PetscFunctionReturn(PETSC_SUCCESS);
1301: }

1303: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer, const char name[])
1304: {
1305:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1307:   PetscFunctionBegin;
1308:   if (viewer->setupcalled && vbinary->filename) {
1309:     /* gzip can be run after the file with the previous filename has been closed */
1310:     PetscCall(PetscFree(vbinary->ogzfilename));
1311:     PetscCall(PetscStrallocpy(vbinary->filename, &vbinary->ogzfilename));
1312:   }
1313:   PetscCall(PetscFree(vbinary->filename));
1314:   PetscCall(PetscStrallocpy(name, &vbinary->filename));
1315:   viewer->setupcalled = PETSC_FALSE;
1316:   PetscFunctionReturn(PETSC_SUCCESS);
1317: }

1319: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer, const char **name)
1320: {
1321:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1323:   PetscFunctionBegin;
1324:   *name = vbinary->filename;
1325:   PetscFunctionReturn(PETSC_SUCCESS);
1326: }

1328: #if defined(PETSC_HAVE_MPIIO)
1329: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1330: {
1331:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1332:   int                 amode;

1334:   PetscFunctionBegin;
1335:   vbinary->storecompressed = PETSC_FALSE;

1337:   vbinary->moff = 0;
1338:   switch (vbinary->filemode) {
1339:   case FILE_MODE_READ:
1340:     amode = MPI_MODE_RDONLY;
1341:     break;
1342:   case FILE_MODE_WRITE:
1343:     amode = MPI_MODE_WRONLY | MPI_MODE_CREATE;
1344:     break;
1345:   case FILE_MODE_APPEND:
1346:     amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND;
1347:     break;
1348:   case FILE_MODE_UNDEFINED:
1349:     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerSetUp()");
1350:   default:
1351:     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vbinary->filemode]);
1352:   }
1353:   PetscCallMPI(MPI_File_open(PetscObjectComm((PetscObject)viewer), vbinary->filename, amode, MPI_INFO_NULL, &vbinary->mfdes));
1354:   /*
1355:       The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
1356:   */
1357:   if (vbinary->filemode == FILE_MODE_WRITE) PetscCallMPI(MPI_File_set_size(vbinary->mfdes, 0));
1358:   /*
1359:       Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
1360:       MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
1361:       Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
1362:       the offset in etype units to an absolute byte position.
1363:    */
1364:   if (vbinary->filemode == FILE_MODE_APPEND) PetscCallMPI(MPI_File_get_position(vbinary->mfdes, &vbinary->moff));
1365:   PetscFunctionReturn(PETSC_SUCCESS);
1366: }
1367: #endif

1369: static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
1370: {
1371:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1372:   const char         *fname;
1373:   char                bname[PETSC_MAX_PATH_LEN], *gz = NULL;
1374:   PetscBool           found;
1375:   PetscMPIInt         rank;

1377:   PetscFunctionBegin;
1378:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));

1380:   /* if file name ends in .gz strip that off and note user wants file compressed */
1381:   vbinary->storecompressed = PETSC_FALSE;
1382:   if (vbinary->filemode == FILE_MODE_WRITE) {
1383:     PetscCall(PetscStrstr(vbinary->filename, ".gz", &gz));
1384:     if (gz && gz[3] == 0) {
1385:       *gz                      = 0;
1386:       vbinary->storecompressed = PETSC_TRUE;
1387:     }
1388:   }
1389: #if !defined(PETSC_HAVE_POPEN)
1390:   PetscCheck(!vbinary->storecompressed, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP_SYS, "Cannot run gzip on this machine");
1391: #endif

1393:   fname = vbinary->filename;
1394:   if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
1395:     PetscCall(PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), fname, bname, PETSC_MAX_PATH_LEN, &found));
1396:     PetscCheck(found, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_OPEN, "Cannot locate file: %s", fname);
1397:     fname = bname;
1398:   }

1400:   vbinary->fdes = -1;
1401:   if (rank == 0) { /* only first processor opens file*/
1402:     PetscFileMode mode = vbinary->filemode;
1403:     if (mode == FILE_MODE_APPEND) {
1404:       /* check if asked to append to a non-existing file */
1405:       PetscCall(PetscTestFile(fname, '\0', &found));
1406:       if (!found) mode = FILE_MODE_WRITE;
1407:     }
1408:     PetscCall(PetscBinaryOpen(fname, mode, &vbinary->fdes));
1409:   }
1410:   PetscFunctionReturn(PETSC_SUCCESS);
1411: }

1413: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1414: {
1415:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1416:   PetscMPIInt         rank;
1417:   PetscBool           found;

1419:   PetscFunctionBegin;
1420:   vbinary->fdes_info = NULL;
1421:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1422:   if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || rank == 0)) {
1423:     char infoname[PETSC_MAX_PATH_LEN], iname[PETSC_MAX_PATH_LEN], *gz;

1425:     PetscCall(PetscStrncpy(infoname, vbinary->filename, sizeof(infoname)));
1426:     /* remove .gz if it ends file name */
1427:     PetscCall(PetscStrstr(infoname, ".gz", &gz));
1428:     if (gz && gz[3] == 0) *gz = 0;

1430:     PetscCall(PetscStrlcat(infoname, ".info", sizeof(infoname)));
1431:     if (vbinary->filemode == FILE_MODE_READ) {
1432:       PetscCall(PetscFixFilename(infoname, iname));
1433:       PetscCall(PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), iname, infoname, PETSC_MAX_PATH_LEN, &found));
1434:       if (found) PetscCall(PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer), ((PetscObject)viewer)->options, infoname, PETSC_FALSE));
1435:     } else if (rank == 0) { /* write or append */
1436:       const char *omode  = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
1437:       vbinary->fdes_info = fopen(infoname, omode);
1438:       PetscCheck(vbinary->fdes_info, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open .info file %s for writing", infoname);
1439:     }
1440:   }
1441:   PetscFunctionReturn(PETSC_SUCCESS);
1442: }

1444: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1445: {
1446:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1447:   PetscBool           usempiio;

1449:   PetscFunctionBegin;
1450:   if (!vbinary->setfromoptionscalled) PetscCall(PetscViewerSetFromOptions(viewer));
1451:   PetscCheck(vbinary->filename, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetName()");
1452:   PetscCheck(vbinary->filemode != (PetscFileMode)-1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode()");
1453:   PetscCall(PetscViewerFileClose_Binary(viewer));

1455:   PetscCall(PetscViewerBinaryGetUseMPIIO(viewer, &usempiio));
1456:   if (usempiio) {
1457: #if defined(PETSC_HAVE_MPIIO)
1458:     PetscCall(PetscViewerFileSetUp_BinaryMPIIO(viewer));
1459: #endif
1460:   } else {
1461:     PetscCall(PetscViewerFileSetUp_BinarySTDIO(viewer));
1462:   }
1463:   PetscCall(PetscViewerFileSetUp_BinaryInfo(viewer));

1465:   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", vbinary->filename));
1466:   PetscFunctionReturn(PETSC_SUCCESS);
1467: }

1469: static PetscErrorCode PetscViewerView_Binary(PetscViewer v, PetscViewer viewer)
1470: {
1471:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
1472:   const char         *fname   = vbinary->filename ? vbinary->filename : "not yet set";
1473:   const char         *fmode   = vbinary->filemode != (PetscFileMode)-1 ? PetscFileModes[vbinary->filemode] : "not yet set";
1474:   PetscBool           usempiio;

1476:   PetscFunctionBegin;
1477:   PetscCall(PetscViewerBinaryGetUseMPIIO(v, &usempiio));
1478:   PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", fname));
1479:   PetscCall(PetscViewerASCIIPrintf(viewer, "Mode: %s (%s)\n", fmode, usempiio ? "mpiio" : "stdio"));
1480:   PetscFunctionReturn(PETSC_SUCCESS);
1481: }

1483: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscViewer viewer, PetscOptionItems *PetscOptionsObject)
1484: {
1485:   PetscViewer_Binary *binary = (PetscViewer_Binary *)viewer->data;
1486:   char                defaultname[PETSC_MAX_PATH_LEN];
1487:   PetscBool           flg;

1489:   PetscFunctionBegin;
1490:   if (viewer->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
1491:   PetscOptionsHeadBegin(PetscOptionsObject, "Binary PetscViewer Options");
1492:   PetscCall(PetscSNPrintf(defaultname, PETSC_MAX_PATH_LEN - 1, "binaryoutput"));
1493:   PetscCall(PetscOptionsString("-viewer_binary_filename", "Specify filename", "PetscViewerFileSetName", defaultname, defaultname, sizeof(defaultname), &flg));
1494:   if (flg) PetscCall(PetscViewerFileSetName_Binary(viewer, defaultname));
1495:   PetscCall(PetscOptionsBool("-viewer_binary_skip_info", "Skip writing/reading .info file", "PetscViewerBinarySetSkipInfo", binary->skipinfo, &binary->skipinfo, NULL));
1496:   PetscCall(PetscOptionsBool("-viewer_binary_skip_options", "Skip parsing Vec/Mat load options", "PetscViewerBinarySetSkipOptions", binary->skipoptions, &binary->skipoptions, NULL));
1497:   PetscCall(PetscOptionsBool("-viewer_binary_skip_header", "Skip writing/reading header information", "PetscViewerBinarySetSkipHeader", binary->skipheader, &binary->skipheader, NULL));
1498: #if defined(PETSC_HAVE_MPIIO)
1499:   PetscCall(PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file", "PetscViewerBinarySetUseMPIIO", binary->usempiio, &binary->usempiio, NULL));
1500: #else
1501:   PetscCall(PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)", "PetscViewerBinarySetUseMPIIO", PETSC_FALSE, NULL, NULL));
1502: #endif
1503:   PetscOptionsHeadEnd();
1504:   binary->setfromoptionscalled = PETSC_TRUE;
1505:   PetscFunctionReturn(PETSC_SUCCESS);
1506: }

1508: /*MC
1509:    PETSCVIEWERBINARY - A viewer that saves to binary files

1511:   Level: beginner

1513: .seealso: [](sec_viewers), `PetscViewerBinaryOpen()`, `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1514:           `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, `PETSCVIEWERDRAW`, `PETSCVIEWERSOCKET`
1515:           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`,
1516:           `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`
1517: M*/

1519: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1520: {
1521:   PetscViewer_Binary *vbinary;

1523:   PetscFunctionBegin;
1524:   PetscCall(PetscNew(&vbinary));
1525:   v->data = (void *)vbinary;

1527:   v->ops->setfromoptions   = PetscViewerSetFromOptions_Binary;
1528:   v->ops->destroy          = PetscViewerDestroy_Binary;
1529:   v->ops->view             = PetscViewerView_Binary;
1530:   v->ops->setup            = PetscViewerSetUp_Binary;
1531:   v->ops->flush            = NULL; /* Should we support Flush() ? */
1532:   v->ops->getsubviewer     = PetscViewerGetSubViewer_Binary;
1533:   v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1534:   v->ops->read             = PetscViewerBinaryRead;

1536:   vbinary->fdes = -1;
1537: #if defined(PETSC_HAVE_MPIIO)
1538:   vbinary->usempiio = PETSC_FALSE;
1539:   vbinary->mfdes    = MPI_FILE_NULL;
1540:   vbinary->mfsub    = MPI_FILE_NULL;
1541: #endif
1542:   vbinary->filename        = NULL;
1543:   vbinary->filemode        = FILE_MODE_UNDEFINED;
1544:   vbinary->fdes_info       = NULL;
1545:   vbinary->skipinfo        = PETSC_FALSE;
1546:   vbinary->skipoptions     = PETSC_TRUE;
1547:   vbinary->skipheader      = PETSC_FALSE;
1548:   vbinary->storecompressed = PETSC_FALSE;
1549:   vbinary->ogzfilename     = NULL;
1550:   vbinary->flowcontrol     = 256; /* seems a good number for Cray XT-5 */

1552:   vbinary->setfromoptionscalled = PETSC_FALSE;

1554:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Binary));
1555:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", PetscViewerBinarySetFlowControl_Binary));
1556:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Binary));
1557:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Binary));
1558:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", PetscViewerBinaryGetSkipOptions_Binary));
1559:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", PetscViewerBinarySetSkipOptions_Binary));
1560:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", PetscViewerBinaryGetSkipInfo_Binary));
1561:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", PetscViewerBinarySetSkipInfo_Binary));
1562:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", PetscViewerBinaryGetInfoPointer_Binary));
1563:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_Binary));
1564:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_Binary));
1565:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_Binary));
1566:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Binary));
1567: #if defined(PETSC_HAVE_MPIIO)
1568:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", PetscViewerBinaryGetUseMPIIO_Binary));
1569:   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", PetscViewerBinarySetUseMPIIO_Binary));
1570: #endif
1571:   PetscFunctionReturn(PETSC_SUCCESS);
1572: }

1574: /*
1575:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1576:   is attached to a communicator, in this case the attribute is a PetscViewer.
1577: */
1578: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

1580: /*@C
1581:      PETSC_VIEWER_BINARY_ - Creates a `PETSCVIEWERBINARY` `PetscViewer` shared by all processors
1582:                      in a communicator.

1584:      Collective

1586:      Input Parameter:
1587: .    comm - the MPI communicator to share the `PETSCVIEWERBINARY`

1589:      Level: intermediate

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

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

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

1606: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PETSC_VIEWER_BINARY_WORLD`, `PETSC_VIEWER_BINARY_SELF`, `PetscViewerBinaryOpen()`, `PetscViewerCreate()`,
1607:           `PetscViewerDestroy()`
1608: @*/
1609: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1610: {
1611:   PetscErrorCode ierr;
1612:   PetscMPIInt    mpi_ierr;
1613:   PetscBool      flg;
1614:   PetscViewer    viewer;
1615:   char           fname[PETSC_MAX_PATH_LEN];
1616:   MPI_Comm       ncomm;

1618:   PetscFunctionBegin;
1619:   ierr = PetscCommDuplicate(comm, &ncomm, NULL);
1620:   if (ierr) {
1621:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1622:     PetscFunctionReturn(NULL);
1623:   }
1624:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1625:     mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Binary_keyval, NULL);
1626:     if (mpi_ierr) {
1627:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1628:       PetscFunctionReturn(NULL);
1629:     }
1630:   }
1631:   mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Binary_keyval, (void **)&viewer, (int *)&flg);
1632:   if (mpi_ierr) {
1633:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1634:     PetscFunctionReturn(NULL);
1635:   }
1636:   if (!flg) { /* PetscViewer not yet created */
1637:     ierr = PetscOptionsGetenv(ncomm, "PETSC_VIEWER_BINARY_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
1638:     if (ierr) {
1639:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1640:       PetscFunctionReturn(NULL);
1641:     }
1642:     if (!flg) {
1643:       ierr = PetscStrncpy(fname, "binaryoutput", sizeof(fname));
1644:       if (ierr) {
1645:         ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1646:         PetscFunctionReturn(NULL);
1647:       }
1648:     }
1649:     ierr = PetscViewerBinaryOpen(ncomm, fname, FILE_MODE_WRITE, &viewer);
1650:     if (ierr) {
1651:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1652:       PetscFunctionReturn(NULL);
1653:     }
1654:     ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
1655:     if (ierr) {
1656:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1657:       PetscFunctionReturn(NULL);
1658:     }
1659:     mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Binary_keyval, (void *)viewer);
1660:     if (mpi_ierr) {
1661:       ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1662:       PetscFunctionReturn(NULL);
1663:     }
1664:   }
1665:   ierr = PetscCommDestroy(&ncomm);
1666:   if (ierr) {
1667:     ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1668:     PetscFunctionReturn(NULL);
1669:   }
1670:   PetscFunctionReturn(viewer);
1671: }