Actual source code: binv.c
1: #include <petsc/private/viewerimpl.h>
3: /*
4: This needs to start the same as PetscViewer_Socket.
5: */
6: typedef struct {
7: int fdes; /* file descriptor, ignored if using MPI IO */
8: PetscInt flowcontrol; /* allow only <flowcontrol> messages outstanding at a time while doing IO */
9: PetscBool skipheader; /* don't write header, only raw data */
10: #if defined(PETSC_HAVE_MPIIO)
11: PetscBool usempiio;
12: MPI_File mfdes; /* ignored unless using MPI IO */
13: MPI_File mfsub; /* subviewer support */
14: MPI_Offset moff;
15: #endif
16: char *filename; /* file name */
17: PetscFileMode filemode; /* read/write/append mode */
18: FILE *fdes_info; /* optional file containing info on binary file*/
19: PetscBool storecompressed; /* gzip the write binary file when closing it*/
20: char *ogzfilename; /* gzip can be run after the filename has been updated */
21: PetscBool skipinfo; /* Don't create info file for writing; don't use for reading */
22: PetscBool skipoptions; /* don't use PETSc options database when loading */
23: PetscBool matlabheaderwritten; /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
24: PetscBool setfromoptionscalled;
25: } PetscViewer_Binary;
27: static PetscErrorCode PetscViewerBinaryClearFunctionList(PetscViewer v)
28: {
29: PetscFunctionBegin;
30: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", NULL));
31: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", NULL));
32: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", NULL));
33: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", NULL));
34: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", NULL));
35: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", NULL));
36: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", NULL));
37: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", NULL));
38: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", NULL));
39: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", NULL));
40: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", NULL));
41: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", NULL));
42: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", NULL));
43: #if defined(PETSC_HAVE_MPIIO)
44: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", NULL));
45: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", NULL));
46: #endif
47: PetscFunctionReturn(PETSC_SUCCESS);
48: }
50: #if defined(PETSC_HAVE_MPIIO)
51: static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer)
52: {
53: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
55: PetscFunctionBegin;
56: if (vbinary->filemode == FILE_MODE_READ) PetscFunctionReturn(PETSC_SUCCESS);
57: if (vbinary->mfsub != MPI_FILE_NULL) PetscCallMPI(MPI_File_sync(vbinary->mfsub));
58: if (vbinary->mfdes != MPI_FILE_NULL) {
59: PetscCallMPI(MPI_Barrier(PetscObjectComm((PetscObject)viewer)));
60: PetscCallMPI(MPI_File_sync(vbinary->mfdes));
61: }
62: PetscFunctionReturn(PETSC_SUCCESS);
63: }
64: #endif
66: static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
67: {
68: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
69: PetscMPIInt rank;
71: PetscFunctionBegin;
72: PetscCall(PetscViewerSetUp(viewer));
74: /* Return subviewer in process zero */
75: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
76: if (rank == 0) {
77: PetscMPIInt flg;
79: PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg));
80: PetscCheck(flg == MPI_IDENT || flg == MPI_CONGRUENT, PETSC_COMM_SELF, PETSC_ERR_SUP, "PetscViewerGetSubViewer() for PETSCVIEWERBINARY requires a singleton MPI_Comm");
81: PetscCall(PetscViewerCreate(comm, outviewer));
82: PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERBINARY));
83: PetscCall(PetscMemcpy((*outviewer)->data, vbinary, sizeof(PetscViewer_Binary)));
84: (*outviewer)->setupcalled = PETSC_TRUE;
85: } else {
86: *outviewer = NULL;
87: }
89: #if defined(PETSC_HAVE_MPIIO)
90: if (vbinary->usempiio && *outviewer) {
91: PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
92: /* Parent viewer opens a new MPI file handle on PETSC_COMM_SELF and keeps track of it for future reuse */
93: if (vbinary->mfsub == MPI_FILE_NULL) {
94: int amode;
95: switch (vbinary->filemode) {
96: case FILE_MODE_READ:
97: amode = MPI_MODE_RDONLY;
98: break;
99: case FILE_MODE_WRITE:
100: amode = MPI_MODE_WRONLY;
101: break;
102: case FILE_MODE_APPEND:
103: amode = MPI_MODE_WRONLY;
104: break;
105: default:
106: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vbinary->filemode]);
107: }
108: PetscCallMPI(MPI_File_open(PETSC_COMM_SELF, vbinary->filename, amode, MPI_INFO_NULL, &vbinary->mfsub));
109: }
110: /* Subviewer gets the MPI file handle on PETSC_COMM_SELF */
111: obinary->mfdes = vbinary->mfsub;
112: obinary->mfsub = MPI_FILE_NULL;
113: obinary->moff = vbinary->moff;
114: }
115: #endif
117: #if defined(PETSC_HAVE_MPIIO)
118: PetscCall(PetscViewerBinarySyncMPIIO(viewer));
119: #endif
120: PetscFunctionReturn(PETSC_SUCCESS);
121: }
123: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
124: {
125: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
126: PetscMPIInt rank;
127: #if defined(PETSC_HAVE_MPIIO)
128: MPI_Offset moff = 0;
129: #endif
131: PetscFunctionBegin;
132: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
133: PetscCheck(rank == 0 || !*outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Subviewer not obtained from viewer");
135: #if defined(PETSC_HAVE_MPIIO)
136: if (vbinary->usempiio && *outviewer) {
137: PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
138: PetscCheck(obinary->mfdes == vbinary->mfsub, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Subviewer not obtained from viewer");
139: if (obinary->mfsub != MPI_FILE_NULL) PetscCallMPI(MPI_File_close(&obinary->mfsub));
140: moff = obinary->moff;
141: }
142: #endif
144: if (*outviewer) {
145: PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
146: PetscCheck(obinary->fdes == vbinary->fdes, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Subviewer not obtained from viewer");
147: PetscCall(PetscFree((*outviewer)->data));
148: PetscCall(PetscViewerBinaryClearFunctionList(*outviewer));
149: PetscCall(PetscHeaderDestroy(outviewer));
150: }
152: #if defined(PETSC_HAVE_MPIIO)
153: if (vbinary->usempiio) {
154: PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */
155: PetscCallMPI(MPI_Bcast(&ioff, 1, MPIU_INT64, 0, PetscObjectComm((PetscObject)viewer)));
156: vbinary->moff = (MPI_Offset)ioff;
157: }
158: #endif
160: #if defined(PETSC_HAVE_MPIIO)
161: PetscCall(PetscViewerBinarySyncMPIIO(viewer));
162: #endif
163: PetscFunctionReturn(PETSC_SUCCESS);
164: }
166: #if defined(PETSC_HAVE_MPIIO)
167: /*@C
168: PetscViewerBinaryGetMPIIOOffset - Gets the current global offset that should be passed to `MPI_File_set_view()` or `MPI_File_{write|read}_at[_all]()`
170: Not Collective; No Fortran Support
172: Input Parameter:
173: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
175: Output Parameter:
176: . off - the current global offset
178: Level: advanced
180: Note:
181: Use `PetscViewerBinaryAddMPIIOOffset()` to increase this value after you have written a view.
183: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryAddMPIIOOffset()`
184: @*/
185: PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer, MPI_Offset *off)
186: {
187: PetscViewer_Binary *vbinary;
189: PetscFunctionBegin;
192: vbinary = (PetscViewer_Binary *)viewer->data;
193: *off = vbinary->moff;
194: PetscFunctionReturn(PETSC_SUCCESS);
195: }
197: /*@C
198: PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset
200: Logically Collective; No Fortran Support
202: Input Parameters:
203: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
204: - off - the addition to the global offset
206: Level: advanced
208: Note:
209: Use `PetscViewerBinaryGetMPIIOOffset()` to get the value that you should pass to `MPI_File_set_view()` or `MPI_File_{write|read}_at[_all]()`
211: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
212: @*/
213: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer, MPI_Offset off)
214: {
215: PetscViewer_Binary *vbinary;
217: PetscFunctionBegin;
220: vbinary = (PetscViewer_Binary *)viewer->data;
221: vbinary->moff += off;
222: PetscFunctionReturn(PETSC_SUCCESS);
223: }
225: /*@C
226: PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a `PetscViewer`.
228: Not Collective; No Fortran Support
230: Input Parameter:
231: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
233: Output Parameter:
234: . fdes - file descriptor
236: Level: advanced
238: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
239: @*/
240: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer, MPI_File *fdes)
241: {
242: PetscViewer_Binary *vbinary;
244: PetscFunctionBegin;
247: PetscCall(PetscViewerSetUp(viewer));
248: vbinary = (PetscViewer_Binary *)viewer->data;
249: *fdes = vbinary->mfdes;
250: PetscFunctionReturn(PETSC_SUCCESS);
251: }
252: #endif
254: /*@
255: PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
256: before `PetscViewerFileSetName()`
258: Logically Collective
260: Input Parameters:
261: + viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`
262: - use - `PETSC_TRUE` means MPI-IO will be used
264: Options Database Key:
265: -viewer_binary_mpiio : Flag for using MPI-IO
267: Level: advanced
269: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
270: `PetscViewerBinaryGetUseMPIIO()`
271: @*/
272: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer, PetscBool use)
273: {
274: PetscFunctionBegin;
277: PetscTryMethod(viewer, "PetscViewerBinarySetUseMPIIO_C", (PetscViewer, PetscBool), (viewer, use));
278: PetscFunctionReturn(PETSC_SUCCESS);
279: }
281: #if defined(PETSC_HAVE_MPIIO)
282: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer, PetscBool use)
283: {
284: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
285: PetscFunctionBegin;
286: PetscCheck(!viewer->setupcalled || vbinary->usempiio == use, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Cannot change MPIIO to %s after setup", PetscBools[use]);
287: vbinary->usempiio = use;
288: PetscFunctionReturn(PETSC_SUCCESS);
289: }
290: #endif
292: /*@
293: PetscViewerBinaryGetUseMPIIO - Returns `PETSC_TRUE` if the binary viewer uses MPI-IO.
295: Not Collective
297: Input Parameter:
298: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`; must be a `PETSCVIEWERBINARY`
300: Output Parameter:
301: . use - `PETSC_TRUE` if MPI-IO is being used
303: Level: advanced
305: Note:
306: If MPI-IO is not available, this function will always return `PETSC_FALSE`
308: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
309: @*/
310: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer, PetscBool *use)
311: {
312: PetscFunctionBegin;
315: *use = PETSC_FALSE;
316: PetscTryMethod(viewer, "PetscViewerBinaryGetUseMPIIO_C", (PetscViewer, PetscBool *), (viewer, use));
317: PetscFunctionReturn(PETSC_SUCCESS);
318: }
320: #if defined(PETSC_HAVE_MPIIO)
321: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer, PetscBool *use)
322: {
323: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
325: PetscFunctionBegin;
326: *use = vbinary->usempiio;
327: PetscFunctionReturn(PETSC_SUCCESS);
328: }
329: #endif
331: /*@
332: PetscViewerBinarySetFlowControl - Sets how many messages are allowed to be outstanding at the same time during parallel IO reads/writes
334: Not Collective
336: Input Parameters:
337: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
338: - fc - the number of messages, defaults to 256 if this function was not called
340: Level: advanced
342: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetFlowControl()`
343: @*/
344: PetscErrorCode PetscViewerBinarySetFlowControl(PetscViewer viewer, PetscInt fc)
345: {
346: PetscFunctionBegin;
349: PetscTryMethod(viewer, "PetscViewerBinarySetFlowControl_C", (PetscViewer, PetscInt), (viewer, fc));
350: PetscFunctionReturn(PETSC_SUCCESS);
351: }
353: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer, PetscInt fc)
354: {
355: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
357: PetscFunctionBegin;
358: PetscCheck(fc > 1, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_OUTOFRANGE, "Flow control count must be greater than 1, %" PetscInt_FMT " was set", fc);
359: vbinary->flowcontrol = fc;
360: PetscFunctionReturn(PETSC_SUCCESS);
361: }
363: /*@
364: PetscViewerBinaryGetFlowControl - Returns how many messages are allowed to be outstanding at the same time during parallel IO reads/writes
366: Not Collective
368: Input Parameter:
369: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
371: Output Parameter:
372: . fc - the number of messages
374: Level: advanced
376: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetFlowControl()`
377: @*/
378: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer, PetscInt *fc)
379: {
380: PetscFunctionBegin;
383: PetscUseMethod(viewer, "PetscViewerBinaryGetFlowControl_C", (PetscViewer, PetscInt *), (viewer, fc));
384: PetscFunctionReturn(PETSC_SUCCESS);
385: }
387: PETSC_INTERN PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer, PetscInt *fc)
388: {
389: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
391: PetscFunctionBegin;
392: *fc = vbinary->flowcontrol;
393: PetscFunctionReturn(PETSC_SUCCESS);
394: }
396: /*@C
397: PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a `PetscViewer` of `PetscViewerType` `PETSCVIEWERBINARY`.
399: Collective because it may trigger a `PetscViewerSetUp()` call; No Fortran Support
401: Input Parameter:
402: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
404: Output Parameter:
405: . fdes - file descriptor
407: Level: advanced
409: Note:
410: For writable binary `PetscViewer`s, the descriptor will only be valid for the
411: first processor in the communicator that shares the `PetscViewer`. For readable
412: files it will only be valid on processes that have the file. If MPI rank 0 does not
413: have the file it generates an error even if another MPI process does have the file.
415: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`
416: @*/
417: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer, int *fdes)
418: {
419: PetscViewer_Binary *vbinary;
421: PetscFunctionBegin;
424: PetscCall(PetscViewerSetUp(viewer));
425: vbinary = (PetscViewer_Binary *)viewer->data;
426: *fdes = vbinary->fdes;
427: PetscFunctionReturn(PETSC_SUCCESS);
428: }
430: /*@
431: PetscViewerBinarySkipInfo - Binary file will not have `.info` file created with it
433: Not Collective
435: Input Parameter:
436: . viewer - `PetscViewer` context, obtained from `PetscViewerCreate()`
438: Options Database Key:
439: . -viewer_binary_skip_info - true indicates do not generate `.info` file
441: Level: advanced
443: Notes:
444: This must be called after `PetscViewerSetType()`. If you use `PetscViewerBinaryOpen()` then
445: you can only skip the info file with the `-viewer_binary_skip_info` flag. To use the function you must open the
446: viewer with `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinarySkipInfo()`.
448: The `.info` files contains meta information about the data in the binary file, for example the block size if it was
449: set for a vector or matrix.
451: This routine is deprecated, use `PetscViewerBinarySetSkipInfo()`
453: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
454: `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
455: @*/
456: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
457: {
458: PetscFunctionBegin;
459: PetscCall(PetscViewerBinarySetSkipInfo(viewer, PETSC_TRUE));
460: PetscFunctionReturn(PETSC_SUCCESS);
461: }
463: /*@
464: PetscViewerBinarySetSkipInfo - Binary file will not have `.info` file created with it
466: Not Collective
468: Input Parameters:
469: + viewer - PetscViewer context, obtained from `PetscViewerCreate()`
470: - skip - `PETSC_TRUE` implies the `.info` file will not be generated
472: Options Database Key:
473: . -viewer_binary_skip_info - true indicates do not generate `.info` file
475: Level: advanced
477: Notes:
478: This must be called after `PetscViewerSetType()`. If you use `PetscViewerBinaryOpen()` then
479: you can only skip the info file with the `-viewer_binary_skip_info` flag. To use the function you must open the
480: viewer with `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinarySkipInfo()`.
482: The `.info` file contains meta information about the data in the binary file, for example the block size if it was
483: set for a vector or matrix.
485: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
486: `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`, `PetscViewerBinaryGetInfoPointer()`
487: @*/
488: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer, PetscBool skip)
489: {
490: PetscFunctionBegin;
493: PetscTryMethod(viewer, "PetscViewerBinarySetSkipInfo_C", (PetscViewer, PetscBool), (viewer, skip));
494: PetscFunctionReturn(PETSC_SUCCESS);
495: }
497: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer, PetscBool skip)
498: {
499: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
501: PetscFunctionBegin;
502: vbinary->skipinfo = skip;
503: PetscFunctionReturn(PETSC_SUCCESS);
504: }
506: /*@
507: PetscViewerBinaryGetSkipInfo - check if viewer wrote a `.info` file
509: Not Collective
511: Input Parameter:
512: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
514: Output Parameter:
515: . skip - `PETSC_TRUE` implies the `.info` file was not generated
517: Level: advanced
519: Note:
520: This must be called after `PetscViewerSetType()`
522: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`,
523: `PetscViewerBinarySetSkipOptions()`, `PetscViewerBinarySetSkipInfo()`, `PetscViewerBinaryGetInfoPointer()`
524: @*/
525: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer, PetscBool *skip)
526: {
527: PetscFunctionBegin;
530: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipInfo_C", (PetscViewer, PetscBool *), (viewer, skip));
531: PetscFunctionReturn(PETSC_SUCCESS);
532: }
534: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer, PetscBool *skip)
535: {
536: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
538: PetscFunctionBegin;
539: *skip = vbinary->skipinfo;
540: PetscFunctionReturn(PETSC_SUCCESS);
541: }
543: /*@
544: PetscViewerBinarySetSkipOptions - do not use values in the PETSc options database when loading objects
546: Not Collective
548: Input Parameters:
549: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
550: - skip - `PETSC_TRUE` means do not use the options from the options database
552: Options Database Key:
553: . -viewer_binary_skip_options <true or false> - true means do not use the options from the options database
555: Level: advanced
557: Note:
558: This must be called after `PetscViewerSetType()`
560: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
561: `PetscViewerBinaryGetSkipOptions()`
562: @*/
563: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer, PetscBool skip)
564: {
565: PetscFunctionBegin;
568: PetscTryMethod(viewer, "PetscViewerBinarySetSkipOptions_C", (PetscViewer, PetscBool), (viewer, skip));
569: PetscFunctionReturn(PETSC_SUCCESS);
570: }
572: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer, PetscBool skip)
573: {
574: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
576: PetscFunctionBegin;
577: vbinary->skipoptions = skip;
578: PetscFunctionReturn(PETSC_SUCCESS);
579: }
581: /*@
582: PetscViewerBinaryGetSkipOptions - checks if viewer uses the PETSc options database when loading objects
584: Not Collective
586: Input Parameter:
587: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
589: Output Parameter:
590: . skip - `PETSC_TRUE` means do not use
592: Level: advanced
594: Note:
595: This must be called after `PetscViewerSetType()`
597: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
598: `PetscViewerBinarySetSkipOptions()`
599: @*/
600: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer, PetscBool *skip)
601: {
602: PetscFunctionBegin;
605: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipOptions_C", (PetscViewer, PetscBool *), (viewer, skip));
606: PetscFunctionReturn(PETSC_SUCCESS);
607: }
609: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer, PetscBool *skip)
610: {
611: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
613: PetscFunctionBegin;
614: *skip = vbinary->skipoptions;
615: PetscFunctionReturn(PETSC_SUCCESS);
616: }
618: /*@
619: PetscViewerBinarySetSkipHeader - do not write a header with size information on output, just raw data
621: Not Collective
623: Input Parameters:
624: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
625: - skip - `PETSC_TRUE` means do not write header
627: Options Database Key:
628: . -viewer_binary_skip_header <true or false> - true means do not write header
630: Level: advanced
632: Notes:
633: This must be called after `PetscViewerSetType()`
635: If this option is selected, the output file cannot be read with the `XXXLoad()` such as `VecLoad()`
637: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
638: `PetscViewerBinaryGetSkipHeader()`
639: @*/
640: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer, PetscBool skip)
641: {
642: PetscFunctionBegin;
645: PetscTryMethod(viewer, "PetscViewerBinarySetSkipHeader_C", (PetscViewer, PetscBool), (viewer, skip));
646: PetscFunctionReturn(PETSC_SUCCESS);
647: }
649: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer, PetscBool skip)
650: {
651: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
653: PetscFunctionBegin;
654: vbinary->skipheader = skip;
655: PetscFunctionReturn(PETSC_SUCCESS);
656: }
658: /*@
659: PetscViewerBinaryGetSkipHeader - checks whether to write a header with size information on output, or just raw data
661: Not Collective
663: Input Parameter:
664: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
666: Output Parameter:
667: . skip - `PETSC_TRUE` means do not write header
669: Level: advanced
671: Notes:
672: This must be called after PetscViewerSetType()
674: Returns `PETSC_FALSE` for `PETSCSOCKETVIEWER`, you cannot skip the header for it.
676: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
677: `PetscViewerBinarySetSkipHeader()`
678: @*/
679: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer, PetscBool *skip)
680: {
681: PetscFunctionBegin;
684: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipHeader_C", (PetscViewer, PetscBool *), (viewer, skip));
685: PetscFunctionReturn(PETSC_SUCCESS);
686: }
688: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer, PetscBool *skip)
689: {
690: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
692: PetscFunctionBegin;
693: *skip = vbinary->skipheader;
694: PetscFunctionReturn(PETSC_SUCCESS);
695: }
697: /*@C
698: PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
699: `.info` file associated with a binary file.
701: Not Collective; No Fortran Support
703: Input Parameter:
704: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
706: Output Parameter:
707: . file - file pointer Always returns `NULL` if not a binary viewer
709: Level: advanced
711: Note:
712: For writable binary `PetscViewer`s, the file pointer will only be valid for the
713: first processor in the MPI communicator that shares the `PetscViewer`.
715: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinaryGetSkipInfo()`,
716: `PetscViewerBinarySetSkipInfo()`
717: @*/
718: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer, FILE **file)
719: {
720: PetscFunctionBegin;
723: *file = NULL;
724: PetscTryMethod(viewer, "PetscViewerBinaryGetInfoPointer_C", (PetscViewer, FILE **), (viewer, file));
725: PetscFunctionReturn(PETSC_SUCCESS);
726: }
728: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer, FILE **file)
729: {
730: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
732: PetscFunctionBegin;
733: PetscCall(PetscViewerSetUp(viewer));
734: *file = vbinary->fdes_info;
735: if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
736: if (vbinary->fdes_info) {
737: FILE *info = vbinary->fdes_info;
738: PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n"));
739: PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#$$ Set.filename = '%s';\n", vbinary->filename));
740: PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#$$ fd = PetscOpenFile(Set.filename);\n"));
741: PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n"));
742: }
743: vbinary->matlabheaderwritten = PETSC_TRUE;
744: }
745: PetscFunctionReturn(PETSC_SUCCESS);
746: }
748: #if defined(PETSC_HAVE_MPIIO)
749: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
750: {
751: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
753: PetscFunctionBegin;
754: if (vbinary->mfdes != MPI_FILE_NULL) PetscCallMPI(MPI_File_close(&vbinary->mfdes));
755: if (vbinary->mfsub != MPI_FILE_NULL) PetscCallMPI(MPI_File_close(&vbinary->mfsub));
756: vbinary->moff = 0;
757: PetscFunctionReturn(PETSC_SUCCESS);
758: }
759: #endif
761: static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
762: {
763: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
765: PetscFunctionBegin;
766: if (vbinary->fdes != -1) {
767: PetscCall(PetscBinaryClose(vbinary->fdes));
768: vbinary->fdes = -1;
769: if (vbinary->storecompressed) {
770: char cmd[8 + PETSC_MAX_PATH_LEN], out[64 + PETSC_MAX_PATH_LEN] = "";
771: const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
772: /* compress the file */
773: PetscCall(PetscStrncpy(cmd, "gzip -f ", sizeof(cmd)));
774: PetscCall(PetscStrlcat(cmd, gzfilename, sizeof(cmd)));
775: #if defined(PETSC_HAVE_POPEN)
776: {
777: FILE *fp;
778: PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, cmd, "r", &fp));
779: PetscCheck(!fgets(out, (int)(sizeof(out) - 1), fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from command %s\n%s", cmd, out);
780: PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
781: }
782: #endif
783: }
784: }
785: PetscCall(PetscFree(vbinary->ogzfilename));
786: PetscFunctionReturn(PETSC_SUCCESS);
787: }
789: static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
790: {
791: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
793: PetscFunctionBegin;
794: if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
795: if (vbinary->fdes_info) {
796: FILE *info = vbinary->fdes_info;
797: PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n"));
798: PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#$$ close(fd);\n"));
799: PetscCall(PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n"));
800: }
801: }
802: if (vbinary->fdes_info) {
803: FILE *info = vbinary->fdes_info;
804: vbinary->fdes_info = NULL;
805: PetscCheck(!fclose(info), PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
806: }
807: PetscFunctionReturn(PETSC_SUCCESS);
808: }
810: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
811: {
812: PetscFunctionBegin;
813: #if defined(PETSC_HAVE_MPIIO)
814: PetscCall(PetscViewerFileClose_BinaryMPIIO(v));
815: #endif
816: PetscCall(PetscViewerFileClose_BinarySTDIO(v));
817: PetscCall(PetscViewerFileClose_BinaryInfo(v));
818: PetscFunctionReturn(PETSC_SUCCESS);
819: }
821: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
822: {
823: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
825: PetscFunctionBegin;
826: PetscCall(PetscViewerFileClose_Binary(v));
827: PetscCall(PetscFree(vbinary->filename));
828: PetscCall(PetscFree(vbinary));
829: PetscCall(PetscViewerBinaryClearFunctionList(v));
830: PetscFunctionReturn(PETSC_SUCCESS);
831: }
833: /*@C
834: PetscViewerBinaryOpen - Opens a file for binary input/output.
836: Collective
838: Input Parameters:
839: + comm - MPI communicator
840: . name - name of file
841: - mode - open mode of file
842: .vb
843: FILE_MODE_WRITE - create new file for binary output
844: FILE_MODE_READ - open existing file for binary input
845: FILE_MODE_APPEND - open existing file for binary output
846: .ve
848: Output Parameter:
849: . viewer - PetscViewer for binary input/output to use with the specified file
851: Options Database Keys:
852: + -viewer_binary_filename <name> - name of file to use
853: . -viewer_binary_skip_info - true to skip opening an info file
854: . -viewer_binary_skip_options - true to not use options database while creating viewer
855: . -viewer_binary_skip_header - true to skip output object headers to the file
856: - -viewer_binary_mpiio - true to use MPI-IO for input and output to the file (more scalable for large problems)
858: Level: beginner
860: Note:
861: This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.
863: For reading files, the filename may begin with ftp:// or http:// and/or
864: end with .gz; in this case file is brought over and uncompressed.
866: For creating files, if the file name ends with .gz it is automatically
867: compressed when closed.
869: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
870: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
871: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`, `PetscViewerBinarySetUseMPIIO()`,
872: `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
873: @*/
874: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm, const char name[], PetscFileMode mode, PetscViewer *viewer)
875: {
876: PetscFunctionBegin;
877: PetscCall(PetscViewerCreate(comm, viewer));
878: PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERBINARY));
879: PetscCall(PetscViewerFileSetMode(*viewer, mode));
880: PetscCall(PetscViewerFileSetName(*viewer, name));
881: PetscCall(PetscViewerSetFromOptions(*viewer));
882: PetscFunctionReturn(PETSC_SUCCESS);
883: }
885: #if defined(PETSC_HAVE_MPIIO)
886: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype, PetscBool write)
887: {
888: MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
889: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
890: MPI_File mfdes = vbinary->mfdes;
891: MPI_Datatype mdtype;
892: PetscMPIInt rank, cnt;
893: MPI_Status status;
894: MPI_Aint ul, dsize;
896: PetscFunctionBegin;
897: PetscCallMPI(MPI_Comm_rank(comm, &rank));
898: PetscCall(PetscMPIIntCast(num, &cnt));
899: PetscCall(PetscDataTypeToMPIDataType(dtype, &mdtype));
900: if (write) {
901: if (rank == 0) PetscCall(MPIU_File_write_at(mfdes, vbinary->moff, data, cnt, mdtype, &status));
902: } else {
903: if (rank == 0) {
904: PetscCall(MPIU_File_read_at(mfdes, vbinary->moff, data, cnt, mdtype, &status));
905: if (cnt > 0) PetscCallMPI(MPI_Get_count(&status, mdtype, &cnt));
906: }
907: PetscCallMPI(MPI_Bcast(&cnt, 1, MPI_INT, 0, comm));
908: PetscCallMPI(MPI_Bcast(data, cnt, mdtype, 0, comm));
909: }
910: PetscCallMPI(MPI_Type_get_extent(mdtype, &ul, &dsize));
911: vbinary->moff += dsize * cnt;
912: if (count) *count = cnt;
913: PetscFunctionReturn(PETSC_SUCCESS);
914: }
915: #endif
917: /*@C
918: PetscViewerBinaryRead - Reads from a binary file, all processors get the same result
920: Collective
922: Input Parameters:
923: + viewer - the `PETSCVIEWERBINARY` viewer
924: . num - number of items of data to read
925: - dtype - type of data to read
927: Output Parameters:
928: + data - location of the read data, treated as an array of the type indicated by `dtype`
929: - count - number of items of data actually read, or `NULL`.
931: Level: beginner
933: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
934: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
935: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
936: @*/
937: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
938: {
939: PetscViewer_Binary *vbinary;
941: PetscFunctionBegin;
944: PetscCall(PetscViewerSetUp(viewer));
945: vbinary = (PetscViewer_Binary *)viewer->data;
946: #if defined(PETSC_HAVE_MPIIO)
947: if (vbinary->usempiio) {
948: PetscCall(PetscViewerBinaryWriteReadMPIIO(viewer, data, num, count, dtype, PETSC_FALSE));
949: } else {
950: #endif
951: PetscCall(PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, num, count, dtype));
952: #if defined(PETSC_HAVE_MPIIO)
953: }
954: #endif
955: PetscFunctionReturn(PETSC_SUCCESS);
956: }
958: /*@C
959: PetscViewerBinaryWrite - writes to a binary file, only from the first MPI rank
961: Collective
963: Input Parameters:
964: + viewer - the `PETSCVIEWERBINARY` viewer
965: . data - location of data, treated as an array of the type indicated by `dtype`
966: . count - number of items of data to write
967: - dtype - type of data to write
969: Level: beginner
971: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
972: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, `PetscDataType`
973: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
974: @*/
975: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer, const void *data, PetscInt count, PetscDataType dtype)
976: {
977: PetscViewer_Binary *vbinary;
979: PetscFunctionBegin;
982: PetscCall(PetscViewerSetUp(viewer));
983: vbinary = (PetscViewer_Binary *)viewer->data;
984: #if defined(PETSC_HAVE_MPIIO)
985: if (vbinary->usempiio) {
986: PetscCall(PetscViewerBinaryWriteReadMPIIO(viewer, (void *)data, count, NULL, dtype, PETSC_TRUE));
987: } else {
988: #endif
989: PetscCall(PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, count, dtype));
990: #if defined(PETSC_HAVE_MPIIO)
991: }
992: #endif
993: PetscFunctionReturn(PETSC_SUCCESS);
994: }
996: static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer, PetscBool write, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
997: {
998: MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
999: PetscMPIInt size, rank;
1000: MPI_Datatype mdtype;
1001: PETSC_UNUSED MPI_Aint lb;
1002: MPI_Aint dsize;
1003: PetscBool useMPIIO;
1005: PetscFunctionBegin;
1010: PetscCall(PetscViewerSetUp(viewer));
1012: PetscCall(PetscDataTypeToMPIDataType(dtype, &mdtype));
1013: PetscCallMPI(MPI_Type_get_extent(mdtype, &lb, &dsize));
1014: PetscCallMPI(MPI_Comm_rank(comm, &rank));
1015: PetscCallMPI(MPI_Comm_size(comm, &size));
1017: PetscCall(PetscViewerBinaryGetUseMPIIO(viewer, &useMPIIO));
1018: #if defined(PETSC_HAVE_MPIIO)
1019: if (useMPIIO) {
1020: MPI_File mfdes;
1021: MPI_Offset off;
1022: PetscMPIInt cnt;
1024: if (start == PETSC_DETERMINE) {
1025: PetscCallMPI(MPI_Scan(&count, &start, 1, MPIU_INT, MPI_SUM, comm));
1026: start -= count;
1027: }
1028: if (total == PETSC_DETERMINE) {
1029: total = start + count;
1030: PetscCallMPI(MPI_Bcast(&total, 1, MPIU_INT, size - 1, comm));
1031: }
1032: PetscCall(PetscMPIIntCast(count, &cnt));
1033: PetscCall(PetscViewerBinaryGetMPIIODescriptor(viewer, &mfdes));
1034: PetscCall(PetscViewerBinaryGetMPIIOOffset(viewer, &off));
1035: off += (MPI_Offset)(start * dsize);
1036: if (write) {
1037: PetscCall(MPIU_File_write_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE));
1038: } else {
1039: PetscCall(MPIU_File_read_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE));
1040: }
1041: off = (MPI_Offset)(total * dsize);
1042: PetscCall(PetscViewerBinaryAddMPIIOOffset(viewer, off));
1043: PetscFunctionReturn(PETSC_SUCCESS);
1044: }
1045: #endif
1046: {
1047: int fdes;
1048: char *workbuf = NULL;
1049: PetscInt tcount = rank == 0 ? 0 : count, maxcount = 0, message_count, flowcontrolcount;
1050: PetscMPIInt tag, cnt, maxcnt, scnt = 0, rcnt = 0, j;
1051: MPI_Status status;
1053: PetscCall(PetscCommGetNewTag(comm, &tag));
1054: PetscCallMPI(MPI_Reduce(&tcount, &maxcount, 1, MPIU_INT, MPI_MAX, 0, comm));
1055: PetscCall(PetscMPIIntCast(maxcount, &maxcnt));
1056: PetscCall(PetscMPIIntCast(count, &cnt));
1058: PetscCall(PetscViewerBinaryGetDescriptor(viewer, &fdes));
1059: PetscCall(PetscViewerFlowControlStart(viewer, &message_count, &flowcontrolcount));
1060: if (rank == 0) {
1061: PetscCall(PetscMalloc(maxcnt * dsize, &workbuf));
1062: if (write) {
1063: PetscCall(PetscBinaryWrite(fdes, data, cnt, dtype));
1064: } else {
1065: PetscCall(PetscBinaryRead(fdes, data, cnt, NULL, dtype));
1066: }
1067: for (j = 1; j < size; j++) {
1068: PetscCall(PetscViewerFlowControlStepMain(viewer, j, &message_count, flowcontrolcount));
1069: if (write) {
1070: PetscCallMPI(MPI_Recv(workbuf, maxcnt, mdtype, j, tag, comm, &status));
1071: PetscCallMPI(MPI_Get_count(&status, mdtype, &rcnt));
1072: PetscCall(PetscBinaryWrite(fdes, workbuf, rcnt, dtype));
1073: } else {
1074: PetscCallMPI(MPI_Recv(&scnt, 1, MPI_INT, j, tag, comm, MPI_STATUS_IGNORE));
1075: PetscCall(PetscBinaryRead(fdes, workbuf, scnt, NULL, dtype));
1076: PetscCallMPI(MPI_Send(workbuf, scnt, mdtype, j, tag, comm));
1077: }
1078: }
1079: PetscCall(PetscFree(workbuf));
1080: PetscCall(PetscViewerFlowControlEndMain(viewer, &message_count));
1081: } else {
1082: PetscCall(PetscViewerFlowControlStepWorker(viewer, rank, &message_count));
1083: if (write) {
1084: PetscCallMPI(MPI_Send(data, cnt, mdtype, 0, tag, comm));
1085: } else {
1086: PetscCallMPI(MPI_Send(&cnt, 1, MPI_INT, 0, tag, comm));
1087: PetscCallMPI(MPI_Recv(data, cnt, mdtype, 0, tag, comm, MPI_STATUS_IGNORE));
1088: }
1089: PetscCall(PetscViewerFlowControlEndWorker(viewer, &message_count));
1090: }
1091: }
1092: PetscFunctionReturn(PETSC_SUCCESS);
1093: }
1095: /*@C
1096: PetscViewerBinaryReadAll - reads from a binary file from all MPI processes, each rank receives its own portion of the data
1098: Collective
1100: Input Parameters:
1101: + viewer - the `PETSCVIEWERBINARY` viewer
1102: . count - local number of items of data to read
1103: . start - local start, can be `PETSC_DETERMINE`
1104: . total - global number of items of data to read, can be `PETSC_DETERMINE`
1105: - dtype - type of data to read
1107: Output Parameter:
1108: . data - location of data, treated as an array of type indicated by `dtype`
1110: Level: advanced
1112: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteAll()`
1113: @*/
1114: PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1115: {
1116: PetscFunctionBegin;
1117: PetscCall(PetscViewerBinaryWriteReadAll(viewer, PETSC_FALSE, data, count, start, total, dtype));
1118: PetscFunctionReturn(PETSC_SUCCESS);
1119: }
1121: /*@C
1122: PetscViewerBinaryWriteAll - writes to a binary file from all MPI processes, each rank writes its own portion of the data
1124: Collective
1126: Input Parameters:
1127: + viewer - the `PETSCVIEWERBINARY` viewer
1128: . data - location of data
1129: . count - local number of items of data to write, treated as an array of type indicated by `dtype`
1130: . start - local start, can be `PETSC_DETERMINE`
1131: . total - global number of items of data to write, can be `PETSC_DETERMINE`
1132: - dtype - type of data to write
1134: Level: advanced
1136: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryWriteAll()`, `PetscViewerBinaryReadAll()`
1137: @*/
1138: PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer, const void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1139: {
1140: PetscFunctionBegin;
1141: PetscCall(PetscViewerBinaryWriteReadAll(viewer, PETSC_TRUE, (void *)data, count, start, total, dtype));
1142: PetscFunctionReturn(PETSC_SUCCESS);
1143: }
1145: /*@C
1146: PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first MPI rank, an array of strings
1148: Collective
1150: Input Parameters:
1151: + viewer - the `PETSCVIEWERBINARY` viewer
1152: - data - location of the array of strings
1154: Level: intermediate
1156: Note:
1157: The array of strings must be `NULL` terminated
1159: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1160: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1161: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1162: @*/
1163: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer, const char *const *data)
1164: {
1165: PetscInt i, n = 0, *sizes;
1166: size_t len;
1168: PetscFunctionBegin;
1169: PetscCall(PetscViewerSetUp(viewer));
1170: /* count number of strings */
1171: while (data[n++])
1172: ;
1173: n--;
1174: PetscCall(PetscMalloc1(n + 1, &sizes));
1175: sizes[0] = n;
1176: for (i = 0; i < n; i++) {
1177: PetscCall(PetscStrlen(data[i], &len));
1178: sizes[i + 1] = (PetscInt)len + 1; /* size includes space for the null terminator */
1179: }
1180: PetscCall(PetscViewerBinaryWrite(viewer, sizes, n + 1, PETSC_INT));
1181: for (i = 0; i < n; i++) PetscCall(PetscViewerBinaryWrite(viewer, (void *)data[i], sizes[i + 1], PETSC_CHAR));
1182: PetscCall(PetscFree(sizes));
1183: PetscFunctionReturn(PETSC_SUCCESS);
1184: }
1186: /*@C
1187: PetscViewerBinaryReadStringArray - reads a binary file an array of strings to all MPI processes
1189: Collective
1191: Input Parameter:
1192: . viewer - the `PETSCVIEWERBINARY` viewer
1194: Output Parameter:
1195: . data - location of the array of strings
1197: Level: intermediate
1199: Note:
1200: The array of strings must `NULL` terminated
1202: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1203: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1204: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1205: @*/
1206: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer, char ***data)
1207: {
1208: PetscInt i, n, *sizes, N = 0;
1210: PetscFunctionBegin;
1211: PetscCall(PetscViewerSetUp(viewer));
1212: /* count number of strings */
1213: PetscCall(PetscViewerBinaryRead(viewer, &n, 1, NULL, PETSC_INT));
1214: PetscCall(PetscMalloc1(n, &sizes));
1215: PetscCall(PetscViewerBinaryRead(viewer, sizes, n, NULL, PETSC_INT));
1216: for (i = 0; i < n; i++) N += sizes[i];
1217: PetscCall(PetscMalloc((n + 1) * sizeof(char *) + N * sizeof(char), data));
1218: (*data)[0] = (char *)((*data) + n + 1);
1219: for (i = 1; i < n; i++) (*data)[i] = (*data)[i - 1] + sizes[i - 1];
1220: PetscCall(PetscViewerBinaryRead(viewer, (*data)[0], N, NULL, PETSC_CHAR));
1221: (*data)[n] = NULL;
1222: PetscCall(PetscFree(sizes));
1223: PetscFunctionReturn(PETSC_SUCCESS);
1224: }
1226: /*@C
1227: PetscViewerFileSetMode - Sets the open mode of file
1229: Logically Collective
1231: Input Parameters:
1232: + viewer - the `PetscViewer`; must be a a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII` `PetscViewer`
1233: - mode - open mode of file
1234: .vb
1235: FILE_MODE_WRITE - create new file for output
1236: FILE_MODE_READ - open existing file for input
1237: FILE_MODE_APPEND - open existing file for output
1238: .ve
1240: Level: advanced
1242: .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1243: @*/
1244: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer, PetscFileMode mode)
1245: {
1246: PetscFunctionBegin;
1249: PetscCheck(mode != FILE_MODE_UNDEFINED, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot set FILE_MODE_UNDEFINED");
1250: PetscCheck(mode >= FILE_MODE_UNDEFINED && mode <= FILE_MODE_APPEND_UPDATE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_OUTOFRANGE, "Invalid file mode %d", (int)mode);
1251: PetscTryMethod(viewer, "PetscViewerFileSetMode_C", (PetscViewer, PetscFileMode), (viewer, mode));
1252: PetscFunctionReturn(PETSC_SUCCESS);
1253: }
1255: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer, PetscFileMode mode)
1256: {
1257: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1259: PetscFunctionBegin;
1260: PetscCheck(!viewer->setupcalled || vbinary->filemode == mode, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Cannot change mode to %s after setup", PetscFileModes[mode]);
1261: vbinary->filemode = mode;
1262: PetscFunctionReturn(PETSC_SUCCESS);
1263: }
1265: /*@C
1266: PetscViewerFileGetMode - Gets the open mode of a file associated with a `PetscViewer`
1268: Not Collective
1270: Input Parameter:
1271: . viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII` `PetscViewer`
1273: Output Parameter:
1274: . mode - open mode of file
1275: .vb
1276: FILE_MODE_WRITE - create new file for binary output
1277: FILE_MODE_READ - open existing file for binary input
1278: FILE_MODE_APPEND - open existing file for binary output
1279: .ve
1281: Level: advanced
1283: .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1284: @*/
1285: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer, PetscFileMode *mode)
1286: {
1287: PetscFunctionBegin;
1290: PetscUseMethod(viewer, "PetscViewerFileGetMode_C", (PetscViewer, PetscFileMode *), (viewer, mode));
1291: PetscFunctionReturn(PETSC_SUCCESS);
1292: }
1294: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer, PetscFileMode *mode)
1295: {
1296: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1298: PetscFunctionBegin;
1299: *mode = vbinary->filemode;
1300: PetscFunctionReturn(PETSC_SUCCESS);
1301: }
1303: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer, const char name[])
1304: {
1305: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1307: PetscFunctionBegin;
1308: if (viewer->setupcalled && vbinary->filename) {
1309: /* gzip can be run after the file with the previous filename has been closed */
1310: PetscCall(PetscFree(vbinary->ogzfilename));
1311: PetscCall(PetscStrallocpy(vbinary->filename, &vbinary->ogzfilename));
1312: }
1313: PetscCall(PetscFree(vbinary->filename));
1314: PetscCall(PetscStrallocpy(name, &vbinary->filename));
1315: viewer->setupcalled = PETSC_FALSE;
1316: PetscFunctionReturn(PETSC_SUCCESS);
1317: }
1319: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer, const char **name)
1320: {
1321: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1323: PetscFunctionBegin;
1324: *name = vbinary->filename;
1325: PetscFunctionReturn(PETSC_SUCCESS);
1326: }
1328: #if defined(PETSC_HAVE_MPIIO)
1329: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1330: {
1331: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1332: int amode;
1334: PetscFunctionBegin;
1335: vbinary->storecompressed = PETSC_FALSE;
1337: vbinary->moff = 0;
1338: switch (vbinary->filemode) {
1339: case FILE_MODE_READ:
1340: amode = MPI_MODE_RDONLY;
1341: break;
1342: case FILE_MODE_WRITE:
1343: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE;
1344: break;
1345: case FILE_MODE_APPEND:
1346: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND;
1347: break;
1348: case FILE_MODE_UNDEFINED:
1349: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerSetUp()");
1350: default:
1351: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vbinary->filemode]);
1352: }
1353: PetscCallMPI(MPI_File_open(PetscObjectComm((PetscObject)viewer), vbinary->filename, amode, MPI_INFO_NULL, &vbinary->mfdes));
1354: /*
1355: The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
1356: */
1357: if (vbinary->filemode == FILE_MODE_WRITE) PetscCallMPI(MPI_File_set_size(vbinary->mfdes, 0));
1358: /*
1359: Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
1360: MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
1361: Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
1362: the offset in etype units to an absolute byte position.
1363: */
1364: if (vbinary->filemode == FILE_MODE_APPEND) PetscCallMPI(MPI_File_get_position(vbinary->mfdes, &vbinary->moff));
1365: PetscFunctionReturn(PETSC_SUCCESS);
1366: }
1367: #endif
1369: static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
1370: {
1371: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1372: const char *fname;
1373: char bname[PETSC_MAX_PATH_LEN], *gz = NULL;
1374: PetscBool found;
1375: PetscMPIInt rank;
1377: PetscFunctionBegin;
1378: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1380: /* if file name ends in .gz strip that off and note user wants file compressed */
1381: vbinary->storecompressed = PETSC_FALSE;
1382: if (vbinary->filemode == FILE_MODE_WRITE) {
1383: PetscCall(PetscStrstr(vbinary->filename, ".gz", &gz));
1384: if (gz && gz[3] == 0) {
1385: *gz = 0;
1386: vbinary->storecompressed = PETSC_TRUE;
1387: }
1388: }
1389: #if !defined(PETSC_HAVE_POPEN)
1390: PetscCheck(!vbinary->storecompressed, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP_SYS, "Cannot run gzip on this machine");
1391: #endif
1393: fname = vbinary->filename;
1394: if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
1395: PetscCall(PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), fname, bname, PETSC_MAX_PATH_LEN, &found));
1396: PetscCheck(found, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_OPEN, "Cannot locate file: %s", fname);
1397: fname = bname;
1398: }
1400: vbinary->fdes = -1;
1401: if (rank == 0) { /* only first processor opens file*/
1402: PetscFileMode mode = vbinary->filemode;
1403: if (mode == FILE_MODE_APPEND) {
1404: /* check if asked to append to a non-existing file */
1405: PetscCall(PetscTestFile(fname, '\0', &found));
1406: if (!found) mode = FILE_MODE_WRITE;
1407: }
1408: PetscCall(PetscBinaryOpen(fname, mode, &vbinary->fdes));
1409: }
1410: PetscFunctionReturn(PETSC_SUCCESS);
1411: }
1413: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1414: {
1415: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1416: PetscMPIInt rank;
1417: PetscBool found;
1419: PetscFunctionBegin;
1420: vbinary->fdes_info = NULL;
1421: PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1422: if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || rank == 0)) {
1423: char infoname[PETSC_MAX_PATH_LEN], iname[PETSC_MAX_PATH_LEN], *gz;
1425: PetscCall(PetscStrncpy(infoname, vbinary->filename, sizeof(infoname)));
1426: /* remove .gz if it ends file name */
1427: PetscCall(PetscStrstr(infoname, ".gz", &gz));
1428: if (gz && gz[3] == 0) *gz = 0;
1430: PetscCall(PetscStrlcat(infoname, ".info", sizeof(infoname)));
1431: if (vbinary->filemode == FILE_MODE_READ) {
1432: PetscCall(PetscFixFilename(infoname, iname));
1433: PetscCall(PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), iname, infoname, PETSC_MAX_PATH_LEN, &found));
1434: if (found) PetscCall(PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer), ((PetscObject)viewer)->options, infoname, PETSC_FALSE));
1435: } else if (rank == 0) { /* write or append */
1436: const char *omode = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
1437: vbinary->fdes_info = fopen(infoname, omode);
1438: PetscCheck(vbinary->fdes_info, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open .info file %s for writing", infoname);
1439: }
1440: }
1441: PetscFunctionReturn(PETSC_SUCCESS);
1442: }
1444: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1445: {
1446: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1447: PetscBool usempiio;
1449: PetscFunctionBegin;
1450: if (!vbinary->setfromoptionscalled) PetscCall(PetscViewerSetFromOptions(viewer));
1451: PetscCheck(vbinary->filename, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetName()");
1452: PetscCheck(vbinary->filemode != (PetscFileMode)-1, PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode()");
1453: PetscCall(PetscViewerFileClose_Binary(viewer));
1455: PetscCall(PetscViewerBinaryGetUseMPIIO(viewer, &usempiio));
1456: if (usempiio) {
1457: #if defined(PETSC_HAVE_MPIIO)
1458: PetscCall(PetscViewerFileSetUp_BinaryMPIIO(viewer));
1459: #endif
1460: } else {
1461: PetscCall(PetscViewerFileSetUp_BinarySTDIO(viewer));
1462: }
1463: PetscCall(PetscViewerFileSetUp_BinaryInfo(viewer));
1465: PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", vbinary->filename));
1466: PetscFunctionReturn(PETSC_SUCCESS);
1467: }
1469: static PetscErrorCode PetscViewerView_Binary(PetscViewer v, PetscViewer viewer)
1470: {
1471: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
1472: const char *fname = vbinary->filename ? vbinary->filename : "not yet set";
1473: const char *fmode = vbinary->filemode != (PetscFileMode)-1 ? PetscFileModes[vbinary->filemode] : "not yet set";
1474: PetscBool usempiio;
1476: PetscFunctionBegin;
1477: PetscCall(PetscViewerBinaryGetUseMPIIO(v, &usempiio));
1478: PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", fname));
1479: PetscCall(PetscViewerASCIIPrintf(viewer, "Mode: %s (%s)\n", fmode, usempiio ? "mpiio" : "stdio"));
1480: PetscFunctionReturn(PETSC_SUCCESS);
1481: }
1483: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscViewer viewer, PetscOptionItems *PetscOptionsObject)
1484: {
1485: PetscViewer_Binary *binary = (PetscViewer_Binary *)viewer->data;
1486: char defaultname[PETSC_MAX_PATH_LEN];
1487: PetscBool flg;
1489: PetscFunctionBegin;
1490: if (viewer->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
1491: PetscOptionsHeadBegin(PetscOptionsObject, "Binary PetscViewer Options");
1492: PetscCall(PetscSNPrintf(defaultname, PETSC_MAX_PATH_LEN - 1, "binaryoutput"));
1493: PetscCall(PetscOptionsString("-viewer_binary_filename", "Specify filename", "PetscViewerFileSetName", defaultname, defaultname, sizeof(defaultname), &flg));
1494: if (flg) PetscCall(PetscViewerFileSetName_Binary(viewer, defaultname));
1495: PetscCall(PetscOptionsBool("-viewer_binary_skip_info", "Skip writing/reading .info file", "PetscViewerBinarySetSkipInfo", binary->skipinfo, &binary->skipinfo, NULL));
1496: PetscCall(PetscOptionsBool("-viewer_binary_skip_options", "Skip parsing Vec/Mat load options", "PetscViewerBinarySetSkipOptions", binary->skipoptions, &binary->skipoptions, NULL));
1497: PetscCall(PetscOptionsBool("-viewer_binary_skip_header", "Skip writing/reading header information", "PetscViewerBinarySetSkipHeader", binary->skipheader, &binary->skipheader, NULL));
1498: #if defined(PETSC_HAVE_MPIIO)
1499: PetscCall(PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file", "PetscViewerBinarySetUseMPIIO", binary->usempiio, &binary->usempiio, NULL));
1500: #else
1501: PetscCall(PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)", "PetscViewerBinarySetUseMPIIO", PETSC_FALSE, NULL, NULL));
1502: #endif
1503: PetscOptionsHeadEnd();
1504: binary->setfromoptionscalled = PETSC_TRUE;
1505: PetscFunctionReturn(PETSC_SUCCESS);
1506: }
1508: /*MC
1509: PETSCVIEWERBINARY - A viewer that saves to binary files
1511: Level: beginner
1513: .seealso: [](sec_viewers), `PetscViewerBinaryOpen()`, `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1514: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, `PETSCVIEWERDRAW`, `PETSCVIEWERSOCKET`
1515: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`,
1516: `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`
1517: M*/
1519: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1520: {
1521: PetscViewer_Binary *vbinary;
1523: PetscFunctionBegin;
1524: PetscCall(PetscNew(&vbinary));
1525: v->data = (void *)vbinary;
1527: v->ops->setfromoptions = PetscViewerSetFromOptions_Binary;
1528: v->ops->destroy = PetscViewerDestroy_Binary;
1529: v->ops->view = PetscViewerView_Binary;
1530: v->ops->setup = PetscViewerSetUp_Binary;
1531: v->ops->flush = NULL; /* Should we support Flush() ? */
1532: v->ops->getsubviewer = PetscViewerGetSubViewer_Binary;
1533: v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1534: v->ops->read = PetscViewerBinaryRead;
1536: vbinary->fdes = -1;
1537: #if defined(PETSC_HAVE_MPIIO)
1538: vbinary->usempiio = PETSC_FALSE;
1539: vbinary->mfdes = MPI_FILE_NULL;
1540: vbinary->mfsub = MPI_FILE_NULL;
1541: #endif
1542: vbinary->filename = NULL;
1543: vbinary->filemode = FILE_MODE_UNDEFINED;
1544: vbinary->fdes_info = NULL;
1545: vbinary->skipinfo = PETSC_FALSE;
1546: vbinary->skipoptions = PETSC_TRUE;
1547: vbinary->skipheader = PETSC_FALSE;
1548: vbinary->storecompressed = PETSC_FALSE;
1549: vbinary->ogzfilename = NULL;
1550: vbinary->flowcontrol = 256; /* seems a good number for Cray XT-5 */
1552: vbinary->setfromoptionscalled = PETSC_FALSE;
1554: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Binary));
1555: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", PetscViewerBinarySetFlowControl_Binary));
1556: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Binary));
1557: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Binary));
1558: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", PetscViewerBinaryGetSkipOptions_Binary));
1559: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", PetscViewerBinarySetSkipOptions_Binary));
1560: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", PetscViewerBinaryGetSkipInfo_Binary));
1561: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", PetscViewerBinarySetSkipInfo_Binary));
1562: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", PetscViewerBinaryGetInfoPointer_Binary));
1563: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_Binary));
1564: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_Binary));
1565: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_Binary));
1566: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Binary));
1567: #if defined(PETSC_HAVE_MPIIO)
1568: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", PetscViewerBinaryGetUseMPIIO_Binary));
1569: PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", PetscViewerBinarySetUseMPIIO_Binary));
1570: #endif
1571: PetscFunctionReturn(PETSC_SUCCESS);
1572: }
1574: /*
1575: The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1576: is attached to a communicator, in this case the attribute is a PetscViewer.
1577: */
1578: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
1580: /*@C
1581: PETSC_VIEWER_BINARY_ - Creates a `PETSCVIEWERBINARY` `PetscViewer` shared by all processors
1582: in a communicator.
1584: Collective
1586: Input Parameter:
1587: . comm - the MPI communicator to share the `PETSCVIEWERBINARY`
1589: Level: intermediate
1591: Options Database Keys:
1592: + -viewer_binary_filename <name> - filename in which to store the binary data, defaults to binaryoutput
1593: . -viewer_binary_skip_info - true means do not create .info file for this viewer
1594: . -viewer_binary_skip_options - true means do not use the options database for this viewer
1595: . -viewer_binary_skip_header - true means do not store the usual header information in the binary file
1596: - -viewer_binary_mpiio - true means use the file via MPI-IO, maybe faster for large files and many MPI ranks
1598: Environmental variable:
1599: - PETSC_VIEWER_BINARY_FILENAME - filename in which to store the binary data, defaults to binaryoutput
1601: Note:
1602: Unlike almost all other PETSc routines, `PETSC_VIEWER_BINARY_` does not return
1603: an error code. The binary PetscViewer is usually used in the form
1604: $ XXXView(XXX object, PETSC_VIEWER_BINARY_(comm));
1606: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PETSC_VIEWER_BINARY_WORLD`, `PETSC_VIEWER_BINARY_SELF`, `PetscViewerBinaryOpen()`, `PetscViewerCreate()`,
1607: `PetscViewerDestroy()`
1608: @*/
1609: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1610: {
1611: PetscErrorCode ierr;
1612: PetscMPIInt mpi_ierr;
1613: PetscBool flg;
1614: PetscViewer viewer;
1615: char fname[PETSC_MAX_PATH_LEN];
1616: MPI_Comm ncomm;
1618: PetscFunctionBegin;
1619: ierr = PetscCommDuplicate(comm, &ncomm, NULL);
1620: if (ierr) {
1621: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1622: PetscFunctionReturn(NULL);
1623: }
1624: if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1625: mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Binary_keyval, NULL);
1626: if (mpi_ierr) {
1627: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1628: PetscFunctionReturn(NULL);
1629: }
1630: }
1631: mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Binary_keyval, (void **)&viewer, (int *)&flg);
1632: if (mpi_ierr) {
1633: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1634: PetscFunctionReturn(NULL);
1635: }
1636: if (!flg) { /* PetscViewer not yet created */
1637: ierr = PetscOptionsGetenv(ncomm, "PETSC_VIEWER_BINARY_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
1638: if (ierr) {
1639: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1640: PetscFunctionReturn(NULL);
1641: }
1642: if (!flg) {
1643: ierr = PetscStrncpy(fname, "binaryoutput", sizeof(fname));
1644: if (ierr) {
1645: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1646: PetscFunctionReturn(NULL);
1647: }
1648: }
1649: ierr = PetscViewerBinaryOpen(ncomm, fname, FILE_MODE_WRITE, &viewer);
1650: if (ierr) {
1651: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1652: PetscFunctionReturn(NULL);
1653: }
1654: ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
1655: if (ierr) {
1656: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1657: PetscFunctionReturn(NULL);
1658: }
1659: mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Binary_keyval, (void *)viewer);
1660: if (mpi_ierr) {
1661: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1662: PetscFunctionReturn(NULL);
1663: }
1664: }
1665: ierr = PetscCommDestroy(&ncomm);
1666: if (ierr) {
1667: ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1668: PetscFunctionReturn(NULL);
1669: }
1670: PetscFunctionReturn(viewer);
1671: }