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: }