Actual source code: binv.c
1: #include <petsc/private/viewerimpl.h>
3: /*
4: This needs to start the same as PetscViewer_Socket.
5: */
6: typedef struct {
7: int fdes; /* file descriptor, ignored if using MPI IO */
8: PetscInt flowcontrol; /* allow only <flowcontrol> messages outstanding at a time while doing IO */
9: PetscBool skipheader; /* don't write header, only raw data */
10: #if defined(PETSC_HAVE_MPIIO)
11: PetscBool usempiio;
12: MPI_File mfdes; /* ignored unless using MPI IO */
13: MPI_File mfsub; /* subviewer support */
14: MPI_Offset moff;
15: #endif
16: char *filename; /* file name */
17: PetscFileMode filemode; /* read/write/append mode */
18: FILE *fdes_info; /* optional file containing info on binary file*/
19: PetscBool storecompressed; /* gzip the write binary file when closing it*/
20: char *ogzfilename; /* gzip can be run after the filename has been updated */
21: PetscBool skipinfo; /* Don't create info file for writing; don't use for reading */
22: PetscBool skipoptions; /* don't use PETSc options database when loading */
23: PetscBool matlabheaderwritten; /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
24: PetscBool setfromoptionscalled;
25: } PetscViewer_Binary;
27: static PetscErrorCode PetscViewerBinaryClearFunctionList(PetscViewer v)
28: {
29: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", NULL);
30: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", NULL);
31: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", NULL);
32: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", NULL);
33: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", NULL);
34: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", NULL);
35: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", NULL);
36: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", NULL);
37: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", NULL);
38: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", NULL);
39: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", NULL);
40: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", NULL);
41: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", NULL);
42: #if defined(PETSC_HAVE_MPIIO)
43: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", NULL);
44: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", NULL);
45: #endif
46: return 0;
47: }
49: #if defined(PETSC_HAVE_MPIIO)
50: static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer)
51: {
52: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
54: if (vbinary->filemode == FILE_MODE_READ) return 0;
55: if (vbinary->mfsub != MPI_FILE_NULL) MPI_File_sync(vbinary->mfsub);
56: if (vbinary->mfdes != MPI_FILE_NULL) {
57: MPI_Barrier(PetscObjectComm((PetscObject)viewer));
58: MPI_File_sync(vbinary->mfdes);
59: }
60: return 0;
61: }
62: #endif
64: static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
65: {
66: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
67: PetscMPIInt rank;
69: PetscViewerSetUp(viewer);
71: /* Return subviewer in process zero */
72: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
73: if (rank == 0) {
74: PetscMPIInt flg;
76: MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg);
78: PetscViewerCreate(comm, outviewer);
79: PetscViewerSetType(*outviewer, PETSCVIEWERBINARY);
80: PetscMemcpy((*outviewer)->data, vbinary, sizeof(PetscViewer_Binary));
81: (*outviewer)->setupcalled = PETSC_TRUE;
82: } else {
83: *outviewer = NULL;
84: }
86: #if defined(PETSC_HAVE_MPIIO)
87: if (vbinary->usempiio && *outviewer) {
88: PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
89: /* Parent viewer opens a new MPI file handle on PETSC_COMM_SELF and keeps track of it for future reuse */
90: if (vbinary->mfsub == MPI_FILE_NULL) {
91: int amode;
92: switch (vbinary->filemode) {
93: case FILE_MODE_READ:
94: amode = MPI_MODE_RDONLY;
95: break;
96: case FILE_MODE_WRITE:
97: amode = MPI_MODE_WRONLY;
98: break;
99: case FILE_MODE_APPEND:
100: amode = MPI_MODE_WRONLY;
101: break;
102: default:
103: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vbinary->filemode]);
104: }
105: MPI_File_open(PETSC_COMM_SELF, vbinary->filename, amode, MPI_INFO_NULL, &vbinary->mfsub);
106: }
107: /* Subviewer gets the MPI file handle on PETSC_COMM_SELF */
108: obinary->mfdes = vbinary->mfsub;
109: obinary->mfsub = MPI_FILE_NULL;
110: obinary->moff = vbinary->moff;
111: }
112: #endif
114: #if defined(PETSC_HAVE_MPIIO)
115: PetscViewerBinarySyncMPIIO(viewer);
116: #endif
117: return 0;
118: }
120: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
121: {
122: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
123: PetscMPIInt rank;
124: #if defined(PETSC_HAVE_MPIIO)
125: MPI_Offset moff = 0;
126: #endif
128: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
131: #if defined(PETSC_HAVE_MPIIO)
132: if (vbinary->usempiio && *outviewer) {
133: PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
135: if (obinary->mfsub != MPI_FILE_NULL) MPI_File_close(&obinary->mfsub);
136: moff = obinary->moff;
137: }
138: #endif
140: if (*outviewer) {
141: PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
143: PetscFree((*outviewer)->data);
144: PetscViewerBinaryClearFunctionList(*outviewer);
145: PetscHeaderDestroy(outviewer);
146: }
148: #if defined(PETSC_HAVE_MPIIO)
149: if (vbinary->usempiio) {
150: PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */
151: MPI_Bcast(&ioff, 1, MPIU_INT64, 0, PetscObjectComm((PetscObject)viewer));
152: vbinary->moff = (MPI_Offset)ioff;
153: }
154: #endif
156: #if defined(PETSC_HAVE_MPIIO)
157: PetscViewerBinarySyncMPIIO(viewer);
158: #endif
159: return 0;
160: }
162: #if defined(PETSC_HAVE_MPIIO)
163: /*@C
164: PetscViewerBinaryGetMPIIOOffset - Gets the current global offset that should be passed to `MPI_File_set_view()` or `MPI_File_{write|read}_at[_all]()`
166: Not Collective
168: Input Parameter:
169: . viewer - PetscViewer context, obtained from `PetscViewerBinaryOpen()`
171: Output Parameter:
172: . off - the current global offset
174: Level: advanced
176: Note:
177: Use `PetscViewerBinaryAddMPIIOOffset()` to increase this value after you have written a view.
179: Fortran Note:
180: This routine is not supported in Fortran.
182: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryAddMPIIOOffset()`
183: @*/
184: PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer, MPI_Offset *off)
185: {
186: PetscViewer_Binary *vbinary;
190: vbinary = (PetscViewer_Binary *)viewer->data;
191: *off = vbinary->moff;
192: return 0;
193: }
195: /*@C
196: PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset
198: Logically Collective
200: Input Parameters:
201: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
202: - off - the addition to the global offset
204: Level: advanced
206: Note:
207: Use `PetscViewerBinaryGetMPIIOOffset()` to get the value that you should pass to `MPI_File_set_view()` or `MPI_File_{write|read}_at[_all]()`
209: Fortran Note:
210: This routine is not supported in Fortran.
212: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
213: @*/
214: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer, MPI_Offset off)
215: {
216: PetscViewer_Binary *vbinary;
220: vbinary = (PetscViewer_Binary *)viewer->data;
221: vbinary->moff += off;
222: return 0;
223: }
225: /*@C
226: PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a `PetscViewer`.
228: Not Collective
230: Input Parameter:
231: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
233: Output Parameter:
234: . fdes - file descriptor
236: Level: advanced
238: Fortran Note:
239: This routine is not supported in Fortran.
241: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
242: @*/
243: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer, MPI_File *fdes)
244: {
245: PetscViewer_Binary *vbinary;
249: PetscViewerSetUp(viewer);
250: vbinary = (PetscViewer_Binary *)viewer->data;
251: *fdes = vbinary->mfdes;
252: return 0;
253: }
254: #endif
256: /*@
257: PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
258: before `PetscViewerFileSetName()`
260: Logically Collective on viewer
262: Input Parameters:
263: + viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`
264: - use - `PETSC_TRUE` means MPI-IO will be used
266: Options Database Key:
267: -viewer_binary_mpiio : Flag for using MPI-IO
269: Level: advanced
271: .seealso: `PETSCVIEWERBINARY`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
272: `PetscViewerBinaryGetUseMPIIO()`
273: @*/
274: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer, PetscBool use)
275: {
278: PetscTryMethod(viewer, "PetscViewerBinarySetUseMPIIO_C", (PetscViewer, PetscBool), (viewer, use));
279: return 0;
280: }
282: #if defined(PETSC_HAVE_MPIIO)
283: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer, PetscBool use)
284: {
285: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
287: vbinary->usempiio = use;
288: return 0;
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: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
309: @*/
310: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer, PetscBool *use)
311: {
314: *use = PETSC_FALSE;
315: PetscTryMethod(viewer, "PetscViewerBinaryGetUseMPIIO_C", (PetscViewer, PetscBool *), (viewer, use));
316: return 0;
317: }
319: #if defined(PETSC_HAVE_MPIIO)
320: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer, PetscBool *use)
321: {
322: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
324: *use = vbinary->usempiio;
325: return 0;
326: }
327: #endif
329: /*@
330: PetscViewerBinarySetFlowControl - Sets how many messages are allowed to outstanding at the same time during parallel IO reads/writes
332: Not Collective
334: Input Parameters:
335: + viewer - PetscViewer context, obtained from `PetscViewerBinaryOpen()`
336: - fc - the number of messages, defaults to 256 if this function was not called
338: Level: advanced
340: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetFlowControl()`
341: @*/
342: PetscErrorCode PetscViewerBinarySetFlowControl(PetscViewer viewer, PetscInt fc)
343: {
346: PetscTryMethod(viewer, "PetscViewerBinarySetFlowControl_C", (PetscViewer, PetscInt), (viewer, fc));
347: return 0;
348: }
350: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer, PetscInt fc)
351: {
352: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
355: vbinary->flowcontrol = fc;
356: return 0;
357: }
359: /*@
360: PetscViewerBinaryGetFlowControl - Returns how many messages are allowed to outstanding at the same time during parallel IO reads/writes
362: Not Collective
364: Input Parameter:
365: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
367: Output Parameter:
368: . fc - the number of messages
370: Level: advanced
372: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetFlowControl()`
373: @*/
374: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer, PetscInt *fc)
375: {
378: PetscUseMethod(viewer, "PetscViewerBinaryGetFlowControl_C", (PetscViewer, PetscInt *), (viewer, fc));
379: return 0;
380: }
382: PETSC_INTERN PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer, PetscInt *fc)
383: {
384: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
386: *fc = vbinary->flowcontrol;
387: return 0;
388: }
390: /*@C
391: PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a `PetscViewer` of `PetscViewerType` `PETSCVIEWERBINARY`.
393: Collective on viewer because it may trigger a `PetscViewerSetUp()` call
395: Input Parameter:
396: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
398: Output Parameter:
399: . fdes - file descriptor
401: Level: advanced
403: Note:
404: For writable binary `PetscViewer`s, the descriptor will only be valid for the
405: first processor in the communicator that shares the `PetscViewer`. For readable
406: files it will only be valid on nodes that have the file. If node 0 does not
407: have the file it generates an error even if another node does have the file.
409: Fortran Note:
410: This routine is not supported in Fortran.
412: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`
413: @*/
414: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer, int *fdes)
415: {
416: PetscViewer_Binary *vbinary;
420: PetscViewerSetUp(viewer);
421: vbinary = (PetscViewer_Binary *)viewer->data;
422: *fdes = vbinary->fdes;
423: return 0;
424: }
426: /*@
427: PetscViewerBinarySkipInfo - Binary file will not have .info file created with it
429: Not Collective
431: Input Parameter:
432: . viewer - `PetscViewer` context, obtained from `PetscViewerCreate()`
434: Options Database Key:
435: . -viewer_binary_skip_info - true indicates do not generate .info file
437: Level: advanced
439: Notes:
440: This must be called after `PetscViewerSetType()`. If you use `PetscViewerBinaryOpen()` then
441: you can only skip the info file with the -viewer_binary_skip_info flag. To use the function you must open the
442: viewer with `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinarySkipInfo()`.
444: The .info contains meta information about the data in the binary file, for example the block size if it was
445: set for a vector or matrix.
447: This routine is deprecated, use `PetscViewerBinarySetSkipInfo()`
449: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
450: `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
451: @*/
452: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
453: {
454: PetscViewerBinarySetSkipInfo(viewer, PETSC_TRUE);
455: return 0;
456: }
458: /*@
459: PetscViewerBinarySetSkipInfo - Binary file will not have .info file created with it
461: Not Collective
463: Input Parameters:
464: + viewer - PetscViewer context, obtained from PetscViewerCreate()
465: - skip - PETSC_TRUE implies the .info file will not be generated
467: Options Database Key:
468: . -viewer_binary_skip_info - true indicates do not generate .info file
470: Level: advanced
472: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
473: `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
474: @*/
475: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer, PetscBool skip)
476: {
479: PetscTryMethod(viewer, "PetscViewerBinarySetSkipInfo_C", (PetscViewer, PetscBool), (viewer, skip));
480: return 0;
481: }
483: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer, PetscBool skip)
484: {
485: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
487: vbinary->skipinfo = skip;
488: return 0;
489: }
491: /*@
492: PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file
494: Not Collective
496: Input Parameter:
497: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
499: Output Parameter:
500: . skip - `PETSC_TRUE` implies the .info file was not generated
502: Level: advanced
504: Note:
505: This must be called after `PetscViewerSetType()`
507: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`,
508: `PetscViewerBinarySetSkipOptions()`, `PetscViewerBinarySetSkipInfo()`
509: @*/
510: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer, PetscBool *skip)
511: {
514: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipInfo_C", (PetscViewer, PetscBool *), (viewer, skip));
515: return 0;
516: }
518: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer, PetscBool *skip)
519: {
520: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
522: *skip = vbinary->skipinfo;
523: return 0;
524: }
526: /*@
527: PetscViewerBinarySetSkipOptions - do not use the PETSc options database when loading objects
529: Not Collective
531: Input Parameters:
532: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
533: - skip - `PETSC_TRUE` means do not use the options from the options database
535: Options Database Key:
536: . -viewer_binary_skip_options <true or false> - true means do not use the options from the options database
538: Level: advanced
540: Note:
541: This must be called after `PetscViewerSetType()`
543: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
544: `PetscViewerBinaryGetSkipOptions()`
545: @*/
546: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer, PetscBool skip)
547: {
550: PetscTryMethod(viewer, "PetscViewerBinarySetSkipOptions_C", (PetscViewer, PetscBool), (viewer, skip));
551: return 0;
552: }
554: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer, PetscBool skip)
555: {
556: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
558: vbinary->skipoptions = skip;
559: return 0;
560: }
562: /*@
563: PetscViewerBinaryGetSkipOptions - checks if viewer uses the PETSc options database when loading objects
565: Not Collective
567: Input Parameter:
568: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
570: Output Parameter:
571: . skip - `PETSC_TRUE` means do not use
573: Level: advanced
575: Note:
576: This must be called after `PetscViewerSetType()`
578: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
579: `PetscViewerBinarySetSkipOptions()`
580: @*/
581: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer, PetscBool *skip)
582: {
585: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipOptions_C", (PetscViewer, PetscBool *), (viewer, skip));
586: return 0;
587: }
589: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer, PetscBool *skip)
590: {
591: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
593: *skip = vbinary->skipoptions;
594: return 0;
595: }
597: /*@
598: PetscViewerBinarySetSkipHeader - do not write a header with size information on output, just raw data
600: Not Collective
602: Input Parameters:
603: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
604: - skip - `PETSC_TRUE `means do not write header
606: Options Database Key:
607: . -viewer_binary_skip_header <true or false> - true means do not write header
609: Level: advanced
611: Notes:
612: This must be called after `PetscViewerSetType()`
614: Is ignored on anything but a binary viewer
616: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
617: `PetscViewerBinaryGetSkipHeader()`
618: @*/
619: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer, PetscBool skip)
620: {
623: PetscTryMethod(viewer, "PetscViewerBinarySetSkipHeader_C", (PetscViewer, PetscBool), (viewer, skip));
624: return 0;
625: }
627: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer, PetscBool skip)
628: {
629: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
631: vbinary->skipheader = skip;
632: return 0;
633: }
635: /*@
636: PetscViewerBinaryGetSkipHeader - checks whether to write a header with size information on output, or just raw data
638: Not Collective
640: Input Parameter:
641: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
643: Output Parameter:
644: . skip - `PETSC_TRUE` means do not write header
646: Level: advanced
648: Notes:
649: This must be called after PetscViewerSetType()
651: Returns `PETSC_FALSE` for `PETSCSOCKETVIEWER`, you cannot skip the header for it.
653: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
654: `PetscViewerBinarySetSkipHeader()`
655: @*/
656: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer, PetscBool *skip)
657: {
660: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipHeader_C", (PetscViewer, PetscBool *), (viewer, skip));
661: return 0;
662: }
664: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer, PetscBool *skip)
665: {
666: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
668: *skip = vbinary->skipheader;
669: return 0;
670: }
672: /*@C
673: PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
674: info file associated with a binary file.
676: Not Collective
678: Input Parameter:
679: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
681: Output Parameter:
682: . file - file pointer Always returns NULL if not a binary viewer
684: Level: advanced
686: Note:
687: For writable binary `PetscViewer`s, the file pointer will only be valid for the
688: first processor in the communicator that shares the `PetscViewer`.
690: Fortran Note:
691: This routine is not supported in Fortran.
693: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`
694: @*/
695: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer, FILE **file)
696: {
699: *file = NULL;
700: PetscTryMethod(viewer, "PetscViewerBinaryGetInfoPointer_C", (PetscViewer, FILE **), (viewer, file));
701: return 0;
702: }
704: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer, FILE **file)
705: {
706: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
708: PetscViewerSetUp(viewer);
709: *file = vbinary->fdes_info;
710: if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
711: if (vbinary->fdes_info) {
712: FILE *info = vbinary->fdes_info;
713: PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
714: PetscFPrintf(PETSC_COMM_SELF, info, "#$$ Set.filename = '%s';\n", vbinary->filename);
715: PetscFPrintf(PETSC_COMM_SELF, info, "#$$ fd = PetscOpenFile(Set.filename);\n");
716: PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
717: }
718: vbinary->matlabheaderwritten = PETSC_TRUE;
719: }
720: return 0;
721: }
723: #if defined(PETSC_HAVE_MPIIO)
724: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
725: {
726: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
728: if (vbinary->mfdes != MPI_FILE_NULL) MPI_File_close(&vbinary->mfdes);
729: if (vbinary->mfsub != MPI_FILE_NULL) MPI_File_close(&vbinary->mfsub);
730: vbinary->moff = 0;
731: return 0;
732: }
733: #endif
735: static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
736: {
737: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
739: if (vbinary->fdes != -1) {
740: PetscBinaryClose(vbinary->fdes);
741: vbinary->fdes = -1;
742: if (vbinary->storecompressed) {
743: char cmd[8 + PETSC_MAX_PATH_LEN], out[64 + PETSC_MAX_PATH_LEN] = "";
744: const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
745: /* compress the file */
746: PetscStrncpy(cmd, "gzip -f ", sizeof(cmd));
747: PetscStrlcat(cmd, gzfilename, sizeof(cmd));
748: #if defined(PETSC_HAVE_POPEN)
749: {
750: FILE *fp;
751: PetscPOpen(PETSC_COMM_SELF, NULL, cmd, "r", &fp);
753: PetscPClose(PETSC_COMM_SELF, fp);
754: }
755: #endif
756: }
757: }
758: PetscFree(vbinary->ogzfilename);
759: return 0;
760: }
762: static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
763: {
764: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
766: if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
767: if (vbinary->fdes_info) {
768: FILE *info = vbinary->fdes_info;
769: PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
770: PetscFPrintf(PETSC_COMM_SELF, info, "#$$ close(fd);\n");
771: PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
772: }
773: }
774: if (vbinary->fdes_info) {
775: FILE *info = vbinary->fdes_info;
776: vbinary->fdes_info = NULL;
778: }
779: return 0;
780: }
782: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
783: {
784: #if defined(PETSC_HAVE_MPIIO)
785: PetscViewerFileClose_BinaryMPIIO(v);
786: #endif
787: PetscViewerFileClose_BinarySTDIO(v);
788: PetscViewerFileClose_BinaryInfo(v);
789: return 0;
790: }
792: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
793: {
794: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
796: PetscViewerFileClose_Binary(v);
797: PetscFree(vbinary->filename);
798: PetscFree(vbinary);
799: PetscViewerBinaryClearFunctionList(v);
800: return 0;
801: }
803: /*@C
804: PetscViewerBinaryOpen - Opens a file for binary input/output.
806: Collective
808: Input Parameters:
809: + comm - MPI communicator
810: . name - name of file
811: - mode - open mode of file
812: $ FILE_MODE_WRITE - create new file for binary output
813: $ FILE_MODE_READ - open existing file for binary input
814: $ FILE_MODE_APPEND - open existing file for binary output
816: Output Parameter:
817: . viewer - PetscViewer for binary input/output to use with the specified file
819: Options Database Keys:
820: + -viewer_binary_filename <name> - name of file to use
821: . -viewer_binary_skip_info - true to skip opening an info file
822: . -viewer_binary_skip_options - true to not use options database while creating viewer
823: . -viewer_binary_skip_header - true to skip output object headers to the file
824: - -viewer_binary_mpiio - true to use MPI-IO for input and output to the file (more scalable for large problems)
826: Level: beginner
828: Note:
829: This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.
831: For reading files, the filename may begin with ftp:// or http:// and/or
832: end with .gz; in this case file is brought over and uncompressed.
834: For creating files, if the file name ends with .gz it is automatically
835: compressed when closed.
837: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
838: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
839: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`, `PetscViewerBinarySetUseMPIIO()`,
840: `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
841: @*/
842: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm, const char name[], PetscFileMode mode, PetscViewer *viewer)
843: {
844: PetscViewerCreate(comm, viewer);
845: PetscViewerSetType(*viewer, PETSCVIEWERBINARY);
846: PetscViewerFileSetMode(*viewer, mode);
847: PetscViewerFileSetName(*viewer, name);
848: PetscViewerSetFromOptions(*viewer);
849: return 0;
850: }
852: #if defined(PETSC_HAVE_MPIIO)
853: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype, PetscBool write)
854: {
855: MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
856: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
857: MPI_File mfdes = vbinary->mfdes;
858: MPI_Datatype mdtype;
859: PetscMPIInt rank, cnt;
860: MPI_Status status;
861: MPI_Aint ul, dsize;
863: MPI_Comm_rank(comm, &rank);
864: PetscMPIIntCast(num, &cnt);
865: PetscDataTypeToMPIDataType(dtype, &mdtype);
866: if (write) {
867: if (rank == 0) MPIU_File_write_at(mfdes, vbinary->moff, data, cnt, mdtype, &status);
868: } else {
869: if (rank == 0) {
870: MPIU_File_read_at(mfdes, vbinary->moff, data, cnt, mdtype, &status);
871: if (cnt > 0) MPI_Get_count(&status, mdtype, &cnt);
872: }
873: MPI_Bcast(&cnt, 1, MPI_INT, 0, comm);
874: MPI_Bcast(data, cnt, mdtype, 0, comm);
875: }
876: MPI_Type_get_extent(mdtype, &ul, &dsize);
877: vbinary->moff += dsize * cnt;
878: if (count) *count = cnt;
879: return 0;
880: }
881: #endif
883: /*@C
884: PetscViewerBinaryRead - Reads from a binary file, all processors get the same result
886: Collective
888: Input Parameters:
889: + viewer - the binary viewer
890: . data - location of the data to be written
891: . num - number of items of data to read
892: - dtype - type of data to read
894: Output Parameters:
895: . count - number of items of data actually read, or NULL.
897: Level: beginner
899: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
900: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
901: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
902: @*/
903: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
904: {
905: PetscViewer_Binary *vbinary;
909: PetscViewerSetUp(viewer);
910: vbinary = (PetscViewer_Binary *)viewer->data;
911: #if defined(PETSC_HAVE_MPIIO)
912: if (vbinary->usempiio) {
913: PetscViewerBinaryWriteReadMPIIO(viewer, data, num, count, dtype, PETSC_FALSE);
914: } else {
915: #endif
916: PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, num, count, dtype);
917: #if defined(PETSC_HAVE_MPIIO)
918: }
919: #endif
920: return 0;
921: }
923: /*@C
924: PetscViewerBinaryWrite - writes to a binary file, only from the first MPI rank
926: Collective
928: Input Parameters:
929: + viewer - the binary viewer
930: . data - location of data
931: . count - number of items of data to write
932: - dtype - type of data to write
934: Level: beginner
936: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
937: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, `PetscDataType`
938: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
939: @*/
940: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer, const void *data, PetscInt count, PetscDataType dtype)
941: {
942: PetscViewer_Binary *vbinary;
946: PetscViewerSetUp(viewer);
947: vbinary = (PetscViewer_Binary *)viewer->data;
948: #if defined(PETSC_HAVE_MPIIO)
949: if (vbinary->usempiio) {
950: PetscViewerBinaryWriteReadMPIIO(viewer, (void *)data, count, NULL, dtype, PETSC_TRUE);
951: } else {
952: #endif
953: PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, count, dtype);
954: #if defined(PETSC_HAVE_MPIIO)
955: }
956: #endif
957: return 0;
958: }
960: static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer, PetscBool write, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
961: {
962: MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
963: PetscMPIInt size, rank;
964: MPI_Datatype mdtype;
965: PETSC_UNUSED MPI_Aint lb;
966: MPI_Aint dsize;
967: PetscBool useMPIIO;
973: PetscViewerSetUp(viewer);
975: PetscDataTypeToMPIDataType(dtype, &mdtype);
976: MPI_Type_get_extent(mdtype, &lb, &dsize);
977: MPI_Comm_rank(comm, &rank);
978: MPI_Comm_size(comm, &size);
980: PetscViewerBinaryGetUseMPIIO(viewer, &useMPIIO);
981: #if defined(PETSC_HAVE_MPIIO)
982: if (useMPIIO) {
983: MPI_File mfdes;
984: MPI_Offset off;
985: PetscMPIInt cnt;
987: if (start == PETSC_DETERMINE) {
988: MPI_Scan(&count, &start, 1, MPIU_INT, MPI_SUM, comm);
989: start -= count;
990: }
991: if (total == PETSC_DETERMINE) {
992: total = start + count;
993: MPI_Bcast(&total, 1, MPIU_INT, size - 1, comm);
994: }
995: PetscMPIIntCast(count, &cnt);
996: PetscViewerBinaryGetMPIIODescriptor(viewer, &mfdes);
997: PetscViewerBinaryGetMPIIOOffset(viewer, &off);
998: off += (MPI_Offset)(start * dsize);
999: if (write) {
1000: MPIU_File_write_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE);
1001: } else {
1002: MPIU_File_read_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE);
1003: }
1004: off = (MPI_Offset)(total * dsize);
1005: PetscViewerBinaryAddMPIIOOffset(viewer, off);
1006: return 0;
1007: }
1008: #endif
1009: {
1010: int fdes;
1011: char *workbuf = NULL;
1012: PetscInt tcount = rank == 0 ? 0 : count, maxcount = 0, message_count, flowcontrolcount;
1013: PetscMPIInt tag, cnt, maxcnt, scnt = 0, rcnt = 0, j;
1014: MPI_Status status;
1016: PetscCommGetNewTag(comm, &tag);
1017: MPI_Reduce(&tcount, &maxcount, 1, MPIU_INT, MPI_MAX, 0, comm);
1018: PetscMPIIntCast(maxcount, &maxcnt);
1019: PetscMPIIntCast(count, &cnt);
1021: PetscViewerBinaryGetDescriptor(viewer, &fdes);
1022: PetscViewerFlowControlStart(viewer, &message_count, &flowcontrolcount);
1023: if (rank == 0) {
1024: PetscMalloc(maxcnt * dsize, &workbuf);
1025: if (write) {
1026: PetscBinaryWrite(fdes, data, cnt, dtype);
1027: } else {
1028: PetscBinaryRead(fdes, data, cnt, NULL, dtype);
1029: }
1030: for (j = 1; j < size; j++) {
1031: PetscViewerFlowControlStepMain(viewer, j, &message_count, flowcontrolcount);
1032: if (write) {
1033: MPI_Recv(workbuf, maxcnt, mdtype, j, tag, comm, &status);
1034: MPI_Get_count(&status, mdtype, &rcnt);
1035: PetscBinaryWrite(fdes, workbuf, rcnt, dtype);
1036: } else {
1037: MPI_Recv(&scnt, 1, MPI_INT, j, tag, comm, MPI_STATUS_IGNORE);
1038: PetscBinaryRead(fdes, workbuf, scnt, NULL, dtype);
1039: MPI_Send(workbuf, scnt, mdtype, j, tag, comm);
1040: }
1041: }
1042: PetscFree(workbuf);
1043: PetscViewerFlowControlEndMain(viewer, &message_count);
1044: } else {
1045: PetscViewerFlowControlStepWorker(viewer, rank, &message_count);
1046: if (write) {
1047: MPI_Send(data, cnt, mdtype, 0, tag, comm);
1048: } else {
1049: MPI_Send(&cnt, 1, MPI_INT, 0, tag, comm);
1050: MPI_Recv(data, cnt, mdtype, 0, tag, comm, MPI_STATUS_IGNORE);
1051: }
1052: PetscViewerFlowControlEndWorker(viewer, &message_count);
1053: }
1054: }
1055: return 0;
1056: }
1058: /*@C
1059: PetscViewerBinaryReadAll - reads from a binary file from all MPI ranks, each rank receives its own portion of the data
1061: Collective
1063: Input Parameters:
1064: + viewer - the binary viewer
1065: . data - location of data
1066: . count - local number of items of data to read
1067: . start - local start, can be `PETSC_DETERMINE`
1068: . total - global number of items of data to read, can be `PETSC_DETERMINE`
1069: - dtype - type of data to read
1071: Level: advanced
1073: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteAll()`
1074: @*/
1075: PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1076: {
1077: PetscViewerBinaryWriteReadAll(viewer, PETSC_FALSE, data, count, start, total, dtype);
1078: return 0;
1079: }
1081: /*@C
1082: PetscViewerBinaryWriteAll - writes to a binary file from all MPI ranks, each rank writes its own portion of the data
1084: Collective
1086: Input Parameters:
1087: + viewer - the binary viewer
1088: . data - location of data
1089: . count - local number of items of data to write
1090: . start - local start, can be `PETSC_DETERMINE`
1091: . total - global number of items of data to write, can be `PETSC_DETERMINE`
1092: - dtype - type of data to write
1094: Level: advanced
1096: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryWriteAll()`, `PetscViewerBinaryReadAll()`
1097: @*/
1098: PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer, const void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1099: {
1100: PetscViewerBinaryWriteReadAll(viewer, PETSC_TRUE, (void *)data, count, start, total, dtype);
1101: return 0;
1102: }
1104: /*@C
1105: PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first MPI rank, an array of strings
1107: Collective
1109: Input Parameters:
1110: + viewer - the binary viewer
1111: - data - location of the array of strings
1113: Level: intermediate
1115: Note:
1116: The array of strings must be null terminated
1118: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1119: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1120: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1121: @*/
1122: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer, const char *const *data)
1123: {
1124: PetscInt i, n = 0, *sizes;
1125: size_t len;
1127: PetscViewerSetUp(viewer);
1128: /* count number of strings */
1129: while (data[n++])
1130: ;
1131: n--;
1132: PetscMalloc1(n + 1, &sizes);
1133: sizes[0] = n;
1134: for (i = 0; i < n; i++) {
1135: PetscStrlen(data[i], &len);
1136: sizes[i + 1] = (PetscInt)len + 1; /* size includes space for the null terminator */
1137: }
1138: PetscViewerBinaryWrite(viewer, sizes, n + 1, PETSC_INT);
1139: for (i = 0; i < n; i++) PetscViewerBinaryWrite(viewer, (void *)data[i], sizes[i + 1], PETSC_CHAR);
1140: PetscFree(sizes);
1141: return 0;
1142: }
1144: /*@C
1145: PetscViewerBinaryReadStringArray - reads a binary file an array of strings to all MPI ranks
1147: Collective
1149: Input Parameter:
1150: . viewer - the binary viewer
1152: Output Parameter:
1153: . data - location of the array of strings
1155: Level: intermediate
1157: Note:
1158: The array of strings must null terminated
1160: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1161: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1162: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1163: @*/
1164: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer, char ***data)
1165: {
1166: PetscInt i, n, *sizes, N = 0;
1168: PetscViewerSetUp(viewer);
1169: /* count number of strings */
1170: PetscViewerBinaryRead(viewer, &n, 1, NULL, PETSC_INT);
1171: PetscMalloc1(n, &sizes);
1172: PetscViewerBinaryRead(viewer, sizes, n, NULL, PETSC_INT);
1173: for (i = 0; i < n; i++) N += sizes[i];
1174: PetscMalloc((n + 1) * sizeof(char *) + N * sizeof(char), data);
1175: (*data)[0] = (char *)((*data) + n + 1);
1176: for (i = 1; i < n; i++) (*data)[i] = (*data)[i - 1] + sizes[i - 1];
1177: PetscViewerBinaryRead(viewer, (*data)[0], N, NULL, PETSC_CHAR);
1178: (*data)[n] = NULL;
1179: PetscFree(sizes);
1180: return 0;
1181: }
1183: /*@C
1184: PetscViewerFileSetMode - Sets the open mode of file
1186: Logically Collective on viewer
1188: Input Parameters:
1189: + viewer - the `PetscViewer`; must be a a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII` `PetscViewer`
1190: - mode - open mode of file
1191: $ FILE_MODE_WRITE - create new file for output
1192: $ FILE_MODE_READ - open existing file for input
1193: $ FILE_MODE_APPEND - open existing file for output
1195: Level: advanced
1197: .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1198: @*/
1199: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer, PetscFileMode mode)
1200: {
1205: PetscTryMethod(viewer, "PetscViewerFileSetMode_C", (PetscViewer, PetscFileMode), (viewer, mode));
1206: return 0;
1207: }
1209: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer, PetscFileMode mode)
1210: {
1211: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1214: vbinary->filemode = mode;
1215: return 0;
1216: }
1218: /*@C
1219: PetscViewerFileGetMode - Gets the open mode of file
1221: Not Collective
1223: Input Parameter:
1224: . viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII` `PetscViewer`
1226: Output Parameter:
1227: . mode - open mode of file
1228: $ FILE_MODE_WRITE - create new file for binary output
1229: $ FILE_MODE_READ - open existing file for binary input
1230: $ FILE_MODE_APPEND - open existing file for binary output
1232: Level: advanced
1234: .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1235: @*/
1236: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer, PetscFileMode *mode)
1237: {
1240: PetscUseMethod(viewer, "PetscViewerFileGetMode_C", (PetscViewer, PetscFileMode *), (viewer, mode));
1241: return 0;
1242: }
1244: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer, PetscFileMode *mode)
1245: {
1246: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1248: *mode = vbinary->filemode;
1249: return 0;
1250: }
1252: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer, const char name[])
1253: {
1254: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1256: if (viewer->setupcalled && vbinary->filename) {
1257: /* gzip can be run after the file with the previous filename has been closed */
1258: PetscFree(vbinary->ogzfilename);
1259: PetscStrallocpy(vbinary->filename, &vbinary->ogzfilename);
1260: }
1261: PetscFree(vbinary->filename);
1262: PetscStrallocpy(name, &vbinary->filename);
1263: viewer->setupcalled = PETSC_FALSE;
1264: return 0;
1265: }
1267: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer, const char **name)
1268: {
1269: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1271: *name = vbinary->filename;
1272: return 0;
1273: }
1275: #if defined(PETSC_HAVE_MPIIO)
1276: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1277: {
1278: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1279: int amode;
1281: vbinary->storecompressed = PETSC_FALSE;
1283: vbinary->moff = 0;
1284: switch (vbinary->filemode) {
1285: case FILE_MODE_READ:
1286: amode = MPI_MODE_RDONLY;
1287: break;
1288: case FILE_MODE_WRITE:
1289: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE;
1290: break;
1291: case FILE_MODE_APPEND:
1292: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND;
1293: break;
1294: case FILE_MODE_UNDEFINED:
1295: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerSetUp()");
1296: default:
1297: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vbinary->filemode]);
1298: }
1299: MPI_File_open(PetscObjectComm((PetscObject)viewer), vbinary->filename, amode, MPI_INFO_NULL, &vbinary->mfdes);
1300: /*
1301: The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
1302: */
1303: if (vbinary->filemode == FILE_MODE_WRITE) MPI_File_set_size(vbinary->mfdes, 0);
1304: /*
1305: Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
1306: MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
1307: Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
1308: the offset in etype units to an absolute byte position.
1309: */
1310: if (vbinary->filemode == FILE_MODE_APPEND) MPI_File_get_position(vbinary->mfdes, &vbinary->moff);
1311: return 0;
1312: }
1313: #endif
1315: static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
1316: {
1317: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1318: const char *fname;
1319: char bname[PETSC_MAX_PATH_LEN], *gz;
1320: PetscBool found;
1321: PetscMPIInt rank;
1323: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
1325: /* if file name ends in .gz strip that off and note user wants file compressed */
1326: vbinary->storecompressed = PETSC_FALSE;
1327: if (vbinary->filemode == FILE_MODE_WRITE) {
1328: PetscStrstr(vbinary->filename, ".gz", &gz);
1329: if (gz && gz[3] == 0) {
1330: *gz = 0;
1331: vbinary->storecompressed = PETSC_TRUE;
1332: }
1333: }
1334: #if !defined(PETSC_HAVE_POPEN)
1336: #endif
1338: fname = vbinary->filename;
1339: if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
1340: PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), fname, bname, PETSC_MAX_PATH_LEN, &found);
1342: fname = bname;
1343: }
1345: vbinary->fdes = -1;
1346: if (rank == 0) { /* only first processor opens file*/
1347: PetscFileMode mode = vbinary->filemode;
1348: if (mode == FILE_MODE_APPEND) {
1349: /* check if asked to append to a non-existing file */
1350: PetscTestFile(fname, '\0', &found);
1351: if (!found) mode = FILE_MODE_WRITE;
1352: }
1353: PetscBinaryOpen(fname, mode, &vbinary->fdes);
1354: }
1355: return 0;
1356: }
1358: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1359: {
1360: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1361: PetscMPIInt rank;
1362: PetscBool found;
1364: vbinary->fdes_info = NULL;
1365: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
1366: if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || rank == 0)) {
1367: char infoname[PETSC_MAX_PATH_LEN], iname[PETSC_MAX_PATH_LEN], *gz;
1369: PetscStrncpy(infoname, vbinary->filename, sizeof(infoname));
1370: /* remove .gz if it ends file name */
1371: PetscStrstr(infoname, ".gz", &gz);
1372: if (gz && gz[3] == 0) *gz = 0;
1374: PetscStrlcat(infoname, ".info", sizeof(infoname));
1375: if (vbinary->filemode == FILE_MODE_READ) {
1376: PetscFixFilename(infoname, iname);
1377: PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), iname, infoname, PETSC_MAX_PATH_LEN, &found);
1378: if (found) PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer), ((PetscObject)viewer)->options, infoname, PETSC_FALSE);
1379: } else if (rank == 0) { /* write or append */
1380: const char *omode = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
1381: vbinary->fdes_info = fopen(infoname, omode);
1383: }
1384: }
1385: return 0;
1386: }
1388: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1389: {
1390: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1391: PetscBool usempiio;
1393: if (!vbinary->setfromoptionscalled) PetscViewerSetFromOptions(viewer);
1396: PetscViewerFileClose_Binary(viewer);
1398: PetscViewerBinaryGetUseMPIIO(viewer, &usempiio);
1399: if (usempiio) {
1400: #if defined(PETSC_HAVE_MPIIO)
1401: PetscViewerFileSetUp_BinaryMPIIO(viewer);
1402: #endif
1403: } else {
1404: PetscViewerFileSetUp_BinarySTDIO(viewer);
1405: }
1406: PetscViewerFileSetUp_BinaryInfo(viewer);
1408: PetscLogObjectState((PetscObject)viewer, "File: %s", vbinary->filename);
1409: return 0;
1410: }
1412: static PetscErrorCode PetscViewerView_Binary(PetscViewer v, PetscViewer viewer)
1413: {
1414: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
1415: const char *fname = vbinary->filename ? vbinary->filename : "not yet set";
1416: const char *fmode = vbinary->filemode != (PetscFileMode)-1 ? PetscFileModes[vbinary->filemode] : "not yet set";
1417: PetscBool usempiio;
1419: PetscViewerBinaryGetUseMPIIO(v, &usempiio);
1420: PetscViewerASCIIPrintf(viewer, "Filename: %s\n", fname);
1421: PetscViewerASCIIPrintf(viewer, "Mode: %s (%s)\n", fmode, usempiio ? "mpiio" : "stdio");
1422: return 0;
1423: }
1425: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscViewer viewer, PetscOptionItems *PetscOptionsObject)
1426: {
1427: PetscViewer_Binary *binary = (PetscViewer_Binary *)viewer->data;
1428: char defaultname[PETSC_MAX_PATH_LEN];
1429: PetscBool flg;
1431: if (viewer->setupcalled) return 0;
1432: PetscOptionsHeadBegin(PetscOptionsObject, "Binary PetscViewer Options");
1433: PetscSNPrintf(defaultname, PETSC_MAX_PATH_LEN - 1, "binaryoutput");
1434: PetscOptionsString("-viewer_binary_filename", "Specify filename", "PetscViewerFileSetName", defaultname, defaultname, sizeof(defaultname), &flg);
1435: if (flg) PetscViewerFileSetName_Binary(viewer, defaultname);
1436: PetscOptionsBool("-viewer_binary_skip_info", "Skip writing/reading .info file", "PetscViewerBinarySetSkipInfo", binary->skipinfo, &binary->skipinfo, NULL);
1437: PetscOptionsBool("-viewer_binary_skip_options", "Skip parsing Vec/Mat load options", "PetscViewerBinarySetSkipOptions", binary->skipoptions, &binary->skipoptions, NULL);
1438: PetscOptionsBool("-viewer_binary_skip_header", "Skip writing/reading header information", "PetscViewerBinarySetSkipHeader", binary->skipheader, &binary->skipheader, NULL);
1439: #if defined(PETSC_HAVE_MPIIO)
1440: PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file", "PetscViewerBinarySetUseMPIIO", binary->usempiio, &binary->usempiio, NULL);
1441: #else
1442: PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)", "PetscViewerBinarySetUseMPIIO", PETSC_FALSE, NULL, NULL);
1443: #endif
1444: PetscOptionsHeadEnd();
1445: binary->setfromoptionscalled = PETSC_TRUE;
1446: return 0;
1447: }
1449: /*MC
1450: PETSCVIEWERBINARY - A viewer that saves to binary files
1452: Level: beginner
1454: .seealso: `PetscViewerBinaryOpen()`, `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1455: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, `PETSCVIEWERDRAW`, `PETSCVIEWERSOCKET`
1456: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`,
1457: `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`
1458: M*/
1460: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1461: {
1462: PetscViewer_Binary *vbinary;
1464: PetscNew(&vbinary);
1465: v->data = (void *)vbinary;
1467: v->ops->setfromoptions = PetscViewerSetFromOptions_Binary;
1468: v->ops->destroy = PetscViewerDestroy_Binary;
1469: v->ops->view = PetscViewerView_Binary;
1470: v->ops->setup = PetscViewerSetUp_Binary;
1471: v->ops->flush = NULL; /* Should we support Flush() ? */
1472: v->ops->getsubviewer = PetscViewerGetSubViewer_Binary;
1473: v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1474: v->ops->read = PetscViewerBinaryRead;
1476: vbinary->fdes = -1;
1477: #if defined(PETSC_HAVE_MPIIO)
1478: vbinary->usempiio = PETSC_FALSE;
1479: vbinary->mfdes = MPI_FILE_NULL;
1480: vbinary->mfsub = MPI_FILE_NULL;
1481: #endif
1482: vbinary->filename = NULL;
1483: vbinary->filemode = FILE_MODE_UNDEFINED;
1484: vbinary->fdes_info = NULL;
1485: vbinary->skipinfo = PETSC_FALSE;
1486: vbinary->skipoptions = PETSC_TRUE;
1487: vbinary->skipheader = PETSC_FALSE;
1488: vbinary->storecompressed = PETSC_FALSE;
1489: vbinary->ogzfilename = NULL;
1490: vbinary->flowcontrol = 256; /* seems a good number for Cray XT-5 */
1492: vbinary->setfromoptionscalled = PETSC_FALSE;
1494: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Binary);
1495: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", PetscViewerBinarySetFlowControl_Binary);
1496: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Binary);
1497: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Binary);
1498: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", PetscViewerBinaryGetSkipOptions_Binary);
1499: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", PetscViewerBinarySetSkipOptions_Binary);
1500: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", PetscViewerBinaryGetSkipInfo_Binary);
1501: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", PetscViewerBinarySetSkipInfo_Binary);
1502: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", PetscViewerBinaryGetInfoPointer_Binary);
1503: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_Binary);
1504: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_Binary);
1505: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_Binary);
1506: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Binary);
1507: #if defined(PETSC_HAVE_MPIIO)
1508: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", PetscViewerBinaryGetUseMPIIO_Binary);
1509: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", PetscViewerBinarySetUseMPIIO_Binary);
1510: #endif
1511: return 0;
1512: }
1514: /* ---------------------------------------------------------------------*/
1515: /*
1516: The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1517: is attached to a communicator, in this case the attribute is a PetscViewer.
1518: */
1519: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
1521: /*@C
1522: PETSC_VIEWER_BINARY_ - Creates a `PETSCVIEWERBINARY` `PetscViewer` shared by all processors
1523: in a communicator.
1525: Collective
1527: Input Parameter:
1528: . comm - the MPI communicator to share the `PETSCVIEWERBINARY`
1530: Level: intermediate
1532: Options Database Keys:
1533: + -viewer_binary_filename <name> - filename in which to store the binary data, defaults to binaryoutput
1534: . -viewer_binary_skip_info - true means do not create .info file for this viewer
1535: . -viewer_binary_skip_options - true means do not use the options database for this viewer
1536: . -viewer_binary_skip_header - true means do not store the usual header information in the binary file
1537: - -viewer_binary_mpiio - true means use the file via MPI-IO, maybe faster for large files and many MPI ranks
1539: Environmental variable:
1540: - PETSC_VIEWER_BINARY_FILENAME - filename in which to store the binary data, defaults to binaryoutput
1542: Note:
1543: Unlike almost all other PETSc routines, `PETSC_VIEWER_BINARY_` does not return
1544: an error code. The binary PetscViewer is usually used in the form
1545: $ XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
1547: .seealso: `PETSCVIEWERBINARY`, `PETSC_VIEWER_BINARY_WORLD`, `PETSC_VIEWER_BINARY_SELF`, `PetscViewerBinaryOpen()`, `PetscViewerCreate()`,
1548: `PetscViewerDestroy()`
1549: @*/
1550: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1551: {
1553: PetscBool flg;
1554: PetscViewer viewer;
1555: char fname[PETSC_MAX_PATH_LEN];
1556: MPI_Comm ncomm;
1558: PetscCommDuplicate(comm, &ncomm, NULL);
1559: if (ierr) {
1560: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1561: return NULL;
1562: }
1563: if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1564: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Binary_keyval, NULL);
1565: if (ierr) {
1566: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1567: return NULL;
1568: }
1569: }
1570: MPI_Comm_get_attr(ncomm, Petsc_Viewer_Binary_keyval, (void **)&viewer, (int *)&flg);
1571: if (ierr) {
1572: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1573: return NULL;
1574: }
1575: if (!flg) { /* PetscViewer not yet created */
1576: PetscOptionsGetenv(ncomm, "PETSC_VIEWER_BINARY_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
1577: if (ierr) {
1578: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1579: return NULL;
1580: }
1581: if (!flg) {
1582: PetscStrcpy(fname, "binaryoutput");
1583: if (ierr) {
1584: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1585: return NULL;
1586: }
1587: }
1588: PetscViewerBinaryOpen(ncomm, fname, FILE_MODE_WRITE, &viewer);
1589: if (ierr) {
1590: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1591: return NULL;
1592: }
1593: PetscObjectRegisterDestroy((PetscObject)viewer);
1594: if (ierr) {
1595: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1596: return NULL;
1597: }
1598: MPI_Comm_set_attr(ncomm, Petsc_Viewer_Binary_keyval, (void *)viewer);
1599: if (ierr) {
1600: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1601: return NULL;
1602: }
1603: }
1604: PetscCommDestroy(&ncomm);
1605: if (ierr) {
1606: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1607: return NULL;
1608: }
1609: return viewer;
1610: }