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;
191:   PetscAssertPointer(off, 2);
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;
246:   PetscAssertPointer(fdes, 2);
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 (true|false) - 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;

286:   PetscFunctionBegin;
287:   PetscCheck(!viewer->setupcalled || vbinary->usempiio == use, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Cannot change MPIIO to %s after setup", PetscBools[use]);
288:   vbinary->usempiio = use;
289:   PetscFunctionReturn(PETSC_SUCCESS);
290: }
291: #endif

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

296:   Not Collective

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

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

304:   Level: advanced

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

309: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
310: @*/
311: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer, PetscBool *use)
312: {
313:   PetscFunctionBegin;
315:   PetscAssertPointer(use, 2);
316:   *use = PETSC_FALSE;
317:   PetscTryMethod(viewer, "PetscViewerBinaryGetUseMPIIO_C", (PetscViewer, PetscBool *), (viewer, use));
318:   PetscFunctionReturn(PETSC_SUCCESS);
319: }

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

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

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

335:   Not Collective

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

341:   Level: advanced

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

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

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

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

367:   Not Collective

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

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

375:   Level: advanced

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

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

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

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

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

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

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

408:   Level: advanced

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

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

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

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

434:   Not Collective

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

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

442:   Level: advanced

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

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

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

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

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

467:   Not Collective

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

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

476:   Level: advanced

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

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

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

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

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

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

510:   Not Collective

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

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

518:   Level: advanced

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

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

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

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

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

547:   Not Collective

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

553:   Options Database Key:
554: . -viewer_binary_skip_options (true|false) - true means do not use the options from the options database

556:   Level: advanced

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

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

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

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

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

585:   Not Collective

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

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

593:   Level: advanced

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

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

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

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

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

622:   Not Collective

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

628:   Options Database Key:
629: . -viewer_binary_skip_header (true|false) - true means do not write header

631:   Level: advanced

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

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

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

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

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

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

662:   Not Collective

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

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

670:   Level: advanced

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

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

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

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

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

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

702:   Not Collective; No Fortran Support

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

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

710:   Level: advanced

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

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

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

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

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

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

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

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

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

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

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

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

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

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

837:   Collective

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

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

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

859:   Level: beginner

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

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

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

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

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

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

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

921:   Collective; No Fortran Support

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

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

932:   Level: beginner

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

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

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

962:   Collective; No Fortran Support

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

970:   Level: beginner

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

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

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

1006:   PetscFunctionBegin;
1011:   PetscCall(PetscViewerSetUp(viewer));

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

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

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

1055:     PetscCall(PetscCommGetNewTag(comm, &tag));
1056:     PetscCallMPI(MPI_Reduce(&tcount, &maxcount, 1, MPIU_COUNT, MPI_MAX, 0, comm));
1057:     PetscCall(PetscMPIIntCast(maxcount, &maxcnt));

1059:     PetscCall(PetscViewerBinaryGetDescriptor(viewer, &fdes));
1060:     if (rank == 0) {
1061:       if (write) PetscCall(PetscBinaryWrite(fdes, data, count, dtype));
1062:       else PetscCall(PetscBinaryRead(fdes, data, count, NULL, dtype));
1063:     }

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

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

1102:   Collective; No Fortran Support

1104:   Input Parameters:
1105: + viewer - the `PETSCVIEWERBINARY` viewer
1106: . count  - local number of items of data to read
1107: . start  - local start, can be `PETSC_DETERMINE`
1108: . total  - global number of items of data to read, can be `PETSC_DETERMINE`
1109: - dtype  - type of data to read

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

1114:   Level: advanced

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

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

1128:   Collective; No Fortran Support

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

1138:   Level: advanced

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

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

1152:   Collective; No Fortran Support

1154:   Input Parameters:
1155: + viewer - the `PETSCVIEWERBINARY` viewer
1156: - data   - location of the array of strings

1158:   Level: intermediate

1160:   Note:
1161:   The array of strings must be `NULL` terminated

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

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

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

1192:   Collective; No Fortran Support

1194:   Input Parameter:
1195: . viewer - the `PETSCVIEWERBINARY` viewer

1197:   Output Parameter:
1198: . data - location of the array of strings

1200:   Level: intermediate

1202:   Note:
1203:   The array of strings must `NULL` terminated

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

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

1229: /*@
1230:   PetscViewerFileSetMode - Sets the open mode of file

1232:   Logically Collective

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

1243:   Level: advanced

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

1258: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer, PetscFileMode mode)
1259: {
1260:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

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

1268: /*@
1269:   PetscViewerFileGetMode - Gets the open mode of a file associated with a `PetscViewer`

1271:   Not Collective

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

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

1284:   Level: advanced

1286: .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1287: @*/
1288: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer, PetscFileMode *mode)
1289: {
1290:   PetscFunctionBegin;
1292:   PetscAssertPointer(mode, 2);
1293:   PetscUseMethod(viewer, "PetscViewerFileGetMode_C", (PetscViewer, PetscFileMode *), (viewer, mode));
1294:   PetscFunctionReturn(PETSC_SUCCESS);
1295: }

1297: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer, PetscFileMode *mode)
1298: {
1299:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1301:   PetscFunctionBegin;
1302:   *mode = vbinary->filemode;
1303:   PetscFunctionReturn(PETSC_SUCCESS);
1304: }

1306: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer, const char name[])
1307: {
1308:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

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

1322: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer, const char **name)
1323: {
1324:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;

1326:   PetscFunctionBegin;
1327:   *name = vbinary->filename;
1328:   PetscFunctionReturn(PETSC_SUCCESS);
1329: }

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

1337:   PetscFunctionBegin;
1338:   vbinary->storecompressed = PETSC_FALSE;

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

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

1380:   PetscFunctionBegin;
1381:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));

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

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

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

1416: #include <errno.h>
1417: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1418: {
1419:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1420:   PetscMPIInt         rank;
1421:   PetscBool           found;

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

1429:     PetscCall(PetscStrncpy(infoname, vbinary->filename, sizeof(infoname)));
1430:     /* remove .gz if it ends file name */
1431:     PetscCall(PetscStrstr(infoname, ".gz", &gz));
1432:     if (gz && gz[3] == 0) *gz = 0;

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

1448: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1449: {
1450:   PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1451:   PetscBool           usempiio;

1453:   PetscFunctionBegin;
1454:   if (!vbinary->setfromoptionscalled) PetscCall(PetscViewerSetFromOptions(viewer));
1455:   PetscCheck(vbinary->filename, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetName()");
1456:   PetscCheck(vbinary->filemode != (PetscFileMode)-1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode()");
1457:   PetscCall(PetscViewerFileClose_Binary(viewer));

1459:   PetscCall(PetscViewerBinaryGetUseMPIIO(viewer, &usempiio));
1460:   if (usempiio) {
1461: #if defined(PETSC_HAVE_MPIIO)
1462:     PetscCall(PetscViewerFileSetUp_BinaryMPIIO(viewer));
1463: #endif
1464:   } else {
1465:     PetscCall(PetscViewerFileSetUp_BinarySTDIO(viewer));
1466:   }
1467:   PetscCall(PetscViewerFileSetUp_BinaryInfo(viewer));

1469:   PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", vbinary->filename));
1470:   PetscFunctionReturn(PETSC_SUCCESS);
1471: }

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

1480:   PetscFunctionBegin;
1481:   PetscCall(PetscViewerBinaryGetUseMPIIO(v, &usempiio));
1482:   PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", fname));
1483:   PetscCall(PetscViewerASCIIPrintf(viewer, "Mode: %s (%s)\n", fmode, usempiio ? "mpiio" : "stdio"));
1484:   PetscFunctionReturn(PETSC_SUCCESS);
1485: }

1487: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscViewer viewer, PetscOptionItems PetscOptionsObject)
1488: {
1489:   PetscViewer_Binary *binary = (PetscViewer_Binary *)viewer->data;
1490:   char                defaultname[PETSC_MAX_PATH_LEN];
1491:   PetscBool           flg;

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

1512: /*MC
1513:    PETSCVIEWERBINARY - A viewer that saves to binary files

1515:   Level: beginner

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

1523: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1524: {
1525:   PetscViewer_Binary *vbinary;

1527:   PetscFunctionBegin;
1528:   PetscCall(PetscNew(&vbinary));
1529:   v->data = (void *)vbinary;

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

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

1556:   vbinary->setfromoptionscalled = PETSC_FALSE;

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

1578: /*
1579:     The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1580:   is attached to a communicator, in this case the attribute is a PetscViewer.
1581: */
1582: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;

1584: /*@C
1585:    PETSC_VIEWER_BINARY_ - Creates a `PETSCVIEWERBINARY` `PetscViewer` shared by all processes in a communicator.

1587:    Collective

1589:    Input Parameter:
1590: .  comm - the MPI communicator to share the `PETSCVIEWERBINARY`

1592:    Level: intermediate

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

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

1604:    Notes:
1605:   This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it

1607:   Unlike almost all other PETSc routines, `PETSC_VIEWER_BINARY_` does not return
1608:   an error code.  The binary PetscViewer is usually used in the form
1609: .vb
1610:   XXXView(XXX object, PETSC_VIEWER_BINARY_(comm));
1611: .ve

1613: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PETSC_VIEWER_BINARY_WORLD`, `PETSC_VIEWER_BINARY_SELF`, `PetscViewerBinaryOpen()`, `PetscViewerCreate()`,
1614:           `PetscViewerDestroy()`
1615: @*/
1616: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1617: {
1618:   PetscBool   flg;
1619:   PetscMPIInt iflg;
1620:   PetscViewer viewer;
1621:   char        fname[PETSC_MAX_PATH_LEN];
1622:   MPI_Comm    ncomm;

1624:   PetscFunctionBegin;
1625:   PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
1626:   if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) PetscCallMPINull(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Binary_keyval, NULL));
1627:   PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Binary_keyval, (void **)&viewer, &iflg));
1628:   if (!iflg) { /* PetscViewer not yet created */
1629:     PetscCallNull(PetscOptionsGetenv(ncomm, "PETSC_VIEWER_BINARY_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg));
1630:     if (!flg) PetscCallNull(PetscStrncpy(fname, "binaryoutput", sizeof(fname)));
1631:     PetscCallNull(PetscViewerBinaryOpen(ncomm, fname, FILE_MODE_WRITE, &viewer));
1632:     PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
1633:     PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Binary_keyval, (void *)viewer));
1634:   }
1635:   PetscCallNull(PetscCommDestroy(&ncomm));
1636:   PetscFunctionReturn(viewer);
1637: }