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; No Fortran Support
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: .seealso: [](sec_viewers), `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; No Fortran Support
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: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
207: @*/
208: PetscErrorCode PetscViewerBinaryAddMPIIOOffset(PetscViewer viewer, MPI_Offset off)
209: {
210: PetscViewer_Binary *vbinary;
214: vbinary = (PetscViewer_Binary *)viewer->data;
215: vbinary->moff += off;
216: return 0;
217: }
219: /*@C
220: PetscViewerBinaryGetMPIIODescriptor - Extracts the MPI IO file descriptor from a `PetscViewer`.
222: Not Collective; No Fortran Support
224: Input Parameter:
225: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
227: Output Parameter:
228: . fdes - file descriptor
230: Level: advanced
232: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
233: @*/
234: PetscErrorCode PetscViewerBinaryGetMPIIODescriptor(PetscViewer viewer, MPI_File *fdes)
235: {
236: PetscViewer_Binary *vbinary;
240: PetscViewerSetUp(viewer);
241: vbinary = (PetscViewer_Binary *)viewer->data;
242: *fdes = vbinary->mfdes;
243: return 0;
244: }
245: #endif
247: /*@
248: PetscViewerBinarySetUseMPIIO - Sets a binary viewer to use MPI-IO for reading/writing. Must be called
249: before `PetscViewerFileSetName()`
251: Logically Collective
253: Input Parameters:
254: + viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`
255: - use - `PETSC_TRUE` means MPI-IO will be used
257: Options Database Key:
258: -viewer_binary_mpiio : Flag for using MPI-IO
260: Level: advanced
262: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`,
263: `PetscViewerBinaryGetUseMPIIO()`
264: @*/
265: PetscErrorCode PetscViewerBinarySetUseMPIIO(PetscViewer viewer, PetscBool use)
266: {
269: PetscTryMethod(viewer, "PetscViewerBinarySetUseMPIIO_C", (PetscViewer, PetscBool), (viewer, use));
270: return 0;
271: }
273: #if defined(PETSC_HAVE_MPIIO)
274: static PetscErrorCode PetscViewerBinarySetUseMPIIO_Binary(PetscViewer viewer, PetscBool use)
275: {
276: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
278: vbinary->usempiio = use;
279: return 0;
280: }
281: #endif
283: /*@
284: PetscViewerBinaryGetUseMPIIO - Returns PETSC_TRUE if the binary viewer uses MPI-IO.
286: Not Collective
288: Input Parameter:
289: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`; must be a `PETSCVIEWERBINARY`
291: Output Parameter:
292: . use - `PETSC_TRUE` if MPI-IO is being used
294: Level: advanced
296: Note:
297: If MPI-IO is not available, this function will always return PETSC_FALSE
299: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
300: @*/
301: PetscErrorCode PetscViewerBinaryGetUseMPIIO(PetscViewer viewer, PetscBool *use)
302: {
305: *use = PETSC_FALSE;
306: PetscTryMethod(viewer, "PetscViewerBinaryGetUseMPIIO_C", (PetscViewer, PetscBool *), (viewer, use));
307: return 0;
308: }
310: #if defined(PETSC_HAVE_MPIIO)
311: static PetscErrorCode PetscViewerBinaryGetUseMPIIO_Binary(PetscViewer viewer, PetscBool *use)
312: {
313: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
315: *use = vbinary->usempiio;
316: return 0;
317: }
318: #endif
320: /*@
321: PetscViewerBinarySetFlowControl - Sets how many messages are allowed to outstanding at the same time during parallel IO reads/writes
323: Not Collective
325: Input Parameters:
326: + viewer - PetscViewer context, obtained from `PetscViewerBinaryOpen()`
327: - fc - the number of messages, defaults to 256 if this function was not called
329: Level: advanced
331: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinaryGetFlowControl()`
332: @*/
333: PetscErrorCode PetscViewerBinarySetFlowControl(PetscViewer viewer, PetscInt fc)
334: {
337: PetscTryMethod(viewer, "PetscViewerBinarySetFlowControl_C", (PetscViewer, PetscInt), (viewer, fc));
338: return 0;
339: }
341: static PetscErrorCode PetscViewerBinarySetFlowControl_Binary(PetscViewer viewer, PetscInt fc)
342: {
343: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
346: vbinary->flowcontrol = fc;
347: return 0;
348: }
350: /*@
351: PetscViewerBinaryGetFlowControl - Returns how many messages are allowed to outstanding at the same time during parallel IO reads/writes
353: Not Collective
355: Input Parameter:
356: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
358: Output Parameter:
359: . fc - the number of messages
361: Level: advanced
363: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`, `PetscViewerBinarySetFlowControl()`
364: @*/
365: PetscErrorCode PetscViewerBinaryGetFlowControl(PetscViewer viewer, PetscInt *fc)
366: {
369: PetscUseMethod(viewer, "PetscViewerBinaryGetFlowControl_C", (PetscViewer, PetscInt *), (viewer, fc));
370: return 0;
371: }
373: PETSC_INTERN PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer viewer, PetscInt *fc)
374: {
375: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
377: *fc = vbinary->flowcontrol;
378: return 0;
379: }
381: /*@C
382: PetscViewerBinaryGetDescriptor - Extracts the file descriptor from a `PetscViewer` of `PetscViewerType` `PETSCVIEWERBINARY`.
384: Collective because it may trigger a `PetscViewerSetUp()` call; No Fortran Support
386: Input Parameter:
387: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
389: Output Parameter:
390: . fdes - file descriptor
392: Level: advanced
394: Note:
395: For writable binary `PetscViewer`s, the descriptor will only be valid for the
396: first processor in the communicator that shares the `PetscViewer`. For readable
397: files it will only be valid on nodes that have the file. If node 0 does not
398: have the file it generates an error even if another node does have the file.
400: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetInfoPointer()`
401: @*/
402: PetscErrorCode PetscViewerBinaryGetDescriptor(PetscViewer viewer, int *fdes)
403: {
404: PetscViewer_Binary *vbinary;
408: PetscViewerSetUp(viewer);
409: vbinary = (PetscViewer_Binary *)viewer->data;
410: *fdes = vbinary->fdes;
411: return 0;
412: }
414: /*@
415: PetscViewerBinarySkipInfo - Binary file will not have .info file created with it
417: Not Collective
419: Input Parameter:
420: . viewer - `PetscViewer` context, obtained from `PetscViewerCreate()`
422: Options Database Key:
423: . -viewer_binary_skip_info - true indicates do not generate .info file
425: Level: advanced
427: Notes:
428: This must be called after `PetscViewerSetType()`. If you use `PetscViewerBinaryOpen()` then
429: you can only skip the info file with the -viewer_binary_skip_info flag. To use the function you must open the
430: viewer with `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinarySkipInfo()`.
432: The .info contains meta information about the data in the binary file, for example the block size if it was
433: set for a vector or matrix.
435: This routine is deprecated, use `PetscViewerBinarySetSkipInfo()`
437: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
438: `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
439: @*/
440: PetscErrorCode PetscViewerBinarySkipInfo(PetscViewer viewer)
441: {
442: PetscViewerBinarySetSkipInfo(viewer, PETSC_TRUE);
443: return 0;
444: }
446: /*@
447: PetscViewerBinarySetSkipInfo - Binary file will not have .info file created with it
449: Not Collective
451: Input Parameters:
452: + viewer - PetscViewer context, obtained from PetscViewerCreate()
453: - skip - PETSC_TRUE implies the .info file will not be generated
455: Options Database Key:
456: . -viewer_binary_skip_info - true indicates do not generate .info file
458: Level: advanced
460: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySetSkipOptions()`,
461: `PetscViewerBinaryGetSkipOptions()`, `PetscViewerBinaryGetSkipInfo()`
462: @*/
463: PetscErrorCode PetscViewerBinarySetSkipInfo(PetscViewer viewer, PetscBool skip)
464: {
467: PetscTryMethod(viewer, "PetscViewerBinarySetSkipInfo_C", (PetscViewer, PetscBool), (viewer, skip));
468: return 0;
469: }
471: static PetscErrorCode PetscViewerBinarySetSkipInfo_Binary(PetscViewer viewer, PetscBool skip)
472: {
473: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
475: vbinary->skipinfo = skip;
476: return 0;
477: }
479: /*@
480: PetscViewerBinaryGetSkipInfo - check if viewer wrote a .info file
482: Not Collective
484: Input Parameter:
485: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
487: Output Parameter:
488: . skip - `PETSC_TRUE` implies the .info file was not generated
490: Level: advanced
492: Note:
493: This must be called after `PetscViewerSetType()`
495: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`,
496: `PetscViewerBinarySetSkipOptions()`, `PetscViewerBinarySetSkipInfo()`
497: @*/
498: PetscErrorCode PetscViewerBinaryGetSkipInfo(PetscViewer viewer, PetscBool *skip)
499: {
502: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipInfo_C", (PetscViewer, PetscBool *), (viewer, skip));
503: return 0;
504: }
506: static PetscErrorCode PetscViewerBinaryGetSkipInfo_Binary(PetscViewer viewer, PetscBool *skip)
507: {
508: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
510: *skip = vbinary->skipinfo;
511: return 0;
512: }
514: /*@
515: PetscViewerBinarySetSkipOptions - do not use the PETSc options database when loading objects
517: Not Collective
519: Input Parameters:
520: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
521: - skip - `PETSC_TRUE` means do not use the options from the options database
523: Options Database Key:
524: . -viewer_binary_skip_options <true or false> - true means do not use the options from the options database
526: Level: advanced
528: Note:
529: This must be called after `PetscViewerSetType()`
531: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
532: `PetscViewerBinaryGetSkipOptions()`
533: @*/
534: PetscErrorCode PetscViewerBinarySetSkipOptions(PetscViewer viewer, PetscBool skip)
535: {
538: PetscTryMethod(viewer, "PetscViewerBinarySetSkipOptions_C", (PetscViewer, PetscBool), (viewer, skip));
539: return 0;
540: }
542: static PetscErrorCode PetscViewerBinarySetSkipOptions_Binary(PetscViewer viewer, PetscBool skip)
543: {
544: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
546: vbinary->skipoptions = skip;
547: return 0;
548: }
550: /*@
551: PetscViewerBinaryGetSkipOptions - checks if viewer uses the PETSc options database when loading objects
553: Not Collective
555: Input Parameter:
556: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
558: Output Parameter:
559: . skip - `PETSC_TRUE` means do not use
561: Level: advanced
563: Note:
564: This must be called after `PetscViewerSetType()`
566: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
567: `PetscViewerBinarySetSkipOptions()`
568: @*/
569: PetscErrorCode PetscViewerBinaryGetSkipOptions(PetscViewer viewer, PetscBool *skip)
570: {
573: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipOptions_C", (PetscViewer, PetscBool *), (viewer, skip));
574: return 0;
575: }
577: static PetscErrorCode PetscViewerBinaryGetSkipOptions_Binary(PetscViewer viewer, PetscBool *skip)
578: {
579: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
581: *skip = vbinary->skipoptions;
582: return 0;
583: }
585: /*@
586: PetscViewerBinarySetSkipHeader - do not write a header with size information on output, just raw data
588: Not Collective
590: Input Parameters:
591: + viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
592: - skip - `PETSC_TRUE `means do not write header
594: Options Database Key:
595: . -viewer_binary_skip_header <true or false> - true means do not write header
597: Level: advanced
599: Notes:
600: This must be called after `PetscViewerSetType()`
602: Is ignored on anything but a binary viewer
604: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
605: `PetscViewerBinaryGetSkipHeader()`
606: @*/
607: PetscErrorCode PetscViewerBinarySetSkipHeader(PetscViewer viewer, PetscBool skip)
608: {
611: PetscTryMethod(viewer, "PetscViewerBinarySetSkipHeader_C", (PetscViewer, PetscBool), (viewer, skip));
612: return 0;
613: }
615: static PetscErrorCode PetscViewerBinarySetSkipHeader_Binary(PetscViewer viewer, PetscBool skip)
616: {
617: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
619: vbinary->skipheader = skip;
620: return 0;
621: }
623: /*@
624: PetscViewerBinaryGetSkipHeader - checks whether to write a header with size information on output, or just raw data
626: Not Collective
628: Input Parameter:
629: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
631: Output Parameter:
632: . skip - `PETSC_TRUE` means do not write header
634: Level: advanced
636: Notes:
637: This must be called after PetscViewerSetType()
639: Returns `PETSC_FALSE` for `PETSCSOCKETVIEWER`, you cannot skip the header for it.
641: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`, `PetscViewerBinarySkipInfo()`,
642: `PetscViewerBinarySetSkipHeader()`
643: @*/
644: PetscErrorCode PetscViewerBinaryGetSkipHeader(PetscViewer viewer, PetscBool *skip)
645: {
648: PetscUseMethod(viewer, "PetscViewerBinaryGetSkipHeader_C", (PetscViewer, PetscBool *), (viewer, skip));
649: return 0;
650: }
652: static PetscErrorCode PetscViewerBinaryGetSkipHeader_Binary(PetscViewer viewer, PetscBool *skip)
653: {
654: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
656: *skip = vbinary->skipheader;
657: return 0;
658: }
660: /*@C
661: PetscViewerBinaryGetInfoPointer - Extracts the file pointer for the ASCII
662: info file associated with a binary file.
664: Not Collective; No Fortran Support
666: Input Parameter:
667: . viewer - `PetscViewer` context, obtained from `PetscViewerBinaryOpen()`
669: Output Parameter:
670: . file - file pointer Always returns NULL if not a binary viewer
672: Level: advanced
674: Note:
675: For writable binary `PetscViewer`s, the file pointer will only be valid for the
676: first processor in the communicator that shares the `PetscViewer`.
678: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinaryGetDescriptor()`
679: @*/
680: PetscErrorCode PetscViewerBinaryGetInfoPointer(PetscViewer viewer, FILE **file)
681: {
684: *file = NULL;
685: PetscTryMethod(viewer, "PetscViewerBinaryGetInfoPointer_C", (PetscViewer, FILE **), (viewer, file));
686: return 0;
687: }
689: static PetscErrorCode PetscViewerBinaryGetInfoPointer_Binary(PetscViewer viewer, FILE **file)
690: {
691: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
693: PetscViewerSetUp(viewer);
694: *file = vbinary->fdes_info;
695: if (viewer->format == PETSC_VIEWER_BINARY_MATLAB && !vbinary->matlabheaderwritten) {
696: if (vbinary->fdes_info) {
697: FILE *info = vbinary->fdes_info;
698: PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
699: PetscFPrintf(PETSC_COMM_SELF, info, "#$$ Set.filename = '%s';\n", vbinary->filename);
700: PetscFPrintf(PETSC_COMM_SELF, info, "#$$ fd = PetscOpenFile(Set.filename);\n");
701: PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
702: }
703: vbinary->matlabheaderwritten = PETSC_TRUE;
704: }
705: return 0;
706: }
708: #if defined(PETSC_HAVE_MPIIO)
709: static PetscErrorCode PetscViewerFileClose_BinaryMPIIO(PetscViewer v)
710: {
711: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
713: if (vbinary->mfdes != MPI_FILE_NULL) MPI_File_close(&vbinary->mfdes);
714: if (vbinary->mfsub != MPI_FILE_NULL) MPI_File_close(&vbinary->mfsub);
715: vbinary->moff = 0;
716: return 0;
717: }
718: #endif
720: static PetscErrorCode PetscViewerFileClose_BinarySTDIO(PetscViewer v)
721: {
722: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
724: if (vbinary->fdes != -1) {
725: PetscBinaryClose(vbinary->fdes);
726: vbinary->fdes = -1;
727: if (vbinary->storecompressed) {
728: char cmd[8 + PETSC_MAX_PATH_LEN], out[64 + PETSC_MAX_PATH_LEN] = "";
729: const char *gzfilename = vbinary->ogzfilename ? vbinary->ogzfilename : vbinary->filename;
730: /* compress the file */
731: PetscStrncpy(cmd, "gzip -f ", sizeof(cmd));
732: PetscStrlcat(cmd, gzfilename, sizeof(cmd));
733: #if defined(PETSC_HAVE_POPEN)
734: {
735: FILE *fp;
736: PetscPOpen(PETSC_COMM_SELF, NULL, cmd, "r", &fp);
738: PetscPClose(PETSC_COMM_SELF, fp);
739: }
740: #endif
741: }
742: }
743: PetscFree(vbinary->ogzfilename);
744: return 0;
745: }
747: static PetscErrorCode PetscViewerFileClose_BinaryInfo(PetscViewer v)
748: {
749: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
751: if (v->format == PETSC_VIEWER_BINARY_MATLAB && vbinary->matlabheaderwritten) {
752: if (vbinary->fdes_info) {
753: FILE *info = vbinary->fdes_info;
754: PetscFPrintf(PETSC_COMM_SELF, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");
755: PetscFPrintf(PETSC_COMM_SELF, info, "#$$ close(fd);\n");
756: PetscFPrintf(PETSC_COMM_SELF, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");
757: }
758: }
759: if (vbinary->fdes_info) {
760: FILE *info = vbinary->fdes_info;
761: vbinary->fdes_info = NULL;
763: }
764: return 0;
765: }
767: static PetscErrorCode PetscViewerFileClose_Binary(PetscViewer v)
768: {
769: #if defined(PETSC_HAVE_MPIIO)
770: PetscViewerFileClose_BinaryMPIIO(v);
771: #endif
772: PetscViewerFileClose_BinarySTDIO(v);
773: PetscViewerFileClose_BinaryInfo(v);
774: return 0;
775: }
777: static PetscErrorCode PetscViewerDestroy_Binary(PetscViewer v)
778: {
779: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
781: PetscViewerFileClose_Binary(v);
782: PetscFree(vbinary->filename);
783: PetscFree(vbinary);
784: PetscViewerBinaryClearFunctionList(v);
785: return 0;
786: }
788: /*@C
789: PetscViewerBinaryOpen - Opens a file for binary input/output.
791: Collective
793: Input Parameters:
794: + comm - MPI communicator
795: . name - name of file
796: - mode - open mode of file
797: $ FILE_MODE_WRITE - create new file for binary output
798: $ FILE_MODE_READ - open existing file for binary input
799: $ FILE_MODE_APPEND - open existing file for binary output
801: Output Parameter:
802: . viewer - PetscViewer for binary input/output to use with the specified file
804: Options Database Keys:
805: + -viewer_binary_filename <name> - name of file to use
806: . -viewer_binary_skip_info - true to skip opening an info file
807: . -viewer_binary_skip_options - true to not use options database while creating viewer
808: . -viewer_binary_skip_header - true to skip output object headers to the file
809: - -viewer_binary_mpiio - true to use MPI-IO for input and output to the file (more scalable for large problems)
811: Level: beginner
813: Note:
814: This `PetscViewer` should be destroyed with `PetscViewerDestroy()`.
816: For reading files, the filename may begin with ftp:// or http:// and/or
817: end with .gz; in this case file is brought over and uncompressed.
819: For creating files, if the file name ends with .gz it is automatically
820: compressed when closed.
822: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
823: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
824: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`, `PetscViewerBinarySetUseMPIIO()`,
825: `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinaryGetMPIIOOffset()`
826: @*/
827: PetscErrorCode PetscViewerBinaryOpen(MPI_Comm comm, const char name[], PetscFileMode mode, PetscViewer *viewer)
828: {
829: PetscViewerCreate(comm, viewer);
830: PetscViewerSetType(*viewer, PETSCVIEWERBINARY);
831: PetscViewerFileSetMode(*viewer, mode);
832: PetscViewerFileSetName(*viewer, name);
833: PetscViewerSetFromOptions(*viewer);
834: return 0;
835: }
837: #if defined(PETSC_HAVE_MPIIO)
838: static PetscErrorCode PetscViewerBinaryWriteReadMPIIO(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype, PetscBool write)
839: {
840: MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
841: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
842: MPI_File mfdes = vbinary->mfdes;
843: MPI_Datatype mdtype;
844: PetscMPIInt rank, cnt;
845: MPI_Status status;
846: MPI_Aint ul, dsize;
848: MPI_Comm_rank(comm, &rank);
849: PetscMPIIntCast(num, &cnt);
850: PetscDataTypeToMPIDataType(dtype, &mdtype);
851: if (write) {
852: if (rank == 0) MPIU_File_write_at(mfdes, vbinary->moff, data, cnt, mdtype, &status);
853: } else {
854: if (rank == 0) {
855: MPIU_File_read_at(mfdes, vbinary->moff, data, cnt, mdtype, &status);
856: if (cnt > 0) MPI_Get_count(&status, mdtype, &cnt);
857: }
858: MPI_Bcast(&cnt, 1, MPI_INT, 0, comm);
859: MPI_Bcast(data, cnt, mdtype, 0, comm);
860: }
861: MPI_Type_get_extent(mdtype, &ul, &dsize);
862: vbinary->moff += dsize * cnt;
863: if (count) *count = cnt;
864: return 0;
865: }
866: #endif
868: /*@C
869: PetscViewerBinaryRead - Reads from a binary file, all processors get the same result
871: Collective
873: Input Parameters:
874: + viewer - the binary viewer
875: . data - location of the data to be written
876: . num - number of items of data to read
877: - dtype - type of data to read
879: Output Parameters:
880: . count - number of items of data actually read, or NULL.
882: Level: beginner
884: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
885: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
886: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
887: @*/
888: PetscErrorCode PetscViewerBinaryRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
889: {
890: PetscViewer_Binary *vbinary;
894: PetscViewerSetUp(viewer);
895: vbinary = (PetscViewer_Binary *)viewer->data;
896: #if defined(PETSC_HAVE_MPIIO)
897: if (vbinary->usempiio) {
898: PetscViewerBinaryWriteReadMPIIO(viewer, data, num, count, dtype, PETSC_FALSE);
899: } else {
900: #endif
901: PetscBinarySynchronizedRead(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, num, count, dtype);
902: #if defined(PETSC_HAVE_MPIIO)
903: }
904: #endif
905: return 0;
906: }
908: /*@C
909: PetscViewerBinaryWrite - writes to a binary file, only from the first MPI rank
911: Collective
913: Input Parameters:
914: + viewer - the binary viewer
915: . data - location of data
916: . count - number of items of data to write
917: - dtype - type of data to write
919: Level: beginner
921: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
922: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`, `PetscDataType`
923: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
924: @*/
925: PetscErrorCode PetscViewerBinaryWrite(PetscViewer viewer, const void *data, PetscInt count, PetscDataType dtype)
926: {
927: PetscViewer_Binary *vbinary;
931: PetscViewerSetUp(viewer);
932: vbinary = (PetscViewer_Binary *)viewer->data;
933: #if defined(PETSC_HAVE_MPIIO)
934: if (vbinary->usempiio) {
935: PetscViewerBinaryWriteReadMPIIO(viewer, (void *)data, count, NULL, dtype, PETSC_TRUE);
936: } else {
937: #endif
938: PetscBinarySynchronizedWrite(PetscObjectComm((PetscObject)viewer), vbinary->fdes, data, count, dtype);
939: #if defined(PETSC_HAVE_MPIIO)
940: }
941: #endif
942: return 0;
943: }
945: static PetscErrorCode PetscViewerBinaryWriteReadAll(PetscViewer viewer, PetscBool write, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
946: {
947: MPI_Comm comm = PetscObjectComm((PetscObject)viewer);
948: PetscMPIInt size, rank;
949: MPI_Datatype mdtype;
950: PETSC_UNUSED MPI_Aint lb;
951: MPI_Aint dsize;
952: PetscBool useMPIIO;
958: PetscViewerSetUp(viewer);
960: PetscDataTypeToMPIDataType(dtype, &mdtype);
961: MPI_Type_get_extent(mdtype, &lb, &dsize);
962: MPI_Comm_rank(comm, &rank);
963: MPI_Comm_size(comm, &size);
965: PetscViewerBinaryGetUseMPIIO(viewer, &useMPIIO);
966: #if defined(PETSC_HAVE_MPIIO)
967: if (useMPIIO) {
968: MPI_File mfdes;
969: MPI_Offset off;
970: PetscMPIInt cnt;
972: if (start == PETSC_DETERMINE) {
973: MPI_Scan(&count, &start, 1, MPIU_INT, MPI_SUM, comm);
974: start -= count;
975: }
976: if (total == PETSC_DETERMINE) {
977: total = start + count;
978: MPI_Bcast(&total, 1, MPIU_INT, size - 1, comm);
979: }
980: PetscMPIIntCast(count, &cnt);
981: PetscViewerBinaryGetMPIIODescriptor(viewer, &mfdes);
982: PetscViewerBinaryGetMPIIOOffset(viewer, &off);
983: off += (MPI_Offset)(start * dsize);
984: if (write) {
985: MPIU_File_write_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE);
986: } else {
987: MPIU_File_read_at_all(mfdes, off, data, cnt, mdtype, MPI_STATUS_IGNORE);
988: }
989: off = (MPI_Offset)(total * dsize);
990: PetscViewerBinaryAddMPIIOOffset(viewer, off);
991: return 0;
992: }
993: #endif
994: {
995: int fdes;
996: char *workbuf = NULL;
997: PetscInt tcount = rank == 0 ? 0 : count, maxcount = 0, message_count, flowcontrolcount;
998: PetscMPIInt tag, cnt, maxcnt, scnt = 0, rcnt = 0, j;
999: MPI_Status status;
1001: PetscCommGetNewTag(comm, &tag);
1002: MPI_Reduce(&tcount, &maxcount, 1, MPIU_INT, MPI_MAX, 0, comm);
1003: PetscMPIIntCast(maxcount, &maxcnt);
1004: PetscMPIIntCast(count, &cnt);
1006: PetscViewerBinaryGetDescriptor(viewer, &fdes);
1007: PetscViewerFlowControlStart(viewer, &message_count, &flowcontrolcount);
1008: if (rank == 0) {
1009: PetscMalloc(maxcnt * dsize, &workbuf);
1010: if (write) {
1011: PetscBinaryWrite(fdes, data, cnt, dtype);
1012: } else {
1013: PetscBinaryRead(fdes, data, cnt, NULL, dtype);
1014: }
1015: for (j = 1; j < size; j++) {
1016: PetscViewerFlowControlStepMain(viewer, j, &message_count, flowcontrolcount);
1017: if (write) {
1018: MPI_Recv(workbuf, maxcnt, mdtype, j, tag, comm, &status);
1019: MPI_Get_count(&status, mdtype, &rcnt);
1020: PetscBinaryWrite(fdes, workbuf, rcnt, dtype);
1021: } else {
1022: MPI_Recv(&scnt, 1, MPI_INT, j, tag, comm, MPI_STATUS_IGNORE);
1023: PetscBinaryRead(fdes, workbuf, scnt, NULL, dtype);
1024: MPI_Send(workbuf, scnt, mdtype, j, tag, comm);
1025: }
1026: }
1027: PetscFree(workbuf);
1028: PetscViewerFlowControlEndMain(viewer, &message_count);
1029: } else {
1030: PetscViewerFlowControlStepWorker(viewer, rank, &message_count);
1031: if (write) {
1032: MPI_Send(data, cnt, mdtype, 0, tag, comm);
1033: } else {
1034: MPI_Send(&cnt, 1, MPI_INT, 0, tag, comm);
1035: MPI_Recv(data, cnt, mdtype, 0, tag, comm, MPI_STATUS_IGNORE);
1036: }
1037: PetscViewerFlowControlEndWorker(viewer, &message_count);
1038: }
1039: }
1040: return 0;
1041: }
1043: /*@C
1044: PetscViewerBinaryReadAll - reads from a binary file from all MPI ranks, each rank receives its own portion of the data
1046: Collective
1048: Input Parameters:
1049: + viewer - the binary viewer
1050: . data - location of data
1051: . count - local number of items of data to read
1052: . start - local start, can be `PETSC_DETERMINE`
1053: . total - global number of items of data to read, can be `PETSC_DETERMINE`
1054: - dtype - type of data to read
1056: Level: advanced
1058: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteAll()`
1059: @*/
1060: PetscErrorCode PetscViewerBinaryReadAll(PetscViewer viewer, void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1061: {
1062: PetscViewerBinaryWriteReadAll(viewer, PETSC_FALSE, data, count, start, total, dtype);
1063: return 0;
1064: }
1066: /*@C
1067: PetscViewerBinaryWriteAll - writes to a binary file from all MPI ranks, each rank writes its own portion of the data
1069: Collective
1071: Input Parameters:
1072: + viewer - the binary viewer
1073: . data - location of data
1074: . count - local number of items of data to write
1075: . start - local start, can be `PETSC_DETERMINE`
1076: . total - global number of items of data to write, can be `PETSC_DETERMINE`
1077: - dtype - type of data to write
1079: Level: advanced
1081: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerBinaryOpen()`, `PetscViewerBinarySetUseMPIIO()`, `PetscViewerBinaryWriteAll()`, `PetscViewerBinaryReadAll()`
1082: @*/
1083: PetscErrorCode PetscViewerBinaryWriteAll(PetscViewer viewer, const void *data, PetscInt count, PetscInt start, PetscInt total, PetscDataType dtype)
1084: {
1085: PetscViewerBinaryWriteReadAll(viewer, PETSC_TRUE, (void *)data, count, start, total, dtype);
1086: return 0;
1087: }
1089: /*@C
1090: PetscViewerBinaryWriteStringArray - writes to a binary file, only from the first MPI rank, an array of strings
1092: Collective
1094: Input Parameters:
1095: + viewer - the binary viewer
1096: - data - location of the array of strings
1098: Level: intermediate
1100: Note:
1101: The array of strings must be null terminated
1103: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1104: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1105: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1106: @*/
1107: PetscErrorCode PetscViewerBinaryWriteStringArray(PetscViewer viewer, const char *const *data)
1108: {
1109: PetscInt i, n = 0, *sizes;
1110: size_t len;
1112: PetscViewerSetUp(viewer);
1113: /* count number of strings */
1114: while (data[n++])
1115: ;
1116: n--;
1117: PetscMalloc1(n + 1, &sizes);
1118: sizes[0] = n;
1119: for (i = 0; i < n; i++) {
1120: PetscStrlen(data[i], &len);
1121: sizes[i + 1] = (PetscInt)len + 1; /* size includes space for the null terminator */
1122: }
1123: PetscViewerBinaryWrite(viewer, sizes, n + 1, PETSC_INT);
1124: for (i = 0; i < n; i++) PetscViewerBinaryWrite(viewer, (void *)data[i], sizes[i + 1], PETSC_CHAR);
1125: PetscFree(sizes);
1126: return 0;
1127: }
1129: /*@C
1130: PetscViewerBinaryReadStringArray - reads a binary file an array of strings to all MPI ranks
1132: Collective
1134: Input Parameter:
1135: . viewer - the binary viewer
1137: Output Parameter:
1138: . data - location of the array of strings
1140: Level: intermediate
1142: Note:
1143: The array of strings must null terminated
1145: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1146: `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1147: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1148: @*/
1149: PetscErrorCode PetscViewerBinaryReadStringArray(PetscViewer viewer, char ***data)
1150: {
1151: PetscInt i, n, *sizes, N = 0;
1153: PetscViewerSetUp(viewer);
1154: /* count number of strings */
1155: PetscViewerBinaryRead(viewer, &n, 1, NULL, PETSC_INT);
1156: PetscMalloc1(n, &sizes);
1157: PetscViewerBinaryRead(viewer, sizes, n, NULL, PETSC_INT);
1158: for (i = 0; i < n; i++) N += sizes[i];
1159: PetscMalloc((n + 1) * sizeof(char *) + N * sizeof(char), data);
1160: (*data)[0] = (char *)((*data) + n + 1);
1161: for (i = 1; i < n; i++) (*data)[i] = (*data)[i - 1] + sizes[i - 1];
1162: PetscViewerBinaryRead(viewer, (*data)[0], N, NULL, PETSC_CHAR);
1163: (*data)[n] = NULL;
1164: PetscFree(sizes);
1165: return 0;
1166: }
1168: /*@C
1169: PetscViewerFileSetMode - Sets the open mode of file
1171: Logically Collective
1173: Input Parameters:
1174: + viewer - the `PetscViewer`; must be a a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII` `PetscViewer`
1175: - mode - open mode of file
1176: .vb
1177: FILE_MODE_WRITE - create new file for output
1178: FILE_MODE_READ - open existing file for input
1179: FILE_MODE_APPEND - open existing file for output
1180: .ve
1182: Level: advanced
1184: .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1185: @*/
1186: PetscErrorCode PetscViewerFileSetMode(PetscViewer viewer, PetscFileMode mode)
1187: {
1192: PetscTryMethod(viewer, "PetscViewerFileSetMode_C", (PetscViewer, PetscFileMode), (viewer, mode));
1193: return 0;
1194: }
1196: static PetscErrorCode PetscViewerFileSetMode_Binary(PetscViewer viewer, PetscFileMode mode)
1197: {
1198: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1201: vbinary->filemode = mode;
1202: return 0;
1203: }
1205: /*@C
1206: PetscViewerFileGetMode - Gets the open mode of file
1208: Not Collective
1210: Input Parameter:
1211: . viewer - the `PetscViewer`; must be a `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`, `PETSCVIEWERHDF5`, or `PETSCVIEWERASCII` `PetscViewer`
1213: Output Parameter:
1214: . mode - open mode of file
1215: .vb
1216: FILE_MODE_WRITE - create new file for binary output
1217: FILE_MODE_READ - open existing file for binary input
1218: FILE_MODE_APPEND - open existing file for binary output
1219: .ve
1221: Level: advanced
1223: .seealso: [](sec_viewers), `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1224: @*/
1225: PetscErrorCode PetscViewerFileGetMode(PetscViewer viewer, PetscFileMode *mode)
1226: {
1229: PetscUseMethod(viewer, "PetscViewerFileGetMode_C", (PetscViewer, PetscFileMode *), (viewer, mode));
1230: return 0;
1231: }
1233: static PetscErrorCode PetscViewerFileGetMode_Binary(PetscViewer viewer, PetscFileMode *mode)
1234: {
1235: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1237: *mode = vbinary->filemode;
1238: return 0;
1239: }
1241: static PetscErrorCode PetscViewerFileSetName_Binary(PetscViewer viewer, const char name[])
1242: {
1243: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1245: if (viewer->setupcalled && vbinary->filename) {
1246: /* gzip can be run after the file with the previous filename has been closed */
1247: PetscFree(vbinary->ogzfilename);
1248: PetscStrallocpy(vbinary->filename, &vbinary->ogzfilename);
1249: }
1250: PetscFree(vbinary->filename);
1251: PetscStrallocpy(name, &vbinary->filename);
1252: viewer->setupcalled = PETSC_FALSE;
1253: return 0;
1254: }
1256: static PetscErrorCode PetscViewerFileGetName_Binary(PetscViewer viewer, const char **name)
1257: {
1258: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1260: *name = vbinary->filename;
1261: return 0;
1262: }
1264: #if defined(PETSC_HAVE_MPIIO)
1265: static PetscErrorCode PetscViewerFileSetUp_BinaryMPIIO(PetscViewer viewer)
1266: {
1267: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1268: int amode;
1270: vbinary->storecompressed = PETSC_FALSE;
1272: vbinary->moff = 0;
1273: switch (vbinary->filemode) {
1274: case FILE_MODE_READ:
1275: amode = MPI_MODE_RDONLY;
1276: break;
1277: case FILE_MODE_WRITE:
1278: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE;
1279: break;
1280: case FILE_MODE_APPEND:
1281: amode = MPI_MODE_WRONLY | MPI_MODE_CREATE | MPI_MODE_APPEND;
1282: break;
1283: case FILE_MODE_UNDEFINED:
1284: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerSetUp()");
1285: default:
1286: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vbinary->filemode]);
1287: }
1288: MPI_File_open(PetscObjectComm((PetscObject)viewer), vbinary->filename, amode, MPI_INFO_NULL, &vbinary->mfdes);
1289: /*
1290: The MPI standard does not have MPI_MODE_TRUNCATE. We emulate this behavior by setting the file size to zero.
1291: */
1292: if (vbinary->filemode == FILE_MODE_WRITE) MPI_File_set_size(vbinary->mfdes, 0);
1293: /*
1294: Initially, all processes view the file as a linear byte stream. Therefore, for files opened with MPI_MODE_APPEND,
1295: MPI_File_get_position[_shared](fh, &offset) returns the absolute byte position at the end of file.
1296: Otherwise, we would need to call MPI_File_get_byte_offset(fh, offset, &byte_offset) to convert
1297: the offset in etype units to an absolute byte position.
1298: */
1299: if (vbinary->filemode == FILE_MODE_APPEND) MPI_File_get_position(vbinary->mfdes, &vbinary->moff);
1300: return 0;
1301: }
1302: #endif
1304: static PetscErrorCode PetscViewerFileSetUp_BinarySTDIO(PetscViewer viewer)
1305: {
1306: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1307: const char *fname;
1308: char bname[PETSC_MAX_PATH_LEN], *gz;
1309: PetscBool found;
1310: PetscMPIInt rank;
1312: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
1314: /* if file name ends in .gz strip that off and note user wants file compressed */
1315: vbinary->storecompressed = PETSC_FALSE;
1316: if (vbinary->filemode == FILE_MODE_WRITE) {
1317: PetscStrstr(vbinary->filename, ".gz", &gz);
1318: if (gz && gz[3] == 0) {
1319: *gz = 0;
1320: vbinary->storecompressed = PETSC_TRUE;
1321: }
1322: }
1323: #if !defined(PETSC_HAVE_POPEN)
1325: #endif
1327: fname = vbinary->filename;
1328: if (vbinary->filemode == FILE_MODE_READ) { /* possibly get the file from remote site or compressed file */
1329: PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), fname, bname, PETSC_MAX_PATH_LEN, &found);
1331: fname = bname;
1332: }
1334: vbinary->fdes = -1;
1335: if (rank == 0) { /* only first processor opens file*/
1336: PetscFileMode mode = vbinary->filemode;
1337: if (mode == FILE_MODE_APPEND) {
1338: /* check if asked to append to a non-existing file */
1339: PetscTestFile(fname, '\0', &found);
1340: if (!found) mode = FILE_MODE_WRITE;
1341: }
1342: PetscBinaryOpen(fname, mode, &vbinary->fdes);
1343: }
1344: return 0;
1345: }
1347: static PetscErrorCode PetscViewerFileSetUp_BinaryInfo(PetscViewer viewer)
1348: {
1349: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1350: PetscMPIInt rank;
1351: PetscBool found;
1353: vbinary->fdes_info = NULL;
1354: MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);
1355: if (!vbinary->skipinfo && (vbinary->filemode == FILE_MODE_READ || rank == 0)) {
1356: char infoname[PETSC_MAX_PATH_LEN], iname[PETSC_MAX_PATH_LEN], *gz;
1358: PetscStrncpy(infoname, vbinary->filename, sizeof(infoname));
1359: /* remove .gz if it ends file name */
1360: PetscStrstr(infoname, ".gz", &gz);
1361: if (gz && gz[3] == 0) *gz = 0;
1363: PetscStrlcat(infoname, ".info", sizeof(infoname));
1364: if (vbinary->filemode == FILE_MODE_READ) {
1365: PetscFixFilename(infoname, iname);
1366: PetscFileRetrieve(PetscObjectComm((PetscObject)viewer), iname, infoname, PETSC_MAX_PATH_LEN, &found);
1367: if (found) PetscOptionsInsertFile(PetscObjectComm((PetscObject)viewer), ((PetscObject)viewer)->options, infoname, PETSC_FALSE);
1368: } else if (rank == 0) { /* write or append */
1369: const char *omode = (vbinary->filemode == FILE_MODE_APPEND) ? "a" : "w";
1370: vbinary->fdes_info = fopen(infoname, omode);
1372: }
1373: }
1374: return 0;
1375: }
1377: static PetscErrorCode PetscViewerSetUp_Binary(PetscViewer viewer)
1378: {
1379: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)viewer->data;
1380: PetscBool usempiio;
1382: if (!vbinary->setfromoptionscalled) PetscViewerSetFromOptions(viewer);
1385: PetscViewerFileClose_Binary(viewer);
1387: PetscViewerBinaryGetUseMPIIO(viewer, &usempiio);
1388: if (usempiio) {
1389: #if defined(PETSC_HAVE_MPIIO)
1390: PetscViewerFileSetUp_BinaryMPIIO(viewer);
1391: #endif
1392: } else {
1393: PetscViewerFileSetUp_BinarySTDIO(viewer);
1394: }
1395: PetscViewerFileSetUp_BinaryInfo(viewer);
1397: PetscLogObjectState((PetscObject)viewer, "File: %s", vbinary->filename);
1398: return 0;
1399: }
1401: static PetscErrorCode PetscViewerView_Binary(PetscViewer v, PetscViewer viewer)
1402: {
1403: PetscViewer_Binary *vbinary = (PetscViewer_Binary *)v->data;
1404: const char *fname = vbinary->filename ? vbinary->filename : "not yet set";
1405: const char *fmode = vbinary->filemode != (PetscFileMode)-1 ? PetscFileModes[vbinary->filemode] : "not yet set";
1406: PetscBool usempiio;
1408: PetscViewerBinaryGetUseMPIIO(v, &usempiio);
1409: PetscViewerASCIIPrintf(viewer, "Filename: %s\n", fname);
1410: PetscViewerASCIIPrintf(viewer, "Mode: %s (%s)\n", fmode, usempiio ? "mpiio" : "stdio");
1411: return 0;
1412: }
1414: static PetscErrorCode PetscViewerSetFromOptions_Binary(PetscViewer viewer, PetscOptionItems *PetscOptionsObject)
1415: {
1416: PetscViewer_Binary *binary = (PetscViewer_Binary *)viewer->data;
1417: char defaultname[PETSC_MAX_PATH_LEN];
1418: PetscBool flg;
1420: if (viewer->setupcalled) return 0;
1421: PetscOptionsHeadBegin(PetscOptionsObject, "Binary PetscViewer Options");
1422: PetscSNPrintf(defaultname, PETSC_MAX_PATH_LEN - 1, "binaryoutput");
1423: PetscOptionsString("-viewer_binary_filename", "Specify filename", "PetscViewerFileSetName", defaultname, defaultname, sizeof(defaultname), &flg);
1424: if (flg) PetscViewerFileSetName_Binary(viewer, defaultname);
1425: PetscOptionsBool("-viewer_binary_skip_info", "Skip writing/reading .info file", "PetscViewerBinarySetSkipInfo", binary->skipinfo, &binary->skipinfo, NULL);
1426: PetscOptionsBool("-viewer_binary_skip_options", "Skip parsing Vec/Mat load options", "PetscViewerBinarySetSkipOptions", binary->skipoptions, &binary->skipoptions, NULL);
1427: PetscOptionsBool("-viewer_binary_skip_header", "Skip writing/reading header information", "PetscViewerBinarySetSkipHeader", binary->skipheader, &binary->skipheader, NULL);
1428: #if defined(PETSC_HAVE_MPIIO)
1429: PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file", "PetscViewerBinarySetUseMPIIO", binary->usempiio, &binary->usempiio, NULL);
1430: #else
1431: PetscOptionsBool("-viewer_binary_mpiio", "Use MPI-IO functionality to write/read binary file (NOT AVAILABLE)", "PetscViewerBinarySetUseMPIIO", PETSC_FALSE, NULL, NULL);
1432: #endif
1433: PetscOptionsHeadEnd();
1434: binary->setfromoptionscalled = PETSC_TRUE;
1435: return 0;
1436: }
1438: /*MC
1439: PETSCVIEWERBINARY - A viewer that saves to binary files
1441: Level: beginner
1443: .seealso: [](sec_viewers), `PetscViewerBinaryOpen()`, `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1444: `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, `PETSCVIEWERDRAW`, `PETSCVIEWERSOCKET`
1445: `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`,
1446: `PetscViewerBinaryGetUseMPIIO()`, `PetscViewerBinarySetUseMPIIO()`
1447: M*/
1449: PETSC_EXTERN PetscErrorCode PetscViewerCreate_Binary(PetscViewer v)
1450: {
1451: PetscViewer_Binary *vbinary;
1453: PetscNew(&vbinary);
1454: v->data = (void *)vbinary;
1456: v->ops->setfromoptions = PetscViewerSetFromOptions_Binary;
1457: v->ops->destroy = PetscViewerDestroy_Binary;
1458: v->ops->view = PetscViewerView_Binary;
1459: v->ops->setup = PetscViewerSetUp_Binary;
1460: v->ops->flush = NULL; /* Should we support Flush() ? */
1461: v->ops->getsubviewer = PetscViewerGetSubViewer_Binary;
1462: v->ops->restoresubviewer = PetscViewerRestoreSubViewer_Binary;
1463: v->ops->read = PetscViewerBinaryRead;
1465: vbinary->fdes = -1;
1466: #if defined(PETSC_HAVE_MPIIO)
1467: vbinary->usempiio = PETSC_FALSE;
1468: vbinary->mfdes = MPI_FILE_NULL;
1469: vbinary->mfsub = MPI_FILE_NULL;
1470: #endif
1471: vbinary->filename = NULL;
1472: vbinary->filemode = FILE_MODE_UNDEFINED;
1473: vbinary->fdes_info = NULL;
1474: vbinary->skipinfo = PETSC_FALSE;
1475: vbinary->skipoptions = PETSC_TRUE;
1476: vbinary->skipheader = PETSC_FALSE;
1477: vbinary->storecompressed = PETSC_FALSE;
1478: vbinary->ogzfilename = NULL;
1479: vbinary->flowcontrol = 256; /* seems a good number for Cray XT-5 */
1481: vbinary->setfromoptionscalled = PETSC_FALSE;
1483: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Binary);
1484: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetFlowControl_C", PetscViewerBinarySetFlowControl_Binary);
1485: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Binary);
1486: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Binary);
1487: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipOptions_C", PetscViewerBinaryGetSkipOptions_Binary);
1488: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipOptions_C", PetscViewerBinarySetSkipOptions_Binary);
1489: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipInfo_C", PetscViewerBinaryGetSkipInfo_Binary);
1490: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipInfo_C", PetscViewerBinarySetSkipInfo_Binary);
1491: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetInfoPointer_C", PetscViewerBinaryGetInfoPointer_Binary);
1492: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_Binary);
1493: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_Binary);
1494: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_Binary);
1495: PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_Binary);
1496: #if defined(PETSC_HAVE_MPIIO)
1497: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetUseMPIIO_C", PetscViewerBinaryGetUseMPIIO_Binary);
1498: PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetUseMPIIO_C", PetscViewerBinarySetUseMPIIO_Binary);
1499: #endif
1500: return 0;
1501: }
1503: /* ---------------------------------------------------------------------*/
1504: /*
1505: The variable Petsc_Viewer_Binary_keyval is used to indicate an MPI attribute that
1506: is attached to a communicator, in this case the attribute is a PetscViewer.
1507: */
1508: PetscMPIInt Petsc_Viewer_Binary_keyval = MPI_KEYVAL_INVALID;
1510: /*@C
1511: PETSC_VIEWER_BINARY_ - Creates a `PETSCVIEWERBINARY` `PetscViewer` shared by all processors
1512: in a communicator.
1514: Collective
1516: Input Parameter:
1517: . comm - the MPI communicator to share the `PETSCVIEWERBINARY`
1519: Level: intermediate
1521: Options Database Keys:
1522: + -viewer_binary_filename <name> - filename in which to store the binary data, defaults to binaryoutput
1523: . -viewer_binary_skip_info - true means do not create .info file for this viewer
1524: . -viewer_binary_skip_options - true means do not use the options database for this viewer
1525: . -viewer_binary_skip_header - true means do not store the usual header information in the binary file
1526: - -viewer_binary_mpiio - true means use the file via MPI-IO, maybe faster for large files and many MPI ranks
1528: Environmental variable:
1529: - PETSC_VIEWER_BINARY_FILENAME - filename in which to store the binary data, defaults to binaryoutput
1531: Note:
1532: Unlike almost all other PETSc routines, `PETSC_VIEWER_BINARY_` does not return
1533: an error code. The binary PetscViewer is usually used in the form
1534: $ XXXView(XXX object,PETSC_VIEWER_BINARY_(comm));
1536: .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PETSC_VIEWER_BINARY_WORLD`, `PETSC_VIEWER_BINARY_SELF`, `PetscViewerBinaryOpen()`, `PetscViewerCreate()`,
1537: `PetscViewerDestroy()`
1538: @*/
1539: PetscViewer PETSC_VIEWER_BINARY_(MPI_Comm comm)
1540: {
1542: PetscBool flg;
1543: PetscViewer viewer;
1544: char fname[PETSC_MAX_PATH_LEN];
1545: MPI_Comm ncomm;
1547: PetscCommDuplicate(comm, &ncomm, NULL);
1548: if (ierr) {
1549: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1550: return NULL;
1551: }
1552: if (Petsc_Viewer_Binary_keyval == MPI_KEYVAL_INVALID) {
1553: MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Binary_keyval, NULL);
1554: if (ierr) {
1555: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1556: return NULL;
1557: }
1558: }
1559: MPI_Comm_get_attr(ncomm, Petsc_Viewer_Binary_keyval, (void **)&viewer, (int *)&flg);
1560: if (ierr) {
1561: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1562: return NULL;
1563: }
1564: if (!flg) { /* PetscViewer not yet created */
1565: PetscOptionsGetenv(ncomm, "PETSC_VIEWER_BINARY_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
1566: if (ierr) {
1567: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1568: return NULL;
1569: }
1570: if (!flg) {
1571: PetscStrcpy(fname, "binaryoutput");
1572: if (ierr) {
1573: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1574: return NULL;
1575: }
1576: }
1577: PetscViewerBinaryOpen(ncomm, fname, FILE_MODE_WRITE, &viewer);
1578: if (ierr) {
1579: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1580: return NULL;
1581: }
1582: PetscObjectRegisterDestroy((PetscObject)viewer);
1583: if (ierr) {
1584: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1585: return NULL;
1586: }
1587: MPI_Comm_set_attr(ncomm, Petsc_Viewer_Binary_keyval, (void *)viewer);
1588: if (ierr) {
1589: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
1590: return NULL;
1591: }
1592: }
1593: PetscCommDestroy(&ncomm);
1594: if (ierr) {
1595: PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_BINARY_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " ");
1596: return NULL;
1597: }
1598: return viewer;
1599: }