Actual source code: binv.c
1: #include <petsc/private/viewerimpl.h>
3: typedef struct {
4: int fdes; /* file descriptor, ignored if using MPI IO */
5: #if defined(PETSC_HAVE_MPIIO)
6: PetscBool usempiio;
7: MPI_File mfdes; /* ignored unless using MPI IO */
8: MPI_File mfsub; /* subviewer support */
9: MPI_Offset moff;
10: #endif
11: char *filename; /* file name */
12: PetscFileMode filemode; /* read/write/append mode */
13: FILE *fdes_info; /* optional file containing info on binary file*/
14: PetscBool storecompressed; /* gzip the write binary file when closing it*/
15: char *ogzfilename; /* gzip can be run after the filename has been updated */
16: PetscBool skipinfo; /* Don't create info file for writing; don't use for reading */
17: PetscBool skipoptions; /* don't use PETSc options database when loading */
18: PetscInt flowcontrol; /* allow only <flowcontrol> messages outstanding at a time while doing IO */
19: PetscBool skipheader; /* don't write header, only raw data */
20: PetscBool matlabheaderwritten; /* if format is PETSC_VIEWER_BINARY_MATLAB has the MATLAB .info header been written yet */
21: PetscBool setfromoptionscalled;
22: } PetscViewer_Binary;
24: static PetscErrorCode PetscViewerBinaryClearFunctionList(PetscViewer v)
25: {
26: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", NULL);
27: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", NULL);
28: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", NULL);
29: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", NULL);
30: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", NULL);
31: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", NULL);
32: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", NULL);
33: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", NULL);
34: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", NULL);
35: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", NULL);
36: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", NULL);
37: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", NULL);
38: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", NULL);
39: #if defined(PETSC_HAVE_MPIIO)
40: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", NULL);
41: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", NULL);
42: #endif
43: return 0;
44: }
46: #if defined(PETSC_HAVE_MPIIO)
47: static PetscErrorCode PetscViewerBinarySyncMPIIO(PetscViewer viewer)
48: {
49: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
51: if (vbinary->filemode == FILE_MODE_READ) return 0;
52: if (vbinary->mfsub != MPI_FILE_NULL) MPI_File_sync(vbinary->mfsub);
53: if (vbinary->mfdes != MPI_FILE_NULL) {
54: MPI_Barrier(PetscObjectComm((PetscObject)viewer));
55: MPI_File_sync(vbinary->mfdes);
56: }
57: return 0;
58: }
59: #endif
61: static PetscErrorCode PetscViewerGetSubViewer_Binary(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
62: {
63: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
64: PetscMPIInt rank;
66: PetscViewerSetUp(viewer);
68: /* Return subviewer in process zero */
69: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
70: if (rank == 0) {
71: PetscMPIInt flg;
73: MPI_Comm_compare(PETSC_COMM_SELF, comm, &flg);
75: PetscViewerCreate(comm, outviewer);
76: PetscViewerSetType(*outviewer, PETSCVIEWERBINARY);
77: PetscMemcpy((*outviewer)->data, vbinary, sizeof(PetscViewer_Binary));
78: (*outviewer)->setupcalled = PETSC_TRUE;
79: } else {
80: *outviewer = NULL;
81: }
83: #if defined(PETSC_HAVE_MPIIO)
84: if (vbinary->usempiio && *outviewer) {
85: PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
86: /* Parent viewer opens a new MPI file handle on PETSC_COMM_SELF and keeps track of it for future reuse */
87: if (vbinary->mfsub == MPI_FILE_NULL) {
88: int amode;
89: switch (vbinary->filemode) {
90: case FILE_MODE_READ:
91: amode = MPI_MODE_RDONLY;
92: break;
93: case FILE_MODE_WRITE:
94: amode = MPI_MODE_WRONLY;
95: break;
96: case FILE_MODE_APPEND:
97: amode = MPI_MODE_WRONLY;
98: break;
99: default:
100: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vbinary->filemode]);
101: }
102: MPI_File_open(PETSC_COMM_SELF, vbinary->filename, amode, MPI_INFO_NULL, &vbinary->mfsub);
103: }
104: /* Subviewer gets the MPI file handle on PETSC_COMM_SELF */
105: obinary->mfdes = vbinary->mfsub;
106: obinary->mfsub = MPI_FILE_NULL;
107: obinary->moff = vbinary->moff;
108: }
109: #endif
111: #if defined(PETSC_HAVE_MPIIO)
112: PetscViewerBinarySyncMPIIO(viewer);
113: #endif
114: return 0;
115: }
117: static PetscErrorCode PetscViewerRestoreSubViewer_Binary(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
118: {
119: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
120: PetscMPIInt rank;
121: #if defined(PETSC_HAVE_MPIIO)
122: MPI_Offset moff = 0;
123: #endif
125: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
128: #if defined(PETSC_HAVE_MPIIO)
129: if (vbinary->usempiio && *outviewer) {
130: PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
132: if (obinary->mfsub != MPI_FILE_NULL) MPI_File_close(&obinary->mfsub);
133: moff = obinary->moff;
134: }
135: #endif
137: if (*outviewer) {
138: PetscViewer_Binary *obinary = (PetscViewer_Binary *)(*outviewer)->data;
140: PetscFree((*outviewer)->data);
141: PetscViewerBinaryClearFunctionList(*outviewer);
142: PetscHeaderDestroy(outviewer);
143: }
145: #if defined(PETSC_HAVE_MPIIO)
146: if (vbinary->usempiio) {
147: PetscInt64 ioff = (PetscInt64)moff; /* We could use MPI_OFFSET datatype (requires MPI 2.2) */
148: MPI_Bcast(&ioff, 1, MPIU_INT64, 0, PetscObjectComm((PetscObject)viewer));
149: vbinary->moff = (MPI_Offset)ioff;
150: }
151: #endif
153: #if defined(PETSC_HAVE_MPIIO)
154: PetscViewerBinarySyncMPIIO(viewer);
155: #endif
156: return 0;
157: }
159: #if defined(PETSC_HAVE_MPIIO)
160: /*@C
161: PetscViewerBinaryGetMPIIOOffset - Gets the current global offset that should be passed to `MPI_File_set_view()` or `MPI_File_{write|read}_at[_all]()`
163: Not Collective
165: Input Parameter:
166: . viewer - PetscViewer context, obtained from `PetscViewerBinaryOpen()`
168: Output Parameter:
169: . off - the current global offset
171: Level: advanced
173: Note:
174: Use `PetscViewerBinaryAddMPIIOOffset()` to increase this value after you have written a view.
176: Fortran Note:
177: This routine is not supported in Fortran.
179: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryAddMPIIOOffset()`
180: @*/
181: PetscErrorCode PetscViewerBinaryGetMPIIOOffset(PetscViewer viewer, MPI_Offset *off)
182: {
183: PetscViewer_Binary *vbinary;
187: vbinary = (PetscViewer_Binary *)viewer->data;
188: *off = vbinary->moff;
189: return 0;
190: }
192: /*@C
193: PetscViewerBinaryAddMPIIOOffset - Adds to the current global offset
195: Logically Collective
197: Input Parameters:
198: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
199: - off - the addition to the global offset
201: Level: advanced
203: Note:
204: Use `PetscViewerBinaryGetMPIIOOffset()` to get the value that you should pass to `MPI_File_set_view()` or `MPI_File_{write|read}_at[_all]()`
206: Fortran Note:
207: This routine is not supported in Fortran.
209: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
210: @*/
211: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer, MPI_Offset off)
212: {
213: PetscViewer_Binary *vbinary;
217: vbinary = (PetscViewer_Binary *)viewer->data;
218: vbinary->moff += off;
219: return 0;
220: }
222: /*@C
223: PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a `PetscViewer`.
225: Not Collective
227: Input Parameter:
228: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
230: Output Parameter:
231: . fdes - file descriptor
233: Level: advanced
235: Fortran Note:
236: This routine is not supported in Fortran.
238: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
239: @*/
240: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer, MPI_File *fdes)
241: {
242: PetscViewer_Binary *vbinary;
246: PetscViewerSetUp(viewer);
247: vbinary = (PetscViewer_Binary *)viewer->data;
248: *fdes = vbinary->mfdes;
249: return 0;
250: }
251: #endif
253: /*@
254: PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
255: before `PetscViewerFileSetName()`
257: Logically Collective on viewer
259: Input Parameters:
260: + viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`
261: - use - `PETSC_TRUE` means MPI-IO will be used
263: Options Database Key:
264: -viewer_binary_mpiio : Flag for using MPI-IO
266: Level: advanced
268: .seealso: `PETSCVIEWERBINARY`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
269: `PetscViewerBinaryGetUseMPIIO()`
270: @*/
271: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer, PetscBool use)
272: {
275: PetscTryMethod(viewer, "PetscViewerBinarySetUseMPIIO_C", (PetscViewer, PetscBool), (viewer, use));
276: return 0;
277: }
279: #if defined(PETSC_HAVE_MPIIO)
280: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer, PetscBool use)
281: {
282: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
284: vbinary->usempiio = use;
285: return 0;
286: }
287: #endif
289: /*@
290: PetscViewerBinaryGetUseMPIIO - Returns PETSC_TRUE if the binary viewer uses MPI-IO.
292: Not Collective
294: Input Parameter:
295: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`; must be a `PETSCVIEWERBINARY`
297: Output Parameter:
298: . use - `PETSC_TRUE` if MPI-IO is being used
300: Level: advanced
302: Note:
303: If MPI-IO is not available, this function will always return PETSC_FALSE
305: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
306: @*/
307: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer, PetscBool *use)
308: {
311: *use = PETSC_FALSE;
312: PetscTryMethod(viewer, "PetscViewerBinaryGetUseMPIIO_C", (PetscViewer, PetscBool *), (viewer, use));
313: return 0;
314: }
316: #if defined(PETSC_HAVE_MPIIO)
317: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer, PetscBool *use)
318: {
319: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
321: *use = vbinary->usempiio;
322: return 0;
323: }
324: #endif
326: /*@
327: PetscViewerBinarySetFlowControl - Sets how many messages are allowed to outstanding at the same time during parallel IO reads/writes
329: Not Collective
331: Input Parameters:
332: + viewer - PetscViewer context, obtained from `PetscViewerBinaryOpen()`
333: - fc - the number of messages, defaults to 256 if this function was not called
335: Level: advanced
337: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetFlowControl()`
338: @*/
339: PetscErrorCode PetscViewerBinarySetFlowControl(PetscViewer viewer, PetscInt fc)
340: {
343: PetscTryMethod(viewer, "PetscViewerBinarySetFlowControl_C", (PetscViewer, PetscInt), (viewer, fc));
344: return 0;
345: }
347: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer, PetscInt fc)
348: {
349: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
352: vbinary->flowcontrol = fc;
353: return 0;
354: }
356: /*@
357: PetscViewerBinaryGetFlowControl - Returns how many messages are allowed to outstanding at the same time during parallel IO reads/writes
359: Not Collective
361: Input Parameter:
362: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
364: Output Parameter:
365: . fc - the number of messages
367: Level: advanced
369: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetFlowControl()`
370: @*/
371: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer, PetscInt *fc)
372: {
375: PetscUseMethod(viewer, "PetscViewerBinaryGetFlowControl_C", (PetscViewer, PetscInt *), (viewer, fc));
376: return 0;
377: }
379: static PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer, PetscInt *fc)
380: {
381: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
383: *fc = vbinary->flowcontrol;
384: return 0;
385: }
387: /*@C
388: PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a `PetscViewer` of `PetscViewerType` `PETSCVIEWERBINARY`.
390: Collective on viewer because it may trigger a `PetscViewerSetUp()` call
392: Input Parameter:
393: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
395: Output Parameter:
396: . fdes - file descriptor
398: Level: advanced
400: Note:
401: For writable binary `PetscViewer`s, the descriptor will only be valid for the
402: first processor in the communicator that shares the `PetscViewer`. For readable
403: files it will only be valid on nodes that have the file. If node 0 does not
404: have the file it generates an error even if another node does have the file.
406: Fortran Note:
407: This routine is not supported in Fortran.
409: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`
410: @*/
411: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer, int *fdes)
412: {
413: PetscViewer_Binary *vbinary;
417: PetscViewerSetUp(viewer);
418: vbinary = (PetscViewer_Binary *)viewer->data;
419: *fdes = vbinary->fdes;
420: return 0;
421: }
423: /*@
424: PetscViewerBinarySkipInfo - Binary file will not have .info file created with it
426: Not Collective
428: Input Parameter:
429: . viewer - `PetscViewer` context, obtained from `PetscViewerCreate()`
431: Options Database Key:
432: . -viewer_binary_skip_info - true indicates do not generate .info file
434: Level: advanced
436: Notes:
437: This must be called after `PetscViewerSetType()`. If you use `PetscViewerBinaryOpen()` then
438: you can only skip the info file with the -viewer_binary_skip_info flag. To use the function you must open the
439: viewer with `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinarySkipInfo()`.
441: The .info contains meta information about the data in the binary file, for example the block size if it was
442: set for a vector or matrix.
444: This routine is deprecated, use `PetscViewerBinarySetSkipInfo()`
446: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
447: `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
448: @*/
449: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
450: {
451: PetscViewerBinarySetSkipInfo(viewer, PETSC_TRUE);
452: return 0;
453: }
455: /*@
456: PetscViewerBinarySetSkipInfo - Binary file will not have .info file created with it
458: Not Collective
460: Input Parameters:
461: + viewer - PetscViewer context, obtained from PetscViewerCreate()
462: - skip - PETSC_TRUE implies the .info file will not be generated
464: Options Database Key:
465: . -viewer_binary_skip_info - true indicates do not generate .info file
467: Level: advanced
469: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
470: `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
471: @*/
472: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer, PetscBool skip)
473: {
476: PetscTryMethod(viewer, "PetscViewerBinarySetSkipInfo_C", (PetscViewer, PetscBool), (viewer, skip));
477: return 0;
478: }
480: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer, PetscBool skip)
481: {
482: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
484: vbinary->skipinfo = skip;
485: return 0;
486: }
488: /*@
489: PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file
491: Not Collective
493: Input Parameter:
494: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
496: Output Parameter:
497: . skip - `PETSC_TRUE` implies the .info file was not generated
499: Level: advanced
501: Note:
502: This must be called after `PetscViewerSetType()`
504: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`,
505: `PetscViewerBinarySetSkipOptions()`, `PetscViewerBinarySetSkipInfo()`
506: @*/
507: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer, PetscBool *skip)
508: {
511: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipInfo_C", (PetscViewer, PetscBool *), (viewer, skip));
512: return 0;
513: }
515: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer, PetscBool *skip)
516: {
517: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
519: *skip = vbinary->skipinfo;
520: return 0;
521: }
523: /*@
524: PetscViewerBinarySetSkipOptions - do not use the PETSc options database when loading objects
526: Not Collective
528: Input Parameters:
529: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
530: - skip - `PETSC_TRUE` means do not use the options from the options database
532: Options Database Key:
533: . -viewer_binary_skip_options <true or false> - true means do not use the options from the options database
535: Level: advanced
537: Note:
538: This must be called after `PetscViewerSetType()`
540: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
541: `PetscViewerBinaryGetSkipOptions()`
542: @*/
543: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer, PetscBool skip)
544: {
547: PetscTryMethod(viewer, "PetscViewerBinarySetSkipOptions_C", (PetscViewer, PetscBool), (viewer, skip));
548: return 0;
549: }
551: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer, PetscBool skip)
552: {
553: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
555: vbinary->skipoptions = skip;
556: return 0;
557: }
559: /*@
560: PetscViewerBinaryGetSkipOptions - checks if viewer uses the PETSc options database when loading objects
562: Not Collective
564: Input Parameter:
565: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
567: Output Parameter:
568: . skip - `PETSC_TRUE` means do not use
570: Level: advanced
572: Note:
573: This must be called after `PetscViewerSetType()`
575: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
576: `PetscViewerBinarySetSkipOptions()`
577: @*/
578: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer, PetscBool *skip)
579: {
582: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipOptions_C", (PetscViewer, PetscBool *), (viewer, skip));
583: return 0;
584: }
586: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer, PetscBool *skip)
587: {
588: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
590: *skip = vbinary->skipoptions;
591: return 0;
592: }
594: /*@
595: PetscViewerBinarySetSkipHeader - do not write a header with size information on output, just raw data
597: Not Collective
599: Input Parameters:
600: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
601: - skip - `PETSC_TRUE `means do not write header
603: Options Database Key:
604: . -viewer_binary_skip_header <true or false> - true means do not write header
606: Level: advanced
608: Notes:
609: This must be called after `PetscViewerSetType()`
611: Is ignored on anything but a binary viewer
613: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
614: `PetscViewerBinaryGetSkipHeader()`
615: @*/
616: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer, PetscBool skip)
617: {
620: PetscTryMethod(viewer, "PetscViewerBinarySetSkipHeader_C", (PetscViewer, PetscBool), (viewer, skip));
621: return 0;
622: }
624: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer, PetscBool skip)
625: {
626: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
628: vbinary->skipheader = skip;
629: return 0;
630: }
632: /*@
633: PetscViewerBinaryGetSkipHeader - checks whether to write a header with size information on output, or just raw data
635: Not Collective
637: Input Parameter:
638: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
640: Output Parameter:
641: . skip - `PETSC_TRUE` means do not write header
643: Level: advanced
645: Notes:
646: This must be called after PetscViewerSetType()
648: Returns `PETSC_FALSE` for `PETSCSOCKETVIEWER`, you cannot skip the header for it.
650: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
651: `PetscViewerBinarySetSkipHeader()`
652: @*/
653: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer, PetscBool *skip)
654: {
657: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipHeader_C", (PetscViewer, PetscBool *), (viewer, skip));
658: return 0;
659: }
661: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer, PetscBool *skip)
662: {
663: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
665: *skip = vbinary->skipheader;
666: return 0;
667: }
669: /*@C
670: PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
671: info file associated with a binary file.
673: Not Collective
675: Input Parameter:
676: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
678: Output Parameter:
679: . file - file pointer Always returns NULL if not a binary viewer
681: Level: advanced
683: Note:
684: For writable binary `PetscViewer`s, the file pointer will only be valid for the
685: first processor in the communicator that shares the `PetscViewer`.
687: Fortran Note:
688: This routine is not supported in Fortran.
690: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`
691: @*/
692: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer, FILE **file)
693: {
696: *file = NULL;
697: PetscTryMethod(viewer, "PetscViewerBinaryGetInfoPointer_C", (PetscViewer, FILE **), (viewer, file));
698: return 0;
699: }
701: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer, FILE **file)
702: {
703: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
705: PetscViewerSetUp(viewer);
706: *file = vbinary->fdes_info;
707: if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
708: if (vbinary->fdes_info) {
709: FILE *info = vbinary->fdes_info;
710: PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
711: PetscFPrintf(PETSC_COMM_SELF, info, "#$$ Set.filename = '%s';\n", vbinary->filename);
712: PetscFPrintf(PETSC_COMM_SELF, info, "#$$ fd = PetscOpenFile(Set.filename);\n");
713: PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
714: }
715: vbinary->matlabheaderwritten = PETSC_TRUE;
716: }
717: return 0;
718: }
720: #if defined(PETSC_HAVE_MPIIO)
721: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
722: {
723: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
725: if (vbinary->mfdes != MPI_FILE_NULL) MPI_File_close(&vbinary->mfdes);
726: if (vbinary->mfsub != MPI_FILE_NULL) MPI_File_close(&vbinary->mfsub);
727: vbinary->moff = 0;
728: return 0;
729: }
730: #endif
732: static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
733: {
734: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
736: if (vbinary->fdes != -1) {
737: PetscBinaryClose(vbinary->fdes);
738: vbinary->fdes = -1;
739: if (vbinary->storecompressed) {
740: char cmd[8 + PETSC_MAX_PATH_LEN], out[64 + PETSC_MAX_PATH_LEN] = "";
741: const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
742: /* compress the file */
743: PetscStrncpy(cmd, "gzip -f ", sizeof(cmd));
744: PetscStrlcat(cmd, gzfilename, sizeof(cmd));
745: #if defined(PETSC_HAVE_POPEN)
746: {
747: FILE *fp;
748: PetscPOpen(PETSC_COMM_SELF, NULL, cmd, "r", &fp);
750: PetscPClose(PETSC_COMM_SELF, fp);
751: }
752: #endif
753: }
754: }
755: PetscFree(vbinary->ogzfilename);
756: return 0;
757: }
759: static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
760: {
761: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
763: if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
764: if (vbinary->fdes_info) {
765: FILE *info = vbinary->fdes_info;
766: PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
767: PetscFPrintf(PETSC_COMM_SELF, info, "#$$ close(fd);\n");
768: PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
769: }
770: }
771: if (vbinary->fdes_info) {
772: FILE *info = vbinary->fdes_info;
773: vbinary->fdes_info = NULL;
775: }
776: return 0;
777: }
779: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
780: {
781: #if defined(PETSC_HAVE_MPIIO)
782: PetscViewerFileClose_BinaryMPIIO(v);
783: #endif
784: PetscViewerFileClose_BinarySTDIO(v);
785: PetscViewerFileClose_BinaryInfo(v);
786: return 0;
787: }
789: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
790: {
791: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
793: PetscViewerFileClose_Binary(v);
794: PetscFree(vbinary->filename);
795: PetscFree(vbinary);
796: PetscViewerBinaryClearFunctionList(v);
797: return 0;
798: }
800: /*@C
801: PetscViewerBinaryOpen - Opens a file for binary input/output.
803: Collective
805: Input Parameters:
806: + comm - MPI communicator
807: . name - name of file
808: - mode - open mode of file
809: $ FILE_MODE_WRITE - create new file for binary output
810: $ FILE_MODE_READ - open existing file for binary input
811: $ FILE_MODE_APPEND - open existing file for binary output
813: Output Parameter:
814: . viewer - PetscViewer for binary input/output to use with the specified file
816: Options Database Keys:
817: + -viewer_binary_filename <name> - name of file to use
818: . -viewer_binary_skip_info - true to skip opening an info file
819: . -viewer_binary_skip_options - true to not use options database while creating viewer
820: . -viewer_binary_skip_header - true to skip output object headers to the file
821: - -viewer_binary_mpiio - true to use MPI-IO for input and output to the file (more scalable for large problems)
823: Level: beginner
825: Note:
826: This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.
828: For reading files, the filename may begin with ftp:// or http:// and/or
829: end with .gz; in this case file is brought over and uncompressed.
831: For creating files, if the file name ends with .gz it is automatically
832: compressed when closed.
834: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
835: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
836: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`, `PetscViewerBinarySetUseMPIIO()`,
837: `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
838: @*/
839: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm, const char name[], PetscFileMode mode, PetscViewer *viewer)
840: {
841: PetscViewerCreate(comm, viewer);
842: PetscViewerSetType(*viewer, PETSCVIEWERBINARY);
843: PetscViewerFileSetMode(*viewer, mode);
844: PetscViewerFileSetName(*viewer, name);
845: PetscViewerSetFromOptions(*viewer);
846: return 0;
847: }
849: #if defined(PETSC_HAVE_MPIIO)
850: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype, PetscBool write)
851: {
852: MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
853: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
854: MPI_File mfdes = vbinary->mfdes;
855: MPI_Datatype mdtype;
856: PetscMPIInt rank, cnt;
857: MPI_Status status;
858: MPI_Aint ul, dsize;
860: MPI_Comm_rank(comm, &rank);
861: PetscMPIIntCast(num, &cnt);
862: PetscDataTypeToMPIDataType(dtype, &mdtype);
863: if (write) {
864: if (rank == 0) MPIU_File_write_at(mfdes, vbinary->moff, data, cnt, mdtype, &status);
865: } else {
866: if (rank == 0) {
867: MPIU_File_read_at(mfdes, vbinary->moff, data, cnt, mdtype, &status);
868: if (cnt > 0) MPI_Get_count(&status, mdtype, &cnt);
869: }
870: MPI_Bcast(&cnt, 1, MPI_INT, 0, comm);
871: MPI_Bcast(data, cnt, mdtype, 0, comm);
872: }
873: MPI_Type_get_extent(mdtype, &ul, &dsize);
874: vbinary->moff += dsize * cnt;
875: if (count) *count = cnt;
876: return 0;
877: }
878: #endif
880: /*@C
881: PetscViewerBinaryRead - Reads from a binary file, all processors get the same result
883: Collective
885: Input Parameters:
886: + viewer - the binary viewer
887: . data - location of the data to be written
888: . num - number of items of data to read
889: - dtype - type of data to read
891: Output Parameters:
892: . count - number of items of data actually read, or NULL.
894: Level: beginner
896: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
897: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
898: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
899: @*/
900: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
901: {
902: PetscViewer_Binary *vbinary;
906: PetscViewerSetUp(viewer);
907: vbinary = (PetscViewer_Binary *)viewer->data;
908: #if defined(PETSC_HAVE_MPIIO)
909: if (vbinary->usempiio) {
910: PetscViewerBinaryWriteReadMPIIO(viewer, data, num, count, dtype, PETSC_FALSE);
911: } else {
912: #endif
913: PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, num, count, dtype);
914: #if defined(PETSC_HAVE_MPIIO)
915: }
916: #endif
917: return 0;
918: }
920: /*@C
921: PetscViewerBinaryWrite - writes to a binary file, only from the first MPI rank
923: Collective
925: Input Parameters:
926: + viewer - the binary viewer
927: . data - location of data
928: . count - number of items of data to write
929: - dtype - type of data to write
931: Level: beginner
933: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
934: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, `PetscDataType`
935: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
936: @*/
937: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer, const void *data, PetscInt count, PetscDataType dtype)
938: {
939: PetscViewer_Binary *vbinary;
943: PetscViewerSetUp(viewer);
944: vbinary = (PetscViewer_Binary *)viewer->data;
945: #if defined(PETSC_HAVE_MPIIO)
946: if (vbinary->usempiio) {
947: PetscViewerBinaryWriteReadMPIIO(viewer, (void *)data, count, NULL, dtype, PETSC_TRUE);
948: } else {
949: #endif
950: PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, count, dtype);
951: #if defined(PETSC_HAVE_MPIIO)
952: }
953: #endif
954: return 0;
955: }
957: static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer, PetscBool write, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
958: {
959: MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
960: PetscMPIInt size, rank;
961: MPI_Datatype mdtype;
962: PETSC_UNUSED MPI_Aint lb;
963: MPI_Aint dsize;
964: PetscBool useMPIIO;
970: PetscViewerSetUp(viewer);
972: PetscDataTypeToMPIDataType(dtype, &mdtype);
973: MPI_Type_get_extent(mdtype, &lb, &dsize);
974: MPI_Comm_rank(comm, &rank);
975: MPI_Comm_size(comm, &size);
977: PetscViewerBinaryGetUseMPIIO(viewer, &useMPIIO);
978: #if defined(PETSC_HAVE_MPIIO)
979: if (useMPIIO) {
980: MPI_File mfdes;
981: MPI_Offset off;
982: PetscMPIInt cnt;
984: if (start == PETSC_DETERMINE) {
985: MPI_Scan(&count, &start, 1, MPIU_INT, MPI_SUM, comm);
986: start -= count;
987: }
988: if (total == PETSC_DETERMINE) {
989: total = start + count;
990: MPI_Bcast(&total, 1, MPIU_INT, size - 1, comm);
991: }
992: PetscMPIIntCast(count, &cnt);
993: PetscViewerBinaryGetMPIIODescriptor(viewer, &mfdes);
994: PetscViewerBinaryGetMPIIOOffset(viewer, &off);
995: off += (MPI_Offset)(start * dsize);
996: if (write) {
997: MPIU_File_write_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE);
998: } else {
999: MPIU_File_read_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE);
1000: }
1001: off = (MPI_Offset)(total * dsize);
1002: PetscViewerBinaryAddMPIIOOffset(viewer, off);
1003: return 0;
1004: }
1005: #endif
1006: {
1007: int fdes;
1008: char *workbuf = NULL;
1009: PetscInt tcount = rank == 0 ? 0 : count, maxcount = 0, message_count, flowcontrolcount;
1010: PetscMPIInt tag, cnt, maxcnt, scnt = 0, rcnt = 0, j;
1011: MPI_Status status;
1013: PetscCommGetNewTag(comm, &tag);
1014: MPI_Reduce(&tcount, &maxcount, 1, MPIU_INT, MPI_MAX, 0, comm);
1015: PetscMPIIntCast(maxcount, &maxcnt);
1016: PetscMPIIntCast(count, &cnt);
1018: PetscViewerBinaryGetDescriptor(viewer, &fdes);
1019: PetscViewerFlowControlStart(viewer, &message_count, &flowcontrolcount);
1020: if (rank == 0) {
1021: PetscMalloc(maxcnt * dsize, &workbuf);
1022: if (write) {
1023: PetscBinaryWrite(fdes, data, cnt, dtype);
1024: } else {
1025: PetscBinaryRead(fdes, data, cnt, NULL, dtype);
1026: }
1027: for (j = 1; j < size; j++) {
1028: PetscViewerFlowControlStepMain(viewer, j, &message_count, flowcontrolcount);
1029: if (write) {
1030: MPI_Recv(workbuf, maxcnt, mdtype, j, tag, comm, &status);
1031: MPI_Get_count(&status, mdtype, &rcnt);
1032: PetscBinaryWrite(fdes, workbuf, rcnt, dtype);
1033: } else {
1034: MPI_Recv(&scnt, 1, MPI_INT, j, tag, comm, MPI_STATUS_IGNORE);
1035: PetscBinaryRead(fdes, workbuf, scnt, NULL, dtype);
1036: MPI_Send(workbuf, scnt, mdtype, j, tag, comm);
1037: }
1038: }
1039: PetscFree(workbuf);
1040: PetscViewerFlowControlEndMain(viewer, &message_count);
1041: } else {
1042: PetscViewerFlowControlStepWorker(viewer, rank, &message_count);
1043: if (write) {
1044: MPI_Send(data, cnt, mdtype, 0, tag, comm);
1045: } else {
1046: MPI_Send(&cnt, 1, MPI_INT, 0, tag, comm);
1047: MPI_Recv(data, cnt, mdtype, 0, tag, comm, MPI_STATUS_IGNORE);
1048: }
1049: PetscViewerFlowControlEndWorker(viewer, &message_count);
1050: }
1051: }
1052: return 0;
1053: }
1055: /*@C
1056: PetscViewerBinaryReadAll - reads from a binary file from all MPI ranks, each rank receives its own portion of the data
1058: Collective
1060: Input Parameters:
1061: + viewer - the binary viewer
1062: . data - location of data
1063: . count - local number of items of data to read
1064: . start - local start, can be `PETSC_DETERMINE`
1065: . total - global number of items of data to read, can be `PETSC_DETERMINE`
1066: - dtype - type of data to read
1068: Level: advanced
1070: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteAll()`
1071: @*/
1072: PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1073: {
1074: PetscViewerBinaryWriteReadAll(viewer, PETSC_FALSE, data, count, start, total, dtype);
1075: return 0;
1076: }
1078: /*@C
1079: PetscViewerBinaryWriteAll - writes to a binary file from all MPI ranks, each rank writes its own portion of the data
1081: Collective
1083: Input Parameters:
1084: + viewer - the binary viewer
1085: . data - location of data
1086: . count - local number of items of data to write
1087: . start - local start, can be `PETSC_DETERMINE`
1088: . total - global number of items of data to write, can be `PETSC_DETERMINE`
1089: - dtype - type of data to write
1091: Level: advanced
1093: .seealso: `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryWriteAll()`, `PetscViewerBinaryReadAll()`
1094: @*/
1095: PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer, const void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1096: {
1097: PetscViewerBinaryWriteReadAll(viewer, PETSC_TRUE, (void *)data, count, start, total, dtype);
1098: return 0;
1099: }
1101: /*@C
1102: PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first MPI rank, an array of strings
1104: Collective
1106: Input Parameters:
1107: + viewer - the binary viewer
1108: - data - location of the array of strings
1110: Level: intermediate
1112: Note:
1113: The array of strings must be null terminated
1115: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1116: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1117: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1118: @*/
1119: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer, const char *const *data)
1120: {
1121: PetscInt i, n = 0, *sizes;
1122: size_t len;
1124: PetscViewerSetUp(viewer);
1125: /* count number of strings */
1126: while (data[n++])
1127: ;
1128: n--;
1129: PetscMalloc1(n + 1, &sizes);
1130: sizes[0] = n;
1131: for (i = 0; i < n; i++) {
1132: PetscStrlen(data[i], &len);
1133: sizes[i + 1] = (PetscInt)len + 1; /* size includes space for the null terminator */
1134: }
1135: PetscViewerBinaryWrite(viewer, sizes, n + 1, PETSC_INT);
1136: for (i = 0; i < n; i++) PetscViewerBinaryWrite(viewer, (void *)data[i], sizes[i + 1], PETSC_CHAR);
1137: PetscFree(sizes);
1138: return 0;
1139: }
1141: /*@C
1142: PetscViewerBinaryReadStringArray - reads a binary file an array of strings to all MPI ranks
1144: Collective
1146: Input Parameter:
1147: . viewer - the binary viewer
1149: Output Parameter:
1150: . data - location of the array of strings
1152: Level: intermediate
1154: Note:
1155: The array of strings must null terminated
1157: .seealso: `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1158: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1159: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1160: @*/
1161: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer, char ***data)
1162: {
1163: PetscInt i, n, *sizes, N = 0;
1165: PetscViewerSetUp(viewer);
1166: /* count number of strings */
1167: PetscViewerBinaryRead(viewer, &n, 1, NULL, PETSC_INT);
1168: PetscMalloc1(n, &sizes);
1169: PetscViewerBinaryRead(viewer, sizes, n, NULL, PETSC_INT);
1170: for (i = 0; i < n; i++) N += sizes[i];
1171: PetscMalloc((n + 1) * sizeof(char *) + N * sizeof(char), data);
1172: (*data)[0] = (char *)((*data) + n + 1);
1173: for (i = 1; i < n; i++) (*data)[i] = (*data)[i - 1] + sizes[i - 1];
1174: PetscViewerBinaryRead(viewer, (*data)[0], N, NULL, PETSC_CHAR);
1175: (*data)[n] = NULL;
1176: PetscFree(sizes);
1177: return 0;
1178: }
1180: /*@C
1181: PetscViewerFileSetMode - Sets the open mode of file
1183: Logically Collective on viewer
1185: Input Parameters:
1186: + viewer - the `PetscViewer`; must be a a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII` `PetscViewer`
1187: - mode - open mode of file
1188: $ FILE_MODE_WRITE - create new file for output
1189: $ FILE_MODE_READ - open existing file for input
1190: $ FILE_MODE_APPEND - open existing file for output
1192: Level: advanced
1194: .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1195: @*/
1196: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer, PetscFileMode mode)
1197: {
1202: PetscTryMethod(viewer, "PetscViewerFileSetMode_C", (PetscViewer, PetscFileMode), (viewer, mode));
1203: return 0;
1204: }
1206: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer, PetscFileMode mode)
1207: {
1208: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1211: vbinary->filemode = mode;
1212: return 0;
1213: }
1215: /*@C
1216: PetscViewerFileGetMode - Gets the open mode of file
1218: Not Collective
1220: Input Parameter:
1221: . viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII` `PetscViewer`
1223: Output Parameter:
1224: . mode - open mode of file
1225: $ FILE_MODE_WRITE - create new file for binary output
1226: $ FILE_MODE_READ - open existing file for binary input
1227: $ FILE_MODE_APPEND - open existing file for binary output
1229: Level: advanced
1231: .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1232: @*/
1233: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer, PetscFileMode *mode)
1234: {
1237: PetscUseMethod(viewer, "PetscViewerFileGetMode_C", (PetscViewer, PetscFileMode *), (viewer, mode));
1238: return 0;
1239: }
1241: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer, PetscFileMode *mode)
1242: {
1243: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1245: *mode = vbinary->filemode;
1246: return 0;
1247: }
1249: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer, const char name[])
1250: {
1251: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1253: if (viewer->setupcalled && vbinary->filename) {
1254: /* gzip can be run after the file with the previous filename has been closed */
1255: PetscFree(vbinary->ogzfilename);
1256: PetscStrallocpy(vbinary->filename, &vbinary->ogzfilename);
1257: }
1258: PetscFree(vbinary->filename);
1259: PetscStrallocpy(name, &vbinary->filename);
1260: viewer->setupcalled = PETSC_FALSE;
1261: return 0;
1262: }
1264: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer, const char **name)
1265: {
1266: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1268: *name = vbinary->filename;
1269: return 0;
1270: }
1272: #if defined(PETSC_HAVE_MPIIO)
1273: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1274: {
1275: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1276: int amode;
1278: vbinary->storecompressed = PETSC_FALSE;
1280: vbinary->moff = 0;
1281: switch (vbinary->filemode) {
1282: case FILE_MODE_READ:
1283: amode = MPI_MODE_RDONLY;
1284: break;
1285: case FILE_MODE_WRITE:
1286: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE;
1287: break;
1288: case FILE_MODE_APPEND:
1289: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND;
1290: break;
1291: case FILE_MODE_UNDEFINED:
1292: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerSetUp()");
1293: default:
1294: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vbinary->filemode]);
1295: }
1296: MPI_File_open(PetscObjectComm((PetscObject)viewer), vbinary->filename, amode, MPI_INFO_NULL, &vbinary->mfdes);
1297: /*
1298: The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
1299: */
1300: if (vbinary->filemode == FILE_MODE_WRITE) MPI_File_set_size(vbinary->mfdes, 0);
1301: /*
1302: Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
1303: MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
1304: Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
1305: the offset in etype units to an absolute byte position.
1306: */
1307: if (vbinary->filemode == FILE_MODE_APPEND) MPI_File_get_position(vbinary->mfdes, &vbinary->moff);
1308: return 0;
1309: }
1310: #endif
1312: static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
1313: {
1314: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1315: const char *fname;
1316: char bname[PETSC_MAX_PATH_LEN], *gz;
1317: PetscBool found;
1318: PetscMPIInt rank;
1320: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
1322: /* if file name ends in .gz strip that off and note user wants file compressed */
1323: vbinary->storecompressed = PETSC_FALSE;
1324: if (vbinary->filemode == FILE_MODE_WRITE) {
1325: PetscStrstr(vbinary->filename, ".gz", &gz);
1326: if (gz && gz[3] == 0) {
1327: *gz = 0;
1328: vbinary->storecompressed = PETSC_TRUE;
1329: }
1330: }
1331: #if !defined(PETSC_HAVE_POPEN)
1333: #endif
1335: fname = vbinary->filename;
1336: if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
1337: PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), fname, bname, PETSC_MAX_PATH_LEN, &found);
1339: fname = bname;
1340: }
1342: vbinary->fdes = -1;
1343: if (rank == 0) { /* only first processor opens file*/
1344: PetscFileMode mode = vbinary->filemode;
1345: if (mode == FILE_MODE_APPEND) {
1346: /* check if asked to append to a non-existing file */
1347: PetscTestFile(fname, '\0', &found);
1348: if (!found) mode = FILE_MODE_WRITE;
1349: }
1350: PetscBinaryOpen(fname, mode, &vbinary->fdes);
1351: }
1352: return 0;
1353: }
1355: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1356: {
1357: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1358: PetscMPIInt rank;
1359: PetscBool found;
1361: vbinary->fdes_info = NULL;
1362: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
1363: if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || rank == 0)) {
1364: char infoname[PETSC_MAX_PATH_LEN], iname[PETSC_MAX_PATH_LEN], *gz;
1366: PetscStrncpy(infoname, vbinary->filename, sizeof(infoname));
1367: /* remove .gz if it ends file name */
1368: PetscStrstr(infoname, ".gz", &gz);
1369: if (gz && gz[3] == 0) *gz = 0;
1371: PetscStrlcat(infoname, ".info", sizeof(infoname));
1372: if (vbinary->filemode == FILE_MODE_READ) {
1373: PetscFixFilename(infoname, iname);
1374: PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), iname, infoname, PETSC_MAX_PATH_LEN, &found);
1375: if (found) PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer), ((PetscObject)viewer)->options, infoname, PETSC_FALSE);
1376: } else if (rank == 0) { /* write or append */
1377: const char *omode = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
1378: vbinary->fdes_info = fopen(infoname, omode);
1380: }
1381: }
1382: return 0;
1383: }
1385: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1386: {
1387: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1388: PetscBool usempiio;
1390: if (!vbinary->setfromoptionscalled) PetscViewerSetFromOptions(viewer);
1393: PetscViewerFileClose_Binary(viewer);
1395: PetscViewerBinaryGetUseMPIIO(viewer, &usempiio);
1396: if (usempiio) {
1397: #if defined(PETSC_HAVE_MPIIO)
1398: PetscViewerFileSetUp_BinaryMPIIO(viewer);
1399: #endif
1400: } else {
1401: PetscViewerFileSetUp_BinarySTDIO(viewer);
1402: }
1403: PetscViewerFileSetUp_BinaryInfo(viewer);
1405: PetscLogObjectState((PetscObject)viewer, "File: %s", vbinary->filename);
1406: return 0;
1407: }
1409: static PetscErrorCode PetscViewerView_Binary(PetscViewer v, PetscViewer viewer)
1410: {
1411: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
1412: const char *fname = vbinary->filename ? vbinary->filename : "not yet set";
1413: const char *fmode = vbinary->filemode != (PetscFileMode)-1 ? PetscFileModes[vbinary->filemode] : "not yet set";
1414: PetscBool usempiio;
1416: PetscViewerBinaryGetUseMPIIO(v, &usempiio);
1417: PetscViewerASCIIPrintf(viewer, "Filename: %s\n", fname);
1418: PetscViewerASCIIPrintf(viewer, "Mode: %s (%s)\n", fmode, usempiio ? "mpiio" : "stdio");
1419: return 0;
1420: }
1422: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscViewer viewer, PetscOptionItems *PetscOptionsObject)
1423: {
1424: PetscViewer_Binary *binary = (PetscViewer_Binary *)viewer->data;
1425: char defaultname[PETSC_MAX_PATH_LEN];
1426: PetscBool flg;
1428: if (viewer->setupcalled) return 0;
1429: PetscOptionsHeadBegin(PetscOptionsObject, "Binary PetscViewer Options");
1430: PetscSNPrintf(defaultname, PETSC_MAX_PATH_LEN - 1, "binaryoutput");
1431: PetscOptionsString("-viewer_binary_filename", "Specify filename", "PetscViewerFileSetName", defaultname, defaultname, sizeof(defaultname), &flg);
1432: if (flg) PetscViewerFileSetName_Binary(viewer, defaultname);
1433: PetscOptionsBool("-viewer_binary_skip_info", "Skip writing/reading .info file", "PetscViewerBinarySetSkipInfo", binary->skipinfo, &binary->skipinfo, NULL);
1434: PetscOptionsBool("-viewer_binary_skip_options", "Skip parsing Vec/Mat load options", "PetscViewerBinarySetSkipOptions", binary->skipoptions, &binary->skipoptions, NULL);
1435: PetscOptionsBool("-viewer_binary_skip_header", "Skip writing/reading header information", "PetscViewerBinarySetSkipHeader", binary->skipheader, &binary->skipheader, NULL);
1436: #if defined(PETSC_HAVE_MPIIO)
1437: PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file", "PetscViewerBinarySetUseMPIIO", binary->usempiio, &binary->usempiio, NULL);
1438: #else
1439: PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)", "PetscViewerBinarySetUseMPIIO", PETSC_FALSE, NULL, NULL);
1440: #endif
1441: PetscOptionsHeadEnd();
1442: binary->setfromoptionscalled = PETSC_TRUE;
1443: return 0;
1444: }
1446: /*MC
1447: PETSCVIEWERBINARY - A viewer that saves to binary files
1449: Level: beginner
1451: .seealso: `PetscViewerBinaryOpen()`, `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1452: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, `PETSCVIEWERDRAW`, `PETSCVIEWERSOCKET`
1453: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`,
1454: `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`
1455: M*/
1457: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1458: {
1459: PetscViewer_Binary *vbinary;
1461: PetscNew(&vbinary);
1462: v->data = (void *)vbinary;
1464: v->ops->setfromoptions = PetscViewerSetFromOptions_Binary;
1465: v->ops->destroy = PetscViewerDestroy_Binary;
1466: v->ops->view = PetscViewerView_Binary;
1467: v->ops->setup = PetscViewerSetUp_Binary;
1468: v->ops->flush = NULL; /* Should we support Flush() ? */
1469: v->ops->getsubviewer = PetscViewerGetSubViewer_Binary;
1470: v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1471: v->ops->read = PetscViewerBinaryRead;
1473: vbinary->fdes = -1;
1474: #if defined(PETSC_HAVE_MPIIO)
1475: vbinary->usempiio = PETSC_FALSE;
1476: vbinary->mfdes = MPI_FILE_NULL;
1477: vbinary->mfsub = MPI_FILE_NULL;
1478: #endif
1479: vbinary->filename = NULL;
1480: vbinary->filemode = FILE_MODE_UNDEFINED;
1481: vbinary->fdes_info = NULL;
1482: vbinary->skipinfo = PETSC_FALSE;
1483: vbinary->skipoptions = PETSC_TRUE;
1484: vbinary->skipheader = PETSC_FALSE;
1485: vbinary->storecompressed = PETSC_FALSE;
1486: vbinary->ogzfilename = NULL;
1487: vbinary->flowcontrol = 256; /* seems a good number for Cray XT-5 */
1489: vbinary->setfromoptionscalled = PETSC_FALSE;
1491: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Binary);
1492: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", PetscViewerBinarySetFlowControl_Binary);
1493: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Binary);
1494: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Binary);
1495: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", PetscViewerBinaryGetSkipOptions_Binary);
1496: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", PetscViewerBinarySetSkipOptions_Binary);
1497: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", PetscViewerBinaryGetSkipInfo_Binary);
1498: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", PetscViewerBinarySetSkipInfo_Binary);
1499: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", PetscViewerBinaryGetInfoPointer_Binary);
1500: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_Binary);
1501: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_Binary);
1502: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_Binary);
1503: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Binary);
1504: #if defined(PETSC_HAVE_MPIIO)
1505: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", PetscViewerBinaryGetUseMPIIO_Binary);
1506: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", PetscViewerBinarySetUseMPIIO_Binary);
1507: #endif
1508: return 0;
1509: }
1511: /* ---------------------------------------------------------------------*/
1512: /*
1513: The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1514: is attached to a communicator, in this case the attribute is a PetscViewer.
1515: */
1516: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
1518: /*@C
1519: PETSC_VIEWER_BINARY_ - Creates a `PETSCVIEWERBINARY` `PetscViewer` shared by all processors
1520: in a communicator.
1522: Collective
1524: Input Parameter:
1525: . comm - the MPI communicator to share the `PETSCVIEWERBINARY`
1527: Level: intermediate
1529: Options Database Keys:
1530: + -viewer_binary_filename <name> - filename in which to store the binary data, defaults to binaryoutput
1531: . -viewer_binary_skip_info - true means do not create .info file for this viewer
1532: . -viewer_binary_skip_options - true means do not use the options database for this viewer
1533: . -viewer_binary_skip_header - true means do not store the usual header information in the binary file
1534: - -viewer_binary_mpiio - true means use the file via MPI-IO, maybe faster for large files and many MPI ranks
1536: Environmental variable:
1537: - PETSC_VIEWER_BINARY_FILENAME - filename in which to store the binary data, defaults to binaryoutput
1539: Note:
1540: Unlike almost all other PETSc routines, `PETSC_VIEWER_BINARY_` does not return
1541: an error code. The binary PetscViewer is usually used in the form
1542: $ XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
1544: .seealso: `PETSCVIEWERBINARY`, `PETSC_VIEWER_BINARY_WORLD`, `PETSC_VIEWER_BINARY_SELF`, `PetscViewerBinaryOpen()`, `PetscViewerCreate()`,
1545: `PetscViewerDestroy()`
1546: @*/
1547: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1548: {
1550: PetscBool flg;
1551: PetscViewer viewer;
1552: char fname[PETSC_MAX_PATH_LEN];
1553: MPI_Comm ncomm;
1555: PetscCommDuplicate(comm, &ncomm, NULL);
1556: if (ierr) {
1557: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1558: return NULL;
1559: }
1560: if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1561: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Binary_keyval, NULL);
1562: if (ierr) {
1563: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1564: return NULL;
1565: }
1566: }
1567: MPI_Comm_get_attr(ncomm, Petsc_Viewer_Binary_keyval, (void **)&viewer, (int *)&flg);
1568: if (ierr) {
1569: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1570: return NULL;
1571: }
1572: if (!flg) { /* PetscViewer not yet created */
1573: PetscOptionsGetenv(ncomm, "PETSC_VIEWER_BINARY_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
1574: if (ierr) {
1575: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1576: return NULL;
1577: }
1578: if (!flg) {
1579: PetscStrcpy(fname, "binaryoutput");
1580: if (ierr) {
1581: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1582: return NULL;
1583: }
1584: }
1585: PetscViewerBinaryOpen(ncomm, fname, FILE_MODE_WRITE, &viewer);
1586: if (ierr) {
1587: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1588: return NULL;
1589: }
1590: PetscObjectRegisterDestroy((PetscObject)viewer);
1591: if (ierr) {
1592: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1593: return NULL;
1594: }
1595: MPI_Comm_set_attr(ncomm, Petsc_Viewer_Binary_keyval, (void *)viewer);
1596: if (ierr) {
1597: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1598: return NULL;
1599: }
1600: }
1601: PetscCommDestroy(&ncomm);
1602: if (ierr) {
1603: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1604: return NULL;
1605: }
1606: return viewer;
1607: }